test/integration/deploy_trigger_test.go
c1f155a9
 // +build integration,!no-etcd
 
 package integration
 
 import (
ab496df3
 	"fmt"
c1f155a9
 	"net/http"
 	"net/http/httptest"
969809c1
 	"strings"
e5edb881
 	"sync"
c1f155a9
 	"testing"
 
9a204c15
 	"github.com/golang/glog"
 
83c702b4
 	kapi "k8s.io/kubernetes/pkg/api"
 	klatest "k8s.io/kubernetes/pkg/api/latest"
 	"k8s.io/kubernetes/pkg/api/rest"
 	"k8s.io/kubernetes/pkg/apiserver"
 	"k8s.io/kubernetes/pkg/client"
 	kclient "k8s.io/kubernetes/pkg/client"
 	"k8s.io/kubernetes/pkg/fields"
 	"k8s.io/kubernetes/pkg/labels"
 	"k8s.io/kubernetes/pkg/master"
 	"k8s.io/kubernetes/pkg/tools/etcdtest"
 	watchapi "k8s.io/kubernetes/pkg/watch"
 	"k8s.io/kubernetes/plugin/pkg/admission/admit"
c1f155a9
 
 	"github.com/openshift/origin/pkg/api/latest"
 	osclient "github.com/openshift/origin/pkg/client"
 	deployapi "github.com/openshift/origin/pkg/deploy/api"
ab496df3
 	deploytest "github.com/openshift/origin/pkg/deploy/api/test"
224b3b44
 	configchangecontroller "github.com/openshift/origin/pkg/deploy/controller/configchange"
6c68632b
 	deployconfigcontroller "github.com/openshift/origin/pkg/deploy/controller/deploymentconfig"
224b3b44
 	imagechangecontroller "github.com/openshift/origin/pkg/deploy/controller/imagechange"
c1f155a9
 	deployconfiggenerator "github.com/openshift/origin/pkg/deploy/generator"
 	deployconfigregistry "github.com/openshift/origin/pkg/deploy/registry/deployconfig"
cbbf48ff
 	deployconfigetcd "github.com/openshift/origin/pkg/deploy/registry/deployconfig/etcd"
b73a77b1
 	deployutil "github.com/openshift/origin/pkg/deploy/util"
c1f155a9
 	imageapi "github.com/openshift/origin/pkg/image/api"
 	"github.com/openshift/origin/pkg/image/registry/image"
9f217aa5
 	imageetcd "github.com/openshift/origin/pkg/image/registry/image/etcd"
e5edb881
 	"github.com/openshift/origin/pkg/image/registry/imagestream"
 	imagestreametcd "github.com/openshift/origin/pkg/image/registry/imagestream/etcd"
400c3669
 	"github.com/openshift/origin/pkg/image/registry/imagestreamimage"
e5edb881
 	"github.com/openshift/origin/pkg/image/registry/imagestreammapping"
 	"github.com/openshift/origin/pkg/image/registry/imagestreamtag"
4811a486
 	testutil "github.com/openshift/origin/test/util"
c1f155a9
 )
 
 func init() {
4811a486
 	testutil.RequireEtcd()
c1f155a9
 }
 
ab496df3
 func TestTriggers_manual(t *testing.T) {
4811a486
 	testutil.DeleteAllEtcdKeys()
e5edb881
 	openshift := NewTestDeployOpenshift(t)
13c5a839
 	defer openshift.Close()
c1f155a9
 
ab496df3
 	config := deploytest.OkDeploymentConfig(0)
 	config.Namespace = testutil.Namespace()
 	config.Triggers = []deployapi.DeploymentTriggerPolicy{
 		{
 			Type: deployapi.DeploymentTriggerManual,
 		},
 	}
 
c1f155a9
 	var err error
 
4811a486
 	dc, err := openshift.Client.DeploymentConfigs(testutil.Namespace()).Create(config)
4fe0e12a
 	if err != nil {
e5b90d99
 		t.Fatalf("Couldn't create DeploymentConfig: %v %#v", err, config)
4fe0e12a
 	}
 
43d56098
 	watch, err := openshift.KubeClient.ReplicationControllers(testutil.Namespace()).Watch(labels.Everything(), fields.Everything(), dc.ResourceVersion)
e5b90d99
 	if err != nil {
 		t.Fatalf("Couldn't subscribe to Deployments: %v", err)
c1f155a9
 	}
e5b90d99
 	defer watch.Stop()
c1f155a9
 
4811a486
 	config, err = openshift.Client.DeploymentConfigs(testutil.Namespace()).Generate(config.Name)
e5b90d99
 	if err != nil {
c1f155a9
 		t.Fatalf("Error generating config: %v", err)
 	}
e5b90d99
 	if config.LatestVersion != 1 {
 		t.Fatalf("Generated deployment should have version 1: %#v", config)
 	}
9a204c15
 	glog.Infof("config(1): %#v", config)
c1f155a9
 
4811a486
 	new, err := openshift.Client.DeploymentConfigs(testutil.Namespace()).Update(config)
e5b90d99
 	if err != nil {
c1f155a9
 		t.Fatalf("Couldn't create updated DeploymentConfig: %v %#v", err, config)
 	}
9a204c15
 	glog.Infof("config(2): %#v", new)
c1f155a9
 
 	event := <-watch.ResultChan()
4f679167
 	if e, a := watchapi.Added, event.Type; e != a {
 		t.Fatalf("expected watch event type %s, got %s", e, a)
 	}
1964dfe0
 	deployment := event.Object.(*kapi.ReplicationController)
c1f155a9
 
b73a77b1
 	if e, a := config.Name, deployutil.DeploymentConfigNameFor(deployment); e != a {
ebec5535
 		t.Fatalf("Expected deployment annotated with deploymentConfig '%s', got '%s'", e, a)
c1f155a9
 	}
b73a77b1
 	if e, a := 1, deployutil.DeploymentVersionFor(deployment); e != a {
e5b90d99
 		t.Fatalf("Deployment annotation version does not match: %#v", deployment)
 	}
c1f155a9
 }
 
ab496df3
 func TestTriggers_imageChange(t *testing.T) {
e5edb881
 	_, clusterAdminKubeConfig, err := testutil.StartTestMaster()
 	if err != nil {
 		t.Fatalf("error starting master: %v", err)
 	}
 	openshiftClusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig)
 	if err != nil {
c3e1dbba
 		t.Fatalf("error getting cluster admin client: %v", err)
e5edb881
 	}
 	openshiftClusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig)
 	if err != nil {
 		t.Fatalf("error getting cluster admin client config: %v", err)
 	}
 	openshiftProjectAdminClient, err := testutil.CreateNewProject(openshiftClusterAdminClient, *openshiftClusterAdminClientConfig, testutil.Namespace(), "bob")
 	if err != nil {
 		t.Fatalf("error creating project: %v", err)
 	}
c1f155a9
 
e5edb881
 	imageStream := &imageapi.ImageStream{ObjectMeta: kapi.ObjectMeta{Name: "test-image-stream"}}
c1f155a9
 
ab496df3
 	config := deploytest.OkDeploymentConfig(0)
 	config.Namespace = testutil.Namespace()
c1f155a9
 
471d99d0
 	configWatch, err := openshiftProjectAdminClient.DeploymentConfigs(testutil.Namespace()).Watch(labels.Everything(), fields.Everything(), "0")
4fe0e12a
 	if err != nil {
 		t.Fatalf("Couldn't subscribe to Deployments %v", err)
 	}
471d99d0
 	defer configWatch.Stop()
4fe0e12a
 
e5edb881
 	if imageStream, err = openshiftProjectAdminClient.ImageStreams(testutil.Namespace()).Create(imageStream); err != nil {
 		t.Fatalf("Couldn't create ImageStream: %v", err)
9a204c15
 	}
 
e5edb881
 	imageWatch, err := openshiftProjectAdminClient.ImageStreams(testutil.Namespace()).Watch(labels.Everything(), fields.Everything(), "0")
e5b90d99
 	if err != nil {
e5edb881
 		t.Fatalf("Couldn't subscribe to ImageStreams: %s", err)
ab496df3
 	}
 	defer imageWatch.Stop()
 
e5edb881
 	// Make a function which can create a new tag event for the image stream and
 	// then wait for the stream status to be asynchronously updated.
ab496df3
 	createTagEvent := func(image string) {
e5edb881
 		mapping := &imageapi.ImageStreamMapping{
 			ObjectMeta: kapi.ObjectMeta{Name: imageStream.Name},
ab496df3
 			Tag:        "latest",
 			Image: imageapi.Image{
 				ObjectMeta: kapi.ObjectMeta{
 					Name: image,
 				},
 				DockerImageReference: fmt.Sprintf("registry:8080/openshift/test-image@%s", image),
 			},
 		}
e5edb881
 		if err := openshiftProjectAdminClient.ImageStreamMappings(testutil.Namespace()).Create(mapping); err != nil {
ab496df3
 			t.Fatalf("unexpected error: %v", err)
 		}
9a204c15
 
e5edb881
 		t.Log("Waiting for image stream mapping to be reflected in the IS status...")
ab496df3
 	statusLoop:
 		for {
 			select {
 			case event := <-imageWatch.ResultChan():
471d99d0
 				stream := event.Object.(*imageapi.ImageStream)
 				if _, ok := stream.Status.Tags["latest"]; ok {
 					t.Logf("ImageStream %s now has Status with tags: %#v", stream.Name, stream.Status.Tags)
ab496df3
 					break statusLoop
 				} else {
471d99d0
 					t.Logf("Still waiting for latest tag status on ImageStream %s", stream.Name)
ab496df3
 				}
 			}
 		}
c1f155a9
 	}
 
e5edb881
 	if config, err = openshiftProjectAdminClient.DeploymentConfigs(testutil.Namespace()).Create(config); err != nil {
c1f155a9
 		t.Fatalf("Couldn't create DeploymentConfig: %v", err)
 	}
 
471d99d0
 	createTagEvent("sha256:00000000000000000000000000000001")
c1f155a9
 
471d99d0
 	var newConfig *deployapi.DeploymentConfig
 	t.Log("Waiting for a new deployment config in response to ImageStream update")
 waitForNewConfig:
e5edb881
 	for {
 		select {
471d99d0
 		case event := <-configWatch.ResultChan():
e5edb881
 			if event.Type == watchapi.Modified {
471d99d0
 				newConfig = event.Object.(*deployapi.DeploymentConfig)
 				break waitForNewConfig
f881f281
 			}
e5edb881
 		}
c1f155a9
 	}
 
471d99d0
 	if e, a := 1, newConfig.LatestVersion; e != a {
 		t.Fatalf("expected config version %d, got %d", e, a)
c1f155a9
 	}
 }
 
ab496df3
 func TestTriggers_configChange(t *testing.T) {
4811a486
 	testutil.DeleteAllEtcdKeys()
e5edb881
 	openshift := NewTestDeployOpenshift(t)
13c5a839
 	defer openshift.Close()
c1f155a9
 
ab496df3
 	config := deploytest.OkDeploymentConfig(0)
 	config.Namespace = testutil.Namespace()
 	config.Triggers[0] = deploytest.OkConfigChangeTrigger()
c1f155a9
 	var err error
 
43d56098
 	watch, err := openshift.KubeClient.ReplicationControllers(testutil.Namespace()).Watch(labels.Everything(), fields.Everything(), "0")
4fe0e12a
 	if err != nil {
 		t.Fatalf("Couldn't subscribe to Deployments %v", err)
 	}
3218b81c
 	defer watch.Stop()
4fe0e12a
 
c1f155a9
 	// submit the initial deployment config
4811a486
 	if _, err := openshift.Client.DeploymentConfigs(testutil.Namespace()).Create(config); err != nil {
c1f155a9
 		t.Fatalf("Couldn't create DeploymentConfig: %v", err)
 	}
 
 	// verify the initial deployment exists
 	event := <-watch.ResultChan()
4f679167
 	if e, a := watchapi.Added, event.Type; e != a {
 		t.Fatalf("expected watch event type %s, got %s", e, a)
 	}
 
1964dfe0
 	deployment := event.Object.(*kapi.ReplicationController)
c1f155a9
 
b73a77b1
 	if e, a := config.Name, deployutil.DeploymentConfigNameFor(deployment); e != a {
ebec5535
 		t.Fatalf("Expected deployment annotated with deploymentConfig '%s', got '%s'", e, a)
c1f155a9
 	}
 
ab496df3
 	assertEnvVarEquals("ENV1", "VAL1", deployment, t)
c1f155a9
 
 	// submit a new config with an updated environment variable
4811a486
 	if config, err = openshift.Client.DeploymentConfigs(testutil.Namespace()).Generate(config.Name); err != nil {
c1f155a9
 		t.Fatalf("Error generating config: %v", err)
 	}
 
b7a240bb
 	config.Template.ControllerTemplate.Template.Spec.Containers[0].Env[0].Value = "UPDATED"
c1f155a9
 
f881f281
 	// before we update the config, we need to update the state of the existing deployment
 	// this is required to be done manually since the deployment and deployer pod controllers are not run in this test
 	deployment.Annotations[deployapi.DeploymentStatusAnnotation] = string(deployapi.DeploymentStatusComplete)
 	// update the deployment
 	if _, err = openshift.KubeClient.ReplicationControllers(testutil.Namespace()).Update(deployment); err != nil {
 		t.Fatalf("Error updating existing deployment: %v", err)
 	}
 
 	event = <-watch.ResultChan()
 	if e, a := watchapi.Modified, event.Type; e != a {
 		t.Fatalf("expected watch event type %s, got %s", e, a)
 	}
 
4811a486
 	if _, err := openshift.Client.DeploymentConfigs(testutil.Namespace()).Update(config); err != nil {
c1f155a9
 		t.Fatalf("Couldn't create updated DeploymentConfig: %v", err)
 	}
 
 	event = <-watch.ResultChan()
4f679167
 	if e, a := watchapi.Added, event.Type; e != a {
 		t.Fatalf("expected watch event type %s, got %s", e, a)
 	}
1964dfe0
 	newDeployment := event.Object.(*kapi.ReplicationController)
c1f155a9
 
ab496df3
 	assertEnvVarEquals("ENV1", "UPDATED", newDeployment, t)
4f679167
 
6416316b
 	if newDeployment.Name == deployment.Name {
 		t.Fatalf("expected new deployment; old=%s, new=%s", deployment.Name, newDeployment.Name)
4f679167
 	}
c1f155a9
 }
 
1964dfe0
 func assertEnvVarEquals(name string, value string, deployment *kapi.ReplicationController, t *testing.T) {
 	env := deployment.Spec.Template.Spec.Containers[0].Env
c1f155a9
 
 	for _, e := range env {
 		if e.Name == name && e.Value == value {
 			return
 		}
 	}
 
 	t.Fatalf("Expected env var with name %s and value %s", name, value)
 }
 
e5edb881
 type testDeployOpenshift struct {
1964dfe0
 	Client     *osclient.Client
e5edb881
 	KubeClient *kclient.Client
 	server     *httptest.Server
1964dfe0
 	stop       chan struct{}
e5edb881
 	lock       sync.Mutex
c1f155a9
 }
 
e5edb881
 func NewTestDeployOpenshift(t *testing.T) *testDeployOpenshift {
a68ee2e6
 	t.Logf("Starting test openshift")
c1f155a9
 
e5edb881
 	openshift := &testDeployOpenshift{
13c5a839
 		stop: make(chan struct{}),
 	}
c1f155a9
 
e5edb881
 	openshift.lock.Lock()
 	defer openshift.lock.Unlock()
 
4811a486
 	etcdClient := testutil.NewEtcdClient()
c76e7b47
 	etcdHelper, _ := master.NewEtcdStorage(etcdClient, latest.InterfacesFor, latest.Version, etcdtest.PathPrefix())
c1f155a9
 
 	osMux := http.NewServeMux()
e5edb881
 	openshift.server = httptest.NewServer(osMux)
c1f155a9
 
e5edb881
 	kubeClient := client.NewOrDie(&client.Config{Host: openshift.server.URL, Version: klatest.Version})
 	osClient := osclient.NewOrDie(&client.Config{Host: openshift.server.URL, Version: latest.Version})
c1f155a9
 
 	openshift.Client = osClient
1964dfe0
 	openshift.KubeClient = kubeClient
c1f155a9
 
6416316b
 	kubeletClient, err := kclient.NewKubeletClient(&kclient.KubeletConfig{Port: 10250})
 	if err != nil {
a68ee2e6
 		t.Fatalf("Unable to configure Kubelet client: %v", err)
6416316b
 	}
 
1f227011
 	handlerContainer := master.NewHandlerContainer(osMux)
 
 	_ = master.New(&master.Config{
c76e7b47
 		DatabaseStorage:  etcdHelper,
ad671275
 		KubeletClient:    kubeletClient,
 		APIPrefix:        "/api",
 		AdmissionControl: admit.NewAlwaysAdmit(),
 		RestfulContainer: handlerContainer,
d3282b30
 		DisableV1:        false,
c1f155a9
 	})
 
 	interfaces, _ := latest.InterfacesFor(latest.Version)
 
9f217aa5
 	imageStorage := imageetcd.NewREST(etcdHelper)
 	imageRegistry := image.NewRegistry(imageStorage)
 
e5edb881
 	imageStreamStorage, imageStreamStatus := imagestreametcd.NewREST(
 		etcdHelper,
 		imagestream.DefaultRegistryFunc(func() (string, bool) {
 			return "registry:3000", true
 		}),
 		&fakeSubjectAccessReviewRegistry{},
 	)
 	imageStreamRegistry := imagestream.NewRegistry(imageStreamStorage, imageStreamStatus)
 
 	imageStreamMappingStorage := imagestreammapping.NewREST(imageRegistry, imageStreamRegistry)
 
 	imageStreamImageStorage := imagestreamimage.NewREST(imageRegistry, imageStreamRegistry)
 	//imageStreamImageRegistry := imagestreamimage.NewRegistry(imageStreamImageStorage)
 
 	imageStreamTagStorage := imagestreamtag.NewREST(imageRegistry, imageStreamRegistry)
 	//imageStreamTagRegistry := imagestreamtag.NewRegistry(imageStreamTagStorage)
9f217aa5
 
cbbf48ff
 	deployConfigStorage := deployconfigetcd.NewStorage(etcdHelper)
 	deployConfigRegistry := deployconfigregistry.NewRegistry(deployConfigStorage)
 
c1f155a9
 	deployConfigGenerator := &deployconfiggenerator.DeploymentConfigGenerator{
9a204c15
 		Client: deployconfiggenerator.Client{
cbbf48ff
 			DCFn:   deployConfigRegistry.GetDeploymentConfig,
e5edb881
 			ISFn:   imageStreamRegistry.GetImageStream,
 			LISFn2: imageStreamRegistry.ListImageStreams,
c431087f
 		},
 	}
17d00230
 
418eaa02
 	storage := map[string]rest.Storage{
e5edb881
 		"images":                    imageStorage,
 		"imageStreams":              imageStreamStorage,
 		"imageStreamImages":         imageStreamImageStorage,
 		"imageStreamMappings":       imageStreamMappingStorage,
 		"imageStreamTags":           imageStreamTagStorage,
cbbf48ff
 		"deploymentConfigs":         deployConfigStorage,
969809c1
 		"generateDeploymentConfigs": deployconfiggenerator.NewREST(deployConfigGenerator, latest.Codec),
 	}
 	for k, v := range storage {
 		storage[strings.ToLower(k)] = v
c1f155a9
 	}
 
e1cb421a
 	version := &apiserver.APIGroupVersion{
3008e521
 		Root:    "/oapi",
 		Version: "v1",
e1cb421a
 
 		Storage: storage,
 		Codec:   latest.Codec,
 
 		Mapper: latest.RESTMapper,
 
e5edb881
 		Creater:   kapi.Scheme,
 		Typer:     kapi.Scheme,
 		Convertor: kapi.Scheme,
 		Linker:    interfaces.MetadataAccessor,
e1cb421a
 
 		Admit:   admit.NewAlwaysAdmit(),
 		Context: kapi.NewRequestContextMapper(),
 	}
 	if err := version.InstallREST(handlerContainer); err != nil {
 		t.Fatalf("unable to install REST: %v", err)
 	}
c1f155a9
 
6c68632b
 	dccFactory := deployconfigcontroller.DeploymentConfigControllerFactory{
1964dfe0
 		Client:     osClient,
 		KubeClient: kubeClient,
 		Codec:      latest.Codec,
13c5a839
 	}
c1f155a9
 	dccFactory.Create().Run()
 
224b3b44
 	cccFactory := configchangecontroller.DeploymentConfigChangeControllerFactory{
1964dfe0
 		Client:     osClient,
 		KubeClient: kubeClient,
 		Codec:      latest.Codec,
13c5a839
 	}
c1f155a9
 	cccFactory.Create().Run()
 
224b3b44
 	iccFactory := imagechangecontroller.ImageChangeControllerFactory{
13c5a839
 		Client: osClient,
 	}
c1f155a9
 	iccFactory.Create().Run()
 
 	return openshift
 }
 
e5edb881
 func (t *testDeployOpenshift) Close() {
13c5a839
 }
 
1964dfe0
 type clientDeploymentInterface struct {
 	KubeClient kclient.Interface
 }
 
 func (c *clientDeploymentInterface) GetDeployment(ctx kapi.Context, id string) (*kapi.ReplicationController, error) {
24411f96
 	return c.KubeClient.ReplicationControllers(kapi.NamespaceValue(ctx)).Get(id)
1964dfe0
 }
 
e5edb881
 func makeStream(name, tag, dir, image string) *imageapi.ImageStream {
 	return &imageapi.ImageStream{
ab496df3
 		ObjectMeta: kapi.ObjectMeta{Name: name},
e5edb881
 		Status: imageapi.ImageStreamStatus{
ab496df3
 			Tags: map[string]imageapi.TagEventList{
 				tag: {
 					Items: []imageapi.TagEvent{
 						{
 							DockerImageReference: dir,
 							Image:                image,
c1f155a9
 						},
 					},
 				},
 			},
 		},
 	}
 }