func TestProcessTemplateParameters(t *testing.T) { var template, expectedTemplate api.Template jsonData, _ := ioutil.ReadFile("../../test/templates/fixtures/guestbook.json") if err := latest.Codec.DecodeInto(jsonData, &template); err != nil { t.Fatalf("unexpected error: %v", err) } expectedData, _ := ioutil.ReadFile("../../test/templates/fixtures/guestbook_list.json") if err := latest.Codec.DecodeInto(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 := v1beta3.Codec.Encode(&template) if err != nil { t.Fatalf("unexpected error during encoding Config: %#v", err) } exp, _ := v1beta3.Codec.Encode(&expectedTemplate) if string(result) != string(exp) { t.Errorf("unexpected output: %s", util.StringDiff(string(exp), string(result))) } }
func TestMasterConfig(t *testing.T) { config := &internal.MasterConfig{ KubernetesMasterConfig: &internal.KubernetesMasterConfig{}, EtcdConfig: &internal.EtcdConfig{}, OAuthConfig: &internal.OAuthConfig{ IdentityProviders: []internal.IdentityProvider{ {Provider: runtime.EmbeddedObject{Object: &internal.BasicAuthPasswordIdentityProvider{}}}, {Provider: runtime.EmbeddedObject{Object: &internal.AllowAllPasswordIdentityProvider{}}}, {Provider: runtime.EmbeddedObject{Object: &internal.DenyAllPasswordIdentityProvider{}}}, {Provider: runtime.EmbeddedObject{Object: &internal.HTPasswdPasswordIdentityProvider{}}}, {Provider: runtime.EmbeddedObject{Object: &internal.LDAPPasswordIdentityProvider{}}}, {Provider: runtime.EmbeddedObject{Object: &internal.RequestHeaderIdentityProvider{}}}, {Provider: runtime.EmbeddedObject{Object: &internal.GitHubIdentityProvider{}}}, {Provider: runtime.EmbeddedObject{Object: &internal.GoogleIdentityProvider{}}}, {Provider: runtime.EmbeddedObject{Object: &internal.OpenIDIdentityProvider{}}}, }, SessionConfig: &internal.SessionConfig{}, Templates: &internal.OAuthTemplates{}, }, AssetConfig: &internal.AssetConfig{ Extensions: []internal.AssetExtensionsConfig{{}}, }, DNSConfig: &internal.DNSConfig{}, } serializedConfig, err := writeYAML(config) if err != nil { t.Fatal(err) } if string(serializedConfig) != expectedSerializedMasterConfig { t.Errorf("Diff:\n-------------\n%s", util.StringDiff(string(serializedConfig), expectedSerializedMasterConfig)) } }
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.RequestHeaderIdentityProvider{}}, {Provider: &internal.KeystonePasswordIdentityProvider{}}, {Provider: &internal.GitHubIdentityProvider{}}, {Provider: &internal.GitLabIdentityProvider{}}, {Provider: &internal.GoogleIdentityProvider{}}, {Provider: &internal.OpenIDIdentityProvider{}}, }, 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 the it's omitempty }, } serializedConfig, err := writeYAML(config) if err != nil { t.Fatal(err) } if string(serializedConfig) != expectedSerializedMasterConfig { t.Errorf("Diff:\n-------------\n%s", util.StringDiff(string(serializedConfig), expectedSerializedMasterConfig)) } }
func TestNodeConfig(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", util.StringDiff(string(serializedConfig), expectedSerializedNodeConfig)) } }
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 util.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 util.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", util.StringDiff(expect, stringResult)) } }
func TestImageWithMetadata(t *testing.T) { tests := map[string]struct { image Image expectedImage Image expectError bool }{ "no manifest data": { image: Image{}, expectedImage: Image{}, }, "error unmarshalling manifest data": { image: Image{ DockerImageManifest: "{ no {{{ json here!!!", }, expectedImage: Image{}, expectError: true, }, "no history": { image: Image{ DockerImageManifest: `{"name": "library/ubuntu", "tag": "latest"}`, }, expectedImage: Image{}, }, "error unmarshalling v1 compat": { image: Image{ DockerImageManifest: `{"name": "library/ubuntu", "tag": "latest", "history": ["v1Compatibility": "{ not valid {{ json" }`, }, expectError: true, }, "happy path": { image: validImageWithManifestData(), expectedImage: Image{ ObjectMeta: kapi.ObjectMeta{ Name: "id", }, DockerImageManifest: "", DockerImageMetadata: DockerImage{ ID: "2d24f826cb16146e2016ff349a8a33ed5830f3b938d45c0f82943f4ab8c097e7", Parent: "117ee323aaa9d1b136ea55e4421f4ce413dfc6c0cc6b2186dea6c88d93e1ad7c", Comment: "", Created: unversioned.Date(2015, 2, 21, 2, 11, 6, 735146646, time.UTC), Container: "c9a3eda5951d28aa8dbe5933be94c523790721e4f80886d0a8e7a710132a38ec", ContainerConfig: DockerConfig{ Hostname: "43bd710ec89a", Domainname: "", User: "", Memory: 0, MemorySwap: 0, CPUShares: 0, CPUSet: "", AttachStdin: false, AttachStdout: false, AttachStderr: false, PortSpecs: nil, ExposedPorts: nil, Tty: false, OpenStdin: false, StdinOnce: false, Env: []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}, Cmd: []string{"/bin/sh", "-c", "#(nop) CMD [/bin/bash]"}, Image: "117ee323aaa9d1b136ea55e4421f4ce413dfc6c0cc6b2186dea6c88d93e1ad7c", Volumes: nil, WorkingDir: "", Entrypoint: nil, NetworkDisabled: false, SecurityOpts: nil, OnBuild: []string{}, }, DockerVersion: "1.4.1", Author: "", Config: &DockerConfig{ Hostname: "43bd710ec89a", Domainname: "", User: "", Memory: 0, MemorySwap: 0, CPUShares: 0, CPUSet: "", AttachStdin: false, AttachStdout: false, AttachStderr: false, PortSpecs: nil, ExposedPorts: nil, Tty: false, OpenStdin: false, StdinOnce: false, Env: []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}, Cmd: []string{"/bin/bash"}, Image: "117ee323aaa9d1b136ea55e4421f4ce413dfc6c0cc6b2186dea6c88d93e1ad7c", Volumes: nil, WorkingDir: "", Entrypoint: nil, NetworkDisabled: false, OnBuild: []string{}, }, Architecture: "amd64", Size: 0, }, }, }, } for name, test := range tests { imageWithMetadata, err := ImageWithMetadata(test.image) gotError := err != nil if e, a := test.expectError, gotError; e != a { t.Fatalf("%s: expectError=%t, gotError=%t: %s", name, e, a, err) } if test.expectError { continue } if e, a := test.expectedImage, *imageWithMetadata; !kapi.Semantic.DeepEqual(e, a) { stringE := fmt.Sprintf("%#v", e) stringA := fmt.Sprintf("%#v", a) t.Errorf("%s: image: %s", name, util.StringDiff(stringE, stringA)) } } }
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": "v1beta3", "metadata": {"labels": {"key1": "v1", "key2": "v2"} } } ] }`, Output: `{ "kind":"Template","apiVersion":"v1beta3","metadata":{"creationTimestamp":null}, "objects":[ { "apiVersion":"v1beta3","kind":"Service","metadata":{ "labels":{"key1":"v1","key2":"v2"}} } ] }`, }, "one different label": { Input: `{ "kind":"Template", "apiVersion":"v1", "objects": [ { "kind": "Service", "apiVersion": "v1beta3", "metadata": {"labels": {"key1": "v1", "key2": "v2"} } } ] }`, Output: `{ "kind":"Template","apiVersion":"v1beta3","metadata":{"creationTimestamp":null}, "objects":[ { "apiVersion":"v1beta3","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 no metadata": { Input: `{ "kind":"Template", "apiVersion":"v1", "objects": [ { "kind": "Service", "apiVersion": "v1beta1", "labels": { "key1": "v1", "key2": "v2" } } ] }`, Output: `{ "kind":"Template","apiVersion":"v1beta3","metadata":{"creationTimestamp":null}, "objects":[ { "apiVersion":"v1beta1","kind":"Service", "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": "v1beta1", "metadata": {}, "labels": { "key1": "v1", "key2": "v2" } } ] }`, Output: `{ "kind":"Template","apiVersion":"v1beta3","metadata":{"creationTimestamp":null}, "objects":[ { "apiVersion":"v1beta1","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": "v1beta3", "metadata": {"labels": {"key1": "v1", "key2": "v2"} } } ] }`, Output: `{ "kind":"Template","apiVersion":"v1beta3","metadata":{"creationTimestamp":null}, "objects":[ { "apiVersion":"v1beta3","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 := latest.Codec.DecodeInto([]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 := v1beta3.Codec.Encode(&template) if err != nil { t.Errorf("%s: unexpected error: %v", k, err) continue } expect := testCase.Output expect = trailingWhitespace.ReplaceAllString(expect, "") if expect != string(result) { t.Errorf("%s: unexpected output: %s", k, util.StringDiff(expect, string(result))) continue } } }
func testObjects(t *testing.T, list *api.List, fixtureFilename string) { filename := filepath.Join("../../../../test/fixtures/bootstrappolicy", fixtureFilename) expectedYAML, err := ioutil.ReadFile(filename) if err != nil { t.Fatal(err) } if err := runtime.EncodeList(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), list.Items); err != nil { t.Fatal(err) } jsonData, err := runtime.Encode(api.Codecs.LegacyCodec(v1.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, util.StringDiff(string(yamlData), string(expectedYAML))) t.Logf("If the change is expected, re-run with %s=true to update the fixtures", updateEnvVar) } } }
func testObjects(t *testing.T, list *api.List, fixtureFilename string) { filename := filepath.Join("../../../../test/fixtures/bootstrappolicy", fixtureFilename) expectedYAML, err := ioutil.ReadFile(filename) if err != nil { t.Fatal(err) } if err := runtime.EncodeList(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), list.Items); err != nil { t.Fatal(err) } jsonData, err := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), list) if err != nil { t.Fatal(err) } yamlData, err := yaml.JSONToYAML(jsonData) if err != nil { t.Fatal(err) } if string(yamlData) != string(expectedYAML) { fmt.Println("Bootstrap policy data does not match the test fixture in " + filename) fmt.Println("If the change is expected, update the fixture with this bootstrap policy data:") fmt.Println("-----------------------------------") fmt.Println(string(yamlData)) fmt.Println("-----------------------------------") t.Errorf("Diff between bootstrap data and fixture data in %s:\n-------------\n%s", filename, util.StringDiff(string(yamlData), string(expectedYAML))) } }