func TestGetInteger(t *testing.T) { tests := []struct { res api.ResourceList name api.ResourceName expected int def int test string }{ { res: api.ResourceList{}, name: CPU, expected: 1, def: 1, test: "nothing present", }, { res: api.ResourceList{ CPU: util.NewIntOrStringFromInt(2), }, name: CPU, expected: 2, def: 1, test: "present", }, { res: api.ResourceList{ Memory: util.NewIntOrStringFromInt(2), }, name: CPU, expected: 1, def: 1, test: "not-present", }, { res: api.ResourceList{ CPU: util.NewIntOrStringFromString("2"), }, name: CPU, expected: 2, def: 1, test: "present-string", }, { res: api.ResourceList{ CPU: util.NewIntOrStringFromString("foo"), }, name: CPU, expected: 1, def: 1, test: "present-invalid", }, } for _, test := range tests { val := GetIntegerResource(test.res, test.name, test.def) if val != test.expected { t.Errorf("expected: %d found %d", test.expected, val) } } }
// Instances returns an implementation of Instances for OpenStack. func (os *OpenStack) Instances() (cloudprovider.Instances, bool) { servers, err := gophercloud.ServersApi(os.access, gophercloud.ApiCriteria{ Type: "compute", UrlChoice: gophercloud.PublicURL, Region: os.region, }) if err != nil { return nil, false } flavors, err := servers.ListFlavors() if err != nil { return nil, false } flavor_to_resource := make(map[string]*api.NodeResources, len(flavors)) for _, flavor := range flavors { rsrc := api.NodeResources{ Capacity: api.ResourceList{ "cpu": util.NewIntOrStringFromInt(flavor.VCpus), "memory": util.NewIntOrStringFromString(fmt.Sprintf("%dMiB", flavor.Ram)), "openstack.org/disk": util.NewIntOrStringFromString(fmt.Sprintf("%dGB", flavor.Disk)), "openstack.org/rxTxFactor": util.NewIntOrStringFromInt(int(flavor.RxTxFactor * 1000)), "openstack.org/swap": util.NewIntOrStringFromString(fmt.Sprintf("%dMiB", flavor.Swap)), }, } flavor_to_resource[flavor.Id] = &rsrc } return &Instances{servers, flavor_to_resource}, true }
func TestGetURLParts(t *testing.T) { testCases := []struct { probe *api.HTTPGetAction ok bool host string port int path string }{ {&api.HTTPGetAction{Host: "", Port: util.NewIntOrStringFromInt(-1), Path: ""}, false, "", -1, ""}, {&api.HTTPGetAction{Host: "", Port: util.NewIntOrStringFromString(""), Path: ""}, false, "", -1, ""}, {&api.HTTPGetAction{Host: "", Port: util.NewIntOrStringFromString("-1"), Path: ""}, false, "", -1, ""}, {&api.HTTPGetAction{Host: "", Port: util.NewIntOrStringFromString("not-found"), Path: ""}, false, "", -1, ""}, {&api.HTTPGetAction{Host: "", Port: util.NewIntOrStringFromString("found"), Path: ""}, true, "127.0.0.1", 93, ""}, {&api.HTTPGetAction{Host: "", Port: util.NewIntOrStringFromInt(76), Path: ""}, true, "127.0.0.1", 76, ""}, {&api.HTTPGetAction{Host: "", Port: util.NewIntOrStringFromString("118"), Path: ""}, true, "127.0.0.1", 118, ""}, {&api.HTTPGetAction{Host: "hostname", Port: util.NewIntOrStringFromInt(76), Path: "path"}, true, "hostname", 76, "path"}, } for _, test := range testCases { state := api.PodStatus{PodIP: "127.0.0.1"} container := api.Container{ Ports: []api.ContainerPort{{Name: "found", HostPort: 93}}, LivenessProbe: &api.Probe{ Handler: api.Handler{ HTTPGet: test.probe, }, }, } scheme := test.probe.Scheme if scheme == "" { scheme = api.URISchemeHTTP } host := test.probe.Host if host == "" { host = state.PodIP } port, err := extractPort(test.probe.Port, container) if test.ok && err != nil { t.Errorf("Unexpected error: %v", err) } path := test.probe.Path if !test.ok && err == nil { t.Errorf("Expected error for %+v, got %s%s:%d/%s", test, scheme, host, port, path) } if test.ok { if host != test.host || port != test.port || path != test.path { t.Errorf("Expected %s:%d/%s, got %s:%d/%s", test.host, test.port, test.path, host, port, path) } } } }
func TestGetFloat(t *testing.T) { tests := []struct { res api.ResourceList name api.ResourceName expected float64 def float64 test string }{ { res: api.ResourceList{}, name: CPU, expected: 1.5, def: 1.5, test: "nothing present", }, { res: api.ResourceList{ CPU: util.NewIntOrStringFromInt(2), }, name: CPU, expected: 2.0, def: 1.5, test: "present", }, { res: api.ResourceList{ CPU: util.NewIntOrStringFromString("2.5"), }, name: CPU, expected: 2.5, def: 1, test: "present-string", }, { res: api.ResourceList{ CPU: util.NewIntOrStringFromString("foo"), }, name: CPU, expected: 1, def: 1, test: "present-invalid", }, } for _, test := range tests { val := GetFloatResource(test.res, test.name, test.def) if val != test.expected { t.Errorf("expected: %d found %d", test.expected, val) } } }
func TestGetString(t *testing.T) { tests := []struct { res api.ResourceList name api.ResourceName expected string def string test string }{ { res: api.ResourceList{}, name: CPU, expected: "foo", def: "foo", test: "nothing present", }, { res: api.ResourceList{ CPU: util.NewIntOrStringFromString("bar"), }, name: CPU, expected: "bar", def: "foo", test: "present", }, } for _, test := range tests { val := GetStringResource(test.res, test.name, test.def) if val != test.expected { t.Errorf("expected: %d found %d", test.expected, val) } } }
func TestSetDefaultServicePort(t *testing.T) { // Unchanged if set. in := &versioned.Service{Spec: versioned.ServiceSpec{ Ports: []versioned.ServicePort{ {Protocol: "UDP", Port: 9376, TargetPort: util.NewIntOrStringFromString("p")}, {Protocol: "UDP", Port: 8675, TargetPort: util.NewIntOrStringFromInt(309)}, }, }} out := roundTrip(t, runtime.Object(in)).(*versioned.Service) if out.Spec.Ports[0].Protocol != versioned.ProtocolUDP { t.Errorf("Expected protocol %s, got %s", versioned.ProtocolUDP, out.Spec.Ports[0].Protocol) } if out.Spec.Ports[0].TargetPort != util.NewIntOrStringFromString("p") { t.Errorf("Expected port %d, got %s", in.Spec.Ports[0].Port, out.Spec.Ports[0].TargetPort) } if out.Spec.Ports[1].Protocol != versioned.ProtocolUDP { t.Errorf("Expected protocol %s, got %s", versioned.ProtocolUDP, out.Spec.Ports[1].Protocol) } if out.Spec.Ports[1].TargetPort != util.NewIntOrStringFromInt(309) { t.Errorf("Expected port %d, got %s", in.Spec.Ports[1].Port, out.Spec.Ports[1].TargetPort) } // Defaulted. in = &versioned.Service{Spec: versioned.ServiceSpec{ Ports: []versioned.ServicePort{ {Protocol: "", Port: 9376, TargetPort: util.NewIntOrStringFromString("")}, {Protocol: "", Port: 8675, TargetPort: util.NewIntOrStringFromInt(0)}, }, }} out = roundTrip(t, runtime.Object(in)).(*versioned.Service) if out.Spec.Ports[0].Protocol != versioned.ProtocolTCP { t.Errorf("Expected protocol %s, got %s", versioned.ProtocolTCP, out.Spec.Ports[0].Protocol) } if out.Spec.Ports[0].TargetPort != util.NewIntOrStringFromInt(in.Spec.Ports[0].Port) { t.Errorf("Expected port %d, got %d", in.Spec.Ports[0].Port, out.Spec.Ports[0].TargetPort) } if out.Spec.Ports[1].Protocol != versioned.ProtocolTCP { t.Errorf("Expected protocol %s, got %s", versioned.ProtocolTCP, out.Spec.Ports[1].Protocol) } if out.Spec.Ports[1].TargetPort != util.NewIntOrStringFromInt(in.Spec.Ports[1].Port) { t.Errorf("Expected port %d, got %d", in.Spec.Ports[1].Port, out.Spec.Ports[1].TargetPort) } }
func TestGetURLParts(t *testing.T) { testCases := []struct { probe *api.HTTPGetProbe ok bool host string port int path string }{ {&api.HTTPGetProbe{Host: "", Port: util.NewIntOrStringFromInt(-1), Path: ""}, false, "", -1, ""}, {&api.HTTPGetProbe{Host: "", Port: util.NewIntOrStringFromString(""), Path: ""}, false, "", -1, ""}, {&api.HTTPGetProbe{Host: "", Port: util.NewIntOrStringFromString("-1"), Path: ""}, false, "", -1, ""}, {&api.HTTPGetProbe{Host: "", Port: util.NewIntOrStringFromString("not-found"), Path: ""}, false, "", -1, ""}, {&api.HTTPGetProbe{Host: "", Port: util.NewIntOrStringFromString("found"), Path: ""}, true, "127.0.0.1", 93, ""}, {&api.HTTPGetProbe{Host: "", Port: util.NewIntOrStringFromInt(76), Path: ""}, true, "127.0.0.1", 76, ""}, {&api.HTTPGetProbe{Host: "", Port: util.NewIntOrStringFromString("118"), Path: ""}, true, "127.0.0.1", 118, ""}, {&api.HTTPGetProbe{Host: "hostname", Port: util.NewIntOrStringFromInt(76), Path: "path"}, true, "hostname", 76, "path"}, } for _, test := range testCases { state := api.PodState{PodIP: "127.0.0.1"} container := api.Container{ Ports: []api.Port{{Name: "found", HostPort: 93}}, LivenessProbe: &api.LivenessProbe{ HTTPGet: test.probe, Type: "http", }, } host, port, path, err := getURLParts(state, container) if !test.ok && err == nil { t.Errorf("Expected error for %+v, got %s:%d/%s", test, host, port, path) } if test.ok && err != nil { t.Errorf("Unexpected error: %v", err) } if test.ok { if host != test.host || port != test.port || path != test.path { t.Errorf("Expected %s:%d/%s, got %s:%d/%s", test.host, test.port, test.path, host, port, path) } } } }
func TestGetTCPAddrParts(t *testing.T) { testCases := []struct { probe *api.TCPSocketAction ok bool host string port int }{ {&api.TCPSocketAction{Port: util.NewIntOrStringFromInt(-1)}, false, "", -1}, {&api.TCPSocketAction{Port: util.NewIntOrStringFromString("")}, false, "", -1}, {&api.TCPSocketAction{Port: util.NewIntOrStringFromString("-1")}, false, "", -1}, {&api.TCPSocketAction{Port: util.NewIntOrStringFromString("not-found")}, false, "", -1}, {&api.TCPSocketAction{Port: util.NewIntOrStringFromString("found")}, true, "1.2.3.4", 93}, {&api.TCPSocketAction{Port: util.NewIntOrStringFromInt(76)}, true, "1.2.3.4", 76}, {&api.TCPSocketAction{Port: util.NewIntOrStringFromString("118")}, true, "1.2.3.4", 118}, } for _, test := range testCases { host := "1.2.3.4" container := api.Container{ Ports: []api.ContainerPort{{Name: "found", HostPort: 93}}, LivenessProbe: &api.Probe{ Handler: api.Handler{ TCPSocket: test.probe, }, }, } port, err := extractPort(test.probe.Port, container) if !test.ok && err == nil { t.Errorf("Expected error for %+v, got %s:%d", test, host, port) } if test.ok && err != nil { t.Errorf("Unexpected error: %v", err) } if test.ok { if host != test.host || port != test.port { t.Errorf("Expected %s:%d, got %s:%d", test.host, test.port, host, port) } } } }
func TestHTTPHealthChecker(t *testing.T) { testCases := []struct { probe *api.HTTPGetAction status int health Status }{ // The probe will be filled in below. This is primarily testing that an HTTP GET happens. {&api.HTTPGetAction{}, http.StatusOK, Healthy}, {&api.HTTPGetAction{}, -1, Unhealthy}, {nil, -1, Unknown}, } hc := &HTTPHealthChecker{ client: &http.Client{}, } for _, test := range testCases { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(test.status) })) u, err := url.Parse(ts.URL) if err != nil { t.Errorf("Unexpected error: %v", err) } host, port, err := net.SplitHostPort(u.Host) if err != nil { t.Errorf("Unexpected error: %v", err) } container := api.Container{ LivenessProbe: &api.LivenessProbe{ HTTPGet: test.probe, Type: "http", }, } params := container.LivenessProbe.HTTPGet if params != nil { params.Port = util.NewIntOrStringFromString(port) params.Host = host } health, err := hc.HealthCheck("test", api.PodState{PodIP: host}, container) if test.health == Unknown && err == nil { t.Errorf("Expected error") } if test.health != Unknown && err != nil { t.Errorf("Unexpected error: %v", err) } if health != test.health { t.Errorf("Expected %v, got %v", test.health, health) } } }
func TestHealthChecker(t *testing.T) { AddHealthChecker(&HTTPHealthChecker{client: &http.Client{}}) var healthCheckerTests = []struct { status int health Status }{ {http.StatusOK, Healthy}, {statusServerEarlyShutdown, Unknown}, {http.StatusBadRequest, Unhealthy}, {http.StatusBadGateway, Unhealthy}, {http.StatusInternalServerError, Unhealthy}, } for _, healthCheckerTest := range healthCheckerTests { tt := healthCheckerTest ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(tt.status) })) defer ts.Close() u, err := url.Parse(ts.URL) if err != nil { t.Fatalf("Unexpected error: %v", err) } host, port, err := net.SplitHostPort(u.Host) if err != nil { t.Fatalf("Unexpected error: %v", err) } if tt.status == statusServerEarlyShutdown { ts.Close() } container := api.Container{ LivenessProbe: &api.LivenessProbe{ HTTPGet: &api.HTTPGetAction{ Port: util.NewIntOrStringFromString(port), Path: "/foo/bar", Host: host, }, }, } hc := NewHealthChecker() health, err := hc.HealthCheck("test", "", api.PodState{}, container) if err != nil && tt.health != Unknown { t.Errorf("Unexpected error: %v", err) } if health != tt.health { t.Errorf("Expected %v, got %v", tt.health, health) } } }
func TestTcpHealthChecker(t *testing.T) { tests := []struct { probe *api.TCPSocketProbe expectedStatus Status expectError bool }{ // The probe will be filled in below. This is primarily testing that a connection is made. {&api.TCPSocketProbe{}, Healthy, false}, {&api.TCPSocketProbe{}, Unhealthy, false}, {nil, Unknown, true}, } checker := &TCPHealthChecker{} server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })) u, err := url.Parse(server.URL) if err != nil { t.Errorf("Unexpected error: %v", err) } host, port, err := net.SplitHostPort(u.Host) if err != nil { t.Errorf("Unexpected error: %v", err) } for _, test := range tests { container := api.Container{ LivenessProbe: &api.LivenessProbe{ TCPSocket: test.probe, Type: "tcp", }, } params := container.LivenessProbe.TCPSocket if params != nil && test.expectedStatus == Healthy { params.Port = util.NewIntOrStringFromString(port) } status, err := checker.HealthCheck("test", api.PodState{PodIP: host}, container) if status != test.expectedStatus { t.Errorf("expected: %v, got: %v", test.expectedStatus, status) } if err != nil && !test.expectError { t.Errorf("unexpected error: %#v", err) } if err == nil && test.expectError { t.Errorf("unexpected non-error.") } } }
func (ServiceGenerator) Generate(params map[string]string) (runtime.Object, error) { selectorString, found := params["selector"] if !found || len(selectorString) == 0 { return nil, fmt.Errorf("'selector' is a required parameter.") } selector := ParseLabels(selectorString) name, found := params["name"] if !found { return nil, fmt.Errorf("'name' is a required parameter.") } portString, found := params["port"] if !found { return nil, fmt.Errorf("'port' is a required parameter.") } port, err := strconv.Atoi(portString) if err != nil { return nil, err } service := api.Service{ ObjectMeta: api.ObjectMeta{ Name: name, }, Spec: api.ServiceSpec{ Port: port, Protocol: api.Protocol(params["protocol"]), Selector: selector, }, } containerPort, found := params["container-port"] if found && len(containerPort) > 0 { if cPort, err := strconv.Atoi(containerPort); err != nil { service.Spec.ContainerPort = util.NewIntOrStringFromString(containerPort) } else { service.Spec.ContainerPort = util.NewIntOrStringFromInt(cPort) } } else { service.Spec.ContainerPort = util.NewIntOrStringFromInt(port) } if params["create-external-load-balancer"] == "true" { service.Spec.CreateExternalLoadBalancer = true } if len(params["public-ip"]) != 0 { service.Spec.PublicIPs = []string{params["public-ip"]} } return &service, nil }
func TestMuxHealthChecker(t *testing.T) { muxHealthCheckerTests := []struct { health Status probeType string }{ {Healthy, "http"}, {Unknown, "ftp"}, } mc := &muxHealthChecker{ checkers: make(map[string]HealthChecker), } hc := &HTTPHealthChecker{ client: &http.Client{}, } mc.checkers["http"] = hc for _, muxHealthCheckerTest := range muxHealthCheckerTests { tt := muxHealthCheckerTest ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })) u, err := url.Parse(ts.URL) if err != nil { t.Errorf("Unexpected error: %v", err) } host, port, err := net.SplitHostPort(u.Host) if err != nil { t.Errorf("Unexpected error: %v", err) } container := api.Container{ LivenessProbe: &api.LivenessProbe{ HTTPGet: &api.HTTPGetProbe{}, }, } container.LivenessProbe.Type = tt.probeType container.LivenessProbe.HTTPGet.Port = util.NewIntOrStringFromString(port) container.LivenessProbe.HTTPGet.Host = host health, err := mc.HealthCheck("test", api.PodState{}, container) if err != nil { t.Errorf("Unexpected error: %v", err) } if health != tt.health { t.Errorf("Expected %v, got %v", tt.health, health) } } }
func TestMuxHealthChecker(t *testing.T) { muxHealthCheckerTests := []struct { health Status }{ // TODO: This test should run through a few different checker types. {Healthy}, } mc := &muxHealthChecker{ checkers: []HealthChecker{ &HTTPHealthChecker{client: &http.Client{}}, }, } for _, muxHealthCheckerTest := range muxHealthCheckerTests { tt := muxHealthCheckerTest ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })) defer ts.Close() u, err := url.Parse(ts.URL) if err != nil { t.Fatalf("Unexpected error: %v", err) } host, port, err := net.SplitHostPort(u.Host) if err != nil { t.Fatalf("Unexpected error: %v", err) } container := api.Container{ LivenessProbe: &api.LivenessProbe{ HTTPGet: &api.HTTPGetAction{}, }, } container.LivenessProbe.HTTPGet.Port = util.NewIntOrStringFromString(port) container.LivenessProbe.HTTPGet.Host = host health, err := mc.HealthCheck("test", "", api.PodState{}, container) if err != nil { t.Errorf("Unexpected error: %v", err) } if health != tt.health { t.Errorf("Expected %v, got %v", tt.health, health) } } }
func TestGetEndpoints(t *testing.T) { // 2 pods each of which have 3 targetPorts exposed via a single service endpointAddresses := []api.EndpointAddress{ {IP: "1.2.3.4"}, {IP: "6.7.8.9"}, } ports := []int{80, 443, 3306} endpointPorts := []api.EndpointPort{ {Port: ports[0], Protocol: "TCP"}, {Port: ports[1], Protocol: "TCP"}, {Port: ports[2], Protocol: "TCP", Name: "mysql"}, } servicePorts := []api.ServicePort{ {Port: 10, TargetPort: util.NewIntOrStringFromInt(ports[0])}, {Port: 20, TargetPort: util.NewIntOrStringFromInt(ports[1])}, {Port: 30, TargetPort: util.NewIntOrStringFromString("mysql")}, } svc := getService(servicePorts) endpoints := []*api.Endpoints{getEndpoints(svc, endpointAddresses, endpointPorts)} flb := newFakeLoadBalancerController(endpoints, []*api.Service{svc}) for i := range ports { eps := flb.getEndpoints(svc, &svc.Spec.Ports[i]) expectedEps := util.NewStringSet() for _, address := range endpointAddresses { expectedEps.Insert(fmt.Sprintf("%v:%v", address.IP, ports[i])) } receivedEps := util.NewStringSet() for _, ep := range eps { receivedEps.Insert(ep) } if len(receivedEps) != len(expectedEps) || !expectedEps.IsSuperset(receivedEps) { t.Fatalf("Unexpected endpoints, received %+v, expected %+v", receivedEps, expectedEps) } glog.Infof("Got endpoints %+v", receivedEps) } }
func init() { // Our TypeMeta was split into two different structs. newer.Scheme.AddStructFieldConversion(TypeMeta{}, "TypeMeta", newer.TypeMeta{}, "TypeMeta") newer.Scheme.AddStructFieldConversion(TypeMeta{}, "TypeMeta", newer.ObjectMeta{}, "ObjectMeta") newer.Scheme.AddStructFieldConversion(TypeMeta{}, "TypeMeta", newer.ListMeta{}, "ListMeta") newer.Scheme.AddStructFieldConversion(newer.TypeMeta{}, "TypeMeta", TypeMeta{}, "TypeMeta") newer.Scheme.AddStructFieldConversion(newer.ObjectMeta{}, "ObjectMeta", TypeMeta{}, "TypeMeta") newer.Scheme.AddStructFieldConversion(newer.ListMeta{}, "ListMeta", TypeMeta{}, "TypeMeta") // TODO: scope this to a specific type once that becomes available and remove the Event conversion functions below // newer.Scheme.AddStructFieldConversion(string(""), "Status", string(""), "Condition") // newer.Scheme.AddStructFieldConversion(string(""), "Condition", string(""), "Status") err := newer.Scheme.AddConversionFuncs( // TypeMeta must be split into two objects func(in *newer.TypeMeta, out *TypeMeta, s conversion.Scope) error { out.Kind = in.Kind out.APIVersion = in.APIVersion return nil }, func(in *TypeMeta, out *newer.TypeMeta, s conversion.Scope) error { out.Kind = in.Kind out.APIVersion = in.APIVersion return nil }, // ListMeta must be converted to TypeMeta func(in *newer.ListMeta, out *TypeMeta, s conversion.Scope) error { out.SelfLink = in.SelfLink if len(in.ResourceVersion) > 0 { v, err := strconv.ParseUint(in.ResourceVersion, 10, 64) if err != nil { return err } out.ResourceVersion = v } return nil }, func(in *TypeMeta, out *newer.ListMeta, s conversion.Scope) error { out.SelfLink = in.SelfLink if in.ResourceVersion != 0 { out.ResourceVersion = strconv.FormatUint(in.ResourceVersion, 10) } else { out.ResourceVersion = "" } return nil }, // ObjectMeta must be converted to TypeMeta func(in *newer.ObjectMeta, out *TypeMeta, s conversion.Scope) error { out.Namespace = in.Namespace out.ID = in.Name out.UID = in.UID out.CreationTimestamp = in.CreationTimestamp out.SelfLink = in.SelfLink if len(in.ResourceVersion) > 0 { v, err := strconv.ParseUint(in.ResourceVersion, 10, 64) if err != nil { return err } out.ResourceVersion = v } return s.Convert(&in.Annotations, &out.Annotations, 0) }, func(in *TypeMeta, out *newer.ObjectMeta, s conversion.Scope) error { out.Namespace = in.Namespace out.Name = in.ID out.UID = in.UID out.CreationTimestamp = in.CreationTimestamp out.SelfLink = in.SelfLink if in.ResourceVersion != 0 { out.ResourceVersion = strconv.FormatUint(in.ResourceVersion, 10) } else { out.ResourceVersion = "" } return s.Convert(&in.Annotations, &out.Annotations, 0) }, // EnvVar's Key is deprecated in favor of Name. func(in *newer.EnvVar, out *EnvVar, s conversion.Scope) error { out.Value = in.Value out.Key = in.Name out.Name = in.Name return nil }, func(in *EnvVar, out *newer.EnvVar, s conversion.Scope) error { out.Value = in.Value if in.Name != "" { out.Name = in.Name } else { out.Name = in.Key } return nil }, // Path & MountType are deprecated. func(in *newer.VolumeMount, out *VolumeMount, s conversion.Scope) error { out.Name = in.Name out.ReadOnly = in.ReadOnly out.MountPath = in.MountPath out.Path = in.MountPath out.MountType = "" // MountType is ignored. return nil }, func(in *VolumeMount, out *newer.VolumeMount, s conversion.Scope) error { out.Name = in.Name out.ReadOnly = in.ReadOnly if in.MountPath == "" { out.MountPath = in.Path } else { out.MountPath = in.MountPath } return nil }, // MinionList.Items had a wrong name in v1beta1 func(in *newer.NodeList, out *MinionList, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ListMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Items, &out.Items, 0); err != nil { return err } out.Minions = out.Items return nil }, func(in *MinionList, out *newer.NodeList, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ListMeta, 0); err != nil { return err } if len(in.Items) == 0 { if err := s.Convert(&in.Minions, &out.Items, 0); err != nil { return err } } else { if err := s.Convert(&in.Items, &out.Items, 0); err != nil { return err } } return nil }, func(in *newer.PodStatus, out *PodState, s conversion.Scope) error { if err := s.Convert(&in.Phase, &out.Status, 0); err != nil { return err } if err := s.Convert(&in.Info, &out.Info, 0); err != nil { return err } out.Message = in.Message out.Host = in.Host out.HostIP = in.HostIP out.PodIP = in.PodIP return nil }, func(in *PodState, out *newer.PodStatus, s conversion.Scope) error { if err := s.Convert(&in.Status, &out.Phase, 0); err != nil { return err } if err := s.Convert(&in.Info, &out.Info, 0); err != nil { return err } out.Message = in.Message out.Host = in.Host out.HostIP = in.HostIP out.PodIP = in.PodIP return nil }, func(in *newer.PodSpec, out *PodState, s conversion.Scope) error { if err := s.Convert(&in, &out.Manifest, 0); err != nil { return err } out.Host = in.Host return nil }, func(in *PodState, out *newer.PodSpec, s conversion.Scope) error { if err := s.Convert(&in.Manifest, &out, 0); err != nil { return err } out.Host = in.Host return nil }, // Convert all to the new PodPhase constants func(in *newer.PodPhase, out *PodStatus, s conversion.Scope) error { switch *in { case "": *out = "" case newer.PodPending: *out = PodWaiting case newer.PodRunning: *out = PodRunning case newer.PodSucceeded: *out = PodSucceeded case newer.PodFailed: *out = PodTerminated case newer.PodUnknown: *out = PodUnknown default: return &newer.ConversionError{ In: in, Out: out, Message: "The string provided is not a valid PodPhase constant value", } } return nil }, func(in *PodStatus, out *newer.PodPhase, s conversion.Scope) error { switch *in { case "": *out = "" case PodWaiting: *out = newer.PodPending case PodRunning: *out = newer.PodRunning case PodTerminated: // Older API versions did not contain enough info to map to PodSucceeded *out = newer.PodFailed case PodSucceeded: *out = newer.PodSucceeded case PodUnknown: *out = newer.PodUnknown default: return &newer.ConversionError{ In: in, Out: out, Message: "The string provided is not a valid PodPhase constant value", } } return nil }, // Convert all the standard objects func(in *newer.Pod, out *Pod, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } // TODO: Change this to use in.ObjectMeta.Labels. if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.DesiredState.Manifest, 0); err != nil { return err } out.DesiredState.Host = in.Spec.Host if err := s.Convert(&in.Status, &out.CurrentState, 0); err != nil { return err } if err := s.Convert(&in.Spec.NodeSelector, &out.NodeSelector, 0); err != nil { return err } return nil }, func(in *Pod, out *newer.Pod, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.DesiredState.Manifest, &out.Spec, 0); err != nil { return err } out.Spec.Host = in.DesiredState.Host if err := s.Convert(&in.CurrentState, &out.Status, 0); err != nil { return err } if err := s.Convert(&in.NodeSelector, &out.Spec.NodeSelector, 0); err != nil { return err } return nil }, func(in *newer.PodStatusResult, out *PodStatusResult, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.State, 0); err != nil { return err } return nil }, func(in *PodStatusResult, out *newer.PodStatusResult, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.State, &out.Status, 0); err != nil { return err } return nil }, func(in *newer.ReplicationController, out *ReplicationController, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.DesiredState, 0); err != nil { return err } out.CurrentState.Replicas = in.Status.Replicas return nil }, func(in *ReplicationController, out *newer.ReplicationController, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.DesiredState, &out.Spec, 0); err != nil { return err } out.Status.Replicas = in.CurrentState.Replicas return nil }, func(in *newer.ReplicationControllerSpec, out *ReplicationControllerState, s conversion.Scope) error { out.Replicas = in.Replicas if err := s.Convert(&in.Selector, &out.ReplicaSelector, 0); err != nil { return err } if in.TemplateRef != nil && in.Template == nil { return &newer.ConversionError{ In: in, Out: out, Message: "objects with a template ref cannot be converted to older objects, must populate template", } } if in.Template != nil { if err := s.Convert(in.Template, &out.PodTemplate, 0); err != nil { return err } } return nil }, func(in *ReplicationControllerState, out *newer.ReplicationControllerSpec, s conversion.Scope) error { out.Replicas = in.Replicas if err := s.Convert(&in.ReplicaSelector, &out.Selector, 0); err != nil { return err } out.Template = &newer.PodTemplateSpec{} if err := s.Convert(&in.PodTemplate, out.Template, 0); err != nil { return err } return nil }, func(in *newer.PodTemplateSpec, out *PodTemplate, s conversion.Scope) error { if err := s.Convert(&in.Spec, &out.DesiredState.Manifest, 0); err != nil { return err } out.DesiredState.Host = in.Spec.Host if err := s.Convert(&in.ObjectMeta.Labels, &out.Labels, 0); err != nil { return err } return nil }, func(in *PodTemplate, out *newer.PodTemplateSpec, s conversion.Scope) error { if err := s.Convert(&in.DesiredState.Manifest, &out.Spec, 0); err != nil { return err } out.Spec.Host = in.DesiredState.Host if err := s.Convert(&in.Labels, &out.ObjectMeta.Labels, 0); err != nil { return err } return nil }, func(in *newer.PodSpec, out *BoundPod, s conversion.Scope) error { if err := s.Convert(&in, &out.Spec, 0); err != nil { return err } return nil }, func(in *BoundPod, out *newer.PodSpec, s conversion.Scope) error { if err := s.Convert(&in.Spec, &out, 0); err != nil { return err } return nil }, func(in *newer.PodSpec, out *ContainerManifest, s conversion.Scope) error { if err := s.Convert(&in.Volumes, &out.Volumes, 0); err != nil { return err } if err := s.Convert(&in.Containers, &out.Containers, 0); err != nil { return err } if err := s.Convert(&in.RestartPolicy, &out.RestartPolicy, 0); err != nil { return err } out.DNSPolicy = DNSPolicy(in.DNSPolicy) out.Version = "v1beta2" return nil }, func(in *ContainerManifest, out *newer.PodSpec, s conversion.Scope) error { if err := s.Convert(&in.Volumes, &out.Volumes, 0); err != nil { return err } if err := s.Convert(&in.Containers, &out.Containers, 0); err != nil { return err } if err := s.Convert(&in.RestartPolicy, &out.RestartPolicy, 0); err != nil { return err } out.DNSPolicy = newer.DNSPolicy(in.DNSPolicy) return nil }, func(in *newer.Service, out *Service, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } out.Port = in.Spec.Port out.Protocol = Protocol(in.Spec.Protocol) if err := s.Convert(&in.Spec.Selector, &out.Selector, 0); err != nil { return err } out.CreateExternalLoadBalancer = in.Spec.CreateExternalLoadBalancer out.PublicIPs = in.Spec.PublicIPs out.ContainerPort = in.Spec.ContainerPort out.PortalIP = in.Spec.PortalIP out.ProxyPort = in.Spec.ProxyPort if err := s.Convert(&in.Spec.SessionAffinity, &out.SessionAffinity, 0); err != nil { return err } return nil }, func(in *Service, out *newer.Service, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } out.Spec.Port = in.Port out.Spec.Protocol = newer.Protocol(in.Protocol) if err := s.Convert(&in.Selector, &out.Spec.Selector, 0); err != nil { return err } out.Spec.CreateExternalLoadBalancer = in.CreateExternalLoadBalancer out.Spec.PublicIPs = in.PublicIPs out.Spec.ContainerPort = in.ContainerPort out.Spec.PortalIP = in.PortalIP out.Spec.ProxyPort = in.ProxyPort if err := s.Convert(&in.SessionAffinity, &out.Spec.SessionAffinity, 0); err != nil { return err } return nil }, func(in *newer.Node, out *Minion, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.Status.Phase, &out.Status.Phase, 0); err != nil { return err } if err := s.Convert(&in.Status.Conditions, &out.Status.Conditions, 0); err != nil { return err } out.HostIP = in.Status.HostIP return s.Convert(&in.Spec.Capacity, &out.NodeResources.Capacity, 0) }, func(in *Minion, out *newer.Node, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.ObjectMeta.Labels, 0); err != nil { return err } if err := s.Convert(&in.Status.Phase, &out.Status.Phase, 0); err != nil { return err } if err := s.Convert(&in.Status.Conditions, &out.Status.Conditions, 0); err != nil { return err } out.Status.HostIP = in.HostIP return s.Convert(&in.NodeResources.Capacity, &out.Spec.Capacity, 0) }, // Object ID <-> Name // TODO: amend the conversion package to allow overriding specific fields. func(in *ObjectReference, out *newer.ObjectReference, s conversion.Scope) error { out.Kind = in.Kind out.Namespace = in.Namespace out.Name = in.ID out.UID = in.UID out.APIVersion = in.APIVersion out.ResourceVersion = in.ResourceVersion out.FieldPath = in.FieldPath return nil }, func(in *newer.ObjectReference, out *ObjectReference, s conversion.Scope) error { out.Kind = in.Kind out.Namespace = in.Namespace out.ID = in.Name out.UID = in.UID out.APIVersion = in.APIVersion out.ResourceVersion = in.ResourceVersion out.FieldPath = in.FieldPath return nil }, // Event Source <-> Source.Component // Event Host <-> Source.Host // TODO: remove this when it becomes possible to specify a field name conversion on a specific type func(in *newer.Event, out *Event, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } out.Reason = in.Reason out.Message = in.Message out.Source = in.Source.Component out.Host = in.Source.Host out.Timestamp = in.Timestamp return s.Convert(&in.InvolvedObject, &out.InvolvedObject, 0) }, func(in *Event, out *newer.Event, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } out.Reason = in.Reason out.Message = in.Message out.Source.Component = in.Source out.Source.Host = in.Host out.Timestamp = in.Timestamp return s.Convert(&in.InvolvedObject, &out.InvolvedObject, 0) }, // This is triggered for the Memory field of Container. func(in *int64, out *resource.Quantity, s conversion.Scope) error { out.Set(*in) out.Format = resource.BinarySI return nil }, func(in *resource.Quantity, out *int64, s conversion.Scope) error { *out = in.Value() return nil }, // This is triggered by the CPU field of Container. // Note that if we add other int/Quantity conversions my // simple hack (int64=Value(), int=MilliValue()) here won't work. func(in *int, out *resource.Quantity, s conversion.Scope) error { out.SetMilli(int64(*in)) out.Format = resource.DecimalSI return nil }, func(in *resource.Quantity, out *int, s conversion.Scope) error { *out = int(in.MilliValue()) return nil }, // Convert resource lists. func(in *ResourceList, out *newer.ResourceList, s conversion.Scope) error { *out = newer.ResourceList{} for k, v := range *in { fv, err := strconv.ParseFloat(v.String(), 64) if err != nil { return &newer.ConversionError{ In: in, Out: out, Message: fmt.Sprintf("value '%v' of '%v': %v", v, k, err), } } if k == ResourceCPU { (*out)[newer.ResourceCPU] = *resource.NewMilliQuantity(int64(fv*1000), resource.DecimalSI) } else { (*out)[newer.ResourceName(k)] = *resource.NewQuantity(int64(fv), resource.BinarySI) } } return nil }, func(in *newer.ResourceList, out *ResourceList, s conversion.Scope) error { *out = ResourceList{} for k, v := range *in { if k == newer.ResourceCPU { (*out)[ResourceCPU] = util.NewIntOrStringFromString(fmt.Sprintf("%v", float64(v.MilliValue())/1000)) } else { (*out)[ResourceName(k)] = util.NewIntOrStringFromInt(int(v.Value())) } } return nil }, // VolumeSource's HostDir is deprecated in favor of HostPath. // TODO: It would be great if I could just map field names to // convert or else maybe say "convert all members of this // struct" and then fix up only the stuff that changed. func(in *newer.VolumeSource, out *VolumeSource, s conversion.Scope) error { if err := s.Convert(&in.EmptyDir, &out.EmptyDir, 0); err != nil { return err } if err := s.Convert(&in.GitRepo, &out.GitRepo, 0); err != nil { return err } if err := s.Convert(&in.GCEPersistentDisk, &out.GCEPersistentDisk, 0); err != nil { return err } if err := s.Convert(&in.HostPath, &out.HostDir, 0); err != nil { return err } return nil }, func(in *VolumeSource, out *newer.VolumeSource, s conversion.Scope) error { if err := s.Convert(&in.EmptyDir, &out.EmptyDir, 0); err != nil { return err } if err := s.Convert(&in.GitRepo, &out.GitRepo, 0); err != nil { return err } if err := s.Convert(&in.GCEPersistentDisk, &out.GCEPersistentDisk, 0); err != nil { return err } if err := s.Convert(&in.HostDir, &out.HostPath, 0); err != nil { return err } return nil }, ) if err != nil { // If one of the conversion functions is malformed, detect it immediately. panic(err) } }
func addConversionFuncs() { // Our TypeMeta was split into two different structs. api.Scheme.AddStructFieldConversion(TypeMeta{}, "TypeMeta", api.TypeMeta{}, "TypeMeta") api.Scheme.AddStructFieldConversion(TypeMeta{}, "TypeMeta", api.ObjectMeta{}, "ObjectMeta") api.Scheme.AddStructFieldConversion(TypeMeta{}, "TypeMeta", api.ListMeta{}, "ListMeta") api.Scheme.AddStructFieldConversion(api.TypeMeta{}, "TypeMeta", TypeMeta{}, "TypeMeta") api.Scheme.AddStructFieldConversion(api.ObjectMeta{}, "ObjectMeta", TypeMeta{}, "TypeMeta") api.Scheme.AddStructFieldConversion(api.ListMeta{}, "ListMeta", TypeMeta{}, "TypeMeta") api.Scheme.AddStructFieldConversion(api.Endpoints{}, "Endpoints", Endpoints{}, "Endpoints") // TODO: scope this to a specific type once that becomes available and remove the Event conversion functions below // api.Scheme.AddStructFieldConversion(string(""), "Status", string(""), "Condition") // api.Scheme.AddStructFieldConversion(string(""), "Condition", string(""), "Status") err := api.Scheme.AddConversionFuncs( // TypeMeta must be split into two objects func(in *api.TypeMeta, out *TypeMeta, s conversion.Scope) error { out.Kind = in.Kind out.APIVersion = in.APIVersion return nil }, func(in *TypeMeta, out *api.TypeMeta, s conversion.Scope) error { out.Kind = in.Kind out.APIVersion = in.APIVersion return nil }, // ListMeta must be converted to TypeMeta func(in *api.ListMeta, out *TypeMeta, s conversion.Scope) error { out.SelfLink = in.SelfLink if len(in.ResourceVersion) > 0 { v, err := strconv.ParseUint(in.ResourceVersion, 10, 64) if err != nil { return err } out.ResourceVersion = v } return nil }, func(in *TypeMeta, out *api.ListMeta, s conversion.Scope) error { out.SelfLink = in.SelfLink if in.ResourceVersion != 0 { out.ResourceVersion = strconv.FormatUint(in.ResourceVersion, 10) } else { out.ResourceVersion = "" } return nil }, // ObjectMeta must be converted to TypeMeta func(in *api.ObjectMeta, out *TypeMeta, s conversion.Scope) error { out.Namespace = in.Namespace out.ID = in.Name out.GenerateName = in.GenerateName out.UID = in.UID out.CreationTimestamp = in.CreationTimestamp out.DeletionTimestamp = in.DeletionTimestamp out.SelfLink = in.SelfLink if len(in.ResourceVersion) > 0 { v, err := strconv.ParseUint(in.ResourceVersion, 10, 64) if err != nil { return err } out.ResourceVersion = v } return s.Convert(&in.Annotations, &out.Annotations, 0) }, func(in *TypeMeta, out *api.ObjectMeta, s conversion.Scope) error { out.Namespace = in.Namespace out.Name = in.ID out.GenerateName = in.GenerateName out.UID = in.UID out.CreationTimestamp = in.CreationTimestamp out.DeletionTimestamp = in.DeletionTimestamp out.SelfLink = in.SelfLink if in.ResourceVersion != 0 { out.ResourceVersion = strconv.FormatUint(in.ResourceVersion, 10) } else { out.ResourceVersion = "" } return s.Convert(&in.Annotations, &out.Annotations, 0) }, // Convert all to the new PodPhase constants func(in *api.PodPhase, out *PodStatus, s conversion.Scope) error { switch *in { case "": *out = "" case api.PodPending: *out = PodWaiting case api.PodRunning: *out = PodRunning case api.PodSucceeded: *out = PodSucceeded case api.PodFailed: *out = PodTerminated case api.PodUnknown: *out = PodUnknown default: return &api.ConversionError{ In: in, Out: out, Message: "The string provided is not a valid PodPhase constant value", } } return nil }, func(in *PodStatus, out *api.PodPhase, s conversion.Scope) error { switch *in { case "": *out = "" case PodWaiting: *out = api.PodPending case PodRunning: *out = api.PodRunning case PodTerminated: // Older API versions did not contain enough info to map to PodSucceeded *out = api.PodFailed case PodSucceeded: *out = api.PodSucceeded case PodUnknown: *out = api.PodUnknown default: return &api.ConversionError{ In: in, Out: out, Message: "The string provided is not a valid PodPhase constant value", } } return nil }, // Convert all the standard objects func(in *api.Pod, out *Pod, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } // TODO: Change this to use in.ObjectMeta.Labels. if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.DesiredState.Manifest, 0); err != nil { return err } out.DesiredState.Host = in.Spec.Host out.CurrentState.Host = in.Spec.Host out.ServiceAccount = in.Spec.ServiceAccount if err := s.Convert(&in.Status, &out.CurrentState, 0); err != nil { return err } if err := s.Convert(&in.Spec.NodeSelector, &out.NodeSelector, 0); err != nil { return err } return nil }, func(in *Pod, out *api.Pod, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.DesiredState.Manifest, &out.Spec, 0); err != nil { return err } out.Spec.ServiceAccount = in.ServiceAccount out.Spec.Host = in.DesiredState.Host if err := s.Convert(&in.CurrentState, &out.Status, 0); err != nil { return err } if err := s.Convert(&in.NodeSelector, &out.Spec.NodeSelector, 0); err != nil { return err } return nil }, func(in *api.ReplicationController, out *ReplicationController, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.DesiredState, 0); err != nil { return err } out.CurrentState.Replicas = in.Status.Replicas return nil }, func(in *ReplicationController, out *api.ReplicationController, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.DesiredState, &out.Spec, 0); err != nil { return err } out.Status.Replicas = in.CurrentState.Replicas return nil }, func(in *api.ReplicationControllerSpec, out *ReplicationControllerState, s conversion.Scope) error { out.Replicas = in.Replicas if err := s.Convert(&in.Selector, &out.ReplicaSelector, 0); err != nil { return err } if in.TemplateRef != nil && in.Template == nil { return &api.ConversionError{ In: in, Out: out, Message: "objects with a template ref cannot be converted to older objects, must populate template", } } if in.Template != nil { if err := s.Convert(in.Template, &out.PodTemplate, 0); err != nil { return err } } return nil }, func(in *ReplicationControllerState, out *api.ReplicationControllerSpec, s conversion.Scope) error { out.Replicas = in.Replicas if err := s.Convert(&in.ReplicaSelector, &out.Selector, 0); err != nil { return err } out.Template = &api.PodTemplateSpec{} if err := s.Convert(&in.PodTemplate, out.Template, 0); err != nil { return err } return nil }, func(in *api.PodTemplateSpec, out *PodTemplate, s conversion.Scope) error { if err := s.Convert(&in.Spec, &out.DesiredState.Manifest, 0); err != nil { return err } out.DesiredState.Host = in.Spec.Host out.ServiceAccount = in.Spec.ServiceAccount if err := s.Convert(&in.Spec.NodeSelector, &out.NodeSelector, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta.Annotations, &out.Annotations, 0); err != nil { return err } return nil }, func(in *PodTemplate, out *api.PodTemplateSpec, s conversion.Scope) error { if err := s.Convert(&in.DesiredState.Manifest, &out.Spec, 0); err != nil { return err } out.Spec.Host = in.DesiredState.Host out.Spec.ServiceAccount = in.ServiceAccount if err := s.Convert(&in.NodeSelector, &out.Spec.NodeSelector, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.ObjectMeta.Labels, 0); err != nil { return err } if err := s.Convert(&in.Annotations, &out.ObjectMeta.Annotations, 0); err != nil { return err } return nil }, // Converts internal Container to v1beta2.Container. // Fields 'CPU' and 'Memory' are not present in the internal Container object. // Hence the need for a custom conversion function. func(in *api.Container, out *Container, s conversion.Scope) error { if err := s.Convert(&in.Name, &out.Name, 0); err != nil { return err } if err := s.Convert(&in.Image, &out.Image, 0); err != nil { return err } if err := s.Convert(&in.Command, &out.Entrypoint, 0); err != nil { return err } if err := s.Convert(&in.Args, &out.Command, 0); err != nil { return err } if err := s.Convert(&in.WorkingDir, &out.WorkingDir, 0); err != nil { return err } if err := s.Convert(&in.Ports, &out.Ports, 0); err != nil { return err } if err := s.Convert(&in.Env, &out.Env, 0); err != nil { return err } if err := s.Convert(&in.Resources, &out.Resources, 0); err != nil { return err } if err := s.Convert(in.Resources.Limits.Cpu(), &out.CPU, 0); err != nil { return err } if err := s.Convert(in.Resources.Limits.Memory(), &out.Memory, 0); err != nil { return err } if err := s.Convert(&in.VolumeMounts, &out.VolumeMounts, 0); err != nil { return err } if err := s.Convert(&in.LivenessProbe, &out.LivenessProbe, 0); err != nil { return err } if err := s.Convert(&in.ReadinessProbe, &out.ReadinessProbe, 0); err != nil { return err } if err := s.Convert(&in.Lifecycle, &out.Lifecycle, 0); err != nil { return err } if err := s.Convert(&in.TerminationMessagePath, &out.TerminationMessagePath, 0); err != nil { return err } if err := s.Convert(&in.ImagePullPolicy, &out.ImagePullPolicy, 0); err != nil { return err } if err := s.Convert(&in.SecurityContext, &out.SecurityContext, 0); err != nil { return err } // now that we've converted set the container field from security context if out.SecurityContext != nil && out.SecurityContext.Privileged != nil { out.Privileged = *out.SecurityContext.Privileged } // now that we've converted set the container field from security context if out.SecurityContext != nil && out.SecurityContext.Capabilities != nil { out.Capabilities = *out.SecurityContext.Capabilities } return nil }, // Internal API does not support CPU to be specified via an explicit field. // Hence it must be stored in Container.Resources. func(in *int, out *api.ResourceList, s conversion.Scope) error { if *in == 0 { return nil } quantity := resource.Quantity{} if err := s.Convert(in, &quantity, 0); err != nil { return err } (*out)[api.ResourceCPU] = quantity return nil }, // Internal API does not support Memory to be specified via an explicit field. // Hence it must be stored in Container.Resources. func(in *int64, out *api.ResourceList, s conversion.Scope) error { if *in == 0 { return nil } quantity := resource.Quantity{} if err := s.Convert(in, &quantity, 0); err != nil { return err } (*out)[api.ResourceMemory] = quantity return nil }, // Converts v1beta2.Container to internal api.Container. // Fields 'CPU' and 'Memory' are not present in the internal api.Container object. // Hence the need for a custom conversion function. func(in *Container, out *api.Container, s conversion.Scope) error { if err := s.Convert(&in.Name, &out.Name, 0); err != nil { return err } if err := s.Convert(&in.Image, &out.Image, 0); err != nil { return err } if err := s.Convert(&in.Command, &out.Args, 0); err != nil { return err } if err := s.Convert(&in.Entrypoint, &out.Command, 0); err != nil { return err } if err := s.Convert(&in.WorkingDir, &out.WorkingDir, 0); err != nil { return err } if err := s.Convert(&in.Ports, &out.Ports, 0); err != nil { return err } if err := s.Convert(&in.Env, &out.Env, 0); err != nil { return err } if err := s.Convert(&in.Resources, &out.Resources, 0); err != nil { return err } if err := s.Convert(&in.CPU, &out.Resources.Limits, 0); err != nil { return err } if err := s.Convert(&in.Memory, &out.Resources.Limits, 0); err != nil { return err } if err := s.Convert(&in.VolumeMounts, &out.VolumeMounts, 0); err != nil { return err } if err := s.Convert(&in.LivenessProbe, &out.LivenessProbe, 0); err != nil { return err } if err := s.Convert(&in.ReadinessProbe, &out.ReadinessProbe, 0); err != nil { return err } if err := s.Convert(&in.Lifecycle, &out.Lifecycle, 0); err != nil { return err } if err := s.Convert(&in.TerminationMessagePath, &out.TerminationMessagePath, 0); err != nil { return err } if err := s.Convert(&in.ImagePullPolicy, &out.ImagePullPolicy, 0); err != nil { return err } if in.SecurityContext != nil { if in.SecurityContext.Capabilities != nil { if !reflect.DeepEqual(in.SecurityContext.Capabilities.Add, in.Capabilities.Add) || !reflect.DeepEqual(in.SecurityContext.Capabilities.Drop, in.Capabilities.Drop) { return fmt.Errorf("container capability settings do not match security context settings, cannot convert") } } if in.SecurityContext.Privileged != nil { if in.Privileged != *in.SecurityContext.Privileged { return fmt.Errorf("container privileged settings do not match security context settings, cannot convert") } } } if err := s.Convert(&in.SecurityContext, &out.SecurityContext, 0); err != nil { return err } return nil }, func(in *api.PodSpec, out *ContainerManifest, s conversion.Scope) error { if err := s.Convert(&in.Volumes, &out.Volumes, 0); err != nil { return err } if err := s.Convert(&in.Containers, &out.Containers, 0); err != nil { return err } if err := s.Convert(&in.RestartPolicy, &out.RestartPolicy, 0); err != nil { return err } if err := s.Convert(&in.ImagePullSecrets, &out.ImagePullSecrets, 0); err != nil { return err } if in.TerminationGracePeriodSeconds != nil { out.TerminationGracePeriodSeconds = new(int64) *out.TerminationGracePeriodSeconds = *in.TerminationGracePeriodSeconds } if in.ActiveDeadlineSeconds != nil { out.ActiveDeadlineSeconds = new(int64) *out.ActiveDeadlineSeconds = *in.ActiveDeadlineSeconds } out.DNSPolicy = DNSPolicy(in.DNSPolicy) out.Version = "v1beta2" out.HostNetwork = in.HostNetwork return nil }, func(in *ContainerManifest, out *api.PodSpec, s conversion.Scope) error { if err := s.Convert(&in.Volumes, &out.Volumes, 0); err != nil { return err } if err := s.Convert(&in.Containers, &out.Containers, 0); err != nil { return err } if err := s.Convert(&in.RestartPolicy, &out.RestartPolicy, 0); err != nil { return err } if err := s.Convert(&in.ImagePullSecrets, &out.ImagePullSecrets, 0); err != nil { return err } if in.TerminationGracePeriodSeconds != nil { out.TerminationGracePeriodSeconds = new(int64) *out.TerminationGracePeriodSeconds = *in.TerminationGracePeriodSeconds } if in.ActiveDeadlineSeconds != nil { out.ActiveDeadlineSeconds = new(int64) *out.ActiveDeadlineSeconds = *in.ActiveDeadlineSeconds } out.DNSPolicy = api.DNSPolicy(in.DNSPolicy) out.HostNetwork = in.HostNetwork return nil }, func(in *api.PodStatus, out *PodState, s conversion.Scope) error { if err := s.Convert(&in.Phase, &out.Status, 0); err != nil { return err } if err := s.Convert(&in.ContainerStatuses, &out.Info, 0); err != nil { return err } if err := s.Convert(&in.Conditions, &out.Conditions, 0); err != nil { return err } out.Message = in.Message out.HostIP = in.HostIP out.PodIP = in.PodIP return nil }, func(in *PodState, out *api.PodStatus, s conversion.Scope) error { if err := s.Convert(&in.Status, &out.Phase, 0); err != nil { return err } if err := s.Convert(&in.Info, &out.ContainerStatuses, 0); err != nil { return err } if err := s.Convert(&in.Conditions, &out.Conditions, 0); err != nil { return err } out.Message = in.Message out.HostIP = in.HostIP out.PodIP = in.PodIP return nil }, func(in *[]api.ContainerStatus, out *PodInfo, s conversion.Scope) error { *out = make(map[string]ContainerStatus) for _, st := range *in { v := ContainerStatus{} if err := s.Convert(&st, &v, 0); err != nil { return err } (*out)[st.Name] = v } return nil }, func(in *PodInfo, out *[]api.ContainerStatus, s conversion.Scope) error { for k, v := range *in { st := api.ContainerStatus{} if err := s.Convert(&v, &st, 0); err != nil { return err } st.Name = k *out = append(*out, st) } return nil }, func(in *api.ContainerStatus, out *ContainerStatus, s conversion.Scope) error { if err := s.Convert(&in.State, &out.State, 0); err != nil { return err } if err := s.Convert(&in.LastTerminationState, &out.LastTerminationState, 0); err != nil { return err } if err := s.Convert(&in.Ready, &out.Ready, 0); err != nil { return err } if err := s.Convert(&in.RestartCount, &out.RestartCount, 0); err != nil { return err } if err := s.Convert(&in.Image, &out.Image, 0); err != nil { return err } if err := s.Convert(&in.ImageID, &out.ImageID, 0); err != nil { return err } if err := s.Convert(&in.ContainerID, &out.ContainerID, 0); err != nil { return err } return nil }, func(in *ContainerStatus, out *api.ContainerStatus, s conversion.Scope) error { if err := s.Convert(&in.State, &out.State, 0); err != nil { return err } if err := s.Convert(&in.LastTerminationState, &out.LastTerminationState, 0); err != nil { return err } if err := s.Convert(&in.Ready, &out.Ready, 0); err != nil { return err } if err := s.Convert(&in.RestartCount, &out.RestartCount, 0); err != nil { return err } if err := s.Convert(&in.Image, &out.Image, 0); err != nil { return err } if err := s.Convert(&in.ImageID, &out.ImageID, 0); err != nil { return err } if err := s.Convert(&in.ContainerID, &out.ContainerID, 0); err != nil { return err } return nil }, func(in *api.PodStatusResult, out *PodStatusResult, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.State, 0); err != nil { return err } return nil }, func(in *PodStatusResult, out *api.PodStatusResult, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.State, &out.Status, 0); err != nil { return err } return nil }, func(in *api.PodSpec, out *PodState, s conversion.Scope) error { if err := s.Convert(&in, &out.Manifest, 0); err != nil { return err } out.Host = in.Host return nil }, func(in *PodState, out *api.PodSpec, s conversion.Scope) error { if err := s.Convert(&in.Manifest, &out, 0); err != nil { return err } out.Host = in.Host return nil }, func(in *api.Service, out *Service, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } // Produce legacy fields. out.Protocol = ProtocolTCP if len(in.Spec.Ports) > 0 { out.PortName = in.Spec.Ports[0].Name out.Port = in.Spec.Ports[0].Port out.Protocol = Protocol(in.Spec.Ports[0].Protocol) out.ContainerPort = in.Spec.Ports[0].TargetPort } // Copy modern fields. for i := range in.Spec.Ports { out.Ports = append(out.Ports, ServicePort{ Name: in.Spec.Ports[i].Name, Port: in.Spec.Ports[i].Port, Protocol: Protocol(in.Spec.Ports[i].Protocol), ContainerPort: in.Spec.Ports[i].TargetPort, NodePort: in.Spec.Ports[i].NodePort, }) } if err := s.Convert(&in.Spec.Selector, &out.Selector, 0); err != nil { return err } out.PublicIPs = in.Spec.DeprecatedPublicIPs out.PortalIP = in.Spec.PortalIP if err := s.Convert(&in.Spec.SessionAffinity, &out.SessionAffinity, 0); err != nil { return err } if err := s.Convert(&in.Status.LoadBalancer, &out.LoadBalancerStatus, 0); err != nil { return err } if err := s.Convert(&in.Spec.Type, &out.Type, 0); err != nil { return err } out.CreateExternalLoadBalancer = in.Spec.Type == api.ServiceTypeLoadBalancer return nil }, func(in *Service, out *api.Service, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } if len(in.Ports) == 0 && in.Port != 0 { // Use legacy fields to produce modern fields. out.Spec.Ports = append(out.Spec.Ports, api.ServicePort{ Name: in.PortName, Port: in.Port, Protocol: api.Protocol(in.Protocol), TargetPort: in.ContainerPort, }) } else { // Use modern fields, ignore legacy. for i := range in.Ports { out.Spec.Ports = append(out.Spec.Ports, api.ServicePort{ Name: in.Ports[i].Name, Port: in.Ports[i].Port, Protocol: api.Protocol(in.Ports[i].Protocol), TargetPort: in.Ports[i].ContainerPort, NodePort: in.Ports[i].NodePort, }) } } if err := s.Convert(&in.Selector, &out.Spec.Selector, 0); err != nil { return err } out.Spec.DeprecatedPublicIPs = in.PublicIPs out.Spec.PortalIP = in.PortalIP if err := s.Convert(&in.SessionAffinity, &out.Spec.SessionAffinity, 0); err != nil { return err } if err := s.Convert(&in.LoadBalancerStatus, &out.Status.LoadBalancer, 0); err != nil { return err } typeIn := in.Type if typeIn == "" { if in.CreateExternalLoadBalancer { typeIn = ServiceTypeLoadBalancer } else { typeIn = ServiceTypeClusterIP } } if err := s.Convert(&typeIn, &out.Spec.Type, 0); err != nil { return err } return nil }, func(in *api.Node, out *Minion, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.Status.Phase, &out.Status.Phase, 0); err != nil { return err } if err := s.Convert(&in.Status.Conditions, &out.Status.Conditions, 0); err != nil { return err } if err := s.Convert(&in.Status.Addresses, &out.Status.Addresses, 0); err != nil { return err } if err := s.Convert(&in.Status.NodeInfo, &out.Status.NodeInfo, 0); err != nil { return err } for _, address := range in.Status.Addresses { if address.Type == api.NodeLegacyHostIP { out.HostIP = address.Address } } out.PodCIDR = in.Spec.PodCIDR out.ExternalID = in.Spec.ExternalID out.Unschedulable = in.Spec.Unschedulable return s.Convert(&in.Status.Capacity, &out.NodeResources.Capacity, 0) }, func(in *Minion, out *api.Node, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.ObjectMeta.Labels, 0); err != nil { return err } if err := s.Convert(&in.Status.Phase, &out.Status.Phase, 0); err != nil { return err } if err := s.Convert(&in.Status.Conditions, &out.Status.Conditions, 0); err != nil { return err } if err := s.Convert(&in.Status.Addresses, &out.Status.Addresses, 0); err != nil { return err } if err := s.Convert(&in.Status.NodeInfo, &out.Status.NodeInfo, 0); err != nil { return err } if in.HostIP != "" { api.AddToNodeAddresses(&out.Status.Addresses, api.NodeAddress{Type: api.NodeLegacyHostIP, Address: in.HostIP}) } out.Spec.PodCIDR = in.PodCIDR out.Spec.ExternalID = in.ExternalID out.Spec.Unschedulable = in.Unschedulable return s.Convert(&in.NodeResources.Capacity, &out.Status.Capacity, 0) }, func(in *api.LimitRange, out *LimitRange, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.Spec, 0); err != nil { return err } return nil }, func(in *LimitRange, out *api.LimitRange, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.Spec, 0); err != nil { return err } return nil }, func(in *Namespace, out *api.Namespace, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.Spec, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.ObjectMeta.Labels, 0); err != nil { return err } return nil }, func(in *api.LimitRangeSpec, out *LimitRangeSpec, s conversion.Scope) error { *out = LimitRangeSpec{} out.Limits = make([]LimitRangeItem, len(in.Limits), len(in.Limits)) for i := range in.Limits { if err := s.Convert(&in.Limits[i], &out.Limits[i], 0); err != nil { return err } } return nil }, func(in *LimitRangeSpec, out *api.LimitRangeSpec, s conversion.Scope) error { *out = api.LimitRangeSpec{} out.Limits = make([]api.LimitRangeItem, len(in.Limits), len(in.Limits)) for i := range in.Limits { if err := s.Convert(&in.Limits[i], &out.Limits[i], 0); err != nil { return err } } return nil }, func(in *api.LimitRangeItem, out *LimitRangeItem, s conversion.Scope) error { *out = LimitRangeItem{} out.Type = LimitType(in.Type) if err := s.Convert(&in.Max, &out.Max, 0); err != nil { return err } if err := s.Convert(&in.Min, &out.Min, 0); err != nil { return err } if err := s.Convert(&in.Default, &out.Default, 0); err != nil { return err } return nil }, func(in *LimitRangeItem, out *api.LimitRangeItem, s conversion.Scope) error { *out = api.LimitRangeItem{} out.Type = api.LimitType(in.Type) if err := s.Convert(&in.Max, &out.Max, 0); err != nil { return err } if err := s.Convert(&in.Min, &out.Min, 0); err != nil { return err } if err := s.Convert(&in.Default, &out.Default, 0); err != nil { return err } return nil }, func(in *api.ResourceQuota, out *ResourceQuota, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.Spec, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } return nil }, func(in *ResourceQuota, out *api.ResourceQuota, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.Spec, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.ObjectMeta.Labels, 0); err != nil { return err } return nil }, func(in *api.ResourceQuotaSpec, out *ResourceQuotaSpec, s conversion.Scope) error { *out = ResourceQuotaSpec{} if err := s.Convert(&in.Hard, &out.Hard, 0); err != nil { return err } return nil }, func(in *ResourceQuotaSpec, out *api.ResourceQuotaSpec, s conversion.Scope) error { *out = api.ResourceQuotaSpec{} if err := s.Convert(&in.Hard, &out.Hard, 0); err != nil { return err } return nil }, func(in *api.ResourceQuotaStatus, out *ResourceQuotaStatus, s conversion.Scope) error { *out = ResourceQuotaStatus{} if err := s.Convert(&in.Hard, &out.Hard, 0); err != nil { return err } if err := s.Convert(&in.Used, &out.Used, 0); err != nil { return err } return nil }, func(in *ResourceQuotaStatus, out *api.ResourceQuotaStatus, s conversion.Scope) error { *out = api.ResourceQuotaStatus{} if err := s.Convert(&in.Hard, &out.Hard, 0); err != nil { return err } if err := s.Convert(&in.Used, &out.Used, 0); err != nil { return err } return nil }, // Object ID <-> Name // TODO: amend the conversion package to allow overriding specific fields. func(in *ObjectReference, out *api.ObjectReference, s conversion.Scope) error { out.Kind = in.Kind out.Namespace = in.Namespace out.Name = in.ID out.UID = in.UID out.APIVersion = in.APIVersion out.ResourceVersion = in.ResourceVersion out.FieldPath = in.FieldPath return nil }, func(in *api.ObjectReference, out *ObjectReference, s conversion.Scope) error { out.Kind = in.Kind out.Namespace = in.Namespace out.ID = in.Name out.UID = in.UID out.APIVersion = in.APIVersion out.ResourceVersion = in.ResourceVersion out.FieldPath = in.FieldPath return nil }, // Event Status <-> Condition // Event Source <-> Source.Component // Event Host <-> Source.Host // TODO: remove this when it becomes possible to specify a field name conversion on a specific type func(in *api.Event, out *Event, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } out.Reason = in.Reason out.Message = in.Message out.Source = in.Source.Component out.Host = in.Source.Host out.Timestamp = in.FirstTimestamp out.FirstTimestamp = in.FirstTimestamp out.LastTimestamp = in.LastTimestamp out.Count = in.Count return s.Convert(&in.InvolvedObject, &out.InvolvedObject, 0) }, func(in *Event, out *api.Event, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } out.Reason = in.Reason out.Message = in.Message out.Source.Component = in.Source out.Source.Host = in.Host if in.FirstTimestamp.IsZero() { // Assume this is an old event that does not specify FirstTimestamp/LastTimestamp/Count out.FirstTimestamp = in.Timestamp out.LastTimestamp = in.Timestamp out.Count = 1 } else { out.FirstTimestamp = in.FirstTimestamp out.LastTimestamp = in.LastTimestamp out.Count = in.Count } return s.Convert(&in.InvolvedObject, &out.InvolvedObject, 0) }, // This is triggered for the Memory field of Container. func(in *int64, out *resource.Quantity, s conversion.Scope) error { out.Set(*in) out.Format = resource.BinarySI return nil }, func(in *resource.Quantity, out *int64, s conversion.Scope) error { *out = in.Value() return nil }, // This is triggered by the CPU field of Container. // Note that if we add other int/Quantity conversions my // simple hack (int64=Value(), int=MilliValue()) here won't work. func(in *int, out *resource.Quantity, s conversion.Scope) error { out.SetMilli(int64(*in)) out.Format = resource.DecimalSI return nil }, func(in *resource.Quantity, out *int, s conversion.Scope) error { *out = int(in.MilliValue()) return nil }, // Convert resource lists. func(in *ResourceList, out *api.ResourceList, s conversion.Scope) error { *out = api.ResourceList{} for k, v := range *in { fv, err := strconv.ParseFloat(v.String(), 64) if err != nil { return &api.ConversionError{ In: in, Out: out, Message: fmt.Sprintf("value '%v' of '%v': %v", v, k, err), } } if k == ResourceCPU { (*out)[api.ResourceCPU] = *resource.NewMilliQuantity(int64(fv*1000), resource.DecimalSI) } else { (*out)[api.ResourceName(k)] = *resource.NewQuantity(int64(fv), resource.BinarySI) } } return nil }, func(in *api.ResourceList, out *ResourceList, s conversion.Scope) error { *out = ResourceList{} for k, v := range *in { if k == api.ResourceCPU { (*out)[ResourceCPU] = util.NewIntOrStringFromString(fmt.Sprintf("%v", float64(v.MilliValue())/1000)) } else { (*out)[ResourceName(k)] = util.NewIntOrStringFromInt(int(v.Value())) } } return nil }, func(in *api.Volume, out *Volume, s conversion.Scope) error { if err := s.Convert(&in.VolumeSource, &out.Source, 0); err != nil { return err } out.Name = in.Name return nil }, func(in *Volume, out *api.Volume, s conversion.Scope) error { if err := s.Convert(&in.Source, &out.VolumeSource, 0); err != nil { return err } out.Name = in.Name return nil }, func(in *api.VolumeSource, out *VolumeSource, s conversion.Scope) error { if err := s.Convert(&in.EmptyDir, &out.EmptyDir, 0); err != nil { return err } if err := s.Convert(&in.GitRepo, &out.GitRepo, 0); err != nil { return err } if err := s.Convert(&in.ISCSI, &out.ISCSI, 0); err != nil { return err } if err := s.Convert(&in.GCEPersistentDisk, &out.GCEPersistentDisk, 0); err != nil { return err } if err := s.Convert(&in.AWSElasticBlockStore, &out.AWSElasticBlockStore, 0); err != nil { return err } if err := s.Convert(&in.HostPath, &out.HostDir, 0); err != nil { return err } if err := s.Convert(&in.Secret, &out.Secret, 0); err != nil { return err } if err := s.Convert(&in.NFS, &out.NFS, 0); err != nil { return err } if err := s.Convert(&in.Glusterfs, &out.Glusterfs, 0); err != nil { return err } if err := s.Convert(&in.PersistentVolumeClaimVolumeSource, &out.PersistentVolumeClaimVolumeSource, 0); err != nil { return err } if err := s.Convert(&in.RBD, &out.RBD, 0); err != nil { return err } return nil }, func(in *VolumeSource, out *api.VolumeSource, s conversion.Scope) error { if err := s.Convert(&in.EmptyDir, &out.EmptyDir, 0); err != nil { return err } if err := s.Convert(&in.GitRepo, &out.GitRepo, 0); err != nil { return err } if err := s.Convert(&in.GCEPersistentDisk, &out.GCEPersistentDisk, 0); err != nil { return err } if err := s.Convert(&in.AWSElasticBlockStore, &out.AWSElasticBlockStore, 0); err != nil { return err } if err := s.Convert(&in.ISCSI, &out.ISCSI, 0); err != nil { return err } if err := s.Convert(&in.HostDir, &out.HostPath, 0); err != nil { return err } if err := s.Convert(&in.Secret, &out.Secret, 0); err != nil { return err } if err := s.Convert(&in.NFS, &out.NFS, 0); err != nil { return err } if err := s.Convert(&in.PersistentVolumeClaimVolumeSource, &out.PersistentVolumeClaimVolumeSource, 0); err != nil { return err } if err := s.Convert(&in.Glusterfs, &out.Glusterfs, 0); err != nil { return err } if err := s.Convert(&in.RBD, &out.RBD, 0); err != nil { return err } return nil }, func(in *api.PullPolicy, out *PullPolicy, s conversion.Scope) error { switch *in { case api.PullAlways: *out = PullAlways case api.PullNever: *out = PullNever case api.PullIfNotPresent: *out = PullIfNotPresent case "": *out = "" default: // Let unknown values through - they will get caught by validation *out = PullPolicy(*in) } return nil }, func(in *PullPolicy, out *api.PullPolicy, s conversion.Scope) error { switch *in { case PullAlways: *out = api.PullAlways case PullNever: *out = api.PullNever case PullIfNotPresent: *out = api.PullIfNotPresent case "": *out = "" default: // Let unknown values through - they will get caught by validation *out = api.PullPolicy(*in) } return nil }, func(in *api.RestartPolicy, out *RestartPolicy, s conversion.Scope) error { switch *in { case api.RestartPolicyAlways: *out = RestartPolicy{Always: &RestartPolicyAlways{}} case api.RestartPolicyNever: *out = RestartPolicy{Never: &RestartPolicyNever{}} case api.RestartPolicyOnFailure: *out = RestartPolicy{OnFailure: &RestartPolicyOnFailure{}} default: *out = RestartPolicy{} } return nil }, func(in *RestartPolicy, out *api.RestartPolicy, s conversion.Scope) error { switch { case in.Always != nil: *out = api.RestartPolicyAlways case in.Never != nil: *out = api.RestartPolicyNever case in.OnFailure != nil: *out = api.RestartPolicyOnFailure default: *out = "" } return nil }, func(in *api.Probe, out *LivenessProbe, s conversion.Scope) error { if err := s.Convert(&in.Exec, &out.Exec, 0); err != nil { return err } if err := s.Convert(&in.HTTPGet, &out.HTTPGet, 0); err != nil { return err } if err := s.Convert(&in.TCPSocket, &out.TCPSocket, 0); err != nil { return err } out.InitialDelaySeconds = in.InitialDelaySeconds out.TimeoutSeconds = in.TimeoutSeconds return nil }, func(in *LivenessProbe, out *api.Probe, s conversion.Scope) error { if err := s.Convert(&in.Exec, &out.Exec, 0); err != nil { return err } if err := s.Convert(&in.HTTPGet, &out.HTTPGet, 0); err != nil { return err } if err := s.Convert(&in.TCPSocket, &out.TCPSocket, 0); err != nil { return err } out.InitialDelaySeconds = in.InitialDelaySeconds out.TimeoutSeconds = in.TimeoutSeconds return nil }, func(in *api.Endpoints, out *Endpoints, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Subsets, &out.Subsets, 0); err != nil { return err } // Produce back-compat fields. firstPortName := "" if len(in.Subsets) > 0 { if len(in.Subsets[0].Ports) > 0 { if err := s.Convert(&in.Subsets[0].Ports[0].Protocol, &out.Protocol, 0); err != nil { return err } firstPortName = in.Subsets[0].Ports[0].Name } } else { out.Protocol = ProtocolTCP } for i := range in.Subsets { ss := &in.Subsets[i] for j := range ss.Ports { ssp := &ss.Ports[j] if ssp.Name != firstPortName { continue } for k := range ss.Addresses { ssa := &ss.Addresses[k] hostPort := net.JoinHostPort(ssa.IP, strconv.Itoa(ssp.Port)) out.Endpoints = append(out.Endpoints, hostPort) if ssa.TargetRef != nil { target := EndpointObjectReference{ Endpoint: hostPort, } if err := s.Convert(ssa.TargetRef, &target.ObjectReference, 0); err != nil { return err } out.TargetRefs = append(out.TargetRefs, target) } } } } return nil }, func(in *Endpoints, out *api.Endpoints, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Subsets, &out.Subsets, 0); err != nil { return err } // Back-compat fields are handled in the defaulting phase. return nil }, func(in *api.NodeCondition, out *NodeCondition, s conversion.Scope) error { if err := s.Convert(&in.Type, &out.Kind, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } if err := s.Convert(&in.LastHeartbeatTime, &out.LastProbeTime, 0); err != nil { return err } if err := s.Convert(&in.LastTransitionTime, &out.LastTransitionTime, 0); err != nil { return err } if err := s.Convert(&in.Reason, &out.Reason, 0); err != nil { return err } if err := s.Convert(&in.Message, &out.Message, 0); err != nil { return err } return nil }, func(in *NodeCondition, out *api.NodeCondition, s conversion.Scope) error { if err := s.Convert(&in.Kind, &out.Type, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } if err := s.Convert(&in.LastProbeTime, &out.LastHeartbeatTime, 0); err != nil { return err } if err := s.Convert(&in.LastTransitionTime, &out.LastTransitionTime, 0); err != nil { return err } if err := s.Convert(&in.Reason, &out.Reason, 0); err != nil { return err } if err := s.Convert(&in.Message, &out.Message, 0); err != nil { return err } return nil }, func(in *api.NodeConditionType, out *NodeConditionKind, s conversion.Scope) error { switch *in { case api.NodeReady: *out = NodeReady break case "": *out = "" default: *out = NodeConditionKind(*in) break } return nil }, func(in *NodeConditionKind, out *api.NodeConditionType, s conversion.Scope) error { switch *in { case NodeReady: *out = api.NodeReady break case "": *out = "" default: *out = api.NodeConditionType(*in) break } return nil }, func(in *api.ConditionStatus, out *ConditionStatus, s conversion.Scope) error { switch *in { case api.ConditionTrue: *out = ConditionFull break case api.ConditionFalse: *out = ConditionNone break default: *out = ConditionStatus(*in) break } return nil }, func(in *ConditionStatus, out *api.ConditionStatus, s conversion.Scope) error { switch *in { case ConditionFull: *out = api.ConditionTrue break case ConditionNone: *out = api.ConditionFalse break default: *out = api.ConditionStatus(*in) break } return nil }, func(in *api.PodCondition, out *PodCondition, s conversion.Scope) error { if err := s.Convert(&in.Type, &out.Kind, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } return nil }, func(in *PodCondition, out *api.PodCondition, s conversion.Scope) error { if err := s.Convert(&in.Kind, &out.Type, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } return nil }, func(in *api.PodConditionType, out *PodConditionKind, s conversion.Scope) error { switch *in { case api.PodReady: *out = PodReady break case "": *out = "" default: *out = PodConditionKind(*in) break } return nil }, func(in *PodConditionKind, out *api.PodConditionType, s conversion.Scope) error { switch *in { case PodReady: *out = api.PodReady break case "": *out = "" default: *out = api.PodConditionType(*in) break } return nil }, func(in *Binding, out *api.Binding, s conversion.Scope) error { if err := s.DefaultConvert(in, out, conversion.IgnoreMissingFields); err != nil { return err } out.Target = api.ObjectReference{ Name: in.Host, } out.Name = in.PodID return nil }, func(in *api.Binding, out *Binding, s conversion.Scope) error { if err := s.DefaultConvert(in, out, conversion.IgnoreMissingFields); err != nil { return err } out.Host = in.Target.Name out.PodID = in.Name return nil }, func(in *api.SecretVolumeSource, out *SecretVolumeSource, s conversion.Scope) error { out.Target.ID = in.SecretName return nil }, func(in *SecretVolumeSource, out *api.SecretVolumeSource, s conversion.Scope) error { out.SecretName = in.Target.ID return nil }, ) if err != nil { // If one of the conversion functions is malformed, detect it immediately. panic(err) } // Add field conversion funcs. err = api.Scheme.AddFieldLabelConversionFunc("v1beta2", "Pod", func(label, value string) (string, string, error) { switch label { case "name": return "metadata.name", value, nil case "DesiredState.Host": return "spec.host", value, nil case "DesiredState.Status": podStatus := PodStatus(value) var internalValue api.PodPhase api.Scheme.Convert(&podStatus, &internalValue) return "status.phase", string(internalValue), nil default: return "", "", fmt.Errorf("field label not supported: %s", label) } }) if err != nil { // If one of the conversion functions is malformed, detect it immediately. panic(err) } err = api.Scheme.AddFieldLabelConversionFunc("v1beta2", "Node", func(label, value string) (string, string, error) { switch label { case "name": return "metadata.name", value, nil case "unschedulable": return "spec.unschedulable", value, nil default: return "", "", fmt.Errorf("field label not supported: %s", label) } }) if err != nil { // if one of the conversion functions is malformed, detect it immediately. panic(err) } err = api.Scheme.AddFieldLabelConversionFunc("v1beta2", "ReplicationController", func(label, value string) (string, string, error) { switch label { case "name": return "metadata.name", value, nil case "currentState.replicas": return "status.replicas", value, nil default: return "", "", fmt.Errorf("field label not supported: %s", label) } }) if err != nil { // If one of the conversion functions is malformed, detect it immediately. panic(err) } err = api.Scheme.AddFieldLabelConversionFunc("v1beta2", "Event", func(label, value string) (string, string, error) { switch label { case "involvedObject.kind", "involvedObject.namespace", "involvedObject.uid", "involvedObject.apiVersion", "involvedObject.resourceVersion", "involvedObject.fieldPath", "reason", "source": return label, value, nil case "involvedObject.id": return "involvedObject.name", value, nil default: return "", "", fmt.Errorf("field label not supported: %s", label) } }) if err != nil { // If one of the conversion functions is malformed, detect it immediately. panic(err) } err = api.Scheme.AddFieldLabelConversionFunc("v1beta2", "Namespace", func(label, value string) (string, string, error) { switch label { case "status.phase": return label, value, nil default: return "", "", fmt.Errorf("field label not supported: %s", label) } }) if err != nil { // If one of the conversion functions is malformed, detect it immediately. panic(err) } err = api.Scheme.AddFieldLabelConversionFunc("v1beta2", "Secret", func(label, value string) (string, string, error) { switch label { case "type": return label, value, nil default: return "", "", fmt.Errorf("field label not supported: %s", label) } }) if err != nil { // If one of the conversion functions is malformed, detect it immediately. panic(err) } err = api.Scheme.AddFieldLabelConversionFunc("v1beta2", "ServiceAccount", func(label, value string) (string, string, error) { switch label { case "name": return "metadata.name", value, nil default: return "", "", fmt.Errorf("field label not supported: %s", label) } }) if err != nil { // If one of the conversion functions is malformed, detect it immediately. panic(err) } }
func proxyContext(version string) { f := NewFramework("proxy") prefix := "/api/" + version It("should proxy logs on node with explicit kubelet port", func() { node, err := pickNode(f.Client) Expect(err).NotTo(HaveOccurred()) // AbsPath preserves the trailing '/'. body, err := f.Client.Get().AbsPath(prefix + "/proxy/nodes/" + node + ":10250/logs/").Do().Raw() if len(body) > 0 { if len(body) > 100 { body = body[:100] body = append(body, '.', '.', '.') } Logf("Got: %s", body) } Expect(err).NotTo(HaveOccurred()) }) It("should proxy logs on node", func() { node, err := pickNode(f.Client) Expect(err).NotTo(HaveOccurred()) body, err := f.Client.Get().AbsPath(prefix + "/proxy/nodes/" + node + "/logs/").Do().Raw() if len(body) > 0 { if len(body) > 100 { body = body[:100] body = append(body, '.', '.', '.') } Logf("Got: %s", body) } Expect(err).NotTo(HaveOccurred()) }) It("should proxy to cadvisor", func() { node, err := pickNode(f.Client) Expect(err).NotTo(HaveOccurred()) body, err := f.Client.Get().AbsPath(prefix + "/proxy/nodes/" + node + ":4194/containers/").Do().Raw() if len(body) > 0 { if len(body) > 100 { body = body[:100] body = append(body, '.', '.', '.') } Logf("Got: %s", body) } Expect(err).NotTo(HaveOccurred()) }) It("should proxy through a service and a pod", func() { labels := map[string]string{"proxy-service-target": "true"} service, err := f.Client.Services(f.Namespace.Name).Create(&api.Service{ ObjectMeta: api.ObjectMeta{ GenerateName: "proxy-service-", }, Spec: api.ServiceSpec{ Selector: labels, Ports: []api.ServicePort{ { Name: "portname1", Port: 80, TargetPort: util.NewIntOrStringFromString("dest1"), }, { Name: "portname2", Port: 81, TargetPort: util.NewIntOrStringFromInt(162), }, }, }, }) Expect(err).NotTo(HaveOccurred()) defer func(name string) { err := f.Client.Services(f.Namespace.Name).Delete(name) if err != nil { Logf("Failed deleting service %v: %v", name, err) } }(service.Name) // Make an RC with a single pod. pods := []*api.Pod{} cfg := RCConfig{ Client: f.Client, Image: "gcr.io/google_containers/porter:91d46193649807d1340b46797774d8b2", Name: service.Name, Namespace: f.Namespace.Name, Replicas: 1, PollInterval: time.Second, Env: map[string]string{ "SERVE_PORT_80": "not accessible via service", "SERVE_PORT_160": "foo", "SERVE_PORT_162": "bar", }, Ports: map[string]int{ "dest1": 160, "dest2": 162, }, Labels: labels, CreatedPods: &pods, } Expect(RunRC(cfg)).NotTo(HaveOccurred()) defer DeleteRC(f.Client, f.Namespace.Name, cfg.Name) Expect(f.WaitForAnEndpoint(service.Name)).NotTo(HaveOccurred()) // Try proxying through the service and directly to through the pod. svcPrefix := prefix + "/proxy/namespaces/" + f.Namespace.Name + "/services/" + service.Name podPrefix := prefix + "/proxy/namespaces/" + f.Namespace.Name + "/pods/" + pods[0].Name expectations := map[string]string{ svcPrefix + ":portname1": "foo", svcPrefix + ":portname2": "bar", podPrefix + ":80": "not accessible via service", podPrefix + ":160": "foo", podPrefix + ":162": "bar", // TODO: below entries don't work, but I believe we should make them work. // svcPrefix + ":80": "foo", // svcPrefix + ":81": "bar", // podPrefix + ":dest1": "foo", // podPrefix + ":dest2": "bar", } errors := []string{} for path, val := range expectations { body, err := f.Client.Get().AbsPath(path).Do().Raw() if err != nil { errors = append(errors, fmt.Sprintf("path %v gave error %v", path, err)) continue } if e, a := val, string(body); e != a { errors = append(errors, fmt.Sprintf("path %v: wanted %v, got %v", path, e, a)) } } if len(errors) != 0 { Fail(strings.Join(errors, "\n")) } }) }
func init() { api.Scheme.AddDefaultingFuncs( func(obj *ReplicationController) { if len(obj.DesiredState.ReplicaSelector) == 0 { obj.DesiredState.ReplicaSelector = obj.DesiredState.PodTemplate.Labels } if len(obj.Labels) == 0 { obj.Labels = obj.DesiredState.PodTemplate.Labels } }, func(obj *Volume) { if util.AllPtrFieldsNil(&obj.Source) { glog.Errorf("Defaulting volume source for %v", obj) obj.Source = VolumeSource{ EmptyDir: &EmptyDirVolumeSource{}, } } }, func(obj *ContainerPort) { if obj.Protocol == "" { obj.Protocol = ProtocolTCP } }, func(obj *Container) { if obj.ImagePullPolicy == "" { // TODO(dchen1107): Move ParseImageName code to pkg/util parts := strings.Split(obj.Image, ":") // Check image tag if parts[len(parts)-1] == "latest" { obj.ImagePullPolicy = PullAlways } else { obj.ImagePullPolicy = PullIfNotPresent } } if obj.TerminationMessagePath == "" { obj.TerminationMessagePath = TerminationMessagePathDefault } }, func(obj *RestartPolicy) { if util.AllPtrFieldsNil(obj) { obj.Always = &RestartPolicyAlways{} } }, func(obj *Service) { if obj.Protocol == "" { obj.Protocol = ProtocolTCP } if obj.SessionAffinity == "" { obj.SessionAffinity = AffinityTypeNone } for i := range obj.Ports { sp := &obj.Ports[i] if sp.Protocol == "" { sp.Protocol = ProtocolTCP } if sp.ContainerPort == util.NewIntOrStringFromInt(0) || sp.ContainerPort == util.NewIntOrStringFromString("") { sp.ContainerPort = util.NewIntOrStringFromInt(sp.Port) } } }, func(obj *PodSpec) { if obj.DNSPolicy == "" { obj.DNSPolicy = DNSClusterFirst } if obj.HostNetwork { defaultHostNetworkPorts(&obj.Containers) } }, func(obj *ContainerManifest) { if obj.DNSPolicy == "" { obj.DNSPolicy = DNSClusterFirst } if obj.HostNetwork { defaultHostNetworkPorts(&obj.Containers) } }, func(obj *LivenessProbe) { if obj.TimeoutSeconds == 0 { obj.TimeoutSeconds = 1 } }, func(obj *Secret) { if obj.Type == "" { obj.Type = SecretTypeOpaque } }, func(obj *Endpoints) { if obj.Protocol == "" { obj.Protocol = ProtocolTCP } if len(obj.Subsets) == 0 && len(obj.Endpoints) > 0 { // Must be a legacy-style object - populate // Subsets from the older fields. Do this the // simplest way, which is dumb (but valid). for i := range obj.Endpoints { host, portStr, err := net.SplitHostPort(obj.Endpoints[i]) if err != nil { glog.Errorf("failed to SplitHostPort(%q)", obj.Endpoints[i]) } var tgtRef *ObjectReference for j := range obj.TargetRefs { if obj.TargetRefs[j].Endpoint == obj.Endpoints[i] { tgtRef = &ObjectReference{} *tgtRef = obj.TargetRefs[j].ObjectReference } } port, err := strconv.Atoi(portStr) if err != nil { glog.Errorf("failed to Atoi(%q)", portStr) } obj.Subsets = append(obj.Subsets, EndpointSubset{ Addresses: []EndpointAddress{{IP: host, TargetRef: tgtRef}}, Ports: []EndpointPort{{Protocol: obj.Protocol, Port: port}}, }) } } for i := range obj.Subsets { ss := &obj.Subsets[i] for i := range ss.Ports { ep := &ss.Ports[i] if ep.Protocol == "" { ep.Protocol = ProtocolTCP } } } }, func(obj *HTTPGetAction) { if obj.Path == "" { obj.Path = "/" } }, func(obj *NamespaceStatus) { if obj.Phase == "" { obj.Phase = NamespaceActive } }, func(obj *Minion) { if obj.ExternalID == "" { obj.ExternalID = obj.ID } }, ) }
func (ServiceGenerator) Generate(params map[string]string) (runtime.Object, error) { selectorString, found := params["selector"] if !found || len(selectorString) == 0 { return nil, fmt.Errorf("'selector' is a required parameter.") } selector, err := ParseLabels(selectorString) if err != nil { return nil, err } labelsString, found := params["labels"] var labels map[string]string if found && len(labelsString) > 0 { labels, err = ParseLabels(labelsString) if err != nil { return nil, err } } name, found := params["name"] if !found { return nil, fmt.Errorf("'name' is a required parameter.") } portString, found := params["port"] if !found { return nil, fmt.Errorf("'port' is a required parameter.") } port, err := strconv.Atoi(portString) if err != nil { return nil, err } service := api.Service{ ObjectMeta: api.ObjectMeta{ Name: name, Labels: labels, }, Spec: api.ServiceSpec{ Selector: selector, Ports: []api.ServicePort{ { Name: "default", Port: port, Protocol: api.Protocol(params["protocol"]), }, }, }, } targetPort, found := params["target-port"] if !found { targetPort, found = params["container-port"] } if found && len(targetPort) > 0 { if portNum, err := strconv.Atoi(targetPort); err != nil { service.Spec.Ports[0].TargetPort = util.NewIntOrStringFromString(targetPort) } else { service.Spec.Ports[0].TargetPort = util.NewIntOrStringFromInt(portNum) } } else { service.Spec.Ports[0].TargetPort = util.NewIntOrStringFromInt(port) } if params["create-external-load-balancer"] == "true" { service.Spec.CreateExternalLoadBalancer = true } if len(params["public-ip"]) != 0 { service.Spec.PublicIPs = []string{params["public-ip"]} } return &service, nil }
func proxyContext(version string) { f := NewFramework("proxy") prefix := "/api/" + version It("should proxy logs on node with explicit kubelet port", func() { nodeProxyTest(f, version, ":10250/logs/") }) It("should proxy logs on node", func() { nodeProxyTest(f, version, "/logs/") }) It("should proxy to cadvisor", func() { nodeProxyTest(f, version, ":4194/containers/") }) It("should proxy through a service and a pod", func() { labels := map[string]string{"proxy-service-target": "true"} service, err := f.Client.Services(f.Namespace.Name).Create(&api.Service{ ObjectMeta: api.ObjectMeta{ GenerateName: "proxy-service-", }, Spec: api.ServiceSpec{ Selector: labels, Ports: []api.ServicePort{ { Name: "portname1", Port: 80, TargetPort: util.NewIntOrStringFromString("dest1"), }, { Name: "portname2", Port: 81, TargetPort: util.NewIntOrStringFromInt(162), }, }, }, }) Expect(err).NotTo(HaveOccurred()) defer func(name string) { err := f.Client.Services(f.Namespace.Name).Delete(name) if err != nil { Logf("Failed deleting service %v: %v", name, err) } }(service.Name) // Make an RC with a single pod. pods := []*api.Pod{} cfg := RCConfig{ Client: f.Client, Image: "gcr.io/google_containers/porter:59ad46ed2c56ba50fa7f1dc176c07c37", Name: service.Name, Namespace: f.Namespace.Name, Replicas: 1, PollInterval: time.Second, Env: map[string]string{ "SERVE_PORT_80": `<a href="/rewriteme">test</a>`, "SERVE_PORT_160": "foo", "SERVE_PORT_162": "bar", }, Ports: map[string]int{ "dest1": 160, "dest2": 162, }, Labels: labels, CreatedPods: &pods, } Expect(RunRC(cfg)).NotTo(HaveOccurred()) defer DeleteRC(f.Client, f.Namespace.Name, cfg.Name) Expect(f.WaitForAnEndpoint(service.Name)).NotTo(HaveOccurred()) // Try proxying through the service and directly to through the pod. svcPrefix := prefix + "/proxy/namespaces/" + f.Namespace.Name + "/services/" + service.Name podPrefix := prefix + "/proxy/namespaces/" + f.Namespace.Name + "/pods/" + pods[0].Name expectations := map[string]string{ svcPrefix + ":portname1/": "foo", svcPrefix + ":portname2/": "bar", podPrefix + ":80/": `<a href="` + podPrefix + `:80/rewriteme">test</a>`, podPrefix + ":160/": "foo", podPrefix + ":162/": "bar", // TODO: below entries don't work, but I believe we should make them work. // svcPrefix + ":80": "foo", // svcPrefix + ":81": "bar", // podPrefix + ":dest1": "foo", // podPrefix + ":dest2": "bar", } wg := sync.WaitGroup{} errors := []string{} errLock := sync.Mutex{} recordError := func(s string) { errLock.Lock() defer errLock.Unlock() errors = append(errors, s) } for i := 0; i < proxyAttempts; i++ { for path, val := range expectations { wg.Add(1) go func(i int, path, val string) { defer wg.Done() body, status, d, err := doProxy(f, path) if err != nil { recordError(fmt.Sprintf("%v: path %v gave error: %v", i, path, err)) return } if status != http.StatusOK { recordError(fmt.Sprintf("%v: path %v gave status: %v", i, path, status)) } if e, a := val, string(body); e != a { recordError(fmt.Sprintf("%v: path %v: wanted %v, got %v", i, path, e, a)) } if d > 15*time.Second { recordError(fmt.Sprintf("%v: path %v took %v > 15s", i, path, d)) } }(i, path, val) time.Sleep(150 * time.Millisecond) } } wg.Wait() if len(errors) != 0 { Fail(strings.Join(errors, "\n")) } }) }
func TestServicePorts(t *testing.T) { testCases := []struct { given current.Service expected newer.Service roundtrip current.Service }{ { given: current.Service{ TypeMeta: current.TypeMeta{ ID: "legacy-with-defaults", }, Port: 111, Protocol: current.ProtocolTCP, }, expected: newer.Service{ Spec: newer.ServiceSpec{Ports: []newer.ServicePort{{ Port: 111, Protocol: newer.ProtocolTCP, }}}, }, roundtrip: current.Service{ Ports: []current.ServicePort{{ Port: 111, Protocol: current.ProtocolTCP, }}, }, }, { given: current.Service{ TypeMeta: current.TypeMeta{ ID: "legacy-full", }, PortName: "p", Port: 111, Protocol: current.ProtocolTCP, ContainerPort: util.NewIntOrStringFromString("p"), }, expected: newer.Service{ Spec: newer.ServiceSpec{Ports: []newer.ServicePort{{ Name: "p", Port: 111, Protocol: newer.ProtocolTCP, TargetPort: util.NewIntOrStringFromString("p"), }}}, }, roundtrip: current.Service{ Ports: []current.ServicePort{{ Name: "p", Port: 111, Protocol: current.ProtocolTCP, ContainerPort: util.NewIntOrStringFromString("p"), }}, }, }, { given: current.Service{ TypeMeta: current.TypeMeta{ ID: "both", }, PortName: "p", Port: 111, Protocol: current.ProtocolTCP, ContainerPort: util.NewIntOrStringFromString("p"), Ports: []current.ServicePort{{ Name: "q", Port: 222, Protocol: current.ProtocolUDP, ContainerPort: util.NewIntOrStringFromInt(93), }}, }, expected: newer.Service{ Spec: newer.ServiceSpec{Ports: []newer.ServicePort{{ Name: "q", Port: 222, Protocol: newer.ProtocolUDP, TargetPort: util.NewIntOrStringFromInt(93), }}}, }, roundtrip: current.Service{ Ports: []current.ServicePort{{ Name: "q", Port: 222, Protocol: current.ProtocolUDP, ContainerPort: util.NewIntOrStringFromInt(93), }}, }, }, { given: current.Service{ TypeMeta: current.TypeMeta{ ID: "one", }, Ports: []current.ServicePort{{ Name: "p", Port: 111, Protocol: current.ProtocolUDP, ContainerPort: util.NewIntOrStringFromInt(93), }}, }, expected: newer.Service{ Spec: newer.ServiceSpec{Ports: []newer.ServicePort{{ Name: "p", Port: 111, Protocol: newer.ProtocolUDP, TargetPort: util.NewIntOrStringFromInt(93), }}}, }, roundtrip: current.Service{ Ports: []current.ServicePort{{ Name: "p", Port: 111, Protocol: current.ProtocolUDP, ContainerPort: util.NewIntOrStringFromInt(93), }}, }, }, { given: current.Service{ TypeMeta: current.TypeMeta{ ID: "two", }, Ports: []current.ServicePort{{ Name: "p", Port: 111, Protocol: current.ProtocolUDP, ContainerPort: util.NewIntOrStringFromInt(93), }, { Name: "q", Port: 222, Protocol: current.ProtocolTCP, ContainerPort: util.NewIntOrStringFromInt(76), }}, }, expected: newer.Service{ Spec: newer.ServiceSpec{Ports: []newer.ServicePort{{ Name: "p", Port: 111, Protocol: newer.ProtocolUDP, TargetPort: util.NewIntOrStringFromInt(93), }, { Name: "q", Port: 222, Protocol: newer.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(76), }}}, }, roundtrip: current.Service{ Ports: []current.ServicePort{{ Name: "p", Port: 111, Protocol: current.ProtocolUDP, ContainerPort: util.NewIntOrStringFromInt(93), }, { Name: "q", Port: 222, Protocol: current.ProtocolTCP, ContainerPort: util.NewIntOrStringFromInt(76), }}, }, }, } for i, tc := range testCases { // Convert versioned -> internal. got := newer.Service{} if err := Convert(&tc.given, &got); err != nil { t.Errorf("[Case: %d] Unexpected error: %v", i, err) continue } if !reflect.DeepEqual(got.Spec.Ports, tc.expected.Spec.Ports) { t.Errorf("[Case: %d] Expected %v, got %v", i, tc.expected.Spec.Ports, got.Spec.Ports) } // Convert internal -> versioned. got2 := current.Service{} if err := Convert(&got, &got2); err != nil { t.Errorf("[Case: %d] Unexpected error: %v", i, err) continue } if !reflect.DeepEqual(got2.Ports, tc.roundtrip.Ports) { t.Errorf("[Case: %d] Expected %v, got %v", i, tc.roundtrip.Ports, got2.Ports) } } }
func TestSetDefaultServicePort(t *testing.T) { // Unchanged if set. in := ¤t.Service{Ports: []current.ServicePort{{Protocol: "UDP", Port: 9376, ContainerPort: util.NewIntOrStringFromInt(118)}}} out := roundTrip(t, runtime.Object(in)).(*current.Service) if out.Ports[0].Protocol != current.ProtocolUDP { t.Errorf("Expected protocol %s, got %s", current.ProtocolUDP, out.Ports[0].Protocol) } if out.Ports[0].ContainerPort != in.Ports[0].ContainerPort { t.Errorf("Expected port %d, got %d", in.Ports[0].ContainerPort, out.Ports[0].ContainerPort) } // Defaulted. in = ¤t.Service{Ports: []current.ServicePort{{Protocol: "", Port: 9376, ContainerPort: util.NewIntOrStringFromInt(0)}}} out = roundTrip(t, runtime.Object(in)).(*current.Service) if out.Ports[0].Protocol != current.ProtocolTCP { t.Errorf("Expected protocol %s, got %s", current.ProtocolTCP, out.Ports[0].Protocol) } if out.Ports[0].ContainerPort != util.NewIntOrStringFromInt(in.Ports[0].Port) { t.Errorf("Expected port %d, got %v", in.Ports[0].Port, out.Ports[0].ContainerPort) } // Defaulted. in = ¤t.Service{Ports: []current.ServicePort{{Protocol: "", Port: 9376, ContainerPort: util.NewIntOrStringFromString("")}}} out = roundTrip(t, runtime.Object(in)).(*current.Service) if out.Ports[0].Protocol != current.ProtocolTCP { t.Errorf("Expected protocol %s, got %s", current.ProtocolTCP, out.Ports[0].Protocol) } if out.Ports[0].ContainerPort != util.NewIntOrStringFromInt(in.Ports[0].Port) { t.Errorf("Expected port %d, got %v", in.Ports[0].Port, out.Ports[0].ContainerPort) } }
func init() { // Our TypeMeta was split into two different structs. newer.Scheme.AddStructFieldConversion(TypeMeta{}, "TypeMeta", newer.TypeMeta{}, "TypeMeta") newer.Scheme.AddStructFieldConversion(TypeMeta{}, "TypeMeta", newer.ObjectMeta{}, "ObjectMeta") newer.Scheme.AddStructFieldConversion(TypeMeta{}, "TypeMeta", newer.ListMeta{}, "ListMeta") newer.Scheme.AddStructFieldConversion(newer.TypeMeta{}, "TypeMeta", TypeMeta{}, "TypeMeta") newer.Scheme.AddStructFieldConversion(newer.ObjectMeta{}, "ObjectMeta", TypeMeta{}, "TypeMeta") newer.Scheme.AddStructFieldConversion(newer.ListMeta{}, "ListMeta", TypeMeta{}, "TypeMeta") newer.Scheme.AddStructFieldConversion(newer.Endpoints{}, "Endpoints", Endpoints{}, "Endpoints") // TODO: scope this to a specific type once that becomes available and remove the Event conversion functions below // newer.Scheme.AddStructFieldConversion(string(""), "Status", string(""), "Condition") // newer.Scheme.AddStructFieldConversion(string(""), "Condition", string(""), "Status") err := newer.Scheme.AddConversionFuncs( // TypeMeta must be split into two objects func(in *newer.TypeMeta, out *TypeMeta, s conversion.Scope) error { out.Kind = in.Kind out.APIVersion = in.APIVersion return nil }, func(in *TypeMeta, out *newer.TypeMeta, s conversion.Scope) error { out.Kind = in.Kind out.APIVersion = in.APIVersion return nil }, // ListMeta must be converted to TypeMeta func(in *newer.ListMeta, out *TypeMeta, s conversion.Scope) error { out.SelfLink = in.SelfLink if len(in.ResourceVersion) > 0 { v, err := strconv.ParseUint(in.ResourceVersion, 10, 64) if err != nil { return err } out.ResourceVersion = v } return nil }, func(in *TypeMeta, out *newer.ListMeta, s conversion.Scope) error { out.SelfLink = in.SelfLink if in.ResourceVersion != 0 { out.ResourceVersion = strconv.FormatUint(in.ResourceVersion, 10) } else { out.ResourceVersion = "" } return nil }, // ObjectMeta must be converted to TypeMeta func(in *newer.ObjectMeta, out *TypeMeta, s conversion.Scope) error { out.Namespace = in.Namespace out.ID = in.Name out.GenerateName = in.GenerateName out.UID = in.UID out.CreationTimestamp = in.CreationTimestamp out.DeletionTimestamp = in.DeletionTimestamp out.SelfLink = in.SelfLink if len(in.ResourceVersion) > 0 { v, err := strconv.ParseUint(in.ResourceVersion, 10, 64) if err != nil { return err } out.ResourceVersion = v } return s.Convert(&in.Annotations, &out.Annotations, 0) }, func(in *TypeMeta, out *newer.ObjectMeta, s conversion.Scope) error { out.Namespace = in.Namespace out.Name = in.ID out.GenerateName = in.GenerateName out.UID = in.UID out.CreationTimestamp = in.CreationTimestamp out.DeletionTimestamp = in.DeletionTimestamp out.SelfLink = in.SelfLink if in.ResourceVersion != 0 { out.ResourceVersion = strconv.FormatUint(in.ResourceVersion, 10) } else { out.ResourceVersion = "" } return s.Convert(&in.Annotations, &out.Annotations, 0) }, // Convert all to the new PodPhase constants func(in *newer.PodPhase, out *PodStatus, s conversion.Scope) error { switch *in { case "": *out = "" case newer.PodPending: *out = PodWaiting case newer.PodRunning: *out = PodRunning case newer.PodSucceeded: *out = PodSucceeded case newer.PodFailed: *out = PodTerminated case newer.PodUnknown: *out = PodUnknown default: return &newer.ConversionError{ In: in, Out: out, Message: "The string provided is not a valid PodPhase constant value", } } return nil }, func(in *PodStatus, out *newer.PodPhase, s conversion.Scope) error { switch *in { case "": *out = "" case PodWaiting: *out = newer.PodPending case PodRunning: *out = newer.PodRunning case PodTerminated: // Older API versions did not contain enough info to map to PodSucceeded *out = newer.PodFailed case PodSucceeded: *out = newer.PodSucceeded case PodUnknown: *out = newer.PodUnknown default: return &newer.ConversionError{ In: in, Out: out, Message: "The string provided is not a valid PodPhase constant value", } } return nil }, // Convert all the standard objects func(in *newer.Pod, out *Pod, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } // TODO: Change this to use in.ObjectMeta.Labels. if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.DesiredState.Manifest, 0); err != nil { return err } out.DesiredState.Host = in.Spec.Host if err := s.Convert(&in.Status, &out.CurrentState, 0); err != nil { return err } if err := s.Convert(&in.Spec.NodeSelector, &out.NodeSelector, 0); err != nil { return err } return nil }, func(in *Pod, out *newer.Pod, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.DesiredState.Manifest, &out.Spec, 0); err != nil { return err } out.Spec.Host = in.DesiredState.Host if err := s.Convert(&in.CurrentState, &out.Status, 0); err != nil { return err } if err := s.Convert(&in.NodeSelector, &out.Spec.NodeSelector, 0); err != nil { return err } return nil }, func(in *newer.ReplicationController, out *ReplicationController, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.DesiredState, 0); err != nil { return err } out.CurrentState.Replicas = in.Status.Replicas return nil }, func(in *ReplicationController, out *newer.ReplicationController, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.DesiredState, &out.Spec, 0); err != nil { return err } out.Status.Replicas = in.CurrentState.Replicas return nil }, func(in *newer.ReplicationControllerSpec, out *ReplicationControllerState, s conversion.Scope) error { out.Replicas = in.Replicas if err := s.Convert(&in.Selector, &out.ReplicaSelector, 0); err != nil { return err } if in.TemplateRef != nil && in.Template == nil { return &newer.ConversionError{ In: in, Out: out, Message: "objects with a template ref cannot be converted to older objects, must populate template", } } if in.Template != nil { if err := s.Convert(in.Template, &out.PodTemplate, 0); err != nil { return err } } return nil }, func(in *ReplicationControllerState, out *newer.ReplicationControllerSpec, s conversion.Scope) error { out.Replicas = in.Replicas if err := s.Convert(&in.ReplicaSelector, &out.Selector, 0); err != nil { return err } out.Template = &newer.PodTemplateSpec{} if err := s.Convert(&in.PodTemplate, out.Template, 0); err != nil { return err } return nil }, func(in *newer.PodTemplateSpec, out *PodTemplate, s conversion.Scope) error { if err := s.Convert(&in.Spec, &out.DesiredState.Manifest, 0); err != nil { return err } out.DesiredState.Host = in.Spec.Host if err := s.Convert(&in.Spec.NodeSelector, &out.NodeSelector, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta.Annotations, &out.Annotations, 0); err != nil { return err } return nil }, func(in *PodTemplate, out *newer.PodTemplateSpec, s conversion.Scope) error { if err := s.Convert(&in.DesiredState.Manifest, &out.Spec, 0); err != nil { return err } out.Spec.Host = in.DesiredState.Host if err := s.Convert(&in.NodeSelector, &out.Spec.NodeSelector, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.ObjectMeta.Labels, 0); err != nil { return err } if err := s.Convert(&in.Annotations, &out.ObjectMeta.Annotations, 0); err != nil { return err } return nil }, // Converts internal Container to v1beta1.Container. // Fields 'CPU' and 'Memory' are not present in the internal Container object. // Hence the need for a custom conversion function. func(in *newer.Container, out *Container, s conversion.Scope) error { if err := s.Convert(&in.Name, &out.Name, 0); err != nil { return err } if err := s.Convert(&in.Image, &out.Image, 0); err != nil { return err } if err := s.Convert(&in.Command, &out.Command, 0); err != nil { return err } if err := s.Convert(&in.WorkingDir, &out.WorkingDir, 0); err != nil { return err } if err := s.Convert(&in.Ports, &out.Ports, 0); err != nil { return err } if err := s.Convert(&in.Env, &out.Env, 0); err != nil { return err } if err := s.Convert(&in.Resources, &out.Resources, 0); err != nil { return err } if err := s.Convert(in.Resources.Limits.Cpu(), &out.CPU, 0); err != nil { return err } if err := s.Convert(in.Resources.Limits.Memory(), &out.Memory, 0); err != nil { return err } if err := s.Convert(&in.VolumeMounts, &out.VolumeMounts, 0); err != nil { return err } if err := s.Convert(&in.LivenessProbe, &out.LivenessProbe, 0); err != nil { return err } if err := s.Convert(&in.ReadinessProbe, &out.ReadinessProbe, 0); err != nil { return err } if err := s.Convert(&in.Lifecycle, &out.Lifecycle, 0); err != nil { return err } if err := s.Convert(&in.TerminationMessagePath, &out.TerminationMessagePath, 0); err != nil { return err } if err := s.Convert(&in.Privileged, &out.Privileged, 0); err != nil { return err } if err := s.Convert(&in.ImagePullPolicy, &out.ImagePullPolicy, 0); err != nil { return err } if err := s.Convert(&in.Capabilities, &out.Capabilities, 0); err != nil { return err } return nil }, // Internal API does not support CPU to be specified via an explicit field. // Hence it must be stored in Container.Resources. func(in *int, out *newer.ResourceList, s conversion.Scope) error { if *in == 0 { return nil } quantity := resource.Quantity{} if err := s.Convert(in, &quantity, 0); err != nil { return err } (*out)[newer.ResourceCPU] = quantity return nil }, // Internal API does not support Memory to be specified via an explicit field. // Hence it must be stored in Container.Resources. func(in *int64, out *newer.ResourceList, s conversion.Scope) error { if *in == 0 { return nil } quantity := resource.Quantity{} if err := s.Convert(in, &quantity, 0); err != nil { return err } (*out)[newer.ResourceMemory] = quantity return nil }, // Converts v1beta1.Container to internal newer.Container. // Fields 'CPU' and 'Memory' are not present in the internal newer.Container object. // Hence the need for a custom conversion function. func(in *Container, out *newer.Container, s conversion.Scope) error { if err := s.Convert(&in.Name, &out.Name, 0); err != nil { return err } if err := s.Convert(&in.Image, &out.Image, 0); err != nil { return err } if err := s.Convert(&in.Command, &out.Command, 0); err != nil { return err } if err := s.Convert(&in.WorkingDir, &out.WorkingDir, 0); err != nil { return err } if err := s.Convert(&in.Ports, &out.Ports, 0); err != nil { return err } if err := s.Convert(&in.Env, &out.Env, 0); err != nil { return err } if err := s.Convert(&in.Resources, &out.Resources, 0); err != nil { return err } if err := s.Convert(&in.CPU, &out.Resources.Limits, 0); err != nil { return err } if err := s.Convert(&in.Memory, &out.Resources.Limits, 0); err != nil { return err } if err := s.Convert(&in.VolumeMounts, &out.VolumeMounts, 0); err != nil { return err } if err := s.Convert(&in.LivenessProbe, &out.LivenessProbe, 0); err != nil { return err } if err := s.Convert(&in.ReadinessProbe, &out.ReadinessProbe, 0); err != nil { return err } if err := s.Convert(&in.Lifecycle, &out.Lifecycle, 0); err != nil { return err } if err := s.Convert(&in.TerminationMessagePath, &out.TerminationMessagePath, 0); err != nil { return err } if err := s.Convert(&in.Privileged, &out.Privileged, 0); err != nil { return err } if err := s.Convert(&in.ImagePullPolicy, &out.ImagePullPolicy, 0); err != nil { return err } if err := s.Convert(&in.Capabilities, &out.Capabilities, 0); err != nil { return err } return nil }, func(in *newer.PodSpec, out *ContainerManifest, s conversion.Scope) error { if err := s.Convert(&in.Volumes, &out.Volumes, 0); err != nil { return err } if err := s.Convert(&in.Containers, &out.Containers, 0); err != nil { return err } if err := s.Convert(&in.RestartPolicy, &out.RestartPolicy, 0); err != nil { return err } out.DNSPolicy = DNSPolicy(in.DNSPolicy) out.Version = "v1beta2" return nil }, func(in *ContainerManifest, out *newer.PodSpec, s conversion.Scope) error { if err := s.Convert(&in.Volumes, &out.Volumes, 0); err != nil { return err } if err := s.Convert(&in.Containers, &out.Containers, 0); err != nil { return err } if err := s.Convert(&in.RestartPolicy, &out.RestartPolicy, 0); err != nil { return err } out.DNSPolicy = newer.DNSPolicy(in.DNSPolicy) return nil }, func(in *newer.PodStatus, out *PodState, s conversion.Scope) error { if err := s.Convert(&in.Phase, &out.Status, 0); err != nil { return err } if err := s.Convert(&in.Info, &out.Info, 0); err != nil { return err } if err := s.Convert(&in.Conditions, &out.Conditions, 0); err != nil { return err } out.Message = in.Message out.Host = in.Host out.HostIP = in.HostIP out.PodIP = in.PodIP return nil }, func(in *PodState, out *newer.PodStatus, s conversion.Scope) error { if err := s.Convert(&in.Status, &out.Phase, 0); err != nil { return err } if err := s.Convert(&in.Info, &out.Info, 0); err != nil { return err } if err := s.Convert(&in.Conditions, &out.Conditions, 0); err != nil { return err } out.Message = in.Message out.Host = in.Host out.HostIP = in.HostIP out.PodIP = in.PodIP return nil }, func(in *newer.PodStatusResult, out *PodStatusResult, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.State, 0); err != nil { return err } return nil }, func(in *PodStatusResult, out *newer.PodStatusResult, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.State, &out.Status, 0); err != nil { return err } return nil }, func(in *newer.PodSpec, out *PodState, s conversion.Scope) error { if err := s.Convert(&in, &out.Manifest, 0); err != nil { return err } out.Host = in.Host return nil }, func(in *PodState, out *newer.PodSpec, s conversion.Scope) error { if err := s.Convert(&in.Manifest, &out, 0); err != nil { return err } out.Host = in.Host return nil }, func(in *newer.Service, out *Service, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } out.Port = in.Spec.Port out.Protocol = Protocol(in.Spec.Protocol) if err := s.Convert(&in.Spec.Selector, &out.Selector, 0); err != nil { return err } out.CreateExternalLoadBalancer = in.Spec.CreateExternalLoadBalancer out.PublicIPs = in.Spec.PublicIPs out.ContainerPort = in.Spec.TargetPort out.PortalIP = in.Spec.PortalIP if err := s.Convert(&in.Spec.SessionAffinity, &out.SessionAffinity, 0); err != nil { return err } return nil }, func(in *Service, out *newer.Service, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } out.Spec.Port = in.Port out.Spec.Protocol = newer.Protocol(in.Protocol) if err := s.Convert(&in.Selector, &out.Spec.Selector, 0); err != nil { return err } out.Spec.CreateExternalLoadBalancer = in.CreateExternalLoadBalancer out.Spec.PublicIPs = in.PublicIPs out.Spec.TargetPort = in.ContainerPort out.Spec.PortalIP = in.PortalIP if err := s.Convert(&in.SessionAffinity, &out.Spec.SessionAffinity, 0); err != nil { return err } return nil }, func(in *newer.Node, out *Minion, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.Status.Phase, &out.Status.Phase, 0); err != nil { return err } if err := s.Convert(&in.Status.Conditions, &out.Status.Conditions, 0); err != nil { return err } if err := s.Convert(&in.Status.Addresses, &out.Status.Addresses, 0); err != nil { return err } if err := s.Convert(&in.Status.NodeInfo, &out.Status.NodeInfo, 0); err != nil { return err } for _, address := range in.Status.Addresses { if address.Type == newer.NodeLegacyHostIP { out.HostIP = address.Address } } out.PodCIDR = in.Spec.PodCIDR out.ExternalID = in.Spec.ExternalID out.Unschedulable = in.Spec.Unschedulable return s.Convert(&in.Spec.Capacity, &out.NodeResources.Capacity, 0) }, func(in *Minion, out *newer.Node, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.ObjectMeta.Labels, 0); err != nil { return err } if err := s.Convert(&in.Status.Phase, &out.Status.Phase, 0); err != nil { return err } if err := s.Convert(&in.Status.Conditions, &out.Status.Conditions, 0); err != nil { return err } if err := s.Convert(&in.Status.Addresses, &out.Status.Addresses, 0); err != nil { return err } if err := s.Convert(&in.Status.NodeInfo, &out.Status.NodeInfo, 0); err != nil { return err } if in.HostIP != "" { newer.AddToNodeAddresses(&out.Status.Addresses, newer.NodeAddress{Type: newer.NodeLegacyHostIP, Address: in.HostIP}) } out.Spec.PodCIDR = in.PodCIDR out.Spec.ExternalID = in.ExternalID out.Spec.Unschedulable = in.Unschedulable return s.Convert(&in.NodeResources.Capacity, &out.Spec.Capacity, 0) }, func(in *newer.LimitRange, out *LimitRange, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.Spec, 0); err != nil { return err } return nil }, func(in *LimitRange, out *newer.LimitRange, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.Spec, 0); err != nil { return err } return nil }, func(in *Namespace, out *newer.Namespace, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.Spec, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.ObjectMeta.Labels, 0); err != nil { return err } return nil }, func(in *newer.LimitRangeSpec, out *LimitRangeSpec, s conversion.Scope) error { *out = LimitRangeSpec{} out.Limits = make([]LimitRangeItem, len(in.Limits), len(in.Limits)) for i := range in.Limits { if err := s.Convert(&in.Limits[i], &out.Limits[i], 0); err != nil { return err } } return nil }, func(in *LimitRangeSpec, out *newer.LimitRangeSpec, s conversion.Scope) error { *out = newer.LimitRangeSpec{} out.Limits = make([]newer.LimitRangeItem, len(in.Limits), len(in.Limits)) for i := range in.Limits { if err := s.Convert(&in.Limits[i], &out.Limits[i], 0); err != nil { return err } } return nil }, func(in *newer.LimitRangeItem, out *LimitRangeItem, s conversion.Scope) error { *out = LimitRangeItem{} out.Type = LimitType(in.Type) if err := s.Convert(&in.Max, &out.Max, 0); err != nil { return err } if err := s.Convert(&in.Min, &out.Min, 0); err != nil { return err } return nil }, func(in *LimitRangeItem, out *newer.LimitRangeItem, s conversion.Scope) error { *out = newer.LimitRangeItem{} out.Type = newer.LimitType(in.Type) if err := s.Convert(&in.Max, &out.Max, 0); err != nil { return err } if err := s.Convert(&in.Min, &out.Min, 0); err != nil { return err } return nil }, func(in *newer.ResourceQuota, out *ResourceQuota, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.Spec, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } return nil }, func(in *ResourceQuota, out *newer.ResourceQuota, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.Spec, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.ObjectMeta.Labels, 0); err != nil { return err } return nil }, func(in *newer.ResourceQuotaSpec, out *ResourceQuotaSpec, s conversion.Scope) error { *out = ResourceQuotaSpec{} if err := s.Convert(&in.Hard, &out.Hard, 0); err != nil { return err } return nil }, func(in *ResourceQuotaSpec, out *newer.ResourceQuotaSpec, s conversion.Scope) error { *out = newer.ResourceQuotaSpec{} if err := s.Convert(&in.Hard, &out.Hard, 0); err != nil { return err } return nil }, func(in *newer.ResourceQuotaStatus, out *ResourceQuotaStatus, s conversion.Scope) error { *out = ResourceQuotaStatus{} if err := s.Convert(&in.Hard, &out.Hard, 0); err != nil { return err } if err := s.Convert(&in.Used, &out.Used, 0); err != nil { return err } return nil }, func(in *ResourceQuotaStatus, out *newer.ResourceQuotaStatus, s conversion.Scope) error { *out = newer.ResourceQuotaStatus{} if err := s.Convert(&in.Hard, &out.Hard, 0); err != nil { return err } if err := s.Convert(&in.Used, &out.Used, 0); err != nil { return err } return nil }, // Object ID <-> Name // TODO: amend the conversion package to allow overriding specific fields. func(in *ObjectReference, out *newer.ObjectReference, s conversion.Scope) error { out.Kind = in.Kind out.Namespace = in.Namespace out.Name = in.ID out.UID = in.UID out.APIVersion = in.APIVersion out.ResourceVersion = in.ResourceVersion out.FieldPath = in.FieldPath return nil }, func(in *newer.ObjectReference, out *ObjectReference, s conversion.Scope) error { out.Kind = in.Kind out.Namespace = in.Namespace out.ID = in.Name out.UID = in.UID out.APIVersion = in.APIVersion out.ResourceVersion = in.ResourceVersion out.FieldPath = in.FieldPath return nil }, // Event Status <-> Condition // Event Source <-> Source.Component // Event Host <-> Source.Host // TODO: remove this when it becomes possible to specify a field name conversion on a specific type func(in *newer.Event, out *Event, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } out.Reason = in.Reason out.Message = in.Message out.Source = in.Source.Component out.Host = in.Source.Host out.Timestamp = in.FirstTimestamp out.FirstTimestamp = in.FirstTimestamp out.LastTimestamp = in.LastTimestamp out.Count = in.Count return s.Convert(&in.InvolvedObject, &out.InvolvedObject, 0) }, func(in *Event, out *newer.Event, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } out.Reason = in.Reason out.Message = in.Message out.Source.Component = in.Source out.Source.Host = in.Host if in.FirstTimestamp.IsZero() { // Assume this is an old event that does not specify FirstTimestamp/LastTimestamp/Count out.FirstTimestamp = in.Timestamp out.LastTimestamp = in.Timestamp out.Count = 1 } else { out.FirstTimestamp = in.FirstTimestamp out.LastTimestamp = in.LastTimestamp out.Count = in.Count } return s.Convert(&in.InvolvedObject, &out.InvolvedObject, 0) }, // This is triggered for the Memory field of Container. func(in *int64, out *resource.Quantity, s conversion.Scope) error { out.Set(*in) out.Format = resource.BinarySI return nil }, func(in *resource.Quantity, out *int64, s conversion.Scope) error { *out = in.Value() return nil }, // This is triggered by the CPU field of Container. // Note that if we add other int/Quantity conversions my // simple hack (int64=Value(), int=MilliValue()) here won't work. func(in *int, out *resource.Quantity, s conversion.Scope) error { out.SetMilli(int64(*in)) out.Format = resource.DecimalSI return nil }, func(in *resource.Quantity, out *int, s conversion.Scope) error { *out = int(in.MilliValue()) return nil }, // Convert resource lists. func(in *ResourceList, out *newer.ResourceList, s conversion.Scope) error { *out = newer.ResourceList{} for k, v := range *in { fv, err := strconv.ParseFloat(v.String(), 64) if err != nil { return &newer.ConversionError{ In: in, Out: out, Message: fmt.Sprintf("value '%v' of '%v': %v", v, k, err), } } if k == ResourceCPU { (*out)[newer.ResourceCPU] = *resource.NewMilliQuantity(int64(fv*1000), resource.DecimalSI) } else { (*out)[newer.ResourceName(k)] = *resource.NewQuantity(int64(fv), resource.BinarySI) } } return nil }, func(in *newer.ResourceList, out *ResourceList, s conversion.Scope) error { *out = ResourceList{} for k, v := range *in { if k == newer.ResourceCPU { (*out)[ResourceCPU] = util.NewIntOrStringFromString(fmt.Sprintf("%v", float64(v.MilliValue())/1000)) } else { (*out)[ResourceName(k)] = util.NewIntOrStringFromInt(int(v.Value())) } } return nil }, func(in *newer.Volume, out *Volume, s conversion.Scope) error { if err := s.Convert(&in.VolumeSource, &out.Source, 0); err != nil { return err } out.Name = in.Name return nil }, func(in *Volume, out *newer.Volume, s conversion.Scope) error { if err := s.Convert(&in.Source, &out.VolumeSource, 0); err != nil { return err } out.Name = in.Name return nil }, func(in *newer.VolumeSource, out *VolumeSource, s conversion.Scope) error { if err := s.Convert(&in.EmptyDir, &out.EmptyDir, 0); err != nil { return err } if err := s.Convert(&in.GitRepo, &out.GitRepo, 0); err != nil { return err } if err := s.Convert(&in.GCEPersistentDisk, &out.GCEPersistentDisk, 0); err != nil { return err } if err := s.Convert(&in.HostPath, &out.HostDir, 0); err != nil { return err } if err := s.Convert(&in.Secret, &out.Secret, 0); err != nil { return err } if err := s.Convert(&in.NFS, &out.NFS, 0); err != nil { return err } return nil }, func(in *VolumeSource, out *newer.VolumeSource, s conversion.Scope) error { if err := s.Convert(&in.EmptyDir, &out.EmptyDir, 0); err != nil { return err } if err := s.Convert(&in.GitRepo, &out.GitRepo, 0); err != nil { return err } if err := s.Convert(&in.GCEPersistentDisk, &out.GCEPersistentDisk, 0); err != nil { return err } if err := s.Convert(&in.HostDir, &out.HostPath, 0); err != nil { return err } if err := s.Convert(&in.Secret, &out.Secret, 0); err != nil { return err } if err := s.Convert(&in.NFS, &out.NFS, 0); err != nil { return err } return nil }, func(in *newer.PullPolicy, out *PullPolicy, s conversion.Scope) error { switch *in { case newer.PullAlways: *out = PullAlways case newer.PullNever: *out = PullNever case newer.PullIfNotPresent: *out = PullIfNotPresent case "": *out = "" default: // Let unknown values through - they will get caught by validation *out = PullPolicy(*in) } return nil }, func(in *PullPolicy, out *newer.PullPolicy, s conversion.Scope) error { switch *in { case PullAlways: *out = newer.PullAlways case PullNever: *out = newer.PullNever case PullIfNotPresent: *out = newer.PullIfNotPresent case "": *out = "" default: // Let unknown values through - they will get caught by validation *out = newer.PullPolicy(*in) } return nil }, func(in *newer.RestartPolicy, out *RestartPolicy, s conversion.Scope) error { switch *in { case newer.RestartPolicyAlways: *out = RestartPolicy{Always: &RestartPolicyAlways{}} case newer.RestartPolicyNever: *out = RestartPolicy{Never: &RestartPolicyNever{}} case newer.RestartPolicyOnFailure: *out = RestartPolicy{OnFailure: &RestartPolicyOnFailure{}} default: *out = RestartPolicy{} } return nil }, func(in *RestartPolicy, out *newer.RestartPolicy, s conversion.Scope) error { switch { case in.Always != nil: *out = newer.RestartPolicyAlways case in.Never != nil: *out = newer.RestartPolicyNever case in.OnFailure != nil: *out = newer.RestartPolicyOnFailure default: *out = "" } return nil }, func(in *newer.Probe, out *LivenessProbe, s conversion.Scope) error { if err := s.Convert(&in.Exec, &out.Exec, 0); err != nil { return err } if err := s.Convert(&in.HTTPGet, &out.HTTPGet, 0); err != nil { return err } if err := s.Convert(&in.TCPSocket, &out.TCPSocket, 0); err != nil { return err } out.InitialDelaySeconds = in.InitialDelaySeconds out.TimeoutSeconds = in.TimeoutSeconds return nil }, func(in *LivenessProbe, out *newer.Probe, s conversion.Scope) error { if err := s.Convert(&in.Exec, &out.Exec, 0); err != nil { return err } if err := s.Convert(&in.HTTPGet, &out.HTTPGet, 0); err != nil { return err } if err := s.Convert(&in.TCPSocket, &out.TCPSocket, 0); err != nil { return err } out.InitialDelaySeconds = in.InitialDelaySeconds out.TimeoutSeconds = in.TimeoutSeconds return nil }, func(in *newer.Endpoints, out *Endpoints, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Protocol, &out.Protocol, 0); err != nil { return err } for i := range in.Endpoints { ep := &in.Endpoints[i] hostPort := net.JoinHostPort(ep.IP, strconv.Itoa(ep.Port)) out.Endpoints = append(out.Endpoints, hostPort) if ep.TargetRef != nil { target := EndpointObjectReference{ Endpoint: hostPort, } if err := s.Convert(ep.TargetRef, &target.ObjectReference, 0); err != nil { return err } out.TargetRefs = append(out.TargetRefs, target) } } return nil }, func(in *Endpoints, out *newer.Endpoints, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Protocol, &out.Protocol, 0); err != nil { return err } for i := range in.Endpoints { out.Endpoints = append(out.Endpoints, newer.Endpoint{}) ep := &out.Endpoints[i] host, port, err := net.SplitHostPort(in.Endpoints[i]) if err != nil { return err } ep.IP = host pn, err := strconv.Atoi(port) if err != nil { return err } ep.Port = pn for j := range in.TargetRefs { if in.TargetRefs[j].Endpoint != in.Endpoints[i] { continue } ep.TargetRef = &newer.ObjectReference{} if err := s.Convert(&in.TargetRefs[j], ep.TargetRef, 0); err != nil { return err } } } return nil }, func(in *newer.NodeCondition, out *NodeCondition, s conversion.Scope) error { if err := s.Convert(&in.Type, &out.Kind, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } if err := s.Convert(&in.LastProbeTime, &out.LastProbeTime, 0); err != nil { return err } if err := s.Convert(&in.LastTransitionTime, &out.LastTransitionTime, 0); err != nil { return err } if err := s.Convert(&in.Reason, &out.Reason, 0); err != nil { return err } if err := s.Convert(&in.Message, &out.Message, 0); err != nil { return err } return nil }, func(in *NodeCondition, out *newer.NodeCondition, s conversion.Scope) error { if err := s.Convert(&in.Kind, &out.Type, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } if err := s.Convert(&in.LastProbeTime, &out.LastProbeTime, 0); err != nil { return err } if err := s.Convert(&in.LastTransitionTime, &out.LastTransitionTime, 0); err != nil { return err } if err := s.Convert(&in.Reason, &out.Reason, 0); err != nil { return err } if err := s.Convert(&in.Message, &out.Message, 0); err != nil { return err } return nil }, func(in *newer.NodeConditionType, out *NodeConditionKind, s conversion.Scope) error { switch *in { case newer.NodeReachable: *out = NodeReachable break case newer.NodeReady: *out = NodeReady break case "": *out = "" default: *out = NodeConditionKind(*in) break } return nil }, func(in *NodeConditionKind, out *newer.NodeConditionType, s conversion.Scope) error { switch *in { case NodeReachable: *out = newer.NodeReachable break case NodeReady: *out = newer.NodeReady break case "": *out = "" default: *out = newer.NodeConditionType(*in) break } return nil }, func(in *newer.PodCondition, out *PodCondition, s conversion.Scope) error { if err := s.Convert(&in.Type, &out.Kind, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } return nil }, func(in *PodCondition, out *newer.PodCondition, s conversion.Scope) error { if err := s.Convert(&in.Kind, &out.Type, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } return nil }, func(in *newer.PodConditionType, out *PodConditionKind, s conversion.Scope) error { switch *in { case newer.PodReady: *out = PodReady break case "": *out = "" default: *out = PodConditionKind(*in) break } return nil }, func(in *PodConditionKind, out *newer.PodConditionType, s conversion.Scope) error { switch *in { case PodReady: *out = newer.PodReady break case "": *out = "" default: *out = newer.PodConditionType(*in) break } return nil }, func(in *Binding, out *newer.Binding, s conversion.Scope) error { if err := s.DefaultConvert(in, out, conversion.IgnoreMissingFields); err != nil { return err } out.Target = newer.ObjectReference{ Name: in.Host, } out.Name = in.PodID return nil }, func(in *newer.Binding, out *Binding, s conversion.Scope) error { if err := s.DefaultConvert(in, out, conversion.IgnoreMissingFields); err != nil { return err } out.Host = in.Target.Name out.PodID = in.Name return nil }, ) if err != nil { // If one of the conversion functions is malformed, detect it immediately. panic(err) } // Add field conversion funcs. err = newer.Scheme.AddFieldLabelConversionFunc("v1beta2", "pods", func(label, value string) (string, string, error) { switch label { case "name": return "name", value, nil case "DesiredState.Host": return "spec.host", value, nil case "DesiredState.Status": podStatus := PodStatus(value) var internalValue newer.PodPhase newer.Scheme.Convert(&podStatus, &internalValue) return "status.phase", string(internalValue), nil default: return "", "", fmt.Errorf("field label not supported: %s", label) } }) if err != nil { // If one of the conversion functions is malformed, detect it immediately. panic(err) } err = newer.Scheme.AddFieldLabelConversionFunc("v1beta2", "events", func(label, value string) (string, string, error) { switch label { case "involvedObject.kind", "involvedObject.namespace", "involvedObject.uid", "involvedObject.apiVersion", "involvedObject.resourceVersion", "involvedObject.fieldPath", "reason", "source": return label, value, nil case "involvedObject.id": return "involvedObject.name", value, nil default: return "", "", fmt.Errorf("field label not supported: %s", label) } }) if err != nil { // If one of the conversion functions is malformed, detect it immediately. panic(err) } }
func TestGenerateService(t *testing.T) { tests := []struct { generator Generator params map[string]string expected api.Service }{ { generator: ServiceGeneratorV2{}, params: map[string]string{ "selector": "foo=bar,baz=blah", "name": "test", "port": "80", "protocol": "TCP", "container-port": "1234", }, expected: api.Service{ ObjectMeta: api.ObjectMeta{ Name: "test", }, Spec: api.ServiceSpec{ Selector: map[string]string{ "foo": "bar", "baz": "blah", }, Ports: []api.ServicePort{ { Port: 80, Protocol: "TCP", TargetPort: util.NewIntOrStringFromInt(1234), }, }, }, }, }, { generator: ServiceGeneratorV2{}, params: map[string]string{ "selector": "foo=bar,baz=blah", "name": "test", "port": "80", "protocol": "UDP", "container-port": "foobar", }, expected: api.Service{ ObjectMeta: api.ObjectMeta{ Name: "test", }, Spec: api.ServiceSpec{ Selector: map[string]string{ "foo": "bar", "baz": "blah", }, Ports: []api.ServicePort{ { Port: 80, Protocol: "UDP", TargetPort: util.NewIntOrStringFromString("foobar"), }, }, }, }, }, { generator: ServiceGeneratorV2{}, params: map[string]string{ "selector": "foo=bar,baz=blah", "labels": "key1=value1,key2=value2", "name": "test", "port": "80", "protocol": "TCP", "container-port": "1234", }, expected: api.Service{ ObjectMeta: api.ObjectMeta{ Name: "test", Labels: map[string]string{ "key1": "value1", "key2": "value2", }, }, Spec: api.ServiceSpec{ Selector: map[string]string{ "foo": "bar", "baz": "blah", }, Ports: []api.ServicePort{ { Port: 80, Protocol: "TCP", TargetPort: util.NewIntOrStringFromInt(1234), }, }, }, }, }, { generator: ServiceGeneratorV2{}, params: map[string]string{ "selector": "foo=bar,baz=blah", "name": "test", "port": "80", "protocol": "UDP", "container-port": "foobar", "public-ip": "1.2.3.4", }, expected: api.Service{ ObjectMeta: api.ObjectMeta{ Name: "test", }, Spec: api.ServiceSpec{ Selector: map[string]string{ "foo": "bar", "baz": "blah", }, Ports: []api.ServicePort{ { Port: 80, Protocol: "UDP", TargetPort: util.NewIntOrStringFromString("foobar"), }, }, DeprecatedPublicIPs: []string{"1.2.3.4"}, }, }, }, { generator: ServiceGeneratorV2{}, params: map[string]string{ "selector": "foo=bar,baz=blah", "name": "test", "port": "80", "protocol": "UDP", "container-port": "foobar", "public-ip": "1.2.3.4", "create-external-load-balancer": "true", }, expected: api.Service{ ObjectMeta: api.ObjectMeta{ Name: "test", }, Spec: api.ServiceSpec{ Selector: map[string]string{ "foo": "bar", "baz": "blah", }, Ports: []api.ServicePort{ { Port: 80, Protocol: "UDP", TargetPort: util.NewIntOrStringFromString("foobar"), }, }, Type: api.ServiceTypeLoadBalancer, DeprecatedPublicIPs: []string{"1.2.3.4"}, }, }, }, { generator: ServiceGeneratorV2{}, params: map[string]string{ "selector": "foo=bar,baz=blah", "name": "test", "port": "80", "protocol": "UDP", "container-port": "foobar", "type": string(api.ServiceTypeNodePort), }, expected: api.Service{ ObjectMeta: api.ObjectMeta{ Name: "test", }, Spec: api.ServiceSpec{ Selector: map[string]string{ "foo": "bar", "baz": "blah", }, Ports: []api.ServicePort{ { Port: 80, Protocol: "UDP", TargetPort: util.NewIntOrStringFromString("foobar"), }, }, Type: api.ServiceTypeNodePort, }, }, }, { generator: ServiceGeneratorV2{}, params: map[string]string{ "selector": "foo=bar,baz=blah", "name": "test", "port": "80", "protocol": "UDP", "container-port": "foobar", "create-external-load-balancer": "true", // ignored when type is present "type": string(api.ServiceTypeNodePort), }, expected: api.Service{ ObjectMeta: api.ObjectMeta{ Name: "test", }, Spec: api.ServiceSpec{ Selector: map[string]string{ "foo": "bar", "baz": "blah", }, Ports: []api.ServicePort{ { Port: 80, Protocol: "UDP", TargetPort: util.NewIntOrStringFromString("foobar"), }, }, Type: api.ServiceTypeNodePort, }, }, }, { generator: ServiceGeneratorV1{}, params: map[string]string{ "selector": "foo=bar,baz=blah", "name": "test", "port": "80", "protocol": "TCP", "container-port": "1234", }, expected: api.Service{ ObjectMeta: api.ObjectMeta{ Name: "test", }, Spec: api.ServiceSpec{ Selector: map[string]string{ "foo": "bar", "baz": "blah", }, Ports: []api.ServicePort{ { Name: "default", Port: 80, Protocol: "TCP", TargetPort: util.NewIntOrStringFromInt(1234), }, }, }, }, }, { generator: ServiceGeneratorV1{}, params: map[string]string{ "selector": "foo=bar,baz=blah", "name": "test", "port": "80", "protocol": "TCP", "container-port": "1234", "session-affinity": "ClientIP", }, expected: api.Service{ ObjectMeta: api.ObjectMeta{ Name: "test", }, Spec: api.ServiceSpec{ Selector: map[string]string{ "foo": "bar", "baz": "blah", }, Ports: []api.ServicePort{ { Name: "default", Port: 80, Protocol: "TCP", TargetPort: util.NewIntOrStringFromInt(1234), }, }, SessionAffinity: api.ServiceAffinityClientIP, }, }, }, } for _, test := range tests { obj, err := test.generator.Generate(test.params) if !reflect.DeepEqual(obj, &test.expected) { t.Errorf("expected:\n%#v\ngot\n%#v\n", &test.expected, obj) } if err != nil { t.Errorf("unexpected error: %v", err) } } }
func TestFindPort(t *testing.T) { servicePort := 999 testCases := []struct { name string containers []api.Container port util.IntOrString expected int pass bool }{{ name: "valid int, no ports", containers: []api.Container{{}}, port: util.NewIntOrStringFromInt(93), expected: 93, pass: true, }, { name: "valid int, with ports", containers: []api.Container{{Ports: []api.ContainerPort{{ Name: "", ContainerPort: 11, Protocol: "TCP", }, { Name: "p", ContainerPort: 22, Protocol: "TCP", }}}}, port: util.NewIntOrStringFromInt(93), expected: 93, pass: true, }, { name: "zero int, no ports", containers: []api.Container{{}}, port: util.NewIntOrStringFromInt(0), expected: servicePort, pass: true, }, { name: "zero int, one ctr with ports", containers: []api.Container{{Ports: []api.ContainerPort{{ Name: "", ContainerPort: 11, Protocol: "UDP", }, { Name: "p", ContainerPort: 22, Protocol: "TCP", }}}}, port: util.NewIntOrStringFromInt(0), expected: 22, pass: true, }, { name: "zero int, two ctr with ports", containers: []api.Container{{}, {Ports: []api.ContainerPort{{ Name: "", ContainerPort: 11, Protocol: "UDP", }, { Name: "p", ContainerPort: 22, Protocol: "TCP", }}}}, port: util.NewIntOrStringFromInt(0), expected: 22, pass: true, }, { name: "empty str, no ports", containers: []api.Container{{}}, port: util.NewIntOrStringFromString(""), expected: servicePort, pass: true, }, { name: "empty str, one ctr with ports", containers: []api.Container{{Ports: []api.ContainerPort{{ Name: "", ContainerPort: 11, Protocol: "UDP", }, { Name: "p", ContainerPort: 22, Protocol: "TCP", }}}}, port: util.NewIntOrStringFromString(""), expected: 22, pass: true, }, { name: "empty str, two ctr with ports", containers: []api.Container{{}, {Ports: []api.ContainerPort{{ Name: "", ContainerPort: 11, Protocol: "UDP", }, { Name: "p", ContainerPort: 22, Protocol: "TCP", }}}}, port: util.NewIntOrStringFromString(""), expected: 22, pass: true, }, { name: "valid str, no ports", containers: []api.Container{{}}, port: util.NewIntOrStringFromString("p"), expected: 0, pass: false, }, { name: "valid str, one ctr with ports", containers: []api.Container{{Ports: []api.ContainerPort{{ Name: "", ContainerPort: 11, Protocol: "UDP", }, { Name: "p", ContainerPort: 22, Protocol: "TCP", }, { Name: "q", ContainerPort: 33, Protocol: "TCP", }}}}, port: util.NewIntOrStringFromString("q"), expected: 33, pass: true, }, { name: "valid str, two ctr with ports", containers: []api.Container{{}, {Ports: []api.ContainerPort{{ Name: "", ContainerPort: 11, Protocol: "UDP", }, { Name: "p", ContainerPort: 22, Protocol: "TCP", }, { Name: "q", ContainerPort: 33, Protocol: "TCP", }}}}, port: util.NewIntOrStringFromString("q"), expected: 33, pass: true, }} for _, tc := range testCases { port, err := findPort(&api.Pod{Spec: api.PodSpec{Containers: tc.containers}}, &api.ServicePort{Protocol: "TCP", Port: servicePort, TargetPort: tc.port}) if err != nil && tc.pass { t.Errorf("unexpected error for %s: %v", tc.name, err) } if err == nil && !tc.pass { t.Errorf("unexpected non-error for %s: %d", tc.name, port) } if port != tc.expected { t.Errorf("wrong result for %s: expected %d, got %d", tc.name, tc.expected, port) } } }
func addDefaultingFuncs() { api.Scheme.AddDefaultingFuncs( func(obj *ReplicationController) { var labels map[string]string if obj.Spec.Template != nil { labels = obj.Spec.Template.Labels } // TODO: support templates defined elsewhere when we support them in the API if labels != nil { if len(obj.Spec.Selector) == 0 { obj.Spec.Selector = labels } if len(obj.Labels) == 0 { obj.Labels = labels } } if obj.Spec.Replicas == nil { obj.Spec.Replicas = new(int) *obj.Spec.Replicas = 1 } }, func(obj *Volume) { if util.AllPtrFieldsNil(&obj.VolumeSource) { obj.VolumeSource = VolumeSource{ EmptyDir: &EmptyDirVolumeSource{}, } } }, func(obj *ContainerPort) { if obj.Protocol == "" { obj.Protocol = ProtocolTCP } }, func(obj *Container) { if obj.ImagePullPolicy == "" { // TODO(dchen1107): Move ParseImageName code to pkg/util parts := strings.Split(obj.Image, ":") // Check image tag if parts[len(parts)-1] == "latest" { obj.ImagePullPolicy = PullAlways } else { obj.ImagePullPolicy = PullIfNotPresent } } if obj.TerminationMessagePath == "" { obj.TerminationMessagePath = TerminationMessagePathDefault } }, func(obj *ServiceSpec) { if obj.SessionAffinity == "" { obj.SessionAffinity = ServiceAffinityNone } if obj.Type == "" { obj.Type = ServiceTypeClusterIP } for i := range obj.Ports { sp := &obj.Ports[i] if sp.Protocol == "" { sp.Protocol = ProtocolTCP } if sp.TargetPort == util.NewIntOrStringFromInt(0) || sp.TargetPort == util.NewIntOrStringFromString("") { sp.TargetPort = util.NewIntOrStringFromInt(sp.Port) } } }, func(obj *PodSpec) { if obj.DNSPolicy == "" { obj.DNSPolicy = DNSClusterFirst } if obj.RestartPolicy == "" { obj.RestartPolicy = RestartPolicyAlways } if obj.HostNetwork { defaultHostNetworkPorts(&obj.Containers) } }, func(obj *Probe) { if obj.TimeoutSeconds == 0 { obj.TimeoutSeconds = 1 } }, func(obj *Secret) { if obj.Type == "" { obj.Type = SecretTypeOpaque } }, func(obj *PersistentVolume) { if obj.Status.Phase == "" { obj.Status.Phase = VolumePending } if obj.Spec.PersistentVolumeReclaimPolicy == "" { obj.Spec.PersistentVolumeReclaimPolicy = PersistentVolumeReclaimRetain } }, func(obj *PersistentVolumeClaim) { if obj.Status.Phase == "" { obj.Status.Phase = ClaimPending } }, func(obj *Endpoints) { for i := range obj.Subsets { ss := &obj.Subsets[i] for i := range ss.Ports { ep := &ss.Ports[i] if ep.Protocol == "" { ep.Protocol = ProtocolTCP } } } }, func(obj *HTTPGetAction) { if obj.Path == "" { obj.Path = "/" } if obj.Scheme == "" { obj.Scheme = URISchemeHTTP } }, func(obj *NamespaceStatus) { if obj.Phase == "" { obj.Phase = NamespaceActive } }, func(obj *Node) { if obj.Spec.ExternalID == "" { obj.Spec.ExternalID = obj.Name } }, func(obj *ObjectFieldSelector) { if obj.APIVersion == "" { obj.APIVersion = "v1" } }, ) }
func init() { // Our TypeMeta was split into two different structs. newer.Scheme.AddStructFieldConversion(TypeMeta{}, "TypeMeta", newer.TypeMeta{}, "TypeMeta") newer.Scheme.AddStructFieldConversion(TypeMeta{}, "TypeMeta", newer.ObjectMeta{}, "ObjectMeta") newer.Scheme.AddStructFieldConversion(TypeMeta{}, "TypeMeta", newer.ListMeta{}, "ListMeta") newer.Scheme.AddStructFieldConversion(newer.TypeMeta{}, "TypeMeta", TypeMeta{}, "TypeMeta") newer.Scheme.AddStructFieldConversion(newer.ObjectMeta{}, "ObjectMeta", TypeMeta{}, "TypeMeta") newer.Scheme.AddStructFieldConversion(newer.ListMeta{}, "ListMeta", TypeMeta{}, "TypeMeta") // TODO: scope this to a specific type once that becomes available and remove the Event conversion functions below // newer.Scheme.AddStructFieldConversion(string(""), "Status", string(""), "Condition") // newer.Scheme.AddStructFieldConversion(string(""), "Condition", string(""), "Status") err := newer.Scheme.AddConversionFuncs( // TypeMeta must be split into two objects func(in *newer.TypeMeta, out *TypeMeta, s conversion.Scope) error { out.Kind = in.Kind out.APIVersion = in.APIVersion return nil }, func(in *TypeMeta, out *newer.TypeMeta, s conversion.Scope) error { out.Kind = in.Kind out.APIVersion = in.APIVersion return nil }, // ListMeta must be converted to TypeMeta func(in *newer.ListMeta, out *TypeMeta, s conversion.Scope) error { out.SelfLink = in.SelfLink if len(in.ResourceVersion) > 0 { v, err := strconv.ParseUint(in.ResourceVersion, 10, 64) if err != nil { return err } out.ResourceVersion = v } return nil }, func(in *TypeMeta, out *newer.ListMeta, s conversion.Scope) error { out.SelfLink = in.SelfLink if in.ResourceVersion != 0 { out.ResourceVersion = strconv.FormatUint(in.ResourceVersion, 10) } else { out.ResourceVersion = "" } return nil }, // ObjectMeta must be converted to TypeMeta func(in *newer.ObjectMeta, out *TypeMeta, s conversion.Scope) error { out.Namespace = in.Namespace out.ID = in.Name out.GenerateName = in.GenerateName out.UID = in.UID out.CreationTimestamp = in.CreationTimestamp out.SelfLink = in.SelfLink if len(in.ResourceVersion) > 0 { v, err := strconv.ParseUint(in.ResourceVersion, 10, 64) if err != nil { return err } out.ResourceVersion = v } return s.Convert(&in.Annotations, &out.Annotations, 0) }, func(in *TypeMeta, out *newer.ObjectMeta, s conversion.Scope) error { out.Namespace = in.Namespace out.Name = in.ID out.GenerateName = in.GenerateName out.UID = in.UID out.CreationTimestamp = in.CreationTimestamp out.SelfLink = in.SelfLink if in.ResourceVersion != 0 { out.ResourceVersion = strconv.FormatUint(in.ResourceVersion, 10) } else { out.ResourceVersion = "" } return s.Convert(&in.Annotations, &out.Annotations, 0) }, // EnvVar's Key is deprecated in favor of Name. func(in *newer.EnvVar, out *EnvVar, s conversion.Scope) error { out.Value = in.Value out.Key = in.Name out.Name = in.Name return nil }, func(in *EnvVar, out *newer.EnvVar, s conversion.Scope) error { out.Value = in.Value if in.Name != "" { out.Name = in.Name } else { out.Name = in.Key } return nil }, // Path & MountType are deprecated. func(in *newer.VolumeMount, out *VolumeMount, s conversion.Scope) error { out.Name = in.Name out.ReadOnly = in.ReadOnly out.MountPath = in.MountPath out.Path = in.MountPath out.MountType = "" // MountType is ignored. return nil }, func(in *VolumeMount, out *newer.VolumeMount, s conversion.Scope) error { out.Name = in.Name out.ReadOnly = in.ReadOnly if in.MountPath == "" { out.MountPath = in.Path } else { out.MountPath = in.MountPath } return nil }, // MinionList.Items had a wrong name in v1beta1 func(in *newer.NodeList, out *MinionList, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ListMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Items, &out.Items, 0); err != nil { return err } out.Minions = out.Items return nil }, func(in *MinionList, out *newer.NodeList, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ListMeta, 0); err != nil { return err } if len(in.Items) == 0 { if err := s.Convert(&in.Minions, &out.Items, 0); err != nil { return err } } else { if err := s.Convert(&in.Items, &out.Items, 0); err != nil { return err } } return nil }, func(in *newer.PodStatus, out *PodState, s conversion.Scope) error { if err := s.Convert(&in.Phase, &out.Status, 0); err != nil { return err } if err := s.Convert(&in.Conditions, &out.Conditions, 0); err != nil { return err } if err := s.Convert(&in.Info, &out.Info, 0); err != nil { return err } out.Message = in.Message out.Host = in.Host out.HostIP = in.HostIP out.PodIP = in.PodIP return nil }, func(in *PodState, out *newer.PodStatus, s conversion.Scope) error { if err := s.Convert(&in.Status, &out.Phase, 0); err != nil { return err } if err := s.Convert(&in.Conditions, &out.Conditions, 0); err != nil { return err } if err := s.Convert(&in.Info, &out.Info, 0); err != nil { return err } out.Message = in.Message out.Host = in.Host out.HostIP = in.HostIP out.PodIP = in.PodIP return nil }, func(in *newer.PodSpec, out *PodState, s conversion.Scope) error { if err := s.Convert(&in, &out.Manifest, 0); err != nil { return err } out.Host = in.Host return nil }, func(in *PodState, out *newer.PodSpec, s conversion.Scope) error { if err := s.Convert(&in.Manifest, &out, 0); err != nil { return err } out.Host = in.Host return nil }, // Convert all to the new PodPhase constants func(in *newer.PodPhase, out *PodStatus, s conversion.Scope) error { switch *in { case "": *out = "" case newer.PodPending: *out = PodWaiting case newer.PodRunning: *out = PodRunning case newer.PodSucceeded: *out = PodSucceeded case newer.PodFailed: *out = PodTerminated case newer.PodUnknown: *out = PodUnknown default: return &newer.ConversionError{ In: in, Out: out, Message: "The string provided is not a valid PodPhase constant value", } } return nil }, func(in *PodStatus, out *newer.PodPhase, s conversion.Scope) error { switch *in { case "": *out = "" case PodWaiting: *out = newer.PodPending case PodRunning: *out = newer.PodRunning case PodTerminated: // Older API versions did not contain enough info to map to PodSucceeded *out = newer.PodFailed case PodSucceeded: *out = newer.PodSucceeded case PodUnknown: *out = newer.PodUnknown default: return &newer.ConversionError{ In: in, Out: out, Message: "The string provided is not a valid PodPhase constant value", } } return nil }, // Convert all the standard objects func(in *newer.Pod, out *Pod, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } // TODO: Change this to use in.ObjectMeta.Labels. if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.DesiredState.Manifest, 0); err != nil { return err } out.DesiredState.Host = in.Spec.Host if err := s.Convert(&in.Status, &out.CurrentState, 0); err != nil { return err } if err := s.Convert(&in.Spec.NodeSelector, &out.NodeSelector, 0); err != nil { return err } return nil }, func(in *Pod, out *newer.Pod, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.DesiredState.Manifest, &out.Spec, 0); err != nil { return err } out.Spec.Host = in.DesiredState.Host if err := s.Convert(&in.CurrentState, &out.Status, 0); err != nil { return err } if err := s.Convert(&in.NodeSelector, &out.Spec.NodeSelector, 0); err != nil { return err } return nil }, func(in *newer.PodStatusResult, out *PodStatusResult, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.State, 0); err != nil { return err } return nil }, func(in *PodStatusResult, out *newer.PodStatusResult, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.State, &out.Status, 0); err != nil { return err } return nil }, func(in *newer.ReplicationController, out *ReplicationController, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.DesiredState, 0); err != nil { return err } out.CurrentState.Replicas = in.Status.Replicas return nil }, func(in *ReplicationController, out *newer.ReplicationController, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.DesiredState, &out.Spec, 0); err != nil { return err } out.Status.Replicas = in.CurrentState.Replicas return nil }, func(in *newer.ReplicationControllerSpec, out *ReplicationControllerState, s conversion.Scope) error { out.Replicas = in.Replicas if err := s.Convert(&in.Selector, &out.ReplicaSelector, 0); err != nil { return err } if in.TemplateRef != nil && in.Template == nil { return &newer.ConversionError{ In: in, Out: out, Message: "objects with a template ref cannot be converted to older objects, must populate template", } } if in.Template != nil { if err := s.Convert(in.Template, &out.PodTemplate, 0); err != nil { return err } } return nil }, func(in *ReplicationControllerState, out *newer.ReplicationControllerSpec, s conversion.Scope) error { out.Replicas = in.Replicas if err := s.Convert(&in.ReplicaSelector, &out.Selector, 0); err != nil { return err } out.Template = &newer.PodTemplateSpec{} if err := s.Convert(&in.PodTemplate, out.Template, 0); err != nil { return err } return nil }, func(in *newer.PodTemplateSpec, out *PodTemplate, s conversion.Scope) error { if err := s.Convert(&in.Spec, &out.DesiredState.Manifest, 0); err != nil { return err } out.DesiredState.Host = in.Spec.Host if err := s.Convert(&in.Spec.NodeSelector, &out.NodeSelector, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta.Annotations, &out.Annotations, 0); err != nil { return err } return nil }, func(in *PodTemplate, out *newer.PodTemplateSpec, s conversion.Scope) error { if err := s.Convert(&in.DesiredState.Manifest, &out.Spec, 0); err != nil { return err } out.Spec.Host = in.DesiredState.Host if err := s.Convert(&in.NodeSelector, &out.Spec.NodeSelector, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.ObjectMeta.Labels, 0); err != nil { return err } if err := s.Convert(&in.Annotations, &out.ObjectMeta.Annotations, 0); err != nil { return err } return nil }, func(in *newer.PodSpec, out *BoundPod, s conversion.Scope) error { if err := s.Convert(&in, &out.Spec, 0); err != nil { return err } return nil }, func(in *BoundPod, out *newer.PodSpec, s conversion.Scope) error { if err := s.Convert(&in.Spec, &out, 0); err != nil { return err } return nil }, // Converts internal Container to v1beta1.Container. // Fields 'CPU' and 'Memory' are not present in the internal Container object. // Hence the need for a custom conversion function. func(in *newer.Container, out *Container, s conversion.Scope) error { if err := s.Convert(&in.Name, &out.Name, 0); err != nil { return err } if err := s.Convert(&in.Image, &out.Image, 0); err != nil { return err } if err := s.Convert(&in.Command, &out.Command, 0); err != nil { return err } if err := s.Convert(&in.WorkingDir, &out.WorkingDir, 0); err != nil { return err } if err := s.Convert(&in.Ports, &out.Ports, 0); err != nil { return err } if err := s.Convert(&in.Env, &out.Env, 0); err != nil { return err } if err := s.Convert(&in.Resources, &out.Resources, 0); err != nil { return err } if err := s.Convert(in.Resources.Limits.Cpu(), &out.CPU, 0); err != nil { return err } if err := s.Convert(in.Resources.Limits.Memory(), &out.Memory, 0); err != nil { return err } if err := s.Convert(&in.VolumeMounts, &out.VolumeMounts, 0); err != nil { return err } if err := s.Convert(&in.LivenessProbe, &out.LivenessProbe, 0); err != nil { return err } if err := s.Convert(&in.ReadinessProbe, &out.ReadinessProbe, 0); err != nil { return err } if err := s.Convert(&in.Lifecycle, &out.Lifecycle, 0); err != nil { return err } if err := s.Convert(&in.TerminationMessagePath, &out.TerminationMessagePath, 0); err != nil { return err } if err := s.Convert(&in.Privileged, &out.Privileged, 0); err != nil { return err } if err := s.Convert(&in.ImagePullPolicy, &out.ImagePullPolicy, 0); err != nil { return err } if err := s.Convert(&in.Capabilities, &out.Capabilities, 0); err != nil { return err } return nil }, // Internal API does not support CPU to be specified via an explicit field. // Hence it must be stored in Container.Resources. func(in *int, out *newer.ResourceList, s conversion.Scope) error { if *in <= 0 { return nil } quantity := resource.Quantity{} if err := s.Convert(in, &quantity, 0); err != nil { return err } (*out)[newer.ResourceCPU] = quantity return nil }, // Internal API does not support Memory to be specified via an explicit field. // Hence it must be stored in Container.Resources. func(in *int64, out *newer.ResourceList, s conversion.Scope) error { if *in <= 0 { return nil } quantity := resource.Quantity{} if err := s.Convert(in, &quantity, 0); err != nil { return err } (*out)[newer.ResourceMemory] = quantity return nil }, // Converts v1beta1.Container to internal Container. // Fields 'CPU' and 'Memory' are not present in the internal Container object. // Hence the need for a custom conversion function. func(in *Container, out *newer.Container, s conversion.Scope) error { if err := s.Convert(&in.Name, &out.Name, 0); err != nil { return err } if err := s.Convert(&in.Image, &out.Image, 0); err != nil { return err } if err := s.Convert(&in.Command, &out.Command, 0); err != nil { return err } if err := s.Convert(&in.WorkingDir, &out.WorkingDir, 0); err != nil { return err } if err := s.Convert(&in.Ports, &out.Ports, 0); err != nil { return err } if err := s.Convert(&in.Env, &out.Env, 0); err != nil { return err } if err := s.Convert(&in.Resources, &out.Resources, 0); err != nil { return err } if err := s.Convert(&in.CPU, &out.Resources.Limits, 0); err != nil { return err } if err := s.Convert(&in.Memory, &out.Resources.Limits, 0); err != nil { return err } if err := s.Convert(&in.VolumeMounts, &out.VolumeMounts, 0); err != nil { return err } if err := s.Convert(&in.LivenessProbe, &out.LivenessProbe, 0); err != nil { return err } if err := s.Convert(&in.ReadinessProbe, &out.ReadinessProbe, 0); err != nil { return err } if err := s.Convert(&in.Lifecycle, &out.Lifecycle, 0); err != nil { return err } if err := s.Convert(&in.TerminationMessagePath, &out.TerminationMessagePath, 0); err != nil { return err } if err := s.Convert(&in.Privileged, &out.Privileged, 0); err != nil { return err } if err := s.Convert(&in.ImagePullPolicy, &out.ImagePullPolicy, 0); err != nil { return err } if err := s.Convert(&in.Capabilities, &out.Capabilities, 0); err != nil { return err } return nil }, func(in *newer.PodSpec, out *ContainerManifest, s conversion.Scope) error { if err := s.Convert(&in.Volumes, &out.Volumes, 0); err != nil { return err } if err := s.Convert(&in.Containers, &out.Containers, 0); err != nil { return err } if err := s.Convert(&in.RestartPolicy, &out.RestartPolicy, 0); err != nil { return err } out.DNSPolicy = DNSPolicy(in.DNSPolicy) out.Version = "v1beta2" return nil }, func(in *ContainerManifest, out *newer.PodSpec, s conversion.Scope) error { if err := s.Convert(&in.Volumes, &out.Volumes, 0); err != nil { return err } if err := s.Convert(&in.Containers, &out.Containers, 0); err != nil { return err } if err := s.Convert(&in.RestartPolicy, &out.RestartPolicy, 0); err != nil { return err } out.DNSPolicy = newer.DNSPolicy(in.DNSPolicy) return nil }, func(in *newer.Service, out *Service, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } out.Port = in.Spec.Port out.Protocol = Protocol(in.Spec.Protocol) if err := s.Convert(&in.Spec.Selector, &out.Selector, 0); err != nil { return err } out.CreateExternalLoadBalancer = in.Spec.CreateExternalLoadBalancer out.PublicIPs = in.Spec.PublicIPs out.ContainerPort = in.Spec.ContainerPort out.PortalIP = in.Spec.PortalIP if err := s.Convert(&in.Spec.SessionAffinity, &out.SessionAffinity, 0); err != nil { return err } return nil }, func(in *Service, out *newer.Service, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil { return err } out.Spec.Port = in.Port out.Spec.Protocol = newer.Protocol(in.Protocol) if err := s.Convert(&in.Selector, &out.Spec.Selector, 0); err != nil { return err } out.Spec.CreateExternalLoadBalancer = in.CreateExternalLoadBalancer out.Spec.PublicIPs = in.PublicIPs out.Spec.ContainerPort = in.ContainerPort out.Spec.PortalIP = in.PortalIP if err := s.Convert(&in.SessionAffinity, &out.Spec.SessionAffinity, 0); err != nil { return err } return nil }, func(in *newer.Node, out *Minion, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta.Labels, &out.Labels, 0); err != nil { return err } if err := s.Convert(&in.Status.Phase, &out.Status.Phase, 0); err != nil { return err } if err := s.Convert(&in.Status.Conditions, &out.Status.Conditions, 0); err != nil { return err } out.HostIP = in.Status.HostIP out.PodCIDR = in.Spec.PodCIDR out.ExternalID = in.Spec.ExternalID return s.Convert(&in.Spec.Capacity, &out.NodeResources.Capacity, 0) }, func(in *Minion, out *newer.Node, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.ObjectMeta.Labels, 0); err != nil { return err } if err := s.Convert(&in.Status.Phase, &out.Status.Phase, 0); err != nil { return err } if err := s.Convert(&in.Status.Conditions, &out.Status.Conditions, 0); err != nil { return err } out.Status.HostIP = in.HostIP out.Spec.PodCIDR = in.PodCIDR out.Spec.ExternalID = in.ExternalID return s.Convert(&in.NodeResources.Capacity, &out.Spec.Capacity, 0) }, func(in *newer.LimitRange, out *LimitRange, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.Spec, 0); err != nil { return err } return nil }, func(in *LimitRange, out *newer.LimitRange, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.Spec, 0); err != nil { return err } return nil }, func(in *Namespace, out *newer.Namespace, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.Spec, 0); err != nil { return err } if err := s.Convert(&in.Labels, &out.ObjectMeta.Labels, 0); err != nil { return err } return nil }, func(in *newer.LimitRangeSpec, out *LimitRangeSpec, s conversion.Scope) error { *out = LimitRangeSpec{} out.Limits = make([]LimitRangeItem, len(in.Limits), len(in.Limits)) for i := range in.Limits { if err := s.Convert(&in.Limits[i], &out.Limits[i], 0); err != nil { return err } } return nil }, func(in *LimitRangeSpec, out *newer.LimitRangeSpec, s conversion.Scope) error { *out = newer.LimitRangeSpec{} out.Limits = make([]newer.LimitRangeItem, len(in.Limits), len(in.Limits)) for i := range in.Limits { if err := s.Convert(&in.Limits[i], &out.Limits[i], 0); err != nil { return err } } return nil }, func(in *newer.LimitRangeItem, out *LimitRangeItem, s conversion.Scope) error { *out = LimitRangeItem{} out.Type = LimitType(in.Type) if err := s.Convert(&in.Max, &out.Max, 0); err != nil { return err } if err := s.Convert(&in.Min, &out.Min, 0); err != nil { return err } return nil }, func(in *LimitRangeItem, out *newer.LimitRangeItem, s conversion.Scope) error { *out = newer.LimitRangeItem{} out.Type = newer.LimitType(in.Type) if err := s.Convert(&in.Max, &out.Max, 0); err != nil { return err } if err := s.Convert(&in.Min, &out.Min, 0); err != nil { return err } return nil }, func(in *newer.ResourceQuota, out *ResourceQuota, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.Spec, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } return nil }, func(in *ResourceQuota, out *newer.ResourceQuota, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Spec, &out.Spec, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } return nil }, func(in *newer.ResourceQuotaUsage, out *ResourceQuotaUsage, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } return nil }, func(in *ResourceQuotaUsage, out *newer.ResourceQuotaUsage, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } return nil }, func(in *newer.ResourceQuotaSpec, out *ResourceQuotaSpec, s conversion.Scope) error { *out = ResourceQuotaSpec{} if err := s.Convert(&in.Hard, &out.Hard, 0); err != nil { return err } return nil }, func(in *ResourceQuotaSpec, out *newer.ResourceQuotaSpec, s conversion.Scope) error { *out = newer.ResourceQuotaSpec{} if err := s.Convert(&in.Hard, &out.Hard, 0); err != nil { return err } return nil }, func(in *newer.ResourceQuotaStatus, out *ResourceQuotaStatus, s conversion.Scope) error { *out = ResourceQuotaStatus{} if err := s.Convert(&in.Hard, &out.Hard, 0); err != nil { return err } if err := s.Convert(&in.Used, &out.Used, 0); err != nil { return err } return nil }, func(in *ResourceQuotaStatus, out *newer.ResourceQuotaStatus, s conversion.Scope) error { *out = newer.ResourceQuotaStatus{} if err := s.Convert(&in.Hard, &out.Hard, 0); err != nil { return err } if err := s.Convert(&in.Used, &out.Used, 0); err != nil { return err } return nil }, // Object ID <-> Name // TODO: amend the conversion package to allow overriding specific fields. func(in *ObjectReference, out *newer.ObjectReference, s conversion.Scope) error { out.Kind = in.Kind out.Namespace = in.Namespace out.Name = in.ID out.UID = in.UID out.APIVersion = in.APIVersion out.ResourceVersion = in.ResourceVersion out.FieldPath = in.FieldPath return nil }, func(in *newer.ObjectReference, out *ObjectReference, s conversion.Scope) error { out.Kind = in.Kind out.Namespace = in.Namespace out.ID = in.Name out.UID = in.UID out.APIVersion = in.APIVersion out.ResourceVersion = in.ResourceVersion out.FieldPath = in.FieldPath return nil }, // Event Source <-> Source.Component // Event Host <-> Source.Host // TODO: remove this when it becomes possible to specify a field name conversion on a specific type func(in *newer.Event, out *Event, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } out.Reason = in.Reason out.Message = in.Message out.Source = in.Source.Component out.Host = in.Source.Host out.Timestamp = in.FirstTimestamp out.FirstTimestamp = in.FirstTimestamp out.LastTimestamp = in.LastTimestamp out.Count = in.Count return s.Convert(&in.InvolvedObject, &out.InvolvedObject, 0) }, func(in *Event, out *newer.Event, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } out.Reason = in.Reason out.Message = in.Message out.Source.Component = in.Source out.Source.Host = in.Host if in.FirstTimestamp.IsZero() { // Assume this is an old event that does not specify FirstTimestamp/LastTimestamp/Count out.FirstTimestamp = in.Timestamp out.LastTimestamp = in.Timestamp out.Count = 1 } else { out.FirstTimestamp = in.FirstTimestamp out.LastTimestamp = in.LastTimestamp out.Count = in.Count } return s.Convert(&in.InvolvedObject, &out.InvolvedObject, 0) }, // This is triggered for the Memory field of Container. func(in *int64, out *resource.Quantity, s conversion.Scope) error { out.Set(*in) out.Format = resource.BinarySI return nil }, func(in *resource.Quantity, out *int64, s conversion.Scope) error { *out = in.Value() return nil }, // This is triggered by the CPU field of Container. // Note that if we add other int/Quantity conversions my // simple hack (int64=Value(), int=MilliValue()) here won't work. func(in *int, out *resource.Quantity, s conversion.Scope) error { out.SetMilli(int64(*in)) out.Format = resource.DecimalSI return nil }, func(in *resource.Quantity, out *int, s conversion.Scope) error { *out = int(in.MilliValue()) return nil }, // Convert resource lists. func(in *ResourceList, out *newer.ResourceList, s conversion.Scope) error { *out = newer.ResourceList{} for k, v := range *in { fv, err := strconv.ParseFloat(v.String(), 64) if err != nil { return &newer.ConversionError{ In: in, Out: out, Message: fmt.Sprintf("value '%v' of '%v': %v", v, k, err), } } if k == ResourceCPU { (*out)[newer.ResourceCPU] = *resource.NewMilliQuantity(int64(fv*1000), resource.DecimalSI) } else { (*out)[newer.ResourceName(k)] = *resource.NewQuantity(int64(fv), resource.BinarySI) } } return nil }, func(in *newer.ResourceList, out *ResourceList, s conversion.Scope) error { *out = ResourceList{} for k, v := range *in { if k == newer.ResourceCPU { (*out)[ResourceCPU] = util.NewIntOrStringFromString(fmt.Sprintf("%v", float64(v.MilliValue())/1000)) } else { (*out)[ResourceName(k)] = util.NewIntOrStringFromInt(int(v.Value())) } } return nil }, // VolumeSource's HostDir is deprecated in favor of HostPath. // TODO: It would be great if I could just map field names to // convert or else maybe say "convert all members of this // struct" and then fix up only the stuff that changed. func(in *newer.VolumeSource, out *VolumeSource, s conversion.Scope) error { if err := s.Convert(&in.EmptyDir, &out.EmptyDir, 0); err != nil { return err } if err := s.Convert(&in.GitRepo, &out.GitRepo, 0); err != nil { return err } if err := s.Convert(&in.GCEPersistentDisk, &out.GCEPersistentDisk, 0); err != nil { return err } if err := s.Convert(&in.HostPath, &out.HostDir, 0); err != nil { return err } if err := s.Convert(&in.Secret, &out.Secret, 0); err != nil { return err } return nil }, func(in *VolumeSource, out *newer.VolumeSource, s conversion.Scope) error { if err := s.Convert(&in.EmptyDir, &out.EmptyDir, 0); err != nil { return err } if err := s.Convert(&in.GitRepo, &out.GitRepo, 0); err != nil { return err } if err := s.Convert(&in.GCEPersistentDisk, &out.GCEPersistentDisk, 0); err != nil { return err } if err := s.Convert(&in.HostDir, &out.HostPath, 0); err != nil { return err } if err := s.Convert(&in.Secret, &out.Secret, 0); err != nil { return err } return nil }, func(in *newer.PullPolicy, out *PullPolicy, s conversion.Scope) error { switch *in { case newer.PullAlways: *out = PullAlways case newer.PullNever: *out = PullNever case newer.PullIfNotPresent: *out = PullIfNotPresent case "": *out = "" default: // Let unknown values through - they will get caught by validation *out = PullPolicy(*in) } return nil }, func(in *PullPolicy, out *newer.PullPolicy, s conversion.Scope) error { switch *in { case PullAlways: *out = newer.PullAlways case PullNever: *out = newer.PullNever case PullIfNotPresent: *out = newer.PullIfNotPresent case "": *out = "" default: // Let unknown values through - they will get caught by validation *out = newer.PullPolicy(*in) } return nil }, func(in *newer.Probe, out *LivenessProbe, s conversion.Scope) error { if err := s.Convert(&in.Exec, &out.Exec, 0); err != nil { return err } if err := s.Convert(&in.HTTPGet, &out.HTTPGet, 0); err != nil { return err } if err := s.Convert(&in.TCPSocket, &out.TCPSocket, 0); err != nil { return err } out.InitialDelaySeconds = in.InitialDelaySeconds out.TimeoutSeconds = in.TimeoutSeconds return nil }, func(in *LivenessProbe, out *newer.Probe, s conversion.Scope) error { if err := s.Convert(&in.Exec, &out.Exec, 0); err != nil { return err } if err := s.Convert(&in.HTTPGet, &out.HTTPGet, 0); err != nil { return err } if err := s.Convert(&in.TCPSocket, &out.TCPSocket, 0); err != nil { return err } out.InitialDelaySeconds = in.InitialDelaySeconds out.TimeoutSeconds = in.TimeoutSeconds return nil }, func(in *newer.Endpoints, out *Endpoints, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.Protocol, &out.Protocol, 0); err != nil { return err } for i := range in.Endpoints { ep := &in.Endpoints[i] out.Endpoints = append(out.Endpoints, net.JoinHostPort(ep.IP, strconv.Itoa(ep.Port))) } return nil }, func(in *Endpoints, out *newer.Endpoints, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { return err } if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil { return err } if err := s.Convert(&in.Protocol, &out.Protocol, 0); err != nil { return err } for i := range in.Endpoints { out.Endpoints = append(out.Endpoints, newer.Endpoint{}) ep := &out.Endpoints[i] host, port, err := net.SplitHostPort(in.Endpoints[i]) if err != nil { return err } ep.IP = host pn, err := strconv.Atoi(port) if err != nil { return err } ep.Port = pn } return nil }, func(in *newer.NodeCondition, out *NodeCondition, s conversion.Scope) error { if err := s.Convert(&in.Type, &out.Kind, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } if err := s.Convert(&in.LastProbeTime, &out.LastProbeTime, 0); err != nil { return err } if err := s.Convert(&in.LastTransitionTime, &out.LastTransitionTime, 0); err != nil { return err } if err := s.Convert(&in.Reason, &out.Reason, 0); err != nil { return err } if err := s.Convert(&in.Message, &out.Message, 0); err != nil { return err } return nil }, func(in *NodeCondition, out *newer.NodeCondition, s conversion.Scope) error { if err := s.Convert(&in.Kind, &out.Type, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } if err := s.Convert(&in.LastProbeTime, &out.LastProbeTime, 0); err != nil { return err } if err := s.Convert(&in.LastTransitionTime, &out.LastTransitionTime, 0); err != nil { return err } if err := s.Convert(&in.Reason, &out.Reason, 0); err != nil { return err } if err := s.Convert(&in.Message, &out.Message, 0); err != nil { return err } return nil }, func(in *newer.NodeConditionType, out *NodeConditionKind, s conversion.Scope) error { switch *in { case newer.NodeReachable: *out = NodeReachable break case newer.NodeReady: *out = NodeReady break case "": *out = "" default: *out = NodeConditionKind(*in) break } return nil }, func(in *NodeConditionKind, out *newer.NodeConditionType, s conversion.Scope) error { switch *in { case NodeReachable: *out = newer.NodeReachable break case NodeReady: *out = newer.NodeReady break case "": *out = "" default: *out = newer.NodeConditionType(*in) break } return nil }, func(in *newer.PodCondition, out *PodCondition, s conversion.Scope) error { if err := s.Convert(&in.Type, &out.Kind, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } return nil }, func(in *PodCondition, out *newer.PodCondition, s conversion.Scope) error { if err := s.Convert(&in.Kind, &out.Type, 0); err != nil { return err } if err := s.Convert(&in.Status, &out.Status, 0); err != nil { return err } return nil }, func(in *newer.PodConditionType, out *PodConditionKind, s conversion.Scope) error { switch *in { case newer.PodReady: *out = PodReady break case "": *out = "" default: *out = PodConditionKind(*in) break } return nil }, func(in *PodConditionKind, out *newer.PodConditionType, s conversion.Scope) error { switch *in { case PodReady: *out = newer.PodReady break case "": *out = "" default: *out = newer.PodConditionType(*in) break } return nil }, ) if err != nil { // If one of the conversion functions is malformed, detect it immediately. panic(err) } }
labels := map[string]string{"foo": "bar"} svc1port := "svc1" svc2port := "svc2" service := &api.Service{ ObjectMeta: api.ObjectMeta{ Name: serviceName, }, Spec: api.ServiceSpec{ Selector: labels, Ports: []api.ServicePort{ { Name: "portname1", Port: 80, TargetPort: util.NewIntOrStringFromString(svc1port), }, { Name: "portname2", Port: 81, TargetPort: util.NewIntOrStringFromString(svc2port), }, }, }, } _, err := c.Services(ns).Create(service) Expect(err).NotTo(HaveOccurred()) port1 := 100 port2 := 101 validateEndpointsOrFail(c, ns, serviceName, map[string][]int{})
func TestGenerateService(t *testing.T) { tests := []struct { params map[string]string expected api.Service }{ { params: map[string]string{ "selector": "foo=bar,baz=blah", "name": "test", "port": "80", "protocol": "TCP", "container-port": "1234", }, expected: api.Service{ ObjectMeta: api.ObjectMeta{ Name: "test", }, Spec: api.ServiceSpec{ Selector: map[string]string{ "foo": "bar", "baz": "blah", }, Ports: []api.ServicePort{ { Name: "default", Port: 80, Protocol: "TCP", TargetPort: util.NewIntOrStringFromInt(1234), }, }, }, }, }, { params: map[string]string{ "selector": "foo=bar,baz=blah", "name": "test", "port": "80", "protocol": "UDP", "container-port": "foobar", }, expected: api.Service{ ObjectMeta: api.ObjectMeta{ Name: "test", }, Spec: api.ServiceSpec{ Selector: map[string]string{ "foo": "bar", "baz": "blah", }, Ports: []api.ServicePort{ { Name: "default", Port: 80, Protocol: "UDP", TargetPort: util.NewIntOrStringFromString("foobar"), }, }, }, }, }, { params: map[string]string{ "selector": "foo=bar,baz=blah", "labels": "key1=value1,key2=value2", "name": "test", "port": "80", "protocol": "TCP", "container-port": "1234", }, expected: api.Service{ ObjectMeta: api.ObjectMeta{ Name: "test", Labels: map[string]string{ "key1": "value1", "key2": "value2", }, }, Spec: api.ServiceSpec{ Selector: map[string]string{ "foo": "bar", "baz": "blah", }, Ports: []api.ServicePort{ { Name: "default", Port: 80, Protocol: "TCP", TargetPort: util.NewIntOrStringFromInt(1234), }, }, }, }, }, { params: map[string]string{ "selector": "foo=bar,baz=blah", "name": "test", "port": "80", "protocol": "UDP", "container-port": "foobar", "public-ip": "1.2.3.4", }, expected: api.Service{ ObjectMeta: api.ObjectMeta{ Name: "test", }, Spec: api.ServiceSpec{ Selector: map[string]string{ "foo": "bar", "baz": "blah", }, Ports: []api.ServicePort{ { Name: "default", Port: 80, Protocol: "UDP", TargetPort: util.NewIntOrStringFromString("foobar"), }, }, PublicIPs: []string{"1.2.3.4"}, }, }, }, { params: map[string]string{ "selector": "foo=bar,baz=blah", "name": "test", "port": "80", "protocol": "UDP", "container-port": "foobar", "public-ip": "1.2.3.4", "create-external-load-balancer": "true", }, expected: api.Service{ ObjectMeta: api.ObjectMeta{ Name: "test", }, Spec: api.ServiceSpec{ Selector: map[string]string{ "foo": "bar", "baz": "blah", }, Ports: []api.ServicePort{ { Name: "default", Port: 80, Protocol: "UDP", TargetPort: util.NewIntOrStringFromString("foobar"), }, }, PublicIPs: []string{"1.2.3.4"}, CreateExternalLoadBalancer: true, }, }, }, } generator := ServiceGenerator{} for _, test := range tests { obj, err := generator.Generate(test.params) if !reflect.DeepEqual(obj, &test.expected) { t.Errorf("expected:\n%#v\ngot\n%#v\n", &test.expected, obj) } if err != nil { t.Errorf("unexpected error: %v", err) } } }