Commit 7a7e6433 authored by Wojciech Tyczynski's avatar Wojciech Tyczynski

Kubelet file read both ContainerManifest and Pod

parent c5d8c391
...@@ -25,11 +25,13 @@ import ( ...@@ -25,11 +25,13 @@ import (
"strings" "strings"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
"github.com/GoogleCloudPlatform/kubernetes/pkg/types" "github.com/GoogleCloudPlatform/kubernetes/pkg/types"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/ghodss/yaml"
"github.com/golang/glog" "github.com/golang/glog"
) )
...@@ -120,3 +122,58 @@ func tryDecodePodList(data []byte, source string, isFile bool) (parsed bool, pod ...@@ -120,3 +122,58 @@ func tryDecodePodList(data []byte, source string, isFile bool) (parsed bool, pod
} }
return true, *newPods, err return true, *newPods, err
} }
func tryDecodeSingleManifest(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) (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
}
// Success.
return true, manifests, pods, nil
}
...@@ -18,23 +18,17 @@ limitations under the License. ...@@ -18,23 +18,17 @@ limitations under the License.
package config package config
import ( import (
"crypto/md5"
"encoding/hex"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"sort" "sort"
"strings"
"time" "time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
"github.com/GoogleCloudPlatform/kubernetes/pkg/types"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/ghodss/yaml"
"github.com/golang/glog" "github.com/golang/glog"
) )
...@@ -131,9 +125,7 @@ func extractFromDir(name string) ([]api.Pod, error) { ...@@ -131,9 +125,7 @@ func extractFromDir(name string) ([]api.Pod, error) {
return pods, nil return pods, nil
} }
func extractFromFile(filename string) (api.Pod, error) { func extractFromFile(filename string) (pod api.Pod, err error) {
var pod api.Pod
glog.V(3).Infof("Reading config file %q", filename) glog.V(3).Infof("Reading config file %q", filename)
file, err := os.Open(filename) file, err := os.Open(filename)
if err != nil { if err != nil {
...@@ -146,65 +138,28 @@ func extractFromFile(filename string) (api.Pod, error) { ...@@ -146,65 +138,28 @@ func extractFromFile(filename string) (api.Pod, error) {
return pod, err return pod, err
} }
// TODO: use api.Scheme.DecodeInto parsed, _, pod, manifestErr := tryDecodeSingleManifest(data)
// This is awful. DecodeInto() expects to find an APIObject, which if parsed {
// Manifest is not. We keep reading manifest for now for compat, but if manifestErr != nil {
// we will eventually change it to read Pod (at which point this all // It parsed but could not be used.
// becomes nicer). Until then, we assert that the ContainerManifest return pod, manifestErr
// structure on disk is always v1beta1. Read that, convert it to a }
// "current" ContainerManifest (should be ~identical), then convert // It parsed!
// that to a Pod (which is a well-understood conversion). This if err = applyDefaults(&pod, filename, true); err != nil {
// avoids writing a v1beta1.ContainerManifest -> api.Pod return pod, err
// conversion which would be identical to the api.ContainerManifest -> }
// api.Pod conversion. return pod, nil
oldManifest := &v1beta1.ContainerManifest{}
if err := yaml.Unmarshal(data, oldManifest); err != nil {
return pod, fmt.Errorf("can't unmarshal file %q: %v", filename, err)
}
newManifest := &api.ContainerManifest{}
if err := api.Scheme.Convert(oldManifest, newManifest); err != nil {
return pod, fmt.Errorf("can't convert pod from file %q: %v", filename, err)
}
if err := api.Scheme.Convert(newManifest, &pod); err != nil {
return pod, fmt.Errorf("can't convert pod from file %q: %v", filename, err)
} }
hostname, err := os.Hostname() //TODO: kubelet name would be better parsed, pod, podErr := tryDecodeSinglePod(data, filename, true)
if err != nil { if parsed {
return pod, err if podErr != nil {
} return pod, podErr
hostname = strings.ToLower(hostname) }
return pod, nil
if len(pod.UID) == 0 {
hasher := md5.New()
fmt.Fprintf(hasher, "host:%s", hostname)
fmt.Fprintf(hasher, "file:%s", filename)
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 file %s", pod.UID, pod.Name, filename)
}
// This is required for backward compatibility, and should be removed once we
// completely deprecate ContainerManifest.
if len(pod.Name) == 0 {
pod.Name = string(pod.UID)
}
if pod.Name, err = GeneratePodName(pod.Name); err != nil {
return pod, err
} }
glog.V(5).Infof("Generated Name %q for UID %q from file %s", pod.Name, pod.UID, filename)
// Always overrides the namespace provided by the file. return pod, fmt.Errorf("%v: read '%v', but couldn't parse as neither "+
pod.Namespace = kubelet.NamespaceDefault "manifest (%v) nor pod (%v).\n",
glog.V(5).Infof("Using namespace %q for pod %q from file %s", pod.Namespace, pod.Name, filename) filename, string(data), manifestErr, podErr)
// 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)
if glog.V(4) {
glog.Infof("Got pod from file %q: %#v", filename, pod)
} else {
glog.V(5).Infof("Got pod from file %q: %s.%s (%s)", filename, pod.Namespace, pod.Name, pod.UID)
}
return pod, nil
} }
...@@ -25,12 +25,9 @@ import ( ...@@ -25,12 +25,9 @@ import (
"time" "time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"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/kubelet"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/ghodss/yaml"
"github.com/golang/glog" "github.com/golang/glog"
) )
...@@ -81,7 +78,7 @@ func (s *sourceURL) extractFromURL() error { ...@@ -81,7 +78,7 @@ func (s *sourceURL) extractFromURL() error {
s.data = data s.data = data
// First try as if it's a single manifest // First try as if it's a single manifest
parsed, manifest, pod, singleErr := tryDecodeSingle(data) parsed, manifest, pod, singleErr := tryDecodeSingleManifest(data)
if parsed { if parsed {
if singleErr != nil { if singleErr != nil {
// It parsed but could not be used. // It parsed but could not be used.
...@@ -96,7 +93,7 @@ func (s *sourceURL) extractFromURL() error { ...@@ -96,7 +93,7 @@ func (s *sourceURL) extractFromURL() error {
} }
// That didn't work, so try an array of manifests. // That didn't work, so try an array of manifests.
parsed, manifests, pods, multiErr := tryDecodeList(data) parsed, manifests, pods, multiErr := tryDecodeManifestList(data)
if parsed { if parsed {
if multiErr != nil { if multiErr != nil {
// It parsed but could not be used. // It parsed but could not be used.
...@@ -151,58 +148,3 @@ func (s *sourceURL) extractFromURL() error { ...@@ -151,58 +148,3 @@ func (s *sourceURL) extractFromURL() error {
s.url, string(data), singleErr, manifest, multiErr, manifests, s.url, string(data), singleErr, manifest, multiErr, manifests,
singlePodErr, multiPodErr) singlePodErr, multiPodErr)
} }
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 tryDecodeList(data []byte) (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
}
// Success.
return true, manifests, pods, nil
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment