func TestEtcdControllerValidatesUpdate(t *testing.T) { ctx := api.NewDefaultContext() storage, _ := newStorage(t) updateController, err := createController(storage, validController, t) if err != nil { t.Errorf("Failed to create controller, cannot proceed with test.") } updaters := []func(rc api.ReplicationController) (runtime.Object, bool, error){ func(rc api.ReplicationController) (runtime.Object, bool, error) { rc.UID = "newUID" return storage.Update(ctx, &rc) }, func(rc api.ReplicationController) (runtime.Object, bool, error) { rc.Name = "" return storage.Update(ctx, &rc) }, func(rc api.ReplicationController) (runtime.Object, bool, error) { rc.Spec.Selector = map[string]string{} return storage.Update(ctx, &rc) }, } for _, u := range updaters { c, updated, err := u(updateController) if c != nil || updated { t.Errorf("Expected nil object and not created") } if !errors.IsInvalid(err) && !errors.IsBadRequest(err) { t.Errorf("Expected invalid or bad request error, got %v of type %T", err, err) } } }
func TestEtcdParseWatchResourceVersion(t *testing.T) { testCases := []struct { Version string Kind string ExpectVersion uint64 Err bool }{ {Version: "", ExpectVersion: 0}, {Version: "a", Err: true}, {Version: " ", Err: true}, {Version: "1", ExpectVersion: 2}, {Version: "10", ExpectVersion: 11}, } for _, testCase := range testCases { version, err := ParseWatchResourceVersion(testCase.Version, testCase.Kind) switch { case testCase.Err: if err == nil { t.Errorf("%s: unexpected non-error", testCase.Version) continue } if !errors.IsInvalid(err) { t.Errorf("%s: unexpected error: %v", testCase.Version, err) continue } case !testCase.Err && err != nil: t.Errorf("%s: unexpected error: %v", testCase.Version, err) continue } if version != testCase.ExpectVersion { t.Errorf("%s: expected version %d but was %d", testCase.Version, testCase.ExpectVersion, version) } } }
func TestMinionRegistryValidatesCreate(t *testing.T) { storage := NewREST(registrytest.NewMinionRegistry([]string{"foo", "bar"}, api.NodeResources{})) ctx := api.NewContext() failureCases := map[string]api.Node{ "zero-length Name": { ObjectMeta: api.ObjectMeta{ Name: "", Labels: validSelector, }, Status: api.NodeStatus{ Addresses: []api.NodeAddress{ {Type: api.NodeLegacyHostIP, Address: "something"}, }, }, }, "invalid-labels": { ObjectMeta: api.ObjectMeta{ Name: "abc-123", Labels: invalidSelector, }, }, } for _, failureCase := range failureCases { c, err := storage.Create(ctx, &failureCase) if c != nil { t.Errorf("Expected nil object") } if !errors.IsInvalid(err) { t.Errorf("Expected to get an invalid resource error, got %v", err) } } }
func TestServiceStorageValidatesCreate(t *testing.T) { registry := registrytest.NewServiceRegistry() storage := NewREST(registry, nil, nil, makeIPNet(t)) failureCases := map[string]api.Service{ "empty ID": { ObjectMeta: api.ObjectMeta{Name: ""}, Spec: api.ServiceSpec{ Port: 6502, Selector: map[string]string{"bar": "baz"}, }, }, "empty selector": { ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, }, }, } ctx := api.NewDefaultContext() for _, failureCase := range failureCases { c, err := storage.Create(ctx, &failureCase) if c != nil { t.Errorf("Expected nil channel") } if !errors.IsInvalid(err) { t.Errorf("Expected to get an invalid resource error, got %v", err) } } }
func TestUpdateWithEmptyResourceVersion(t *testing.T) { // Starting conditions associatedUser1, associatedIdentity1User1 := makeAssociated() unassociatedUser2 := makeUser() // Finishing conditions _, unassociatedIdentity1 := disassociate(associatedUser1, associatedIdentity1User1) expectedActions := []test.Action{ // Existing mapping lookup {"GetIdentity", associatedIdentity1User1.Name}, {"GetUser", associatedUser1.Name}, } mapping := &api.UserIdentityMapping{ Identity: kapi.ObjectReference{Name: unassociatedIdentity1.Name}, User: kapi.ObjectReference{Name: unassociatedUser2.Name}, } actions, _, _, rest := setupRegistries(associatedIdentity1User1, associatedUser1, unassociatedUser2) _, _, err := rest.Update(kapi.NewContext(), mapping) if err == nil { t.Errorf("Expected error") } if !kerrs.IsInvalid(err) { t.Errorf("Unexpected error: %v", err) } verifyActions(expectedActions, *actions, t) }
func TestControllerStorageValidatesUpdate(t *testing.T) { mockRegistry := registrytest.ControllerRegistry{} storage := REST{ registry: &mockRegistry, podLister: nil, pollPeriod: time.Millisecond * 1, } failureCases := map[string]api.ReplicationController{ "empty ID": { ObjectMeta: api.ObjectMeta{Name: ""}, Spec: api.ReplicationControllerSpec{ Selector: map[string]string{"bar": "baz"}, }, }, "empty selector": { ObjectMeta: api.ObjectMeta{Name: "abc"}, Spec: api.ReplicationControllerSpec{}, }, } ctx := api.NewDefaultContext() for _, failureCase := range failureCases { c, err := storage.Update(ctx, &failureCase) if c != nil { t.Errorf("Expected nil channel") } if !errors.IsInvalid(err) { t.Errorf("Expected to get an invalid resource error, got %v", err) } } }
func TestServiceStorageValidatesCreate(t *testing.T) { registry := registrytest.NewServiceRegistry() storage := NewREST(registry, nil, nil) failureCases := map[string]api.Service{ "empty ID": { Port: 6502, JSONBase: api.JSONBase{ID: ""}, Selector: map[string]string{"bar": "baz"}, }, "empty selector": { JSONBase: api.JSONBase{ID: "foo"}, Selector: map[string]string{}, }, } for _, failureCase := range failureCases { c, err := storage.Create(&failureCase) if c != nil { t.Errorf("Expected nil channel") } if !errors.IsInvalid(err) { t.Errorf("Expected to get an invalid resource error, got %v", err) } } }
func checkCustomErr(customPrefix string, err error, handleErr func(string)) { if err == nil { return } if errors.IsInvalid(err) { details := err.(*errors.StatusError).Status().Details for i := range details.Causes { c := &details.Causes[i] s := strings.Split(c.Message, "}': ") if len(s) == 2 { c.Message = s[1] c.Field = "" } } prefix := fmt.Sprintf("%s", customPrefix) errs := statusCausesToAggrError(details.Causes) handleErr(MultilineError(prefix, errs)) } // handle multiline errors if clientcmd.IsConfigurationInvalid(err) { handleErr(MultilineError("Error in configuration: ", err)) } if agg, ok := err.(utilerrors.Aggregate); ok && len(agg.Errors()) > 0 { handleErr(MultipleErrors("", agg.Errors())) } msg, ok := StandardErrorMessage(err) if !ok { msg = fmt.Sprintf("error: %s\n", err.Error()) } handleErr(msg) }
func checkErr(err error, handleErr func(string)) { if err == nil { return } if errors.IsInvalid(err) { details := err.(*errors.StatusError).Status().Details prefix := fmt.Sprintf("The %s %q is invalid:", details.Kind, details.Name) errs := statusCausesToAggrError(details.Causes) handleErr(MultilineError(prefix, errs)) } // handle multiline errors if clientcmd.IsConfigurationInvalid(err) { handleErr(MultilineError("Error in configuration: ", err)) } if agg, ok := err.(utilerrors.Aggregate); ok && len(agg.Errors()) > 0 { handleErr(MultipleErrors("", agg.Errors())) } msg, ok := StandardErrorMessage(err) if !ok { msg = fmt.Sprintf("error: %s\n", err.Error()) } handleErr(msg) }
func TestControllerStorageValidatesUpdate(t *testing.T) { mockRegistry := registrytest.ControllerRegistry{} storage := REST{ registry: &mockRegistry, podLister: nil, pollPeriod: time.Millisecond * 1, } failureCases := map[string]api.ReplicationController{ "empty ID": { JSONBase: api.JSONBase{ID: ""}, DesiredState: api.ReplicationControllerState{ ReplicaSelector: map[string]string{"bar": "baz"}, }, }, "empty selector": { JSONBase: api.JSONBase{ID: "abc"}, DesiredState: api.ReplicationControllerState{}, }, } for _, failureCase := range failureCases { c, err := storage.Update(&failureCase) if c != nil { t.Errorf("Expected nil channel") } if !errors.IsInvalid(err) { t.Errorf("Expected to get an invalid resource error, got %v", err) } } }
func TestMinionStorageValidatesCreate(t *testing.T) { storage := NewREST(registrytest.NewMinionRegistry([]string{"foo", "bar"}, api.NodeResources{})) ctx := api.NewContext() validSelector := map[string]string{"a": "b"} invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"} failureCases := map[string]api.Minion{ "zero-length Name": { ObjectMeta: api.ObjectMeta{ Name: "", Labels: validSelector, }, Status: api.NodeStatus{ HostIP: "something", }, }, "invalid-labels": { ObjectMeta: api.ObjectMeta{ Name: "abc-123", Labels: invalidSelector, }, }, } for _, failureCase := range failureCases { c, err := storage.Create(ctx, &failureCase) if c != nil { t.Errorf("Expected nil channel") } if !errors.IsInvalid(err) { t.Errorf("Expected to get an invalid resource error, got %v", err) } } }
func TestBuildStorageValidatesUpdate(t *testing.T) { mockRegistry := test.BuildRegistry{} storage := Storage{&mockRegistry} failureCases := map[string]api.Build{ "empty ID": { JSONBase: kubeapi.JSONBase{ID: ""}, Input: api.BuildInput{ Type: api.DockerBuildType, SourceURI: "http://my.build.com/the/build/Dockerfile", ImageTag: "repository/dataBuild", }, }, "empty build input": { JSONBase: kubeapi.JSONBase{ID: "abc"}, Input: api.BuildInput{}, }, } for desc, failureCase := range failureCases { c, err := storage.Update(&failureCase) if c != nil { t.Errorf("%s: Expected nil channel", desc) } if !errors.IsInvalid(err) { t.Errorf("%s: Expected to get an invalid resource error, got %v", desc, err) } } }
func TestBuildStorageValidatesUpdate(t *testing.T) { mockRegistry := test.BuildConfigRegistry{} storage := Storage{&mockRegistry} failureCases := map[string]api.BuildConfig{ "empty ID": { JSONBase: kubeapi.JSONBase{ID: ""}, DesiredInput: api.BuildInput{ SourceURI: "http://github.com/test/source", ImageTag: "data/image", Type: api.DockerBuildType, }, }, "blank sourceURI": { JSONBase: kubeapi.JSONBase{ID: "abc"}, DesiredInput: api.BuildInput{ SourceURI: "", ImageTag: "data/image", Type: api.STIBuildType, BuilderImage: "builder/image", }, }, "blank ImageTag": { JSONBase: kubeapi.JSONBase{ID: "abc"}, DesiredInput: api.BuildInput{ SourceURI: "http://github.com/test/source", ImageTag: "", Type: api.DockerBuildType, }, }, "blank BuilderImage on STIBuildType": { JSONBase: kubeapi.JSONBase{ID: "abc"}, DesiredInput: api.BuildInput{ SourceURI: "http://github.com/test/source", ImageTag: "data/image", Type: api.STIBuildType, BuilderImage: "", }, }, "non-blank BuilderImage on DockerBuildType": { JSONBase: kubeapi.JSONBase{ID: "abc"}, DesiredInput: api.BuildInput{ SourceURI: "http://github.com/test/source", ImageTag: "data/image", Type: api.DockerBuildType, BuilderImage: "builder/image", }, }, } for desc, failureCase := range failureCases { c, err := storage.Update(&failureCase) if c != nil { t.Errorf("%s: Expected nil channel", desc) } if !errors.IsInvalid(err) { t.Errorf("%s: Expected to get an invalid resource error, got %v", desc, err) } } }
func (t *Tester) TestCreateInvokesValidation(invalid ...runtime.Object) { for i, obj := range invalid { ctx := api.NewDefaultContext() _, err := t.storage.(rest.Creater).Create(ctx, obj) if !errors.IsInvalid(err) { t.Errorf("%d: Expected to get an invalid resource error, got %v", i, err) } } }
// NewCommandStartMaster provides a CLI handler for 'start master' command func NewCommandStartMaster(out io.Writer) (*cobra.Command, *MasterOptions) { options := &MasterOptions{Output: out} cmd := &cobra.Command{ Use: "master", Short: "Launch OpenShift master", Long: masterLong, Run: func(c *cobra.Command, args []string) { if err := options.Complete(); err != nil { fmt.Println(err.Error()) c.Help() return } if err := options.Validate(args); err != nil { fmt.Println(err.Error()) c.Help() return } startProfiler() if err := options.StartMaster(); err != nil { if kerrors.IsInvalid(err) { if details := err.(*kerrors.StatusError).ErrStatus.Details; details != nil { fmt.Fprintf(options.Output, "Invalid %s %s\n", details.Kind, details.Name) for _, cause := range details.Causes { fmt.Fprintln(options.Output, cause.Message) } os.Exit(255) } } glog.Fatal(err) } }, } options.MasterArgs = NewDefaultMasterArgs() flags := cmd.Flags() flags.Var(options.MasterArgs.ConfigDir, "write-config", "Directory to write an initial config into. After writing, exit without starting the server.") flags.StringVar(&options.ConfigFile, "config", "", "Location of the master configuration file to run from. When running from a configuration file, all other command-line arguments are ignored.") flags.BoolVar(&options.CreateCertificates, "create-certs", true, "Indicates whether missing certs should be created") BindMasterArgs(options.MasterArgs, flags, "") BindListenArg(options.MasterArgs.ListenArg, flags, "") BindImageFormatArgs(options.MasterArgs.ImageFormatArgs, flags, "") BindKubeConnectionArgs(options.MasterArgs.KubeConnectionArgs, flags, "") BindNetworkArgs(options.MasterArgs.NetworkArgs, flags, "") // autocompletion hints cmd.MarkFlagFilename("write-config") cmd.MarkFlagFilename("config", "yaml", "yml") return cmd, options }
func TestCreateImageMissingID(t *testing.T) { storage := REST{} channel, err := storage.Create(&api.Image{}) if channel != nil { t.Errorf("Expected nil channel, got %v", channel) } if !errors.IsInvalid(err) { t.Errorf("Expected 'invalid' error, got %v", err) } }
func TestCreateInvalidProject(t *testing.T) { mockClient := &testclient.Fake{} storage := NewREST(mockClient.Namespaces(), &mockLister{}) _, err := storage.Create(nil, &api.Project{ ObjectMeta: kapi.ObjectMeta{ Annotations: map[string]string{"openshift.io/display-name": "h\t\ni"}, }, }) if !errors.IsInvalid(err) { t.Errorf("Expected 'invalid' error, got %v", err) } }
func TestCreateMissingID(t *testing.T) { _, helper := newHelper(t) storage := NewREST(helper) obj, err := storage.Create(kapi.NewDefaultContext(), &api.Image{}) if obj != nil { t.Errorf("Expected nil obj, got %v", obj) } if !errors.IsInvalid(err) { t.Errorf("Expected 'invalid' error, got %v", err) } }
// NewCommandStartNode provides a CLI handler for 'start node' command func NewCommandStartNode(out io.Writer) (*cobra.Command, *NodeOptions) { options := &NodeOptions{Output: out} cmd := &cobra.Command{ Use: "node", Short: "Launch OpenShift node", Long: nodeLong, Run: func(c *cobra.Command, args []string) { if err := options.Complete(); err != nil { fmt.Println(err.Error()) c.Help() return } if err := options.Validate(args); err != nil { fmt.Println(err.Error()) c.Help() return } startProfiler() if err := options.StartNode(); err != nil { if kerrors.IsInvalid(err) { if details := err.(*kerrors.StatusError).ErrStatus.Details; details != nil { fmt.Fprintf(out, "Invalid %s %s\n", details.Kind, details.ID) for _, cause := range details.Causes { fmt.Fprintln(out, cause.Message) } os.Exit(255) } } glog.Fatal(err) } }, } flags := cmd.Flags() flags.StringVar(&options.ConfigFile, "config", "", "Location of the node configuration file to run from. When running from a configuration file, all other command-line arguments are ignored.") options.NodeArgs = NewDefaultNodeArgs() BindNodeArgs(options.NodeArgs, flags, "") BindListenArg(options.NodeArgs.ListenArg, flags, "") BindImageFormatArgs(options.NodeArgs.ImageFormatArgs, flags, "") BindKubeConnectionArgs(options.NodeArgs.KubeConnectionArgs, flags, "") // autocompletion hints cmd.MarkFlagFilename("config", "yaml", "yml") return cmd, options }
func (r *editResults) AddError(err error, info *resource.Info) string { switch { case errors.IsInvalid(err): r.edit = append(r.edit, info) reason := editReason{ head: fmt.Sprintf("%s %s was not valid", info.Mapping.Kind, info.Name), } if err, ok := err.(kclient.APIStatus); ok { if details := err.Status().Details; details != nil { for _, cause := range details.Causes { reason.other = append(reason.other, cause.Message) } } } r.header.reasons = append(r.header.reasons, reason) return fmt.Sprintf("Error: the %s %s is invalid", info.Mapping.Kind, info.Name) case errors.IsNotFound(err): r.notfound++ return fmt.Sprintf("Error: the %s %s has been deleted on the server", info.Mapping.Kind, info.Name) case errors.IsConflict(err): if r.delta != nil { v1 := info.ResourceVersion if perr := applyPatch(r.delta, info, r.version); perr != nil { // the error was related to the patching process if nerr, ok := perr.(patchError); ok { r.conflict++ if jsonmerge.IsPreconditionFailed(nerr.error) { return fmt.Sprintf("Error: the API version of the provided object cannot be changed") } // the patch is in conflict, report to user and exit if jsonmerge.IsConflicting(nerr.error) { // TODO: read message return fmt.Sprintf("Error: a conflicting change was made to the %s %s on the server", info.Mapping.Kind, info.Name) } glog.V(4).Infof("Attempted to patch the resource, but failed: %v", perr) return fmt.Sprintf("Error: %v", err) } // try processing this server error and unset delta so we don't recurse r.delta = nil return r.AddError(err, info) } return fmt.Sprintf("Applied your changes to %s from version %s onto %s", info.Name, v1, info.ResourceVersion) } // no delta was available r.conflict++ return fmt.Sprintf("Error: %v", err) default: r.retryable++ return fmt.Sprintf("Error: the %s %s could not be updated: %v", info.Mapping.Kind, info.Name, err) } }
func (t *Tester) TestDeleteInvokesValidation(invalid ...runtime.Object) { for i, obj := range invalid { objectMeta, err := api.ObjectMetaFor(obj) if err != nil { t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, obj) } ctx := api.NewDefaultContext() _, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, nil) if !errors.IsInvalid(err) { t.Errorf("%d: Expected to get an invalid resource error, got %v", i, err) } } }
func TestServiceStorageValidatesCreate(t *testing.T) { storage, _ := NewTestREST(t, nil) failureCases := map[string]api.Service{ "empty ID": { ObjectMeta: api.ObjectMeta{Name: ""}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(6502), }}, }, }, "empty port": { ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, Ports: []api.ServicePort{{ Protocol: api.ProtocolTCP, }}, }, }, "missing targetPort": { ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, }}, }, }, } ctx := api.NewDefaultContext() for _, failureCase := range failureCases { c, err := storage.Create(ctx, &failureCase) if c != nil { t.Errorf("Expected nil object") } if !errors.IsInvalid(err) { t.Errorf("Expected to get an invalid resource error, got %v", err) } } }
func TestServiceStorageValidatesUpdate(t *testing.T) { ctx := api.NewDefaultContext() storage, registry := NewTestREST(t, nil) registry.CreateService(ctx, &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, }}, }, }) failureCases := map[string]api.Service{ "empty ID": { ObjectMeta: api.ObjectMeta{Name: ""}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(6502), }}, }, }, "invalid selector": { ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"ThisSelectorFailsValidation": "ok"}, SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(6502), }}, }, }, } for _, failureCase := range failureCases { c, created, err := storage.Update(ctx, &failureCase) if c != nil || created { t.Errorf("Expected nil object or created false") } if !errors.IsInvalid(err) { t.Errorf("Expected to get an invalid resource error, got %v", err) } } }
func TestPodStorageValidatesUpdate(t *testing.T) { podRegistry := registrytest.NewPodRegistry(nil) podRegistry.Err = fmt.Errorf("test error") storage := REST{ registry: podRegistry, } pod := &api.Pod{} c, err := storage.Update(pod) if c != nil { t.Errorf("Expected nil channel") } if !errors.IsInvalid(err) { t.Errorf("Expected to get an invalid resource error, got %v", err) } }
func TestEtcdCreateControllerValidates(t *testing.T) { ctx := api.NewDefaultContext() storage, _ := newStorage(t) emptyName := validController emptyName.Name = "" failureCases := []api.ReplicationController{emptyName} for _, failureCase := range failureCases { c, err := storage.Create(ctx, &failureCase) if c != nil { t.Errorf("Expected nil channel") } if !errors.IsInvalid(err) { t.Errorf("Expected to get an invalid resource error, got %v", err) } } }
// TODO: remove, this is covered by RESTTest.TestCreate func TestPodStorageValidatesCreate(t *testing.T) { fakeEtcdClient, etcdStorage := newEtcdStorage(t) fakeEtcdClient.Err = fmt.Errorf("test error") storage := NewStorage(etcdStorage, nil).Pod pod := validNewPod() pod.Labels = map[string]string{ "invalid/label/to/cause/validation/failure": "bar", } c, err := storage.Create(api.NewDefaultContext(), pod) if c != nil { t.Errorf("Expected nil object") } if !errors.IsInvalid(err) { t.Errorf("Expected to get an invalid resource error, got %v", err) } }
func TestServiceRegistryIPUpdate(t *testing.T) { registry := registrytest.NewServiceRegistry() fakeCloud := &cloud.FakeCloud{} machines := []string{"foo", "bar", "baz"} rest := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes") rest.portalMgr.randomAttempts = 0 svc := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Port: 6502, Protocol: api.ProtocolTCP, SessionAffinity: api.AffinityTypeNone, }, } ctx := api.NewDefaultContext() created_svc, _ := rest.Create(ctx, svc) created_service := created_svc.(*api.Service) if created_service.Spec.Port != 6502 { t.Errorf("Expected port 6502, but got %v", created_service.Spec.Port) } if created_service.Spec.PortalIP != "1.2.3.1" { t.Errorf("Unexpected PortalIP: %s", created_service.Spec.PortalIP) } update := new(api.Service) *update = *created_service update.Spec.Port = 6503 updated_svc, _, _ := rest.Update(ctx, update) updated_service := updated_svc.(*api.Service) if updated_service.Spec.Port != 6503 { t.Errorf("Expected port 6503, but got %v", updated_service.Spec.Port) } *update = *created_service update.Spec.Port = 6503 update.Spec.PortalIP = "1.2.3.76" // error _, _, err := rest.Update(ctx, update) if err == nil || !errors.IsInvalid(err) { t.Error("Unexpected error type: %v", err) } }
func TestServiceRegistryIPUpdate(t *testing.T) { rest, _ := NewTestREST(t, nil) svc := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(6502), }}, }, } ctx := api.NewDefaultContext() created_svc, _ := rest.Create(ctx, svc) created_service := created_svc.(*api.Service) if created_service.Spec.Ports[0].Port != 6502 { t.Errorf("Expected port 6502, but got %v", created_service.Spec.Ports[0].Port) } if !makeIPNet(t).Contains(net.ParseIP(created_service.Spec.ClusterIP)) { t.Errorf("Unexpected ClusterIP: %s", created_service.Spec.ClusterIP) } update := deepCloneService(created_service) update.Spec.Ports[0].Port = 6503 updated_svc, _, _ := rest.Update(ctx, update) updated_service := updated_svc.(*api.Service) if updated_service.Spec.Ports[0].Port != 6503 { t.Errorf("Expected port 6503, but got %v", updated_service.Spec.Ports[0].Port) } update = deepCloneService(created_service) update.Spec.Ports[0].Port = 6503 update.Spec.ClusterIP = "1.2.3.76" // error _, _, err := rest.Update(ctx, update) if err == nil || !errors.IsInvalid(err) { t.Errorf("Unexpected error type: %v", err) } }
func handlePodUpdateError(out io.Writer, err error, resource string) { errored := false if statusError, ok := err.(*errors.StatusError); ok && errors.IsInvalid(err) { errorDetails := statusError.Status().Details if errorDetails.Kind == "Pod" { for _, cause := range errorDetails.Causes { if cause.Field == "spec" && strings.Contains(cause.Message, "may not update fields other than") { fmt.Fprintf(out, "Error updating pod %q: may not update %s in a pod directly\n", errorDetails.Name, resource) errored = true break } } } } if !errored { fmt.Fprintf(out, "error: %v\n", err) } }
func TestServiceRegistryIPUpdate(t *testing.T) { rest, _ := NewTestREST(t, nil) rest.portalMgr.randomAttempts = 0 svc := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, SessionAffinity: api.AffinityTypeNone, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, }}, }, } ctx := api.NewDefaultContext() created_svc, _ := rest.Create(ctx, svc) created_service := created_svc.(*api.Service) if created_service.Spec.Ports[0].Port != 6502 { t.Errorf("Expected port 6502, but got %v", created_service.Spec.Ports[0].Port) } if created_service.Spec.PortalIP != "1.2.3.1" { t.Errorf("Unexpected PortalIP: %s", created_service.Spec.PortalIP) } update := deepCloneService(created_service) update.Spec.Ports[0].Port = 6503 updated_svc, _, _ := rest.Update(ctx, update) updated_service := updated_svc.(*api.Service) if updated_service.Spec.Ports[0].Port != 6503 { t.Errorf("Expected port 6503, but got %v", updated_service.Spec.Ports[0].Port) } update = deepCloneService(created_service) update.Spec.Ports[0].Port = 6503 update.Spec.PortalIP = "1.2.3.76" // error _, _, err := rest.Update(ctx, update) if err == nil || !errors.IsInvalid(err) { t.Errorf("Unexpected error type: %v", err) } }