From f40a471efd1daa8d81967b5a9b17737fe71e76ff Mon Sep 17 00:00:00 2001 From: Tamer Tas Date: Tue, 2 Aug 2016 16:47:56 +0300 Subject: [PATCH 1/3] Add the ContainerRuntime interface stub for rkt app level API --- pkg/kubelet/rktshim/app-interface.go | 71 ++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 pkg/kubelet/rktshim/app-interface.go diff --git a/pkg/kubelet/rktshim/app-interface.go b/pkg/kubelet/rktshim/app-interface.go new file mode 100644 index 00000000000..cb45a7ba731 --- /dev/null +++ b/pkg/kubelet/rktshim/app-interface.go @@ -0,0 +1,71 @@ +/* +Copyright 2016 The Kubernetes Authors. + +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. +*/ + +package rktshim + +import ( + "io" + + kubeletApi "k8s.io/kubernetes/pkg/kubelet/api" + runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" +) + +// Runtime provides an API for lifecycle, inspection and introspection +// operations in a blocking manner using the App level API provided by rkt. +type Runtime struct{} + +// TODO(tmrts): Fill out the creation configuration fields. +type RuntimeConfig struct{} + +// NewRuntime creates a container.Runtime instance using the Runtime. +func NewRuntime(RuntimeConfig) (kubeletApi.ContainerManager, error) { + return &Runtime{}, nil +} + +// CreateContainer creates an app inside the provided pod sandbox and returns the RawContainerID. +func (*Runtime) CreateContainer(string, *runtimeApi.ContainerConfig, *runtimeApi.PodSandboxConfig) (string, error) { + panic("not implemented") +} + +// StartContainer starts a created app. +func (*Runtime) StartContainer(string) error { + panic("not implemented") +} + +// StopContainer stops a running app with a grace period (i.e. timeout). +func (*Runtime) StopContainer(string, int64) error { + panic("not implemented") +} + +// RemoveContainer removes the app from a pod sandbox. +func (*Runtime) RemoveContainer(string) error { + panic("not implemented") +} + +// ListContainers lists out the apps residing inside the pod sandbox using the ContainerFilter. +func (*Runtime) ListContainers(*runtimeApi.ContainerFilter) ([]*runtimeApi.Container, error) { + panic("not implemented") +} + +// ContainerStatus returns the RawContainerStatus of an app inside the pod sandbox. +func (*Runtime) ContainerStatus(string) (*runtimeApi.ContainerStatus, error) { + panic("not implemented") +} + +// Exec executes a command inside an app running inside a pod sanbox. +func (*Runtime) Exec(string, []string, bool, io.Reader, io.WriteCloser, io.WriteCloser) error { + panic("not implemented") +} From dcc8e9d4de23be2b9b6f323d8965f3510fc0b4d6 Mon Sep 17 00:00:00 2001 From: Tamer Tas Date: Tue, 2 Aug 2016 18:39:53 +0300 Subject: [PATCH 2/3] Add a fake rkt app-level API to rktshim pkg --- pkg/kubelet/rktshim/fake-app-interface.go | 215 ++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 pkg/kubelet/rktshim/fake-app-interface.go diff --git a/pkg/kubelet/rktshim/fake-app-interface.go b/pkg/kubelet/rktshim/fake-app-interface.go new file mode 100644 index 00000000000..7176d513920 --- /dev/null +++ b/pkg/kubelet/rktshim/fake-app-interface.go @@ -0,0 +1,215 @@ +/* +Copyright 2016 The Kubernetes Authors. + +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. +*/ + +package rktshim + +import ( + "errors" + "io" + "math/rand" + "time" + + kubeletApi "k8s.io/kubernetes/pkg/kubelet/api" + runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" +) + +func init() { + // Don't randomize due to testing purposes + // rand.Seed(time.Now().UnixNano()) +} + +func randString(n int) string { + runeAlphabet := []rune("abcdefghijklmnopqrstuvwxyz") + dictLen := len(runeAlphabet) + + buf := make([]rune, n) + for i := range buf { + buf[i] = runeAlphabet[rand.Intn(dictLen)] + } + + return string(buf) +} + +var ( + ErrContainerNotFound = errors.New("rktshim: container not found") + ErrInvalidContainerStateTransition = errors.New("rktshim: wrong container operation for current state") +) + +type FakeRuntime struct { + Containers containerRegistry +} + +type FakeRuntimeConfig struct{} + +func NewFakeRuntime() (kubeletApi.ContainerManager, error) { + return &FakeRuntime{Containers: make(containerRegistry)}, nil +} + +type characterStreams struct { + In io.Reader + Out io.Writer + Err io.Writer +} + +func newCharacterStreams(in io.Reader, out io.Writer, err io.Writer) characterStreams { + std := characterStreams{in, out, err} + + return std +} + +type fakeContainer struct { + Config *runtimeApi.ContainerConfig + + Status runtimeApi.ContainerStatus + + State runtimeApi.ContainerState + + Streams characterStreams +} + +func (c *fakeContainer) Start() { + c.State = runtimeApi.ContainerState_RUNNING + + c.Status.State = &c.State +} + +func (c *fakeContainer) Stop() { + c.State = runtimeApi.ContainerState_EXITED + + c.Status.State = &c.State + + exitSuccess := int32(0) + c.Status.ExitCode = &exitSuccess + + // c.Status.Reason +} + +func (c *fakeContainer) Exec(cmd []string, in io.Reader, out, err io.WriteCloser) error { + // TODO(tmrts): incomplete command execution logic + // c.StreamCompare(c.Streams.In, s.InputStream) + // c.StreamFlush(c.Streams.Out, s.OutputStream) + // c.StreamFlush(c.Streams.Err, s.ErrorStream) + + return nil +} + +type containerRegistry map[string]*fakeContainer + +func (r *FakeRuntime) CreateContainer(pid string, cfg *runtimeApi.ContainerConfig, sandboxCfg *runtimeApi.PodSandboxConfig) (string, error) { + // TODO(tmrts): allow customization + containerIDLength := 8 + + cid := randString(containerIDLength) + + r.Containers[cid] = &fakeContainer{ + Config: cfg, + Streams: newCharacterStreams(nil, nil, nil), + } + + return cid, nil +} + +func (r *FakeRuntime) StartContainer(id string) error { + c, ok := r.Containers[id] + if !ok { + return ErrContainerNotFound + } + switch c.State { + case runtimeApi.ContainerState_EXITED: + fallthrough + case runtimeApi.ContainerState_CREATED: + c.Start() + case runtimeApi.ContainerState_UNKNOWN: + // TODO(tmrts): add timeout to Start API or generalize timeout somehow + //<-time.After(time.Duration(timeout) * time.Second) + fallthrough + default: + return ErrInvalidContainerStateTransition + } + + return nil +} + +func (r *FakeRuntime) StopContainer(id string, timeout int64) error { + c, ok := r.Containers[id] + if !ok { + return ErrContainerNotFound + } + + switch c.State { + case runtimeApi.ContainerState_RUNNING: + c.State = runtimeApi.ContainerState_EXITED // This state might not be the best one + case runtimeApi.ContainerState_UNKNOWN: + <-time.After(time.Duration(timeout) * time.Second) + fallthrough + default: + return ErrInvalidContainerStateTransition + } + + return nil +} + +func (r *FakeRuntime) RemoveContainer(id string) error { + _, ok := r.Containers[id] + if !ok { + return ErrContainerNotFound + } + + // Remove regardless of the container state + delete(r.Containers, id) + + return nil +} + +func (r *FakeRuntime) ListContainers(*runtimeApi.ContainerFilter) ([]*runtimeApi.Container, error) { + list := []*runtimeApi.Container{} + + // TODO(tmrts): apply the filter + for _, c := range r.Containers { + list = append(list, &runtimeApi.Container{ + Id: c.Status.Id, + Name: c.Config.Name, + Labels: c.Config.Labels, + ImageRef: c.Status.ImageRef, + State: &c.State, + }) + } + + return list, nil +} + +func (r *FakeRuntime) ContainerStatus(id string) (*runtimeApi.ContainerStatus, error) { + c, ok := r.Containers[id] + if !ok { + return &runtimeApi.ContainerStatus{}, ErrContainerNotFound + } + + return &c.Status, nil +} + +func (r *FakeRuntime) Exec(id string, cmd []string, tty bool, in io.Reader, out, err io.WriteCloser) error { + c, ok := r.Containers[id] + if !ok { + return ErrContainerNotFound + } + + // TODO(tmrts): Validate the assumption that container has to be running for exec to work. + if c.State != runtimeApi.ContainerState_RUNNING { + return ErrInvalidContainerStateTransition + } + + return c.Exec(cmd, in, out, err) +} From f82a41b3296af9e8324e3413d02782fee4a46b11 Mon Sep 17 00:00:00 2001 From: Tamer Tas Date: Tue, 2 Aug 2016 18:45:41 +0300 Subject: [PATCH 3/3] Create a stub PodSandboxManager for rkt --- pkg/kubelet/rktshim/pod-level-interface.go | 59 ++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 pkg/kubelet/rktshim/pod-level-interface.go diff --git a/pkg/kubelet/rktshim/pod-level-interface.go b/pkg/kubelet/rktshim/pod-level-interface.go new file mode 100644 index 00000000000..f78126b5907 --- /dev/null +++ b/pkg/kubelet/rktshim/pod-level-interface.go @@ -0,0 +1,59 @@ +/* +Copyright 2016 The Kubernetes Authors. + +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. +*/ + +package rktshim + +import ( + kubeletApi "k8s.io/kubernetes/pkg/kubelet/api" + runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" +) + +// PodSandboxManager provides basic operations to create/delete and examine +// the pod sandboxes in a blocking manner. +type PodSandboxManager struct{} + +// TODO(tmrts): Fill the configuration struct fields. +type PodSandboxManagerConfig struct{} + +// NewPodSandboxManager creates a PodSandboxManager. +func NewPodSandboxManager(PodSandboxManagerConfig) (kubeletApi.PodSandboxManager, error) { + return &PodSandboxManager{}, nil +} + +// CreatePodSandbox creates a pod sandbox given a pod sandbox configuration. +func (*PodSandboxManager) CreatePodSandbox(*runtimeApi.PodSandboxConfig) (string, error) { + panic("not implemented") +} + +// StopPodSandbox stops a pod sandbox and the apps inside the sandbox. +func (*PodSandboxManager) StopPodSandbox(string) error { + panic("not implemented") +} + +// RemovePodSandbox deletes the pod sandbox and the apps inside the sandbox. +func (*PodSandboxManager) RemovePodSandbox(string) error { + panic("not implemented") +} + +// PodSandboxStatus queries the status of the pod sandbox. +func (*PodSandboxManager) PodSandboxStatus(string) (*runtimeApi.PodSandboxStatus, error) { + panic("not implemented") +} + +// ListPodSandbox lists existing sandboxes, filtered by the PodSandboxFilter. +func (*PodSandboxManager) ListPodSandbox(*runtimeApi.PodSandboxFilter) ([]*runtimeApi.PodSandbox, error) { + panic("not implemented") +}