func TestStringDiff(t *testing.T) { diff := diff.StringDiff("aaabb", "aaacc") expect := "aaa\n\nA: bb\n\nB: cc\n\n" if diff != expect { t.Errorf("diff returned %v", diff) } }
func TestProcessTemplateParameters(t *testing.T) { var template, expectedTemplate api.Template jsonData, _ := ioutil.ReadFile("../../test/templates/testdata/guestbook.json") if err := runtime.DecodeInto(kapi.Codecs.UniversalDecoder(), jsonData, &template); err != nil { t.Fatalf("unexpected error: %v", err) } expectedData, _ := ioutil.ReadFile("../../test/templates/testdata/guestbook_list.json") if err := runtime.DecodeInto(kapi.Codecs.UniversalDecoder(), expectedData, &expectedTemplate); err != nil { t.Fatalf("unexpected error: %v", err) } generators := map[string]generator.Generator{ "expression": generator.NewExpressionValueGenerator(rand.New(rand.NewSource(1337))), } processor := NewProcessor(generators) // Define custom parameter for the transformation: AddParameter(&template, makeParameter("CUSTOM_PARAM1", "1", "", false)) // Transform the template config into the result config errs := processor.Process(&template) if len(errs) > 0 { t.Fatalf("unexpected error: %v", errs) } result, err := runtime.Encode(kapi.Codecs.LegacyCodec(v1.SchemeGroupVersion), &template) if err != nil { t.Fatalf("unexpected error during encoding Config: %#v", err) } exp, _ := runtime.Encode(kapi.Codecs.LegacyCodec(v1.SchemeGroupVersion), &expectedTemplate) if string(result) != string(exp) { t.Errorf("unexpected output: %s", diff.StringDiff(string(exp), string(result))) } }
func (_ *IAMRole) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *IAMRole) error { policy, err := e.RolePolicyDocument.AsString() if err != nil { return fmt.Errorf("error rendering RolePolicyDocument: %v", err) } if a == nil { glog.V(2).Infof("Creating IAMRole with Name:%q", *e.Name) request := &iam.CreateRoleInput{} request.AssumeRolePolicyDocument = aws.String(policy) request.RoleName = e.Name response, err := t.Cloud.IAM.CreateRole(request) if err != nil { return fmt.Errorf("error creating IAMRole: %v", err) } e.ID = response.Role.RoleId } else { if changes.RolePolicyDocument != nil { glog.V(2).Infof("Updating IAMRole AssumeRolePolicy %q", *e.Name) var err error actualPolicy := "" if a.RolePolicyDocument != nil { actualPolicy, err = a.RolePolicyDocument.AsString() if err != nil { return fmt.Errorf("error reading actual policy document: %v", err) } } if actualPolicy == policy { glog.Warning("Policies were actually the same") } else { d := diff.StringDiff(actualPolicy, policy) glog.V(2).Infof("diff: %s", d) } request := &iam.UpdateAssumeRolePolicyInput{} request.PolicyDocument = aws.String(policy) request.RoleName = e.Name _, err = t.Cloud.IAM.UpdateAssumeRolePolicy(request) if err != nil { return fmt.Errorf("error updating IAMRole: %v", err) } } } // TODO: Should we use path as our tag? return nil // No tags in IAM }
func TestSerializeNodeConfig(t *testing.T) { config := &internal.NodeConfig{ PodManifestConfig: &internal.PodManifestConfig{}, } serializedConfig, err := writeYAML(config) if err != nil { t.Fatal(err) } if string(serializedConfig) != expectedSerializedNodeConfig { t.Errorf("Diff:\n-------------\n%s", diff.StringDiff(string(serializedConfig), expectedSerializedNodeConfig)) } }
func (_ *IAMRolePolicy) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *IAMRolePolicy) error { policy, err := e.PolicyDocument.AsString() if err != nil { return fmt.Errorf("error rendering PolicyDocument: %v", err) } doPut := false if a == nil { glog.V(2).Infof("Creating IAMRolePolicy") doPut = true } else if changes != nil { if changes.PolicyDocument != nil { glog.V(2).Infof("Applying changed role policy to %q:", *e.Name) var err error actualPolicy := "" if a.PolicyDocument != nil { actualPolicy, err = a.PolicyDocument.AsString() if err != nil { return fmt.Errorf("error reading actual policy document: %v", err) } } if actualPolicy == policy { glog.Warning("Policies were actually the same") } else { d := diff.StringDiff(actualPolicy, policy) glog.V(2).Infof("diff: %s", d) } doPut = true } } if doPut { request := &iam.PutRolePolicyInput{} request.PolicyDocument = aws.String(policy) request.RoleName = e.Name request.PolicyName = e.Name _, err = t.Cloud.IAM.PutRolePolicy(request) if err != nil { return fmt.Errorf("error creating/updating IAMRolePolicy: %v", err) } } // TODO: Should we use path as our tag? return nil // No tags in IAM }
func objDiff(a, b interface{}) string { ab, err := json.Marshal(a) if err != nil { panic("a") } bb, err := json.Marshal(b) if err != nil { panic("b") } return diff.StringDiff(string(ab), string(bb)) // An alternate diff attempt, in case json isn't showing you // the difference. (reflect.DeepEqual makes a distinction between // nil and empty slices, for example.) //return diff.StringDiff( // fmt.Sprintf("%#v", a), // fmt.Sprintf("%#v", b), //) }
func TestProcessValueEscape(t *testing.T) { var template api.Template if err := runtime.DecodeInto(kapi.Codecs.UniversalDecoder(), []byte(`{ "kind":"Template", "apiVersion":"v1", "objects": [ { "kind": "Service", "apiVersion": "v1beta3${VALUE}", "metadata": { "labels": { "key1": "${VALUE}", "key2": "$${VALUE}" } } } ] }`), &template); err != nil { t.Fatalf("unexpected error: %v", err) } generators := map[string]generator.Generator{ "expression": generator.NewExpressionValueGenerator(rand.New(rand.NewSource(1337))), } processor := NewProcessor(generators) // Define custom parameter for the transformation: AddParameter(&template, makeParameter("VALUE", "1", "", false)) // Transform the template config into the result config errs := processor.Process(&template) if len(errs) > 0 { t.Fatalf("unexpected error: %v", errs) } result, err := runtime.Encode(kapi.Codecs.LegacyCodec(v1beta3.SchemeGroupVersion), &template) if err != nil { t.Fatalf("unexpected error during encoding Config: %#v", err) } expect := `{"kind":"Template","apiVersion":"v1beta3","metadata":{"creationTimestamp":null},"objects":[{"apiVersion":"v1beta31","kind":"Service","metadata":{"labels":{"key1":"1","key2":"$1"}}}],"parameters":[{"name":"VALUE","value":"1"}]}` stringResult := strings.TrimSpace(string(result)) if expect != stringResult { t.Errorf("unexpected output: %s", diff.StringDiff(expect, stringResult)) } }
func doDeepCopyTest(t *testing.T, kind unversioned.GroupVersionKind, f *fuzz.Fuzzer) { item, err := api.Scheme.New(kind) if err != nil { t.Fatalf("Could not create a %v: %s", kind, err) } f.Fuzz(item) itemCopy, err := api.Scheme.DeepCopy(item) if err != nil { t.Errorf("Could not deep copy a %v: %s", kind, err) return } if !reflect.DeepEqual(item, itemCopy) { t.Errorf("\nexpected: %#v\n\ngot: %#v\n\ndiff: %v", item, itemCopy, diff.ObjectReflectDiff(item, itemCopy)) } prefuzzData := &bytes.Buffer{} if err := api.Codecs.LegacyCodec(kind.GroupVersion()).Encode(item, prefuzzData); err != nil { t.Errorf("Could not encode a %v: %s", kind, err) return } // Refuzz the copy, which should have no effect on the original f.Fuzz(itemCopy) postfuzzData := &bytes.Buffer{} if err := api.Codecs.LegacyCodec(kind.GroupVersion()).Encode(item, postfuzzData); err != nil { t.Errorf("Could not encode a %v: %s", kind, err) return } if bytes.Compare(prefuzzData.Bytes(), postfuzzData.Bytes()) != 0 { t.Log(diff.StringDiff(prefuzzData.String(), postfuzzData.String())) t.Errorf("Fuzzing copy modified original of %#v", kind) return } }
func TestEvaluateLabels(t *testing.T) { testCases := map[string]struct { Input string Output string Labels map[string]string }{ "no labels": { Input: `{ "kind":"Template", "apiVersion":"v1", "objects": [ { "kind": "Service", "apiVersion": "v1", "metadata": {"labels": {"key1": "v1", "key2": "v2"} } } ] }`, Output: `{ "kind":"Template","apiVersion":"v1","metadata":{"creationTimestamp":null}, "objects":[ { "apiVersion":"v1","kind":"Service","metadata":{ "labels":{"key1":"v1","key2":"v2"}} } ] }`, }, "one different label": { Input: `{ "kind":"Template", "apiVersion":"v1", "objects": [ { "kind": "Service", "apiVersion": "v1", "metadata": {"labels": {"key1": "v1", "key2": "v2"} } } ] }`, Output: `{ "kind":"Template","apiVersion":"v1","metadata":{"creationTimestamp":null}, "objects":[ { "apiVersion":"v1","kind":"Service","metadata":{ "labels":{"key1":"v1","key2":"v2","key3":"v3"}} } ], "labels":{"key3":"v3"} }`, Labels: map[string]string{"key3": "v3"}, }, "when the root object has labels and metadata": { Input: `{ "kind":"Template", "apiVersion":"v1", "objects": [ { "kind": "Service", "apiVersion": "v1", "metadata": {}, "labels": { "key1": "v1", "key2": "v2" } } ] }`, Output: `{ "kind":"Template","apiVersion":"v1","metadata":{"creationTimestamp":null}, "objects":[ { "apiVersion":"v1","kind":"Service", "labels":{"key1":"v1","key2":"v2"}, "metadata":{"labels":{"key3":"v3"}} } ], "labels":{"key3":"v3"} }`, Labels: map[string]string{"key3": "v3"}, }, "overwrites label": { Input: `{ "kind":"Template", "apiVersion":"v1", "objects": [ { "kind": "Service", "apiVersion": "v1", "metadata": {"labels": {"key1": "v1", "key2": "v2"} } } ] }`, Output: `{ "kind":"Template","apiVersion":"v1","metadata":{"creationTimestamp":null}, "objects":[ { "apiVersion":"v1","kind":"Service","metadata":{ "labels":{"key1":"v1","key2":"v3"}} } ], "labels":{"key2":"v3"} }`, Labels: map[string]string{"key2": "v3"}, }, } for k, testCase := range testCases { var template api.Template if err := runtime.DecodeInto(kapi.Codecs.UniversalDecoder(), []byte(testCase.Input), &template); err != nil { t.Errorf("%s: unexpected error: %v", k, err) continue } generators := map[string]generator.Generator{ "expression": generator.NewExpressionValueGenerator(rand.New(rand.NewSource(1337))), } processor := NewProcessor(generators) template.ObjectLabels = testCase.Labels // Transform the template config into the result config errs := processor.Process(&template) if len(errs) > 0 { t.Errorf("%s: unexpected error: %v", k, errs) continue } result, err := runtime.Encode(kapi.Codecs.LegacyCodec(v1.SchemeGroupVersion), &template) if err != nil { t.Errorf("%s: unexpected error: %v", k, err) continue } expect := testCase.Output expect = trailingWhitespace.ReplaceAllString(expect, "") stringResult := strings.TrimSpace(string(result)) if expect != stringResult { t.Errorf("%s: unexpected output: %s", k, diff.StringDiff(expect, stringResult)) continue } } }
func TestProcessValue(t *testing.T) { var template api.Template if err := runtime.DecodeInto(kapi.Codecs.UniversalDecoder(), []byte(`{ "kind":"Template", "apiVersion":"v1", "objects": [ { "kind": "Service", "apiVersion": "v${VALUE}", "metadata": { "labels": { "i1": "${{INT_1}}", "invalidjsonmap": "${{INVALID_JSON_MAP}}", "invalidjsonarray": "${{INVALID_JSON_ARRAY}}", "key1": "${VALUE}", "key2": "$${VALUE}", "quoted_string": "${{STRING_1}}", "s1_s1": "${STRING_1}_${STRING_1}", "s1_s2": "${STRING_1}_${STRING_2}", "untouched": "a${{INT_1}}", "untouched2": "${{INT_1}}a", "untouched3": "${{INVALID_PARAMETER}}", "untouched4": "${{INVALID PARAMETER}}", "validjsonmap": "${{VALID_JSON_MAP}}", "validjsonarray": "${{VALID_JSON_ARRAY}}" } } } ] }`), &template); err != nil { t.Fatalf("unexpected error: %v", err) } generators := map[string]generator.Generator{ "expression": generator.NewExpressionValueGenerator(rand.New(rand.NewSource(1337))), } processor := NewProcessor(generators) // Define custom parameter for the transformation: AddParameter(&template, makeParameter("VALUE", "1", "", false)) AddParameter(&template, makeParameter("STRING_1", "string1", "", false)) AddParameter(&template, makeParameter("STRING_2", "string2", "", false)) AddParameter(&template, makeParameter("INT_1", "1", "", false)) AddParameter(&template, makeParameter("VALID_JSON_MAP", "{\"key\":\"value\"}", "", false)) AddParameter(&template, makeParameter("INVALID_JSON_MAP", "{\"key\":\"value\"", "", false)) AddParameter(&template, makeParameter("VALID_JSON_ARRAY", "[\"key\",\"value\"]", "", false)) AddParameter(&template, makeParameter("INVALID_JSON_ARRAY", "[\"key\":\"value\"", "", false)) // Transform the template config into the result config errs := processor.Process(&template) if len(errs) > 0 { t.Fatalf("unexpected error: %v", errs) } result, err := runtime.Encode(kapi.Codecs.LegacyCodec(v1.SchemeGroupVersion), &template) if err != nil { t.Fatalf("unexpected error during encoding Config: %#v", err) } expect := `{"kind":"Template","apiVersion":"v1","metadata":{"creationTimestamp":null},"objects":[{"apiVersion":"v1","kind":"Service","metadata":{"labels":{"i1":1,"invalidjsonarray":"[\"key\":\"value\"","invalidjsonmap":"{\"key\":\"value\"","key1":"1","key2":"$1","quoted_string":"string1","s1_s1":"string1_string1","s1_s2":"string1_string2","untouched":"a${{INT_1}}","untouched2":"${{INT_1}}a","untouched3":"${{INVALID_PARAMETER}}","untouched4":"${{INVALID PARAMETER}}","validjsonarray":["key","value"],"validjsonmap":{"key":"value"}}}}],"parameters":[{"name":"VALUE","value":"1"},{"name":"STRING_1","value":"string1"},{"name":"STRING_2","value":"string2"},{"name":"INT_1","value":"1"},{"name":"VALID_JSON_MAP","value":"{\"key\":\"value\"}"},{"name":"INVALID_JSON_MAP","value":"{\"key\":\"value\""},{"name":"VALID_JSON_ARRAY","value":"[\"key\",\"value\"]"},{"name":"INVALID_JSON_ARRAY","value":"[\"key\":\"value\""}]}` stringResult := strings.TrimSpace(string(result)) if expect != stringResult { //t.Errorf("unexpected output, expected: \n%s\nGot:\n%s\n", expect, stringResult) t.Errorf("unexpected output: %s", diff.StringDiff(expect, stringResult)) } }
func TestMasterConfig(t *testing.T) { internal.Scheme.AddKnownTypes(v1.SchemeGroupVersion, &AdmissionPluginTestConfig{}) internal.Scheme.AddKnownTypes(internal.SchemeGroupVersion, &AdmissionPluginTestConfig{}) config := &internal.MasterConfig{ ServingInfo: internal.HTTPServingInfo{ ServingInfo: internal.ServingInfo{ NamedCertificates: []internal.NamedCertificate{{}}, }, }, KubernetesMasterConfig: &internal.KubernetesMasterConfig{ AdmissionConfig: internal.AdmissionConfig{ PluginConfig: map[string]internal.AdmissionPluginConfig{ // test config as an embedded object "plugin": { Configuration: &AdmissionPluginTestConfig{}, }, }, PluginOrderOverride: []string{"plugin"}, // explicitly set this field because it's omitempty }, }, EtcdConfig: &internal.EtcdConfig{}, OAuthConfig: &internal.OAuthConfig{ IdentityProviders: []internal.IdentityProvider{ {Provider: &internal.BasicAuthPasswordIdentityProvider{}}, {Provider: &internal.AllowAllPasswordIdentityProvider{}}, {Provider: &internal.DenyAllPasswordIdentityProvider{}}, {Provider: &internal.HTPasswdPasswordIdentityProvider{}}, {Provider: &internal.LDAPPasswordIdentityProvider{}}, {Provider: &internal.LDAPPasswordIdentityProvider{BindPassword: internal.StringSource{StringSourceSpec: internal.StringSourceSpec{File: "filename"}}}}, {Provider: &internal.RequestHeaderIdentityProvider{}}, {Provider: &internal.KeystonePasswordIdentityProvider{}}, {Provider: &internal.GitHubIdentityProvider{}}, {Provider: &internal.GitHubIdentityProvider{ClientSecret: internal.StringSource{StringSourceSpec: internal.StringSourceSpec{File: "filename"}}}}, {Provider: &internal.GitLabIdentityProvider{}}, {Provider: &internal.GitLabIdentityProvider{ClientSecret: internal.StringSource{StringSourceSpec: internal.StringSourceSpec{File: "filename"}}}}, {Provider: &internal.GoogleIdentityProvider{}}, {Provider: &internal.GoogleIdentityProvider{ClientSecret: internal.StringSource{StringSourceSpec: internal.StringSourceSpec{File: "filename"}}}}, {Provider: &internal.OpenIDIdentityProvider{}}, {Provider: &internal.OpenIDIdentityProvider{ClientSecret: internal.StringSource{StringSourceSpec: internal.StringSourceSpec{File: "filename"}}}}, }, SessionConfig: &internal.SessionConfig{}, Templates: &internal.OAuthTemplates{}, }, AssetConfig: &internal.AssetConfig{ Extensions: []internal.AssetExtensionsConfig{{}}, }, DNSConfig: &internal.DNSConfig{}, AdmissionConfig: internal.AdmissionConfig{ PluginConfig: map[string]internal.AdmissionPluginConfig{ // test config as an embedded object "plugin": { Configuration: &AdmissionPluginTestConfig{}, }, }, PluginOrderOverride: []string{"plugin"}, // explicitly set this field because it's omitempty }, VolumeConfig: internal.MasterVolumeConfig{ DynamicProvisioningEnabled: false, }, } serializedConfig, err := writeYAML(config) if err != nil { t.Fatal(err) } if string(serializedConfig) != expectedSerializedMasterConfig { t.Errorf("Diff:\n-------------\n%s", diff.StringDiff(string(serializedConfig), expectedSerializedMasterConfig)) } }
func testObjects(t *testing.T, list *api.List, fixtureFilename string) { filename := filepath.Join("testdata", fixtureFilename) expectedYAML, err := ioutil.ReadFile(filename) if err != nil { t.Fatal(err) } if err := runtime.EncodeList(api.Codecs.LegacyCodec(v1.SchemeGroupVersion, rbacv1alpha1.SchemeGroupVersion), list.Items); err != nil { t.Fatal(err) } jsonData, err := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion, rbacv1alpha1.SchemeGroupVersion), list) if err != nil { t.Fatal(err) } yamlData, err := yaml.JSONToYAML(jsonData) if err != nil { t.Fatal(err) } if string(yamlData) != string(expectedYAML) { t.Errorf("Bootstrap policy data does not match the test fixture in %s", filename) const updateEnvVar = "UPDATE_BOOTSTRAP_POLICY_FIXTURE_DATA" if os.Getenv(updateEnvVar) == "true" { if err := ioutil.WriteFile(filename, []byte(yamlData), os.FileMode(0755)); err == nil { t.Logf("Updated data in %s", filename) t.Logf("Verify the diff, commit changes, and rerun the tests") } else { t.Logf("Could not update data in %s: %v", filename, err) } } else { t.Logf("Diff between bootstrap data and fixture data in %s:\n-------------\n%s", filename, diff.StringDiff(string(yamlData), string(expectedYAML))) t.Logf("If the change is expected, re-run with %s=true to update the fixtures", updateEnvVar) } } }