func DefaultTemplate() *templateapi.Template { ret := &templateapi.Template{} ret.Name = DefaultTemplateName ns := "${" + ProjectNameParam + "}" templateContents := []runtime.Object{} project := &projectapi.Project{} project.Name = ns project.Annotations = map[string]string{ projectapi.ProjectDescription: "${" + ProjectDescriptionParam + "}", projectapi.ProjectDisplayName: "${" + ProjectDisplayNameParam + "}", projectapi.ProjectRequester: "${" + ProjectRequesterParam + "}", } templateContents = append(templateContents, project) serviceAccountRoleBindings := bootstrappolicy.GetBootstrapServiceAccountProjectRoleBindings(ns) for i := range serviceAccountRoleBindings { templateContents = append(templateContents, &serviceAccountRoleBindings[i]) } binding := &authorizationapi.RoleBinding{} binding.Name = bootstrappolicy.AdminRoleName binding.Namespace = ns binding.Subjects = []kapi.ObjectReference{{Kind: authorizationapi.UserKind, Name: "${" + ProjectAdminUserParam + "}"}} binding.RoleRef.Name = bootstrappolicy.AdminRoleName templateContents = append(templateContents, binding) if err := templateapi.AddObjectsToTemplate(ret, templateContents, latest.Version); err != nil { // this should never happen because we're tightly controlling what goes in. panic(err) } for _, parameterName := range parameters { parameter := templateapi.Parameter{} parameter.Name = parameterName ret.Parameters = append(ret.Parameters, parameter) } return ret }
func TestTemplate(t *testing.T) { _, path, err := testserver.StartTestMasterAPI() if err != nil { t.Fatalf("unexpected error: %v", err) } for _, version := range []unversioned.GroupVersion{v1.SchemeGroupVersion} { config, err := testutil.GetClusterAdminClientConfig(path) if err != nil { t.Fatalf("unexpected error: %v", err) } config.GroupVersion = &version c, err := client.New(config) if err != nil { t.Fatalf("unexpected error: %v", err) } template := &templateapi.Template{ Parameters: []templateapi.Parameter{ { Name: "NAME", Value: "test", }, }, } templateObjects := []runtime.Object{ &v1.Service{ ObjectMeta: v1.ObjectMeta{ Name: "${NAME}-tester", Namespace: "somevalue", }, Spec: v1.ServiceSpec{ ClusterIP: "1.2.3.4", SessionAffinity: "some-bad-${VALUE}", }, }, } templateapi.AddObjectsToTemplate(template, templateObjects, v1.SchemeGroupVersion) obj, err := c.TemplateConfigs("default").Create(template) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(obj.Objects) != 1 { t.Fatalf("unexpected object: %#v", obj) } if err := runtime.DecodeList(obj.Objects, runtime.UnstructuredJSONScheme); err != nil { t.Fatalf("unexpected error: %v", err) } svc := obj.Objects[0].(*runtime.Unstructured).Object spec := svc["spec"].(map[string]interface{}) meta := svc["metadata"].(map[string]interface{}) // keep existing values if spec["clusterIP"] != "1.2.3.4" { t.Fatalf("unexpected object: %#v", svc) } // replace a value if meta["name"] != "test-tester" { t.Fatalf("unexpected object: %#v", svc) } // clear namespace if meta["namespace"] != "" { t.Fatalf("unexpected object: %#v", svc) } // preserve values exactly if spec["sessionAffinity"] != "some-bad-${VALUE}" { t.Fatalf("unexpected object: %#v", svc) } } }
func TestNewRESTTemplateLabels(t *testing.T) { testLabels := map[string]string{ "label1": "value1", "label2": "value2", } storage := NewREST() // because of encoding changes, we to round-trip ourselves templateToCreate := &template.Template{ ObjectMeta: kapi.ObjectMeta{ Name: "test", }, ObjectLabels: testLabels, } templateObjects := []runtime.Object{ &kapi.Service{ ObjectMeta: kapi.ObjectMeta{ Name: "test-service", }, Spec: kapi.ServiceSpec{ Ports: []kapi.ServicePort{ { Port: 80, Protocol: kapi.ProtocolTCP, }, }, SessionAffinity: kapi.ServiceAffinityNone, }, }, } template.AddObjectsToTemplate(templateToCreate, templateObjects, registered.GroupOrDie(kapi.GroupName).GroupVersions[0]) originalBytes, err := runtime.Encode(kapi.Codecs.LegacyCodec(registered.GroupOrDie(kapi.GroupName).GroupVersions[0]), templateToCreate) if err != nil { t.Fatalf("unexpected error: %v", err) } objToCreate, err := runtime.Decode(kapi.Codecs.UniversalDecoder(), originalBytes) if err != nil { t.Fatalf("unexpected error: %v", err) } templateToCreate = objToCreate.(*template.Template) obj, err := storage.Create(nil, templateToCreate) if err != nil { t.Fatalf("unexpected error: %v", err) } bytes, err := runtime.Encode(kapi.Codecs.LegacyCodec(registered.GroupOrDie(kapi.GroupName).GroupVersions[0]), obj) if err != nil { t.Fatalf("unexpected error: %v", err) } obj, err = runtime.Decode(kapi.Codecs.UniversalDecoder(), bytes) if err != nil { t.Fatalf("unexpected error: %v", err) } config := obj.(*template.Template) if err := utilerrors.NewAggregate(runtime.DecodeList(config.Objects, kapi.Codecs.UniversalDecoder())); err != nil { t.Fatalf("unexpected error: %v", err) } svc, ok := config.Objects[0].(*kapi.Service) if !ok { t.Fatalf("Unexpected object in config: %#v", config.Objects[0]) } for k, v := range testLabels { value, ok := svc.Labels[k] if !ok { t.Fatalf("Missing output label: %s", k) } if value != v { t.Fatalf("Unexpected label value: %s", value) } } }
func TestProjectRequestError(t *testing.T) { testutil.RequireEtcd(t) defer testutil.DumpEtcdOnFailure(t) const ( ns = "testns" templateNamespace = "default" templateName = "project-request-template" ) masterConfig, err := testserver.DefaultMasterOptions() if err != nil { t.Fatalf("error creating config: %v", err) } masterConfig.ProjectConfig.ProjectRequestTemplate = templateNamespace + "/" + templateName kubeConfigFile, err := testserver.StartConfiguredMaster(masterConfig) if err != nil { t.Fatalf("error starting server: %v", err) } kubeClient, err := testutil.GetClusterAdminKubeClient(kubeConfigFile) if err != nil { t.Fatalf("error getting client: %v", err) } openshiftClient, err := testutil.GetClusterAdminClient(kubeConfigFile) if err != nil { t.Fatalf("error getting openshift client: %v", err) } // Create custom template template := delegated.DefaultTemplate() template.Name = templateName additionalObjects := []runtime.Object{ // Append an object that will succeed &kapi.ConfigMap{ObjectMeta: kapi.ObjectMeta{Name: "configmapname"}}, // Append a custom object that will fail validation &kapi.ConfigMap{}, // Append another object that should never be created, since we short circuit &kapi.ConfigMap{ObjectMeta: kapi.ObjectMeta{Name: "configmapname2"}}, } if err := templateapi.AddObjectsToTemplate(template, additionalObjects, kapiv1.SchemeGroupVersion); err != nil { t.Fatal(err) } if _, err := openshiftClient.Templates(templateNamespace).Create(template); err != nil { t.Fatal(err) } // Watch the project, rolebindings, and configmaps nswatch, err := kubeClient.Namespaces().Watch(kapi.ListOptions{FieldSelector: fields.OneTermEqualSelector("metadata.name", ns)}) if err != nil { t.Fatal(err) } policywatch, err := openshiftClient.PolicyBindings(ns).Watch(kapi.ListOptions{}) if err != nil { t.Fatal(err) } cmwatch, err := kubeClient.ConfigMaps(ns).Watch(kapi.ListOptions{}) if err != nil { t.Fatal(err) } // Create project request _, err = openshiftClient.ProjectRequests().Create(&projectapi.ProjectRequest{ObjectMeta: kapi.ObjectMeta{Name: ns}}) if err == nil || err.Error() != `Internal error occurred: ConfigMap "" is invalid: metadata.name: Required value: name or generateName is required` { t.Fatalf("Expected internal error creating project, got %v", err) } pairCreationDeletion := func(w watch.Interface) (int, int, []watch.Event) { added := 0 deleted := 0 events := []watch.Event{} for { select { case e := <-w.ResultChan(): events = append(events, e) switch e.Type { case watch.Added: added++ case watch.Deleted: deleted++ } case <-time.After(10 * time.Second): return added, deleted, events } if added == deleted && added > 0 { return added, deleted, events } } } if added, deleted, events := pairCreationDeletion(nswatch); added != deleted || added != 1 { for _, e := range events { t.Logf("%s %#v", e.Type, e.Object) } t.Errorf("expected 1 namespace to be added and deleted, got %d added / %d deleted", added, deleted) } if added, deleted, events := pairCreationDeletion(policywatch); added != deleted || added != 1 { for _, e := range events { t.Logf("%s %#v", e.Type, e.Object) } t.Errorf("expected 1 policybinding to be added and deleted, got %d added / %d deleted", added, deleted) } if added, deleted, events := pairCreationDeletion(cmwatch); added != deleted || added != 1 { for _, e := range events { t.Logf("%s %#v", e.Type, e.Object) } t.Errorf("expected 1 configmap to be added and deleted, got %d added / %d deleted", added, deleted) } // Verify project is deleted if nsObj, err := kubeClient.Namespaces().Get(ns); !kapierrors.IsNotFound(err) { t.Errorf("Expected namespace to be gone, got %#v, %#v", nsObj, err) } }