mirror of https://github.com/k3s-io/k3s
More Task -> Pod
parent
4bd809e11e
commit
66e2575f2b
|
@ -2,7 +2,7 @@
|
|||
"$schema": "http://json-schema.org/draft-03/schema",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"description": "A replicationController resource. A replicationController helps to create and manage a set of tasks. It acts as a factory to create new tasks based on a template. It ensures that there are a specific number of tasks running. If fewer tasks are running than `replicas` then the needed tasks are generated using `taskTemplate`. If more tasks are running than `replicas`, then excess tasks are deleted.",
|
||||
"description": "A replicationController resource. A replicationController helps to create and manage a set of tasks. It acts as a factory to create new tasks based on a template. It ensures that there are a specific number of tasks running. If fewer tasks are running than `replicas` then the needed tasks are generated using `podTemplate`. If more tasks are running than `replicas`, then excess tasks are deleted.",
|
||||
"properties": {
|
||||
"kind": {
|
||||
"type": "string",
|
||||
|
@ -35,7 +35,7 @@
|
|||
"required": false,
|
||||
"description": "Required labels used to identify tasks in the set"
|
||||
},
|
||||
"taskTemplate": {
|
||||
"podTemplate": {
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"description": "Template from which to create new tasks, as necessary. Identical to task schema."
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
"replicasInSet": {
|
||||
"name": "testRun"
|
||||
},
|
||||
"taskTemplate": {
|
||||
"podTemplate": {
|
||||
"desiredState": {
|
||||
"image": "dockerfile/nginx",
|
||||
"networkPorts": [
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"desiredState": {
|
||||
"replicas": 2,
|
||||
"replicasInSet": {"name": "nginx"},
|
||||
"taskTemplate": {
|
||||
"podTemplate": {
|
||||
"desiredState": {
|
||||
"manifest": {
|
||||
"containers": [{
|
||||
|
|
|
@ -52,7 +52,7 @@ func main() {
|
|||
}
|
||||
|
||||
var (
|
||||
taskRegistry registry.TaskRegistry
|
||||
podRegistry registry.PodRegistry
|
||||
controllerRegistry registry.ControllerRegistry
|
||||
serviceRegistry registry.ServiceRegistry
|
||||
)
|
||||
|
@ -60,11 +60,11 @@ func main() {
|
|||
if len(etcdServerList) > 0 {
|
||||
log.Printf("Creating etcd client pointing to %v", etcdServerList)
|
||||
etcdClient := etcd.NewClient(etcdServerList)
|
||||
taskRegistry = registry.MakeEtcdRegistry(etcdClient, machineList)
|
||||
podRegistry = registry.MakeEtcdRegistry(etcdClient, machineList)
|
||||
controllerRegistry = registry.MakeEtcdRegistry(etcdClient, machineList)
|
||||
serviceRegistry = registry.MakeEtcdRegistry(etcdClient, machineList)
|
||||
} else {
|
||||
taskRegistry = registry.MakeMemoryRegistry()
|
||||
podRegistry = registry.MakeMemoryRegistry()
|
||||
controllerRegistry = registry.MakeMemoryRegistry()
|
||||
serviceRegistry = registry.MakeMemoryRegistry()
|
||||
}
|
||||
|
@ -75,12 +75,12 @@ func main() {
|
|||
}
|
||||
|
||||
storage := map[string]apiserver.RESTStorage{
|
||||
"tasks": registry.MakeTaskRegistryStorage(taskRegistry, containerInfo, registry.MakeFirstFitScheduler(machineList, taskRegistry)),
|
||||
"tasks": registry.MakeTaskRegistryStorage(podRegistry, containerInfo, registry.MakeFirstFitScheduler(machineList, podRegistry)),
|
||||
"replicationControllers": registry.MakeControllerRegistryStorage(controllerRegistry),
|
||||
"services": registry.MakeServiceRegistryStorage(serviceRegistry),
|
||||
}
|
||||
|
||||
endpoints := registry.MakeEndpointController(serviceRegistry, taskRegistry)
|
||||
endpoints := registry.MakeEndpointController(serviceRegistry, podRegistry)
|
||||
go util.Forever(func() { endpoints.SyncServiceEndpoints() }, time.Second*10)
|
||||
|
||||
s := &http.Server{
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"desiredState": {
|
||||
"replicas": 3,
|
||||
"replicasInSet": {"name": "frontend"},
|
||||
"taskTemplate": {
|
||||
"podTemplate": {
|
||||
"desiredState": {
|
||||
"manifest": {
|
||||
"containers": [{
|
||||
|
|
|
@ -82,7 +82,7 @@ Although the redis master is a single task, the redis read slaves are a 'replica
|
|||
"desiredState": {
|
||||
"replicas": 2,
|
||||
"replicasInSet": {"name": "redis-slave"},
|
||||
"taskTemplate": {
|
||||
"podTemplate": {
|
||||
"desiredState": {
|
||||
"manifest": {
|
||||
"containers": [{
|
||||
|
@ -149,7 +149,7 @@ This is a simple PHP server that is configured to talk to both the slave and mas
|
|||
"desiredState": {
|
||||
"replicas": 3,
|
||||
"replicasInSet": {"name": "frontend"},
|
||||
"taskTemplate": {
|
||||
"podTemplate": {
|
||||
"desiredState": {
|
||||
"manifest": {
|
||||
"containers": [{
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"desiredState": {
|
||||
"replicas": 2,
|
||||
"replicasInSet": {"name": "redisslave"},
|
||||
"taskTemplate": {
|
||||
"podTemplate": {
|
||||
"desiredState": {
|
||||
"manifest": {
|
||||
"containers": [{
|
||||
|
|
|
@ -81,8 +81,8 @@ type JSONBase struct {
|
|||
SelfLink string `json:"selfLink,omitempty" yaml:"selfLink,omitempty"`
|
||||
}
|
||||
|
||||
// TaskState is the state of a task, used as either input (desired state) or output (current state)
|
||||
type TaskState struct {
|
||||
// PodState is the state of a pod, used as either input (desired state) or output (current state)
|
||||
type PodState struct {
|
||||
Manifest ContainerManifest `json:"manifest,omitempty" yaml:"manifest,omitempty"`
|
||||
Status string `json:"status,omitempty" yaml:"status,omitempty"`
|
||||
Host string `json:"host,omitempty" yaml:"host,omitempty"`
|
||||
|
@ -90,24 +90,24 @@ type TaskState struct {
|
|||
Info interface{} `json:"info,omitempty" yaml:"info,omitempty"`
|
||||
}
|
||||
|
||||
type TaskList struct {
|
||||
type PodList struct {
|
||||
JSONBase
|
||||
Items []Pod `json:"items" yaml:"items,omitempty"`
|
||||
}
|
||||
|
||||
// Task is a single task, used as either input (create, update) or as output (list, get)
|
||||
// Pod is a collection of containers, used as either input (create, update) or as output (list, get)
|
||||
type Pod struct {
|
||||
JSONBase
|
||||
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
|
||||
DesiredState TaskState `json:"desiredState,omitempty" yaml:"desiredState,omitempty"`
|
||||
CurrentState TaskState `json:"currentState,omitempty" yaml:"currentState,omitempty"`
|
||||
DesiredState PodState `json:"desiredState,omitempty" yaml:"desiredState,omitempty"`
|
||||
CurrentState PodState `json:"currentState,omitempty" yaml:"currentState,omitempty"`
|
||||
}
|
||||
|
||||
// ReplicationControllerState is the state of a replication controller, either input (create, update) or as output (list, get)
|
||||
type ReplicationControllerState struct {
|
||||
Replicas int `json:"replicas" yaml:"replicas"`
|
||||
ReplicasInSet map[string]string `json:"replicasInSet,omitempty" yaml:"replicasInSet,omitempty"`
|
||||
TaskTemplate TaskTemplate `json:"taskTemplate,omitempty" yaml:"taskTemplate,omitempty"`
|
||||
PodTemplate PodTemplate `json:"podTemplate,omitempty" yaml:"podTemplate,omitempty"`
|
||||
}
|
||||
|
||||
type ReplicationControllerList struct {
|
||||
|
@ -122,9 +122,9 @@ type ReplicationController struct {
|
|||
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
|
||||
}
|
||||
|
||||
// TaskTemplate holds the information used for creating tasks
|
||||
type TaskTemplate struct {
|
||||
DesiredState TaskState `json:"desiredState,omitempty" yaml:"desiredState,omitempty"`
|
||||
// PodTemplate holds the information used for creating pods
|
||||
type PodTemplate struct {
|
||||
DesiredState PodState `json:"desiredState,omitempty" yaml:"desiredState,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ import (
|
|||
|
||||
// ClientInterface holds the methods for clients of Kubenetes, an interface to allow mock testing
|
||||
type ClientInterface interface {
|
||||
ListTasks(labelQuery map[string]string) (api.TaskList, error)
|
||||
ListTasks(labelQuery map[string]string) (api.PodList, error)
|
||||
GetTask(name string) (api.Pod, error)
|
||||
DeleteTask(name string) error
|
||||
CreateTask(api.Pod) (api.Pod, error)
|
||||
|
@ -143,12 +143,12 @@ func DecodeLabelQuery(labelQuery string) map[string]string {
|
|||
}
|
||||
|
||||
// ListTasks takes a label query, and returns the list of tasks that match that query
|
||||
func (client Client) ListTasks(labelQuery map[string]string) (api.TaskList, error) {
|
||||
func (client Client) ListTasks(labelQuery map[string]string) (api.PodList, error) {
|
||||
path := "tasks"
|
||||
if labelQuery != nil && len(labelQuery) > 0 {
|
||||
path += "?labels=" + EncodeLabelQuery(labelQuery)
|
||||
}
|
||||
var result api.TaskList
|
||||
var result api.PodList
|
||||
_, err := client.rawRequest("GET", path, nil, &result)
|
||||
return result, err
|
||||
}
|
||||
|
|
|
@ -61,10 +61,10 @@ func TestListEmptyTasks(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestListTasks(t *testing.T) {
|
||||
expectedTaskList := api.TaskList{
|
||||
expectedTaskList := api.PodList{
|
||||
Items: []api.Pod{
|
||||
api.Pod{
|
||||
CurrentState: api.TaskState{
|
||||
CurrentState: api.PodState{
|
||||
Status: "Foobar",
|
||||
},
|
||||
Labels: map[string]string{
|
||||
|
@ -95,10 +95,10 @@ func TestListTasks(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestListTasksLabels(t *testing.T) {
|
||||
expectedTaskList := api.TaskList{
|
||||
expectedTaskList := api.PodList{
|
||||
Items: []api.Pod{
|
||||
api.Pod{
|
||||
CurrentState: api.TaskState{
|
||||
CurrentState: api.PodState{
|
||||
Status: "Foobar",
|
||||
},
|
||||
Labels: map[string]string{
|
||||
|
@ -138,7 +138,7 @@ func TestListTasksLabels(t *testing.T) {
|
|||
|
||||
func TestGetTask(t *testing.T) {
|
||||
expectedTask := api.Pod{
|
||||
CurrentState: api.TaskState{
|
||||
CurrentState: api.PodState{
|
||||
Status: "Foobar",
|
||||
},
|
||||
Labels: map[string]string{
|
||||
|
@ -185,7 +185,7 @@ func TestDeleteTask(t *testing.T) {
|
|||
|
||||
func TestCreateTask(t *testing.T) {
|
||||
requestTask := api.Pod{
|
||||
CurrentState: api.TaskState{
|
||||
CurrentState: api.PodState{
|
||||
Status: "Foobar",
|
||||
},
|
||||
Labels: map[string]string{
|
||||
|
@ -216,7 +216,7 @@ func TestCreateTask(t *testing.T) {
|
|||
func TestUpdateTask(t *testing.T) {
|
||||
requestTask := api.Pod{
|
||||
JSONBase: api.JSONBase{ID: "foo"},
|
||||
CurrentState: api.TaskState{
|
||||
CurrentState: api.PodState{
|
||||
Status: "Foobar",
|
||||
},
|
||||
Labels: map[string]string{
|
||||
|
|
|
@ -183,8 +183,8 @@ func RunController(image, name string, replicas int, client client.ClientInterfa
|
|||
ReplicasInSet: map[string]string{
|
||||
"name": name,
|
||||
},
|
||||
TaskTemplate: api.TaskTemplate{
|
||||
DesiredState: api.TaskState{
|
||||
PodTemplate: api.PodTemplate{
|
||||
DesiredState: api.PodState{
|
||||
Manifest: api.ContainerManifest{
|
||||
Containers: []api.Container{
|
||||
api.Container{
|
||||
|
|
|
@ -40,11 +40,11 @@ type Action struct {
|
|||
|
||||
type FakeKubeClient struct {
|
||||
actions []Action
|
||||
tasks TaskList
|
||||
tasks PodList
|
||||
ctrl ReplicationController
|
||||
}
|
||||
|
||||
func (client *FakeKubeClient) ListTasks(labelQuery map[string]string) (TaskList, error) {
|
||||
func (client *FakeKubeClient) ListTasks(labelQuery map[string]string) (PodList, error) {
|
||||
client.actions = append(client.actions, Action{action: "list-tasks"})
|
||||
return client.tasks, nil
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ func validateAction(expectedAction, actualAction Action, t *testing.T) {
|
|||
|
||||
func TestUpdateWithTasks(t *testing.T) {
|
||||
client := FakeKubeClient{
|
||||
tasks: TaskList{
|
||||
tasks: PodList{
|
||||
Items: []Pod{
|
||||
Pod{JSONBase: JSONBase{ID: "task-1"}},
|
||||
Pod{JSONBase: JSONBase{ID: "task-2"}},
|
||||
|
@ -177,7 +177,7 @@ func TestRunController(t *testing.T) {
|
|||
controller := fakeClient.actions[0].value.(ReplicationController)
|
||||
if controller.ID != name ||
|
||||
controller.DesiredState.Replicas != replicas ||
|
||||
controller.DesiredState.TaskTemplate.DesiredState.Manifest.Containers[0].Image != image {
|
||||
controller.DesiredState.PodTemplate.DesiredState.Manifest.Containers[0].Image != image {
|
||||
t.Errorf("Unexpected controller: %#v", controller)
|
||||
}
|
||||
}
|
||||
|
@ -196,7 +196,7 @@ func TestRunControllerWithService(t *testing.T) {
|
|||
controller := fakeClient.actions[0].value.(ReplicationController)
|
||||
if controller.ID != name ||
|
||||
controller.DesiredState.Replicas != replicas ||
|
||||
controller.DesiredState.TaskTemplate.DesiredState.Manifest.Containers[0].Image != image {
|
||||
controller.DesiredState.PodTemplate.DesiredState.Manifest.Containers[0].Image != image {
|
||||
t.Errorf("Unexpected controller: %#v", controller)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -141,8 +141,8 @@ func TestControllerParsing(t *testing.T) {
|
|||
ReplicasInSet: map[string]string{
|
||||
"name": "nginx",
|
||||
},
|
||||
TaskTemplate: TaskTemplate{
|
||||
DesiredState: TaskState{
|
||||
PodTemplate: PodTemplate{
|
||||
DesiredState: PodState{
|
||||
Manifest: ContainerManifest{
|
||||
Containers: []Container{
|
||||
Container{
|
||||
|
|
|
@ -22,7 +22,7 @@ import (
|
|||
. "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
func MakeEndpointController(serviceRegistry ServiceRegistry, taskRegistry TaskRegistry) *EndpointController {
|
||||
func MakeEndpointController(serviceRegistry ServiceRegistry, taskRegistry PodRegistry) *EndpointController {
|
||||
return &EndpointController{
|
||||
serviceRegistry: serviceRegistry,
|
||||
taskRegistry: taskRegistry,
|
||||
|
@ -31,7 +31,7 @@ func MakeEndpointController(serviceRegistry ServiceRegistry, taskRegistry TaskRe
|
|||
|
||||
type EndpointController struct {
|
||||
serviceRegistry ServiceRegistry
|
||||
taskRegistry TaskRegistry
|
||||
taskRegistry PodRegistry
|
||||
}
|
||||
|
||||
func (e *EndpointController) SyncServiceEndpoints() error {
|
||||
|
|
|
@ -24,7 +24,7 @@ import (
|
|||
|
||||
func TestSyncEndpointsEmpty(t *testing.T) {
|
||||
serviceRegistry := MockServiceRegistry{}
|
||||
taskRegistry := MockTaskRegistry{}
|
||||
taskRegistry := MockPodRegistry{}
|
||||
|
||||
endpoints := MakeEndpointController(&serviceRegistry, &taskRegistry)
|
||||
err := endpoints.SyncServiceEndpoints()
|
||||
|
@ -35,7 +35,7 @@ func TestSyncEndpointsError(t *testing.T) {
|
|||
serviceRegistry := MockServiceRegistry{
|
||||
err: fmt.Errorf("Test Error"),
|
||||
}
|
||||
taskRegistry := MockTaskRegistry{}
|
||||
taskRegistry := MockPodRegistry{}
|
||||
|
||||
endpoints := MakeEndpointController(&serviceRegistry, &taskRegistry)
|
||||
err := endpoints.SyncServiceEndpoints()
|
||||
|
@ -56,10 +56,10 @@ func TestSyncEndpointsItems(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
taskRegistry := MockTaskRegistry{
|
||||
tasks: []Pod{
|
||||
taskRegistry := MockPodRegistry{
|
||||
pods: []Pod{
|
||||
Pod{
|
||||
DesiredState: TaskState{
|
||||
DesiredState: PodState{
|
||||
Manifest: ContainerManifest{
|
||||
Containers: []Container{
|
||||
Container{
|
||||
|
@ -96,7 +96,7 @@ func TestSyncEndpointsTaskError(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
taskRegistry := MockTaskRegistry{
|
||||
taskRegistry := MockPodRegistry{
|
||||
err: fmt.Errorf("test error."),
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ func TestEtcdCreateTask(t *testing.T) {
|
|||
JSONBase: JSONBase{
|
||||
ID: "foo",
|
||||
},
|
||||
DesiredState: TaskState{
|
||||
DesiredState: PodState{
|
||||
Manifest: ContainerManifest{
|
||||
Containers: []Container{
|
||||
Container{
|
||||
|
@ -167,7 +167,7 @@ func TestEtcdCreateTaskWithContainersNotFound(t *testing.T) {
|
|||
JSONBase: JSONBase{
|
||||
ID: "foo",
|
||||
},
|
||||
DesiredState: TaskState{
|
||||
DesiredState: PodState{
|
||||
Manifest: ContainerManifest{
|
||||
Id: "foo",
|
||||
Containers: []Container{
|
||||
|
@ -214,7 +214,7 @@ func TestEtcdCreateTaskWithExistingContainers(t *testing.T) {
|
|||
JSONBase: JSONBase{
|
||||
ID: "foo",
|
||||
},
|
||||
DesiredState: TaskState{
|
||||
DesiredState: PodState{
|
||||
Manifest: ContainerManifest{
|
||||
Id: "foo",
|
||||
Containers: []Container{
|
||||
|
|
|
@ -20,7 +20,7 @@ import (
|
|||
)
|
||||
|
||||
// TaskRegistry is an interface implemented by things that know how to store Task objects
|
||||
type TaskRegistry interface {
|
||||
type PodRegistry interface {
|
||||
// ListTasks obtains a list of tasks that match query.
|
||||
// Query may be nil in which case all tasks are returned.
|
||||
ListTasks(query *map[string]string) ([]api.Pod, error)
|
||||
|
|
|
@ -29,7 +29,7 @@ func TestMakeManifestNoServices(t *testing.T) {
|
|||
|
||||
manifest, err := factory.MakeManifest("machine", Pod{
|
||||
JSONBase: JSONBase{ID: "foobar"},
|
||||
DesiredState: TaskState{
|
||||
DesiredState: PodState{
|
||||
Manifest: ContainerManifest{
|
||||
Containers: []Container{
|
||||
Container{
|
||||
|
@ -67,7 +67,7 @@ func TestMakeManifestServices(t *testing.T) {
|
|||
}
|
||||
|
||||
manifest, err := factory.MakeManifest("machine", Pod{
|
||||
DesiredState: TaskState{
|
||||
DesiredState: PodState{
|
||||
Manifest: ContainerManifest{
|
||||
Containers: []Container{
|
||||
Container{
|
||||
|
@ -104,7 +104,7 @@ func TestMakeManifestServicesExistingEnvVar(t *testing.T) {
|
|||
}
|
||||
|
||||
manifest, err := factory.MakeManifest("machine", Pod{
|
||||
DesiredState: TaskState{
|
||||
DesiredState: PodState{
|
||||
Manifest: ContainerManifest{
|
||||
Containers: []Container{
|
||||
Container{
|
||||
|
|
|
@ -58,7 +58,7 @@ func TestMemorySetUpdateGetTasks(t *testing.T) {
|
|||
JSONBase: JSONBase{
|
||||
ID: "foo",
|
||||
},
|
||||
DesiredState: TaskState{
|
||||
DesiredState: PodState{
|
||||
Host: "foo.com",
|
||||
},
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ type RealTaskControl struct {
|
|||
}
|
||||
|
||||
func (r RealTaskControl) createReplica(controllerSpec ReplicationController) {
|
||||
labels := controllerSpec.DesiredState.TaskTemplate.Labels
|
||||
labels := controllerSpec.DesiredState.PodTemplate.Labels
|
||||
if labels != nil {
|
||||
labels["replicationController"] = controllerSpec.ID
|
||||
}
|
||||
|
@ -60,8 +60,8 @@ func (r RealTaskControl) createReplica(controllerSpec ReplicationController) {
|
|||
JSONBase: JSONBase{
|
||||
ID: fmt.Sprintf("%x", rand.Int()),
|
||||
},
|
||||
DesiredState: controllerSpec.DesiredState.TaskTemplate.DesiredState,
|
||||
Labels: controllerSpec.DesiredState.TaskTemplate.Labels,
|
||||
DesiredState: controllerSpec.DesiredState.PodTemplate.DesiredState,
|
||||
Labels: controllerSpec.DesiredState.PodTemplate.Labels,
|
||||
}
|
||||
_, err := r.kubeClient.CreateTask(task)
|
||||
if err != nil {
|
||||
|
|
|
@ -53,8 +53,8 @@ func makeReplicationController(replicas int) ReplicationController {
|
|||
return ReplicationController{
|
||||
DesiredState: ReplicationControllerState{
|
||||
Replicas: replicas,
|
||||
TaskTemplate: TaskTemplate{
|
||||
DesiredState: TaskState{
|
||||
PodTemplate: PodTemplate{
|
||||
DesiredState: PodState{
|
||||
Manifest: ContainerManifest{
|
||||
Containers: []Container{
|
||||
Container{
|
||||
|
@ -72,7 +72,7 @@ func makeReplicationController(replicas int) ReplicationController {
|
|||
}
|
||||
}
|
||||
|
||||
func makeTaskList(count int) TaskList {
|
||||
func makeTaskList(count int) PodList {
|
||||
tasks := []Pod{}
|
||||
for i := 0; i < count; i++ {
|
||||
tasks = append(tasks, Pod{
|
||||
|
@ -81,7 +81,7 @@ func makeTaskList(count int) TaskList {
|
|||
},
|
||||
})
|
||||
}
|
||||
return TaskList{
|
||||
return PodList{
|
||||
Items: tasks,
|
||||
}
|
||||
}
|
||||
|
@ -178,8 +178,8 @@ func TestCreateReplica(t *testing.T) {
|
|||
|
||||
controllerSpec := ReplicationController{
|
||||
DesiredState: ReplicationControllerState{
|
||||
TaskTemplate: TaskTemplate{
|
||||
DesiredState: TaskState{
|
||||
PodTemplate: PodTemplate{
|
||||
DesiredState: PodState{
|
||||
Manifest: ContainerManifest{
|
||||
Containers: []Container{
|
||||
Container{
|
||||
|
@ -199,8 +199,8 @@ func TestCreateReplica(t *testing.T) {
|
|||
taskControl.createReplica(controllerSpec)
|
||||
|
||||
//expectedTask := Task{
|
||||
// Labels: controllerSpec.DesiredState.TaskTemplate.Labels,
|
||||
// DesiredState: controllerSpec.DesiredState.TaskTemplate.DesiredState,
|
||||
// Labels: controllerSpec.DesiredState.PodTemplate.Labels,
|
||||
// DesiredState: controllerSpec.DesiredState.PodTemplate.DesiredState,
|
||||
//}
|
||||
// TODO: fix this so that it validates the body.
|
||||
fakeHandler.ValidateRequest(t, makeUrl("/tasks"), "POST", nil)
|
||||
|
|
|
@ -65,10 +65,10 @@ func (s *RoundRobinScheduler) Schedule(task Pod) (string, error) {
|
|||
|
||||
type FirstFitScheduler struct {
|
||||
machines []string
|
||||
registry TaskRegistry
|
||||
registry PodRegistry
|
||||
}
|
||||
|
||||
func MakeFirstFitScheduler(machines []string, registry TaskRegistry) Scheduler {
|
||||
func MakeFirstFitScheduler(machines []string, registry PodRegistry) Scheduler {
|
||||
return &FirstFitScheduler{
|
||||
machines: machines,
|
||||
registry: registry,
|
||||
|
|
|
@ -46,7 +46,7 @@ func TestRandomScheduler(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFirstFitSchedulerNothingScheduled(t *testing.T) {
|
||||
mockRegistry := MockTaskRegistry{}
|
||||
mockRegistry := MockPodRegistry{}
|
||||
scheduler := MakeFirstFitScheduler([]string{"m1", "m2", "m3"}, &mockRegistry)
|
||||
expectSchedule(scheduler, Pod{}, "m1", t)
|
||||
}
|
||||
|
@ -57,10 +57,10 @@ func makeTask(host string, hostPorts ...int) Pod {
|
|||
networkPorts = append(networkPorts, Port{HostPort: port})
|
||||
}
|
||||
return Pod{
|
||||
CurrentState: TaskState{
|
||||
CurrentState: PodState{
|
||||
Host: host,
|
||||
},
|
||||
DesiredState: TaskState{
|
||||
DesiredState: PodState{
|
||||
Manifest: ContainerManifest{
|
||||
Containers: []Container{
|
||||
Container{
|
||||
|
@ -73,8 +73,8 @@ func makeTask(host string, hostPorts ...int) Pod {
|
|||
}
|
||||
|
||||
func TestFirstFitSchedulerFirstScheduled(t *testing.T) {
|
||||
mockRegistry := MockTaskRegistry{
|
||||
tasks: []Pod{
|
||||
mockRegistry := MockPodRegistry{
|
||||
pods: []Pod{
|
||||
makeTask("m1", 8080),
|
||||
},
|
||||
}
|
||||
|
@ -83,8 +83,8 @@ func TestFirstFitSchedulerFirstScheduled(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFirstFitSchedulerFirstScheduledComplicated(t *testing.T) {
|
||||
mockRegistry := MockTaskRegistry{
|
||||
tasks: []Pod{
|
||||
mockRegistry := MockPodRegistry{
|
||||
pods: []Pod{
|
||||
makeTask("m1", 80, 8080),
|
||||
makeTask("m2", 8081, 8082, 8083),
|
||||
makeTask("m3", 80, 443, 8085),
|
||||
|
@ -95,8 +95,8 @@ func TestFirstFitSchedulerFirstScheduledComplicated(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFirstFitSchedulerFirstScheduledImpossible(t *testing.T) {
|
||||
mockRegistry := MockTaskRegistry{
|
||||
tasks: []Pod{
|
||||
mockRegistry := MockPodRegistry{
|
||||
pods: []Pod{
|
||||
makeTask("m1", 8080),
|
||||
makeTask("m2", 8081),
|
||||
makeTask("m3", 8080),
|
||||
|
|
|
@ -1,121 +0,0 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
package registry
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
. "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
||||
)
|
||||
|
||||
// TaskRegistryStorage implements the RESTStorage interface in terms of a TaskRegistry
|
||||
type TaskRegistryStorage struct {
|
||||
registry TaskRegistry
|
||||
containerInfo client.ContainerInfo
|
||||
scheduler Scheduler
|
||||
}
|
||||
|
||||
func MakeTaskRegistryStorage(registry TaskRegistry, containerInfo client.ContainerInfo, scheduler Scheduler) apiserver.RESTStorage {
|
||||
return &TaskRegistryStorage{
|
||||
registry: registry,
|
||||
containerInfo: containerInfo,
|
||||
scheduler: scheduler,
|
||||
}
|
||||
}
|
||||
|
||||
// LabelMatch tests to see if a Task's labels map contains 'key' mapping to 'value'
|
||||
func LabelMatch(task Pod, queryKey, queryValue string) bool {
|
||||
for key, value := range task.Labels {
|
||||
if queryKey == key && queryValue == value {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// LabelMatch tests to see if a Task's labels map contains all key/value pairs in 'labelQuery'
|
||||
func LabelsMatch(task Pod, labelQuery *map[string]string) bool {
|
||||
if labelQuery == nil {
|
||||
return true
|
||||
}
|
||||
for key, value := range *labelQuery {
|
||||
if !LabelMatch(task, key, value) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (storage *TaskRegistryStorage) List(url *url.URL) (interface{}, error) {
|
||||
var result TaskList
|
||||
var query *map[string]string
|
||||
if url != nil {
|
||||
queryMap := client.DecodeLabelQuery(url.Query().Get("labels"))
|
||||
query = &queryMap
|
||||
}
|
||||
tasks, err := storage.registry.ListTasks(query)
|
||||
if err == nil {
|
||||
result = TaskList{
|
||||
Items: tasks,
|
||||
}
|
||||
}
|
||||
result.Kind = "cluster#taskList"
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (storage *TaskRegistryStorage) Get(id string) (interface{}, error) {
|
||||
task, err := storage.registry.GetTask(id)
|
||||
if err != nil {
|
||||
return task, err
|
||||
}
|
||||
info, err := storage.containerInfo.GetContainerInfo(task.CurrentState.Host, id)
|
||||
if err != nil {
|
||||
return task, err
|
||||
}
|
||||
task.CurrentState.Info = info
|
||||
task.Kind = "cluster#task"
|
||||
return task, err
|
||||
}
|
||||
|
||||
func (storage *TaskRegistryStorage) Delete(id string) error {
|
||||
return storage.registry.DeleteTask(id)
|
||||
}
|
||||
|
||||
func (storage *TaskRegistryStorage) Extract(body string) (interface{}, error) {
|
||||
task := Pod{}
|
||||
err := json.Unmarshal([]byte(body), &task)
|
||||
return task, err
|
||||
}
|
||||
|
||||
func (storage *TaskRegistryStorage) Create(task interface{}) error {
|
||||
taskObj := task.(Pod)
|
||||
if len(taskObj.ID) == 0 {
|
||||
return fmt.Errorf("ID is unspecified: %#v", task)
|
||||
}
|
||||
machine, err := storage.scheduler.Schedule(taskObj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return storage.registry.CreateTask(machine, taskObj)
|
||||
}
|
||||
|
||||
func (storage *TaskRegistryStorage) Update(task interface{}) error {
|
||||
return storage.registry.UpdateTask(task.(Pod))
|
||||
}
|
|
@ -1,204 +0,0 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
package registry
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
. "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
type MockTaskRegistry struct {
|
||||
err error
|
||||
tasks []Pod
|
||||
}
|
||||
|
||||
func expectNoError(t *testing.T, err error) {
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %#v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (registry *MockTaskRegistry) ListTasks(*map[string]string) ([]Pod, error) {
|
||||
return registry.tasks, registry.err
|
||||
}
|
||||
|
||||
func (registry *MockTaskRegistry) GetTask(taskId string) (*Pod, error) {
|
||||
return &Pod{}, registry.err
|
||||
}
|
||||
|
||||
func (registry *MockTaskRegistry) CreateTask(machine string, task Pod) error {
|
||||
return registry.err
|
||||
}
|
||||
|
||||
func (registry *MockTaskRegistry) UpdateTask(task Pod) error {
|
||||
return registry.err
|
||||
}
|
||||
func (registry *MockTaskRegistry) DeleteTask(taskId string) error {
|
||||
return registry.err
|
||||
}
|
||||
|
||||
func TestListTasksError(t *testing.T) {
|
||||
mockRegistry := MockTaskRegistry{
|
||||
err: fmt.Errorf("Test Error"),
|
||||
}
|
||||
storage := TaskRegistryStorage{
|
||||
registry: &mockRegistry,
|
||||
}
|
||||
tasks, err := storage.List(nil)
|
||||
if err != mockRegistry.err {
|
||||
t.Errorf("Expected %#v, Got %#v", mockRegistry.err, err)
|
||||
}
|
||||
if len(tasks.(TaskList).Items) != 0 {
|
||||
t.Errorf("Unexpected non-zero task list: %#v", tasks)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListEmptyTaskList(t *testing.T) {
|
||||
mockRegistry := MockTaskRegistry{}
|
||||
storage := TaskRegistryStorage{
|
||||
registry: &mockRegistry,
|
||||
}
|
||||
tasks, err := storage.List(nil)
|
||||
expectNoError(t, err)
|
||||
if len(tasks.(TaskList).Items) != 0 {
|
||||
t.Errorf("Unexpected non-zero task list: %#v", tasks)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListTaskList(t *testing.T) {
|
||||
mockRegistry := MockTaskRegistry{
|
||||
tasks: []Pod{
|
||||
Pod{
|
||||
JSONBase: JSONBase{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
Pod{
|
||||
JSONBase: JSONBase{
|
||||
ID: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
storage := TaskRegistryStorage{
|
||||
registry: &mockRegistry,
|
||||
}
|
||||
tasksObj, err := storage.List(nil)
|
||||
tasks := tasksObj.(TaskList)
|
||||
expectNoError(t, err)
|
||||
if len(tasks.Items) != 2 {
|
||||
t.Errorf("Unexpected task list: %#v", tasks)
|
||||
}
|
||||
if tasks.Items[0].ID != "foo" {
|
||||
t.Errorf("Unexpected task: %#v", tasks.Items[0])
|
||||
}
|
||||
if tasks.Items[1].ID != "bar" {
|
||||
t.Errorf("Unexpected task: %#v", tasks.Items[1])
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractJson(t *testing.T) {
|
||||
mockRegistry := MockTaskRegistry{}
|
||||
storage := TaskRegistryStorage{
|
||||
registry: &mockRegistry,
|
||||
}
|
||||
task := Pod{
|
||||
JSONBase: JSONBase{
|
||||
ID: "foo",
|
||||
},
|
||||
}
|
||||
body, err := json.Marshal(task)
|
||||
expectNoError(t, err)
|
||||
taskOut, err := storage.Extract(string(body))
|
||||
expectNoError(t, err)
|
||||
jsonOut, err := json.Marshal(taskOut)
|
||||
expectNoError(t, err)
|
||||
if string(body) != string(jsonOut) {
|
||||
t.Errorf("Expected %#v, found %#v", task, taskOut)
|
||||
}
|
||||
}
|
||||
|
||||
func expectLabelMatch(t *testing.T, task Pod, key, value string) {
|
||||
if !LabelMatch(task, key, value) {
|
||||
t.Errorf("Unexpected match failure: %#v %s %s", task, key, value)
|
||||
}
|
||||
}
|
||||
|
||||
func expectNoLabelMatch(t *testing.T, task Pod, key, value string) {
|
||||
if LabelMatch(task, key, value) {
|
||||
t.Errorf("Unexpected match success: %#v %s %s", task, key, value)
|
||||
}
|
||||
}
|
||||
|
||||
func expectLabelsMatch(t *testing.T, task Pod, query *map[string]string) {
|
||||
if !LabelsMatch(task, query) {
|
||||
t.Errorf("Unexpected match failure: %#v %#v", task, *query)
|
||||
}
|
||||
}
|
||||
|
||||
func expectNoLabelsMatch(t *testing.T, task Pod, query *map[string]string) {
|
||||
if LabelsMatch(task, query) {
|
||||
t.Errorf("Unexpected match success: %#v %#v", task, *query)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLabelMatch(t *testing.T) {
|
||||
task := Pod{
|
||||
Labels: map[string]string{
|
||||
"foo": "bar",
|
||||
"baz": "blah",
|
||||
},
|
||||
}
|
||||
expectLabelMatch(t, task, "foo", "bar")
|
||||
expectLabelMatch(t, task, "baz", "blah")
|
||||
expectNoLabelMatch(t, task, "foo", "blah")
|
||||
expectNoLabelMatch(t, task, "baz", "bar")
|
||||
}
|
||||
|
||||
func TestLabelsMatch(t *testing.T) {
|
||||
task := Pod{
|
||||
Labels: map[string]string{
|
||||
"foo": "bar",
|
||||
"baz": "blah",
|
||||
},
|
||||
}
|
||||
expectLabelsMatch(t, task, &map[string]string{})
|
||||
expectLabelsMatch(t, task, &map[string]string{
|
||||
"foo": "bar",
|
||||
})
|
||||
expectLabelsMatch(t, task, &map[string]string{
|
||||
"baz": "blah",
|
||||
})
|
||||
expectLabelsMatch(t, task, &map[string]string{
|
||||
"foo": "bar",
|
||||
"baz": "blah",
|
||||
})
|
||||
expectNoLabelsMatch(t, task, &map[string]string{
|
||||
"foo": "blah",
|
||||
})
|
||||
expectNoLabelsMatch(t, task, &map[string]string{
|
||||
"baz": "bar",
|
||||
})
|
||||
expectNoLabelsMatch(t, task, &map[string]string{
|
||||
"foo": "bar",
|
||||
"foobar": "bar",
|
||||
"baz": "blah",
|
||||
})
|
||||
|
||||
}
|
Loading…
Reference in New Issue