Example #1
0
// Deploy allows the creation of deploy.Deployments remotely
func (s *SpreadCli) Deploy() *cli.Command {
	return &cli.Command{
		Name:        "deploy",
		Usage:       "spread deploy [-s] PATH | COMMIT [kubectl context]",
		Description: "Deploys objects to a remote Kubernetes cluster.",
		ArgsUsage:   "-s will deploy only if no other deployment found (otherwise fails)",
		Action: func(c *cli.Context) {
			ref := c.Args().First()
			var dep *deploy.Deployment

			proj, err := s.project()
			if err == nil {
				var docs map[string]*pb.Document
				if len(ref) == 0 {
					s.printf("Deploying from index...")
					docs, err = proj.Index()
					if err != nil {
						s.fatalf("Error getting index: %v", err)
					}

					if err = s.promptForArgs(docs, false); err == nil {
						dep, err = deploy.DeploymentFromDocMap(docs)
					}

				} else {
					if docs, err = proj.ResolveCommit(ref); err == nil {
						if err = s.promptForArgs(docs, false); err == nil {
							dep, err = deploy.DeploymentFromDocMap(docs)
						}
					} else {
						dep, err = s.globalDeploy(ref)
					}
				}
			} else {
				dep, err = s.globalDeploy(ref)
			}

			if err != nil {
				s.fatalf("Failed to assemble deployment: %v", err)
			}

			context := c.Args().Get(1)
			cluster, err := deploy.NewKubeClusterFromContext(context)
			if err != nil {
				s.fatalf("Failed to deploy: %v", err)
			}

			s.printf("Deploying %d objects using the %s.", dep.Len(), displayContext(context))

			update := !c.Bool("s")
			err = cluster.Deploy(dep, update, false)
			if err != nil {
				//TODO: make better error messages (one to indicate a deployment already existed; another one if a deployment did not exist but some other error was thrown
				s.fatalf("Did not deploy.: %v", err)
			}

			s.printf("Deployment successful!")
		},
	}
}
Example #2
0
func TestImageDeployment(t *testing.T) {
	imageName := "arch"
	simple := newDockerImage(t, imageName)

	image, err := NewImage(simple, kube.ObjectMeta{}, "test")
	assert.NoError(t, err, "valid image")

	expectedPod := kube.Pod{
		ObjectMeta: kube.ObjectMeta{
			GenerateName: imageName,
			Namespace:    "default",
		},
		Spec: kube.PodSpec{
			Containers: []kube.Container{
				{
					Name:            imageName,
					Image:           imageName,
					ImagePullPolicy: kube.PullAlways,
				},
			},
			RestartPolicy: kube.RestartPolicyAlways,
			DNSPolicy:     kube.DNSDefault,
		},
	}

	expected := new(deploy.Deployment)
	assert.NoError(t, expected.Add(&expectedPod), "should be able to add pod")

	actual, err := image.Deployment()
	assert.NoError(t, err, "deploy ok")
	testDeploymentEqual(t, expected, actual)
}
Example #3
0
func TestBaseNew(t *testing.T) {
	entityType := Type(rand.Intn(5))
	source := randomString(8)
	var objects []deploy.KubeObject

	base, err := newBase(entityType, kube.ObjectMeta{}, source, objects)
	assert.NoError(t, err, "valid entity")

	assert.Equal(t, entityType, base.Type(), "type cannot change")
	assert.Equal(t, source, base.Source(), "source cannot change")

	emptyDeploy := deploy.Deployment{}
	assert.True(t, emptyDeploy.Equal(&base.objects))
}
Example #4
0
func TestContainerWithImageDeployment(t *testing.T) {
	const imageName = "busybox:latest"
	kubeContainer := kube.Container{
		Name:            "simple-container",
		Image:           imageName,
		Command:         []string{"/bin/busybox", "ls"},
		ImagePullPolicy: kube.PullAlways,
	}

	ctr, err := NewContainer(kubeContainer, kube.ObjectMeta{}, "simpleTest")
	assert.NoError(t, err, "should be able to create container")
	assert.NotNil(t, ctr.image, "an image should have been created")

	// check images
	images := ctr.Images()
	assert.Len(t, images, 1, "should have single image")

	expectedImage := newDockerImage(t, imageName)
	actualImage := images[0]
	assert.Equal(t, expectedImage.KubeImage(), actualImage.KubeImage(), "image should not have changed")

	// check kube
	kubectr, objects, err := ctr.data()
	assert.NoError(t, err, "should be able to produce kube")
	assert.True(t, kube.Semantic.DeepEqual(&kubectr, &kubeContainer), "kube should be same as container")
	assert.Equal(t, objects.Len(), 0, "no objects should have been added")

	pod := kube.Pod{
		ObjectMeta: kube.ObjectMeta{
			GenerateName: kubeContainer.Name,
			Namespace:    kube.NamespaceDefault,
		},
		Spec: kube.PodSpec{
			Containers: []kube.Container{
				kubeContainer,
			},
			RestartPolicy: kube.RestartPolicyAlways,
			DNSPolicy:     kube.DNSDefault,
		},
	}

	expected := new(deploy.Deployment)
	assert.NoError(t, expected.Add(&pod), "valid pod")
	actual, err := ctr.Deployment()
	assert.NoError(t, err, "deploy ok")

	testDeploymentEqual(t, expected, actual)
}
Example #5
0
func TestPodWithContainersDeployment(t *testing.T) {
	kubePod := testCreateKubePodSourcegraph("deploy")
	pod, err := NewPod(kubePod, kube.ObjectMeta{}, "containers-deploy")
	assert.NoError(t, err, "valid pod")

	kubePod.Namespace = kube.NamespaceDefault

	expected := new(deploy.Deployment)
	err = expected.Add(kubePod)
	assert.NoError(t, err, "valid pod")

	actual, err := pod.Deployment()
	assert.NoError(t, err, "deployment should be valid")

	testDeploymentEqual(t, expected, actual)
}
Example #6
0
func objectOnlyDeploy(input *dir.FileInput) (*deploy.Deployment, error) {
	objects, err := input.Objects()
	if err != nil {
		return nil, err
	} else if len(objects) == 0 {
		return nil, ErrNothingDeployable
	}

	deployment := new(deploy.Deployment)
	for _, obj := range objects {
		err = deployment.Add(obj)
		if err != nil {
			return nil, err
		}
	}
	return deployment, nil
}
Example #7
0
// Deployment is created using Deployments of child Entities
func (c *App) Deployment() (*deploy.Deployment, error) {
	d := new(deploy.Deployment)
	err := d.AddDeployment(c.objects)
	if err != nil {
		return nil, err
	}
	for _, entity := range c.children() {
		deploy, err := entity.Deployment()
		if err != nil {
			return nil, err
		}

		err = d.AddDeployment(*deploy)
		if err != nil {
			return nil, err
		}
	}
	return d, nil
}
Example #8
0
func TestContainerAttach(t *testing.T) {
	imageName := "to-be-attached"
	image := testNewImage(t, imageName, kube.ObjectMeta{}, "test", []deploy.KubeObject{})

	kubeContainer := testNewKubeContainer("test-container", "") // no image
	container, err := NewContainer(kubeContainer, kube.ObjectMeta{}, "attach")
	assert.NoError(t, err, "valid container")

	_, err = container.Deployment()
	assert.Error(t, err, "cannot be deployed without image")

	err = container.Attach(image)
	assert.NoError(t, err, "attach should be allowed")
	children := container.children()
	assert.Contains(t, children, image, "should have image as child")

	images := container.Images()
	assert.Len(t, images, 1, "only one image should exist")

	kubeContainer.Image = imageName
	pod := kube.Pod{
		ObjectMeta: kube.ObjectMeta{
			GenerateName: kubeContainer.Name,
			Namespace:    kube.NamespaceDefault,
		},
		Spec: kube.PodSpec{
			Containers: []kube.Container{
				kubeContainer,
			},
			RestartPolicy: kube.RestartPolicyAlways,
			DNSPolicy:     kube.DNSDefault,
		},
	}

	expected := new(deploy.Deployment)
	assert.NoError(t, expected.Add(&pod), "valid pod")
	actual, err := container.Deployment()
	assert.NoError(t, err, "deploy ok")

	testDeploymentEqual(t, expected, actual)
}
func TestRCValidPodDeployment(t *testing.T) {
	selector := map[string]string{
		"service": "postgres",
	}
	kubePod := testCreateKubePodSourcegraph("sourcegraph")
	kubePod.Labels = selector
	kubeRC := testNewKubeRC(kube.ObjectMeta{Name: "sourcegraph-rc", Namespace: kube.NamespaceDefault}, selector, kubePod)

	rc, err := NewReplicationController(kubeRC, kube.ObjectMeta{}, "")
	assert.NoError(t, err)
	assert.NotNil(t, rc.pod, "a pod should have be created")
	assert.Len(t, rc.pod.containers, 2, "two containers should have been created")

	expected := new(deploy.Deployment)
	err = expected.Add(kubeRC)
	assert.NoError(t, err, "should be valid RC")

	actual, err := rc.Deployment()
	assert.NoError(t, err)
	testDeploymentEqual(t, expected, actual)
}
Example #10
0
func newBase(t Type, defaults kube.ObjectMeta, source string, objects []deploy.KubeObject) (base base, err error) {
	base.defaults = defaults

	deployment := deploy.Deployment{}
	for _, obj := range objects {
		if obj == nil {
			err = ErrorNilObject
			return
		}
		base.setDefaults(obj)
		err = deployment.Add(obj)
		if err != nil {
			err = fmt.Errorf("error adding '%s': %v", source, err)
			return
		}
	}

	base.source = source
	base.entityType = t
	base.objects = deployment
	return
}
Example #11
0
// Deployment is created containing Pod with attached Containers.
func (c *Pod) Deployment() (*deploy.Deployment, error) {
	deployment := deploy.Deployment{}

	// create Pod from tree of Entities
	kubePod, childObj, err := c.data()
	if err != nil {
		return nil, err
	}

	// add Pod to deployment
	err = deployment.Add(kubePod)
	if err != nil {
		return nil, err
	}

	// add child objects
	err = deployment.AddDeployment(childObj)
	if err != nil {
		return nil, err
	}
	return &deployment, nil
}
Example #12
0
func TestPodAttachImage(t *testing.T) {
	podObjects := testRandomObjects(3)
	kubePod := testNewKubePod("containerless")
	pod, err := NewPod(kubePod, kube.ObjectMeta{}, "pod", podObjects...)
	assert.NoError(t, err, "valid")

	imageObjects := testRandomObjects(3)
	kubeImage, err := image.FromString("bprashanth/nginxhttps:1.0")
	assert.NoError(t, err, "image should be valid")

	image, err := NewImage(kubeImage, kube.ObjectMeta{}, "image", imageObjects...)
	assert.NoError(t, err, "valid")

	err = pod.Attach(image)
	assert.NoError(t, err, "should be attachable")

	kubePod.Namespace = kube.NamespaceDefault
	kubePod.Spec.Containers = []kube.Container{
		{
			Name:            "nginxhttps",
			Image:           "bprashanth/nginxhttps:1.0",
			ImagePullPolicy: kube.PullAlways,
		},
	}

	objects := append(podObjects, imageObjects...)

	expected := new(deploy.Deployment)
	err = expected.Add(kubePod)
	assert.NoError(t, err, "valid")

	for _, obj := range objects {
		assert.NoError(t, expected.Add(obj))
	}

	actual, err := pod.Deployment()
	assert.NoError(t, err, "deployment should be ok")
	testDeploymentEqual(t, expected, actual)
}
Example #13
0
// Deployment is created for RC attached with it's Pod.
func (c *ReplicationController) Deployment() (*deploy.Deployment, error) {
	deployment := new(deploy.Deployment)

	// create RC
	kubeRC, childObj, err := c.data()
	if err != nil {
		return nil, err
	}

	// add RC to deployment
	err = deployment.Add(kubeRC)
	if err != nil {
		return nil, err
	}

	// add child objects
	err = deployment.AddDeployment(childObj)
	if err != nil {
		return nil, err
	}
	return deployment, nil
}
Example #14
0
func TestPodAttachContainer(t *testing.T) {
	podObjects := testRandomObjects(60)
	kubePod := testNewKubePod("containerless")
	pod, err := NewPod(kubePod, kube.ObjectMeta{}, "pod", podObjects...)
	assert.NoError(t, err, "valid")

	containerObjects := testRandomObjects(20)

	kubeContainer := testNewKubeContainer("container", "busybox:latest")
	container, err := NewContainer(kubeContainer, kube.ObjectMeta{}, "container", containerObjects...)
	assert.NoError(t, err)

	err = pod.Attach(container)
	assert.NoError(t, err)
	children := pod.children()
	assert.Contains(t, children, container, "should have container as child")

	kubePod.Namespace = kube.NamespaceDefault
	kubePod.Spec.Containers = []kube.Container{
		kubeContainer,
	}

	expected := new(deploy.Deployment)
	err = expected.Add(kubePod)
	assert.NoError(t, err)

	actual, err := pod.Deployment()
	assert.NoError(t, err)

	objects := append(podObjects, containerObjects...)

	for _, obj := range objects {
		assert.NoError(t, expected.Add(obj))
	}

	testDeploymentEqual(t, expected, actual)
}
Example #15
0
func testDeploymentEqual(t *testing.T, expected, actual *deploy.Deployment) bool {
	equal := expected.Equal(actual)
	return assert.True(t, equal, "expected: %s,\n actual: %s,\n diff:\n%s", expected, actual, expected.Diff(actual))
}
func TestRCAttachPod(t *testing.T) {
	kubeContainer := kube.Container{
		Name:            "redis",
		Image:           "redis",
		ImagePullPolicy: kube.PullAlways,
	}
	selector := map[string]string{
		"app": "db",
	}

	// create ReplicationController
	rcObjects := testRandomObjects(10)
	rc := testNewRC(t, "container-test", selector, rcObjects)

	// create kube.Pod
	// create Pod from created pod
	kubePod := &kube.Pod{
		ObjectMeta: kube.ObjectMeta{Name: "attached"},
		Spec: kube.PodSpec{
			Containers: []kube.Container{
				kubeContainer,
			},
			RestartPolicy: kube.RestartPolicyAlways,
			DNSPolicy:     kube.DNSDefault,
		},
	}
	podObjects := testRandomObjects(10)
	pod, err := NewPod(kubePod, kube.ObjectMeta{}, "", podObjects...)
	assert.NoError(t, err, "should be valid pod")

	// Attach pod to RC
	// Should assume defaults up tree creating necessary components
	err = rc.Attach(pod)
	assert.NoError(t, err, "pod should be able to attach to ")
	children := rc.children()
	assert.Contains(t, children, pod, "should have image as child")

	// Compare internal elements
	assert.NotNil(t, rc.pod, "should of created pod")
	assert.Len(t, rc.pod.containers, 1)

	// Create struct representation for expected
	// Insert into Deployment
	// Create Deployment from RC
	rcMeta := rc.rc.ObjectMeta
	rcMeta.Namespace = kube.NamespaceDefault

	podMeta := pod.pod.ObjectMeta
	podMeta.Labels = selector
	expectedRC := &kube.ReplicationController{
		ObjectMeta: rcMeta,
		Spec: kube.ReplicationControllerSpec{
			Selector: selector,
			Template: &kube.PodTemplateSpec{
				ObjectMeta: kube.ObjectMeta{
					Namespace: kube.NamespaceDefault,
					Labels:    selector,
				},
				Spec: kubePod.Spec,
			},
		},
	}

	// Insert into Deployment
	expected := new(deploy.Deployment)
	err = expected.Add(expectedRC)
	assert.NoError(t, err, "should be valid RC")

	// add objects to deployment
	expected.AddDeployment(pod.objects)
	expected.AddDeployment(rc.objects)

	// Create Deployment from RC
	actual, err := rc.Deployment()
	assert.NoError(t, err, "should produce valid deployment")

	// Compare deployments
	testDeploymentEqual(t, expected, actual)

	// check images
	images := rc.Images()
	assert.Len(t, images, 1)
}
func TestRCAttachImage(t *testing.T) {
	imageName := "rc-attach-image"
	rcName := "image-test"
	selector := map[string]string{
		"app": "cache",
	}

	// create ReplicationController
	rcObjects := testRandomObjects(10)
	rc := testNewRC(t, rcName, selector, rcObjects)

	// create Image
	imageObjects := testRandomObjects(10)
	imageEntity := testNewImage(t, imageName, kube.ObjectMeta{}, "", imageObjects)

	// Attach image to RC
	// Should assume defaults up tree creating necessary components
	err := rc.Attach(imageEntity)
	assert.NoError(t, err, "attachment should be allowed")

	// Compare internal elements
	assert.NotNil(t, rc.pod, "should of created template")

	// Create struct representation for expected
	expectedRC := &kube.ReplicationController{
		ObjectMeta: kube.ObjectMeta{
			Name:      rcName,
			Namespace: kube.NamespaceDefault,
		},
		Spec: kube.ReplicationControllerSpec{
			Selector: selector,
			Template: &kube.PodTemplateSpec{
				ObjectMeta: kube.ObjectMeta{
					Namespace: kube.NamespaceDefault,
					Labels:    selector,
				},
				Spec: kube.PodSpec{
					Containers: []kube.Container{
						{
							Name:            imageName,
							Image:           imageName,
							ImagePullPolicy: kube.PullAlways,
						},
					},
					RestartPolicy: kube.RestartPolicyAlways,
					DNSPolicy:     kube.DNSDefault,
				},
			},
		},
	}

	// Insert into Deployment
	expected := new(deploy.Deployment)
	err = expected.Add(expectedRC)
	assert.NoError(t, err, "should be valid RC")

	// add objects to deployment
	expected.AddDeployment(imageEntity.objects)
	expected.AddDeployment(rc.objects)

	// Create Deployment from RC
	actual, err := rc.Deployment()
	assert.NoError(t, err, "should produce valid deployment")

	// Compare deployments
	testDeploymentEqual(t, expected, actual)

	// check images
	images := rc.Images()
	expectedImage, _ := image.FromString(imageName)
	assert.Len(t, images, 1)
	for _, v := range images {
		assert.EqualValues(t, expectedImage, v, "should match original image")
	}
}
func TestRCAttachContainer(t *testing.T) {
	containerName := "attached"
	imageName := "embedded-image"
	selector := map[string]string{
		"app": "db",
	}

	// create ReplicationController
	rcObjects := testRandomObjects(10)
	rc := testNewRC(t, "container-test", selector, rcObjects)

	// create kube.Container
	// create Container from created container
	containerObjects := testRandomObjects(20)
	kubeContainer := testNewKubeContainer(containerName, imageName)
	container, err := NewContainer(kubeContainer, kube.ObjectMeta{}, "", containerObjects...)
	assert.NoError(t, err, "should be valid container")

	// Attach container to RC
	// Should assume defaults up tree creating necessary components
	err = rc.Attach(container)
	assert.NoError(t, err, "container should be able to attach to rc")

	// Compare internal elements
	assert.NotNil(t, rc.pod, "should of created pod")
	// assert.Len(t, rc.pod.containers, 1)

	// Create struct representation for expected
	// Insert into Deployment
	// Create Deployment from RC
	rcMeta := rc.rc.ObjectMeta
	rcMeta.Namespace = kube.NamespaceDefault
	expectedRC := &kube.ReplicationController{
		ObjectMeta: rcMeta,
		Spec: kube.ReplicationControllerSpec{
			Selector: selector,
			Template: &kube.PodTemplateSpec{
				ObjectMeta: kube.ObjectMeta{
					Labels:    selector,
					Namespace: kube.NamespaceDefault,
				},
				Spec: kube.PodSpec{
					Containers: []kube.Container{
						kubeContainer,
					},
					RestartPolicy: kube.RestartPolicyAlways,
					DNSPolicy:     kube.DNSDefault,
				},
			},
		},
	}

	// Insert into Deployment
	expected := new(deploy.Deployment)
	err = expected.Add(expectedRC)
	assert.NoError(t, err, "should be valid RC")

	// add objects to deployment
	expected.AddDeployment(container.objects)
	expected.AddDeployment(rc.objects)

	// Create Deployment from RC
	actual, err := rc.Deployment()
	assert.NoError(t, err, "should produce valid deployment")

	// Compare deployments
	testDeploymentEqual(t, expected, actual)

	// check images
	images := rc.Images()
	assert.Len(t, images, 1)
}