diff --git a/pkg/kubelet/config/common.go b/pkg/kubelet/config/common.go new file mode 100644 index 0000000000000..beae2d552d4dd --- /dev/null +++ b/pkg/kubelet/config/common.go @@ -0,0 +1,122 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Common logic used by both http and file channels. +package config + +import ( + "crypto/md5" + "encoding/hex" + "fmt" + "os" + "strings" + + "github.com/GoogleCloudPlatform/kubernetes/pkg/api" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet" + "github.com/GoogleCloudPlatform/kubernetes/pkg/types" + "github.com/GoogleCloudPlatform/kubernetes/pkg/util" + + "github.com/golang/glog" +) + +func applyDefaults(pod *api.Pod, source string, isFile bool) error { + if len(pod.UID) == 0 { + hasher := md5.New() + if isFile { + hostname, err := os.Hostname() // TODO: kubelet name would be better + if err != nil { + return err + } + hostname = strings.ToLower(hostname) + fmt.Fprintf(hasher, "host:%s", hostname) + fmt.Fprintf(hasher, "file:%s", source) + } else { + fmt.Fprintf(hasher, "url:%s", source) + } + util.DeepHashObject(hasher, pod) + pod.UID = types.UID(hex.EncodeToString(hasher.Sum(nil)[0:])) + glog.V(5).Infof("Generated UID %q pod %q from %s", pod.UID, pod.Name, source) + } + + // This is required for backward compatibility, and should be removed once we + // completely deprecate ContainerManifest. + var err error + if len(pod.Name) == 0 { + pod.Name = string(pod.UID) + } + if pod.Name, err = GeneratePodName(pod.Name); err != nil { + return err + } + glog.V(5).Infof("Generated Name %q for UID %q from URL %s", pod.Name, pod.UID, source) + + if pod.Namespace == "" { + pod.Namespace = kubelet.NamespaceDefault + } + glog.V(5).Infof("Using namespace %q for pod %q from %s", pod.Namespace, pod.Name, source) + + // Currently just simply follow the same format in resthandler.go + pod.ObjectMeta.SelfLink = + fmt.Sprintf("/api/v1beta2/pods/%s?namespace=%s", pod.Name, pod.Namespace) + return nil +} + +func tryDecodeSinglePod(data []byte, source string, isFile bool) (parsed bool, pod api.Pod, err error) { + obj, err := api.Scheme.Decode(data) + if err != nil { + return false, pod, err + } + // Check whether the object could be converted to single pod. + if _, ok := obj.(*api.Pod); !ok { + err = fmt.Errorf("invalid pod: %+v", obj) + return false, pod, err + } + newPod := obj.(*api.Pod) + // Apply default values and validate the pod. + if err = applyDefaults(newPod, source, isFile); err != nil { + return true, pod, err + } + if errs := validation.ValidatePod(newPod); len(errs) > 0 { + err = fmt.Errorf("invalid pod: %v", errs) + return true, pod, err + } + return true, *newPod, nil +} + +func tryDecodePodList(data []byte, source string, isFile bool) (parsed bool, pods api.PodList, err error) { + obj, err := api.Scheme.Decode(data) + if err != nil { + return false, pods, err + } + // Check whether the object could be converted to list of pods. + if _, ok := obj.(*api.PodList); !ok { + err = fmt.Errorf("invalid pods list: %+v", obj) + return false, pods, err + } + newPods := obj.(*api.PodList) + // Apply default values and validate pods. + for i := range newPods.Items { + newPod := &newPods.Items[i] + if err = applyDefaults(newPod, source, isFile); err != nil { + return true, pods, err + } + if errs := validation.ValidatePod(newPod); len(errs) > 0 { + err = fmt.Errorf("invalid pod: %v", errs) + return true, pods, err + } + } + return true, *newPods, err +} diff --git a/pkg/kubelet/config/http.go b/pkg/kubelet/config/http.go index 68d6e807d287e..fb573f35387e4 100644 --- a/pkg/kubelet/config/http.go +++ b/pkg/kubelet/config/http.go @@ -19,8 +19,6 @@ package config import ( "bytes" - "crypto/md5" - "encoding/hex" "fmt" "io/ioutil" "net/http" @@ -30,7 +28,6 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet" - "github.com/GoogleCloudPlatform/kubernetes/pkg/types" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/ghodss/yaml" @@ -91,7 +88,7 @@ func (s *sourceURL) extractFromURL() error { return singleErr } // It parsed! - if err = applyDefaults(&pod, s.url); err != nil { + if err = applyDefaults(&pod, s.url, false); err != nil { return err } s.updates <- kubelet.PodUpdate{[]api.Pod{pod}, kubelet.SET, kubelet.HTTPSource} @@ -115,7 +112,7 @@ func (s *sourceURL) extractFromURL() error { // Assume it parsed. for i := range pods.Items { pod := &pods.Items[i] - if err = applyDefaults(pod, s.url); err != nil { + if err = applyDefaults(pod, s.url, false); err != nil { return err } } @@ -127,7 +124,7 @@ func (s *sourceURL) extractFromURL() error { // Try to parse it as Pod(s). // First try as it is a single pod. - parsed, pod, singlePodErr := tryDecodeSinglePod(data, s.url) + parsed, pod, singlePodErr := tryDecodeSinglePod(data, s.url, false) if parsed { if singlePodErr != nil { // It parsed but could not be used. @@ -138,7 +135,7 @@ func (s *sourceURL) extractFromURL() error { } // That didn't work, so try a list of pods. - parsed, pods, multiPodErr := tryDecodePodList(data, s.url) + parsed, pods, multiPodErr := tryDecodePodList(data, s.url, false) if parsed { if multiPodErr != nil { // It parsed but could not be used. @@ -209,79 +206,3 @@ func tryDecodeList(data []byte) (parsed bool, manifests []v1beta1.ContainerManif // Success. return true, manifests, pods, nil } - -func tryDecodeSinglePod(data []byte, url string) (parsed bool, pod api.Pod, err error) { - obj, err := api.Scheme.Decode(data) - if err != nil { - return false, pod, err - } - // Check whether the object could be converted to single pod. - if _, ok := obj.(*api.Pod); !ok { - err = fmt.Errorf("invalid pod: %+v", obj) - return false, pod, err - } - newPod := obj.(*api.Pod) - // Apply default values and validate the pod. - if err = applyDefaults(newPod, url); err != nil { - return true, pod, err - } - if errs := validation.ValidatePod(newPod); len(errs) > 0 { - err = fmt.Errorf("invalid pod: %v", errs) - return true, pod, err - } - return true, *newPod, nil -} - -func tryDecodePodList(data []byte, url string) (parsed bool, pods api.PodList, err error) { - obj, err := api.Scheme.Decode(data) - if err != nil { - return false, pods, err - } - // Check whether the object could be converted to list of pods. - if _, ok := obj.(*api.PodList); !ok { - err = fmt.Errorf("invalid pods list: %+v", obj) - return false, pods, err - } - newPods := obj.(*api.PodList) - // Apply default values and validate pods. - for i := range newPods.Items { - newPod := &newPods.Items[i] - if err = applyDefaults(newPod, url); err != nil { - return true, pods, err - } - if errs := validation.ValidatePod(newPod); len(errs) > 0 { - err = fmt.Errorf("invalid pod: %v", errs) - return true, pods, err - } - } - return true, *newPods, err -} - -func applyDefaults(pod *api.Pod, url string) error { - if len(pod.UID) == 0 { - hasher := md5.New() - fmt.Fprintf(hasher, "url:%s", url) - util.DeepHashObject(hasher, pod) - pod.UID = types.UID(hex.EncodeToString(hasher.Sum(nil)[0:])) - glog.V(5).Infof("Generated UID %q for pod %q from URL %s", pod.UID, pod.Name, url) - } - // This is required for backward compatibility, and should be removed once we - // completely deprecate ContainerManifest. - var err error - if len(pod.Name) == 0 { - pod.Name = string(pod.UID) - } - pod.Name, err = GeneratePodName(pod.Name) - if err != nil { - return err - } - glog.V(5).Infof("Generated Name %q for UID %q from URL %s", pod.Name, pod.UID, url) - - if pod.Namespace == "" { - pod.Namespace = kubelet.NamespaceDefault - } - glog.V(5).Infof("Using namespace %q for pod %q from URL %s", pod.Namespace, pod.Name, url) - pod.ObjectMeta.SelfLink = fmt.Sprintf("/api/v1beta2/pods/%s?namespace=%s", - pod.Name, pod.Namespace) - return nil -}