func validateObject(obj interface{}) (errors []error) { switch t := obj.(type) { case *api.ReplicationController: errors = validation.ValidateManifest(&t.DesiredState.PodTemplate.DesiredState.Manifest) case *api.ReplicationControllerList: for i := range t.Items { errors = append(errors, validateObject(&t.Items[i])...) } case *api.Service: errors = validation.ValidateService(t) case *api.ServiceList: for i := range t.Items { errors = append(errors, validateObject(&t.Items[i])...) } case *api.Pod: errors = validation.ValidateManifest(&t.DesiredState.Manifest) case *api.PodList: for i := range t.Items { errors = append(errors, validateObject(&t.Items[i])...) } default: return []error{fmt.Errorf("no validation defined for %#v", obj)} } return errors }
func validateObject(obj runtime.Object) (errors []error) { ctx := api.NewDefaultContext() switch t := obj.(type) { case *api.ReplicationController: errors = validation.ValidateManifest(&t.DesiredState.PodTemplate.DesiredState.Manifest) case *api.ReplicationControllerList: for i := range t.Items { errors = append(errors, validateObject(&t.Items[i])...) } case *api.Service: api.ValidNamespace(ctx, &t.ObjectMeta) errors = validation.ValidateService(t, registrytest.NewServiceRegistry(), api.NewDefaultContext()) case *api.ServiceList: for i := range t.Items { errors = append(errors, validateObject(&t.Items[i])...) } case *api.Pod: api.ValidNamespace(ctx, &t.ObjectMeta) errors = validation.ValidateManifest(&t.DesiredState.Manifest) case *api.PodList: for i := range t.Items { errors = append(errors, validateObject(&t.Items[i])...) } default: return []error{fmt.Errorf("no validation defined for %#v", obj)} } return errors }
func tryDecodeSingle(data []byte) (parsed bool, manifest v1beta1.ContainerManifest, pod api.Pod, err error) { // TODO: should be api.Scheme.Decode // This is awful. DecodeInto() expects to find an APIObject, which // Manifest is not. We keep reading manifest for now for compat, but // we will eventually change it to read Pod (at which point this all // becomes nicer). Until then, we assert that the ContainerManifest // structure on disk is always v1beta1. Read that, convert it to a // "current" ContainerManifest (should be ~identical), then convert // that to a Pod (which is a well-understood conversion). This // avoids writing a v1beta1.ContainerManifest -> api.Pod // conversion which would be identical to the api.ContainerManifest -> // api.Pod conversion. if err = yaml.Unmarshal(data, &manifest); err != nil { return false, manifest, pod, err } newManifest := api.ContainerManifest{} if err = api.Scheme.Convert(&manifest, &newManifest); err != nil { return false, manifest, pod, err } if errs := validation.ValidateManifest(&newManifest); len(errs) > 0 { err = fmt.Errorf("invalid manifest: %v", errs) return false, manifest, pod, err } if err = api.Scheme.Convert(&newManifest, &pod); err != nil { return true, manifest, pod, err } // Success. return true, manifest, pod, nil }
func tryDecodeManifestList(data []byte, defaultFn defaultFunc) (parsed bool, manifests []v1beta1.ContainerManifest, pods api.PodList, err error) { // TODO: should be api.Scheme.Decode // See the comment in tryDecodeSingle(). if err = yaml.Unmarshal(data, &manifests); err != nil { return false, manifests, pods, err } newManifests := []api.ContainerManifest{} if err = api.Scheme.Convert(&manifests, &newManifests); err != nil { return false, manifests, pods, err } for i := range newManifests { manifest := &newManifests[i] if errs := validation.ValidateManifest(manifest); len(errs) > 0 { err = fmt.Errorf("invalid manifest: %v", errs) return false, manifests, pods, err } } list := api.ContainerManifestList{Items: newManifests} if err = api.Scheme.Convert(&list, &pods); err != nil { return true, manifests, pods, err } for i := range pods.Items { pod := &pods.Items[i] if err := defaultFn(pod); err != nil { return true, manifests, pods, err } } // Success. return true, manifests, pods, nil }
func ValidatePod(pod *Pod) (errors []error) { if !util.IsDNSSubdomain(pod.Name) { errors = append(errors, apierrs.NewFieldInvalid("name", pod.Name)) } if errs := validation.ValidateManifest(&pod.Manifest); len(errs) != 0 { errors = append(errors, errs...) } return errors }
func (s *sourceURL) extractFromURL() error { resp, err := http.Get(s.url) if err != nil { return err } defer resp.Body.Close() data, err := ioutil.ReadAll(resp.Body) if err != nil { return err } if resp.StatusCode != 200 { return fmt.Errorf("%v: %v", s.url, resp.Status) } if len(data) == 0 { // Emit an update with an empty PodList to allow HTTPSource to be marked as seen s.updates <- kubelet.PodUpdate{[]api.BoundPod{}, kubelet.SET, kubelet.HTTPSource} return fmt.Errorf("zero-length data received from %v", s.url) } // Short circuit if the manifest has not changed since the last time it was read. if bytes.Compare(data, s.data) == 0 { return nil } s.data = data // First try as if it's a single manifest var manifest api.ContainerManifest // TODO: should be api.Scheme.Decode singleErr := yaml.Unmarshal(data, &manifest) if singleErr == nil { if errs := validation.ValidateManifest(&manifest); len(errs) > 0 { singleErr = fmt.Errorf("invalid manifest: %v", errs) } } if singleErr == nil { pod := api.BoundPod{} if err := api.Scheme.Convert(&manifest, &pod); err != nil { return err } applyDefaults(&pod, s.url) s.updates <- kubelet.PodUpdate{[]api.BoundPod{pod}, kubelet.SET, kubelet.HTTPSource} return nil } // That didn't work, so try an array of manifests. var manifests []api.ContainerManifest // TODO: should be api.Scheme.Decode multiErr := yaml.Unmarshal(data, &manifests) // We're not sure if the person reading the logs is going to care about the single or // multiple manifest unmarshalling attempt, so we need to put both in the logs, as is // done at the end. Hence not returning early here. if multiErr == nil { for _, manifest := range manifests { if errs := validation.ValidateManifest(&manifest); len(errs) > 0 { multiErr = fmt.Errorf("invalid manifest: %v", errs) break } } } if multiErr == nil { // A single manifest that did not pass semantic validation will yield an empty // array of manifests (and no error) when unmarshaled as such. In that case, // if the single manifest at least had a Version, we return the single-manifest // error (if any). if len(manifests) == 0 && len(manifest.Version) != 0 { return singleErr } list := api.ContainerManifestList{Items: manifests} boundPods := &api.BoundPods{} if err := api.Scheme.Convert(&list, boundPods); err != nil { return err } for i := range boundPods.Items { pod := &boundPods.Items[i] applyDefaults(pod, s.url) } s.updates <- kubelet.PodUpdate{boundPods.Items, kubelet.SET, kubelet.HTTPSource} return nil } return fmt.Errorf("%v: received '%v', but couldn't parse as a "+ "single manifest (%v: %+v) or as multiple manifests (%v: %+v).\n", s.url, string(data), singleErr, manifest, multiErr, manifests) }
func (s *SourceURL) extractFromURL() error { resp, err := http.Get(s.url) if err != nil { return err } defer resp.Body.Close() data, err := ioutil.ReadAll(resp.Body) if err != nil { return err } if resp.StatusCode != 200 { return fmt.Errorf("%v: %v", s.url, resp.Status) } if len(data) == 0 { return fmt.Errorf("zero-length data received from %v", s.url) } // First try as if it's a single manifest var manifest api.ContainerManifest singleErr := yaml.Unmarshal(data, &manifest) if singleErr == nil { if errs := validation.ValidateManifest(&manifest); len(errs) > 0 { singleErr = fmt.Errorf("invalid manifest: %v", errs) } } if singleErr == nil { pod := kubelet.Pod{Name: manifest.ID, Manifest: manifest} if pod.Name == "" { pod.Name = "1" } s.updates <- kubelet.PodUpdate{[]kubelet.Pod{pod}, kubelet.SET} return nil } // That didn't work, so try an array of manifests. var manifests []api.ContainerManifest multiErr := yaml.Unmarshal(data, &manifests) // We're not sure if the person reading the logs is going to care about the single or // multiple manifest unmarshalling attempt, so we need to put both in the logs, as is // done at the end. Hence not returning early here. if multiErr == nil { for _, manifest := range manifests { if errs := validation.ValidateManifest(&manifest); len(errs) > 0 { multiErr = fmt.Errorf("invalid manifest: %v", errs) break } } } if multiErr == nil { pods := []kubelet.Pod{} for i, manifest := range manifests { pod := kubelet.Pod{Name: manifest.ID, Manifest: manifest} if pod.Name == "" { pod.Name = fmt.Sprintf("%d", i+1) } pods = append(pods, pod) } s.updates <- kubelet.PodUpdate{pods, kubelet.SET} return nil } return fmt.Errorf("%v: received '%v', but couldn't parse as a "+ "single manifest (%v: %+v) or as multiple manifests (%v: %+v).\n", s.url, string(data), singleErr, manifest, multiErr, manifests) }