Пример #1
0
// DeleteController deletes a replication controller named 'name', requires that the controller
// already be stopped.
func DeleteController(ctx api.Context, name string, client client.Interface) error {
	// TODO remove ctx in favor of just namespace string
	controller, err := client.ReplicationControllers(api.Namespace(ctx)).Get(name)
	if err != nil {
		return err
	}
	if controller.Spec.Replicas != 0 {
		return fmt.Errorf("controller has non-zero replicas (%d), please stop it first", controller.Spec.Replicas)
	}
	return client.ReplicationControllers(api.Namespace(ctx)).Delete(name)
}
Пример #2
0
// TestValidNamespace validates that namespace rules are enforced on a resource prior to create or update
func TestValidNamespace(t *testing.T) {
	ctx := api.NewDefaultContext()
	namespace, _ := api.NamespaceFrom(ctx)
	resource := api.ReplicationController{}
	if !api.ValidNamespace(ctx, &resource.ObjectMeta) {
		t.Errorf("expected success")
	}
	if namespace != resource.Namespace {
		t.Errorf("expected resource to have the default namespace assigned during validation")
	}
	resource = api.ReplicationController{ObjectMeta: api.ObjectMeta{Namespace: "other"}}
	if api.ValidNamespace(ctx, &resource.ObjectMeta) {
		t.Errorf("Expected error that resource and context errors do not match because resource has different namespace")
	}
	ctx = api.NewContext()
	if api.ValidNamespace(ctx, &resource.ObjectMeta) {
		t.Errorf("Expected error that resource and context errors do not match since context has no namespace")
	}

	ctx = api.NewContext()
	ns := api.Namespace(ctx)
	if ns != "" {
		t.Errorf("Expected the empty string")
	}
}
Пример #3
0
// RunController creates a new replication controller named 'name' which creates 'replicas' pods running 'image'.
func RunController(ctx api.Context, image, name string, replicas int, client client.Interface, portSpec string, servicePort int) error {
	// TODO replace ctx with a namespace string
	if servicePort > 0 && !util.IsDNSLabel(name) {
		return fmt.Errorf("service creation requested, but an invalid name for a service was provided (%s). Service names must be valid DNS labels.", name)
	}
	ports, err := portsFromString(portSpec)
	if err != nil {
		return err
	}
	controller := &api.ReplicationController{
		ObjectMeta: api.ObjectMeta{
			Name: name,
		},
		Spec: api.ReplicationControllerSpec{
			Replicas: replicas,
			Selector: map[string]string{
				"name": name,
			},
			Template: &api.PodTemplateSpec{
				ObjectMeta: api.ObjectMeta{
					Labels: map[string]string{
						"name": name,
					},
				},
				Spec: api.PodSpec{
					Containers: []api.Container{
						{
							Name:  strings.ToLower(name),
							Image: image,
							Ports: ports,
						},
					},
				},
			},
		},
	}

	controllerOut, err := client.ReplicationControllers(api.Namespace(ctx)).Create(controller)
	if err != nil {
		return err
	}
	data, err := yaml.Marshal(controllerOut)
	if err != nil {
		return err
	}
	fmt.Print(string(data))

	if servicePort > 0 {
		svc, err := createService(ctx, name, servicePort, client)
		if err != nil {
			return err
		}
		data, err = yaml.Marshal(svc)
		if err != nil {
			return err
		}
		fmt.Printf(string(data))
	}
	return nil
}
Пример #4
0
// ResizeController resizes a controller named 'name' by setting replicas to 'replicas'.
func ResizeController(ctx api.Context, name string, replicas int, client client.Interface) error {
	// TODO ctx is not needed, and should just be a namespace
	controller, err := client.ReplicationControllers(api.Namespace(ctx)).Get(name)
	if err != nil {
		return err
	}
	controller.Spec.Replicas = replicas
	controllerOut, err := client.ReplicationControllers(api.Namespace(ctx)).Update(controller)
	if err != nil {
		return err
	}
	data, err := yaml.Marshal(controllerOut)
	if err != nil {
		return err
	}
	fmt.Print(string(data))
	return nil
}
Пример #5
0
// Update performs a rolling update of a collection of pods.
// 'name' points to a replication controller.
// 'client' is used for updating pods.
// 'updatePeriod' is the time between pod updates.
// 'imageName' is the new image to update for the template.  This will work
//     with the first container in the pod.  There is no support yet for
//     updating more complex replication controllers.  If this is blank then no
//     update of the image is performed.
func Update(ctx api.Context, name string, client client.Interface, updatePeriod time.Duration, imageName string) error {
	// TODO ctx is not needed as input to this function, should just be 'namespace'
	controller, err := client.ReplicationControllers(api.Namespace(ctx)).Get(name)
	if err != nil {
		return err
	}

	if len(imageName) != 0 {
		controller.Spec.Template.Spec.Containers[0].Image = imageName
		controller, err = client.ReplicationControllers(controller.Namespace).Update(controller)
		if err != nil {
			return err
		}
	}

	s := labels.Set(controller.Spec.Selector).AsSelector()

	podList, err := client.Pods(api.Namespace(ctx)).List(s)
	if err != nil {
		return err
	}
	expected := len(podList.Items)
	if expected == 0 {
		return nil
	}
	for _, pod := range podList.Items {
		// We delete the pod here, the controller will recreate it.  This will result in pulling
		// a new Docker image.  This isn't a full "update" but it's what we support for now.
		err = client.Pods(pod.Namespace).Delete(pod.Name)
		if err != nil {
			return err
		}
		time.Sleep(updatePeriod)
	}
	return wait.Poll(time.Second*5, time.Second*300, func() (bool, error) {
		podList, err := client.Pods(api.Namespace(ctx)).List(s)
		if err != nil {
			return false, err
		}
		return len(podList.Items) == expected, nil
	})
}
Пример #6
0
// Implement ResourceWatcher.
func (storage *SimpleRESTStorage) Watch(ctx api.Context, label, field labels.Selector, resourceVersion string) (watch.Interface, error) {
	storage.requestedLabelSelector = label
	storage.requestedFieldSelector = field
	storage.requestedResourceVersion = resourceVersion
	storage.requestedResourceNamespace = api.Namespace(ctx)
	if err := storage.errors["watch"]; err != nil {
		return nil, err
	}
	storage.fakeWatch = watch.NewFake()
	return storage.fakeWatch, nil
}
Пример #7
0
// Implement Redirector.
func (storage *SimpleRESTStorage) ResourceLocation(ctx api.Context, id string) (string, error) {
	// validate that the namespace context on the request matches the expected input
	storage.requestedResourceNamespace = api.Namespace(ctx)
	if storage.expectedResourceNamespace != storage.requestedResourceNamespace {
		return "", fmt.Errorf("Expected request namespace %s, but got namespace %s", storage.expectedResourceNamespace, storage.requestedResourceNamespace)
	}
	storage.requestedResourceLocationID = id
	if err := storage.errors["resourceLocation"]; err != nil {
		return "", err
	}
	return storage.resourceLocation, nil
}
Пример #8
0
func TestRESTCreate(t *testing.T) {
	table := []struct {
		ctx   api.Context
		event *api.Event
		valid bool
	}{
		{
			ctx:   api.NewDefaultContext(),
			event: testEvent("foo"),
			valid: true,
		}, {
			ctx:   api.NewContext(),
			event: testEvent("bar"),
			valid: true,
		}, {
			ctx:   api.WithNamespace(api.NewContext(), "nondefault"),
			event: testEvent("bazzzz"),
			valid: false,
		},
	}

	for _, item := range table {
		_, rest := NewTestREST()
		c, err := rest.Create(item.ctx, item.event)
		if !item.valid {
			if err == nil {
				ctxNS := api.Namespace(item.ctx)
				t.Errorf("unexpected non-error for %v (%v, %v)", item.event.Name, ctxNS, item.event.Namespace)
			}
			continue
		}
		if err != nil {
			t.Errorf("%v: Unexpected error %v", item.event.Name, err)
			continue
		}
		if !api.HasObjectMetaSystemFieldValues(&item.event.ObjectMeta) {
			t.Errorf("storage did not populate object meta field values")
		}
		if e, a := item.event, (<-c).Object; !reflect.DeepEqual(e, a) {
			t.Errorf("diff: %s", util.ObjectDiff(e, a))
		}
		// Ensure we implement the interface
		_ = apiserver.ResourceWatcher(rest)
	}
}
Пример #9
0
func createService(ctx api.Context, name string, port int, client client.Interface) (*api.Service, error) {
	// TODO remove context in favor of just namespace string
	svc := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name: name,
			Labels: map[string]string{
				"name": name,
			},
		},
		Spec: api.ServiceSpec{
			Port: port,
			Selector: map[string]string{
				"name": name,
			},
		},
	}
	svc, err := client.Services(api.Namespace(ctx)).Create(svc)
	return svc, err
}
Пример #10
0
func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) {
	event, ok := obj.(*api.Event)
	if !ok {
		return nil, fmt.Errorf("invalid object type")
	}
	if api.Namespace(ctx) != "" {
		if !api.ValidNamespace(ctx, &event.ObjectMeta) {
			return nil, errors.NewConflict("event", event.Namespace, fmt.Errorf("event.namespace does not match the provided context"))
		}
	}
	if errs := validation.ValidateEvent(event); len(errs) > 0 {
		return nil, errors.NewInvalid("event", event.Name, errs)
	}
	api.FillObjectMetaSystemFields(ctx, &event.ObjectMeta)

	return apiserver.MakeAsync(func() (runtime.Object, error) {
		err := rs.registry.Create(ctx, event.Name, event)
		if err != nil {
			return nil, err
		}
		return rs.registry.Get(ctx, event.Name)
	}), nil
}
Пример #11
0
func executeAPIRequest(ctx api.Context, method string, c *client.Client) bool {
	storage, path, hasSuffix := storagePathFromArg(flag.Arg(1))
	validStorage := checkStorage(storage)
	verb := ""
	setBody := false
	var version string

	printer := getPrinter()

	switch method {
	case "get":
		verb = "GET"
		if !validStorage || !hasSuffix {
			glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>[/<id>]", method, prettyWireStorage())
		}
	case "list":
		verb = "GET"
		if !validStorage || hasSuffix {
			glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>", method, prettyWireStorage())
		}
	case "delete":
		verb = "DELETE"
		if !validStorage || !hasSuffix {
			glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>/<id>", method, prettyWireStorage())
		}
	case "create":
		verb = "POST"
		setBody = true
		if !validStorage || hasSuffix {
			glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>", method, prettyWireStorage())
		}
	case "update":
		obj, err := c.Verb("GET").Namespace(api.Namespace(ctx)).Suffix(path).Do().Get()
		if err != nil {
			glog.Fatalf("error obtaining resource version for update: %v", err)
		}
		meta, err := meta.Accessor(obj)
		if err != nil {
			glog.Fatalf("error finding json base for update: %v", err)
		}
		version = meta.ResourceVersion()
		verb = "PUT"
		setBody = true
		if !validStorage || !hasSuffix {
			glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>/<id>", method, prettyWireStorage())
		}
	case "print":
		data := readConfig(storage, c)
		obj, err := latest.Codec.Decode(data)
		if err != nil {
			glog.Fatalf("error setting resource version: %v", err)
		}
		printer.PrintObj(obj, os.Stdout)
		return true
	default:
		return false
	}

	r := c.Verb(verb).Namespace(api.Namespace(ctx)).Suffix(path)
	if len(*selector) > 0 {
		r.ParseSelectorParam("labels", *selector)
	}
	if len(*fieldSelector) > 0 {
		r.ParseSelectorParam("fields", *fieldSelector)
	}
	if setBody {
		if len(version) > 0 {
			data := readConfig(storage, c)
			obj, err := latest.Codec.Decode(data)
			if err != nil {
				glog.Fatalf("error setting resource version: %v", err)
			}
			jsonBase, err := meta.Accessor(obj)
			if err != nil {
				glog.Fatalf("error setting resource version: %v", err)
			}
			jsonBase.SetResourceVersion(version)
			data, err = c.RESTClient.Codec.Encode(obj)
			if err != nil {
				glog.Fatalf("error setting resource version: %v", err)
			}
			r.Body(data)
		} else {
			r.Body(readConfig(storage, c))
		}
	}
	result := r.Do()
	obj, err := result.Get()
	if err != nil {
		glog.Fatalf("Got request error: %v\n", err)
		return false
	}

	if err = printer.PrintObj(obj, os.Stdout); err != nil {
		body, _ := result.Raw()
		glog.Fatalf("Failed to print: %v\nRaw received object:\n%#v\n\nBody received: %v", err, obj, string(body))
	}
	fmt.Print("\n")

	return true
}
Пример #12
0
// Bind just does a POST binding RPC.
func (b *binder) Bind(binding *api.Binding) error {
	glog.V(2).Infof("Attempting to bind %v to %v", binding.PodID, binding.Host)
	ctx := api.WithNamespace(api.NewContext(), binding.Namespace)
	return b.Post().Namespace(api.Namespace(ctx)).Resource("bindings").Body(binding).Do().Error()
}
Пример #13
0
// UpdatePodStatus PUT pod RPC
func (s *status) UpdatePodStatus(pod *api.Pod) error {
	glog.V(2).Infof("Attempting to update pod (%s) status to %s", pod.Name, pod.Status.Phase)
	ctx := api.WithNamespace(api.NewContext(), pod.Namespace)
	return s.Put().Namespace(api.Namespace(ctx)).Path("pods").Path(pod.Name).Body(pod).Do().Error()
}