Skip to content

Commit

Permalink
Implement deployments without Deployment
Browse files Browse the repository at this point in the history
Deprecate the Deployment resource and remplement deployment mechanics
using ReplicationControllers instead of Deployment. The result is a deployment
subsystem which adds fewer new concepts to Kubernetes while providing the same
functionality as the former subsystem.
  • Loading branch information
ironcladlou committed Jan 8, 2015
1 parent 986ac46 commit 0eb0234
Show file tree
Hide file tree
Showing 22 changed files with 569 additions and 390 deletions.
10 changes: 7 additions & 3 deletions assets/app/scripts/controllers/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,18 @@ angular.module('openshiftConsole')
// Sets up subscription for deployments and deploymentsByConfig
var deploymentsCallback = function(action, deployment) {
$scope.$apply(function() {
DataService.objectByAttribute(deployment, "metadata.name", $scope.deployments, action);
DataService.objectByAttribute(deployment, "metadata.annotations.deploymentConfig", $scope.deploymentsByConfig, action, "id");
if (deployment.annotations && deployment.annotations.encodedDeploymentConfig) {
var depConfig = $.parseJSON(deployment.annotations.encodedDeploymentConfig);
deployment.details = depConfig.details;
}
DataService.objectByAttribute(deployment, "id", $scope.deployments, action);
DataService.objectByAttribute(deployment, "annotations.deploymentConfig", $scope.deploymentsByConfig, action, "id");
});

console.log("deployments (subscribe)", $scope.deployments);
console.log("deploymentsByConfig (subscribe)", $scope.deploymentsByConfig);
};
DataService.subscribe("deployments", deploymentsCallback, $scope);
DataService.subscribe("replicationControllers", deploymentsCallback, $scope);

// Sets up subscription for images and imagesByDockerReference
var imagesCallback = function(action, image) {
Expand Down
3 changes: 2 additions & 1 deletion assets/app/scripts/services/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ angular.module('openshiftConsole')
images : "osapi",
projects : "osapi",
pods : "api",
services : "api"
services : "api",
replicationControllers: "api"
};

function DataService() {
Expand Down
8 changes: 4 additions & 4 deletions assets/app/views/project.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ <h2 class="service">{{serviceId}}
</div>
</div>
<div ng-repeat="deployment in deploymentsByConfig[deploymentConfigId]" style="margin-top: 10px; text-align: center;">
<div ng-if="servicePodsByLabel.deployment[deployment.metadata.name]">
<div ng-if="servicePodsByLabel.deployment[deployment.id]">
<div class="small muted" ng-if="deployment" style="margin-bottom: 10px;">
<relative-timestamp timestamp="deployment.metadata.creationTimestamp"></relative-timestamp>
<relative-timestamp timestamp="deployment.creationTimestamp"></relative-timestamp>
<span ng-if="deployment.details && deployment.details.causes && deployment.details.causes.length > 0">
<span>, triggered by
<span ng-repeat="cause in deployment.details.causes">
Expand All @@ -48,8 +48,8 @@ <h2 class="service">{{serviceId}}
</div>
<div style="display: inline-block;">
<!-- TODO figure out why podTemplate can't be done the same way as pods -->
<pod-template ng-init="podTemplate = deployment.controllerTemplate.podTemplate"></pod-template>
<pods pods="servicePodsByLabel.deployment[deployment.metadata.name]"></pods>
<pod-template ng-init="podTemplate = deployment.desiredState.podTemplate"></pod-template>
<pods pods="servicePodsByLabel.deployment[deployment.id]"></pods>
</div>
</div>
</div>
Expand Down
13 changes: 9 additions & 4 deletions pkg/assets/bindata.go
Original file line number Diff line number Diff line change
Expand Up @@ -1084,7 +1084,8 @@ deploymentConfigs:"osapi",
images:"osapi",
projects:"osapi",
pods:"api",
services:"api"
services:"api",
replicationControllers:"api"
};
a.prototype.getList = function(a, b, c) {
if (b.fire) {
Expand Down Expand Up @@ -1247,10 +1248,14 @@ f(d), e(b), c.subscribe("services", g, a), c.subscribePolling("pods", e, a);
}, this));
var i = function(b, d) {
a.$apply(function() {
c.objectByAttribute(d, "metadata.name", a.deployments, b), c.objectByAttribute(d, "metadata.annotations.deploymentConfig", a.deploymentsByConfig, b, "id");
if (d.annotations && d.annotations.encodedDeploymentConfig) {
var e = $.parseJSON(d.annotations.encodedDeploymentConfig);
d.details = e.details;
}
c.objectByAttribute(d, "id", a.deployments, b), c.objectByAttribute(d, "annotations.deploymentConfig", a.deploymentsByConfig, b, "id");
}), console.log("deployments (subscribe)", a.deployments), console.log("deploymentsByConfig (subscribe)", a.deploymentsByConfig);
};
c.subscribe("deployments", i, a);
c.subscribe("replicationControllers", i, a);
var j = function(b, d) {
a.$apply(function() {
c.objectByAttribute(d, "metadata.name", a.images, b), c.objectByAttribute(d, "dockerImageReference", a.imagesByDockerReference, b);
Expand Down Expand Up @@ -45546,7 +45551,7 @@ func views_pods_html2() ([]byte, error) {
return _views_pods_html2, nil
}

var _views_project_html = []byte(`<div> <h1 style="margin-top: 10px">Project {{project.displayName || project.metadata.name}}</h1> <div class="small muted" style="margin-top: -15px; margin-bottom: 20px" ng-if="project | annotation : 'description'">{{project | annotation : 'description'}}</div> <!-- TODO handle things that don't live under services --> <!-- TODO handle multiple services mapping to the same deploymentConfig/deployment/pod --> <section ng-repeat="(serviceId, servicePodsByLabel) in podsByServiceByLabel"> <div class="row"> <div class="col-md-12"> <div class="tile"> <h2 class="service">{{serviceId}} <span class="small"> - routing {{services[serviceId].protocol}} traffic on {{services[serviceId].portalIP}}:{{services[serviceId].port}} to port {{services[serviceId].containerPort}}</span> <span class="connector connector-vertical" style="left: 50%; top: 35px; height: 21px"> <span class="connector-endpoint connector-endpoint-top"></span> <span class="connector-line" style="height: 21px"></span> <span class="connector-endpoint" style="top: 18px"></span> </span> </h2> <div class="separator"></div> <div ng-repeat="(deploymentConfigId, deploymentConfig) in deploymentConfigs" ng-if="!deploymentConfig || services[serviceId].selector.name == deploymentConfig.template.controllerTemplate.replicaSelector.name"> <!-- deploymentConfig could be null when we have any deployments that were not generated from a deploymentConfig --> <div ng-if="deploymentConfig"> <div ng-repeat="trigger in deploymentConfig.triggers"> <div ng-repeat="build in trigger.builds" style="border-bottom: 1px solid #ddd; padding-bottom: 10px; margin-top: 10px" ng-if="(build.status != 'Complete' && build.status != 'Failed') || (build.metadata.creationTimestamp | ageLessThan : 5 : 'minutes')" class="animate-repeat"> <span ng-switch="build.status" class="hide-ng-leave"> <span ng-switch-when="Complete" class="font-icon icon-ok font-icon-green" aria-hidden="true" style="margin-right: 5px"></span> <span ng-switch-when="Failed" class="font-icon icon-remove font-icon-red" aria-hidden="true" style="margin-right: 5px"></span> <span ng-switch-default class="font-icon icon-ci-arrows clockwise" aria-hidden="true" style="margin-right: 5px"></span> </span> <span>A build of {{build.metadata.labels.buildconfig}} is {{build.status | lowercase}}.</span> <span ng-if="build.status != 'Complete' && build.status != 'Failed' && trigger.imageChangeParams.automatic"> A new deployment will be created automatically once the build completes.</span> </div> </div> </div> <div ng-repeat="deployment in deploymentsByConfig[deploymentConfigId]" style="margin-top: 10px; text-align: center"> <div ng-if="servicePodsByLabel.deployment[deployment.metadata.name]"> <div class="small muted" ng-if="deployment" style="margin-bottom: 10px"> <relative-timestamp timestamp="deployment.metadata.creationTimestamp"></relative-timestamp> <span ng-if="deployment.details && deployment.details.causes && deployment.details.causes.length > 0"> <span>, triggered by <span ng-repeat="cause in deployment.details.causes"> <span ng-switch="cause.type"> <span ng-switch-when="ImageChange">new image for {{cause.imageTrigger.repositoryName | imageName}}:{{cause.imageTrigger.tag}}</span> <span ng-switch-when="ConfigChange">deployment configuration change</span> </span> </span> </span> </span> </div> <div style="display: inline-block"> <!-- TODO figure out why podTemplate can't be done the same way as pods --> <pod-template ng-init="podTemplate = deployment.controllerTemplate.podTemplate"></pod-template> <pods pods="servicePodsByLabel.deployment[deployment.metadata.name]"></pods> </div> </div> </div> </div> <!-- TODO implement filters for empty and present to return booleans for cases like this --> <div ng-if="(servicePodsByLabel | hashSize) == 0" style="margin-top: 10px"> <span style="margin-left: 20px">There are currently no pods for this service.</span> </div> </div> </div> </div> </section> </div>`)
var _views_project_html = []byte(`<div> <h1 style="margin-top: 10px">Project {{project.displayName || project.metadata.name}}</h1> <div class="small muted" style="margin-top: -15px; margin-bottom: 20px" ng-if="project | annotation : 'description'">{{project | annotation : 'description'}}</div> <!-- TODO handle things that don't live under services --> <!-- TODO handle multiple services mapping to the same deploymentConfig/deployment/pod --> <section ng-repeat="(serviceId, servicePodsByLabel) in podsByServiceByLabel"> <div class="row"> <div class="col-md-12"> <div class="tile"> <h2 class="service">{{serviceId}} <span class="small"> - routing {{services[serviceId].protocol}} traffic on {{services[serviceId].portalIP}}:{{services[serviceId].port}} to port {{services[serviceId].containerPort}}</span> <span class="connector connector-vertical" style="left: 50%; top: 35px; height: 21px"> <span class="connector-endpoint connector-endpoint-top"></span> <span class="connector-line" style="height: 21px"></span> <span class="connector-endpoint" style="top: 18px"></span> </span> </h2> <div class="separator"></div> <div ng-repeat="(deploymentConfigId, deploymentConfig) in deploymentConfigs" ng-if="!deploymentConfig || services[serviceId].selector.name == deploymentConfig.template.controllerTemplate.replicaSelector.name"> <!-- deploymentConfig could be null when we have any deployments that were not generated from a deploymentConfig --> <div ng-if="deploymentConfig"> <div ng-repeat="trigger in deploymentConfig.triggers"> <div ng-repeat="build in trigger.builds" style="border-bottom: 1px solid #ddd; padding-bottom: 10px; margin-top: 10px" ng-if="(build.status != 'Complete' && build.status != 'Failed') || (build.metadata.creationTimestamp | ageLessThan : 5 : 'minutes')" class="animate-repeat"> <span ng-switch="build.status" class="hide-ng-leave"> <span ng-switch-when="Complete" class="font-icon icon-ok font-icon-green" aria-hidden="true" style="margin-right: 5px"></span> <span ng-switch-when="Failed" class="font-icon icon-remove font-icon-red" aria-hidden="true" style="margin-right: 5px"></span> <span ng-switch-default class="font-icon icon-ci-arrows clockwise" aria-hidden="true" style="margin-right: 5px"></span> </span> <span>A build of {{build.metadata.labels.buildconfig}} is {{build.status | lowercase}}.</span> <span ng-if="build.status != 'Complete' && build.status != 'Failed' && trigger.imageChangeParams.automatic"> A new deployment will be created automatically once the build completes.</span> </div> </div> </div> <div ng-repeat="deployment in deploymentsByConfig[deploymentConfigId]" style="margin-top: 10px; text-align: center"> <div ng-if="servicePodsByLabel.deployment[deployment.id]"> <div class="small muted" ng-if="deployment" style="margin-bottom: 10px"> <relative-timestamp timestamp="deployment.creationTimestamp"></relative-timestamp> <span ng-if="deployment.details && deployment.details.causes && deployment.details.causes.length > 0"> <span>, triggered by <span ng-repeat="cause in deployment.details.causes"> <span ng-switch="cause.type"> <span ng-switch-when="ImageChange">new image for {{cause.imageTrigger.repositoryName | imageName}}:{{cause.imageTrigger.tag}}</span> <span ng-switch-when="ConfigChange">deployment configuration change</span> </span> </span> </span> </span> </div> <div style="display: inline-block"> <!-- TODO figure out why podTemplate can't be done the same way as pods --> <pod-template ng-init="podTemplate = deployment.desiredState.podTemplate"></pod-template> <pods pods="servicePodsByLabel.deployment[deployment.id]"></pods> </div> </div> </div> </div> <!-- TODO implement filters for empty and present to return booleans for cases like this --> <div ng-if="(servicePodsByLabel | hashSize) == 0" style="margin-top: 10px"> <span style="margin-left: 20px">There are currently no pods for this service.</span> </div> </div> </div> </div> </section> </div>`)

func views_project_html() ([]byte, error) {
return _views_project_html, nil
Expand Down
15 changes: 10 additions & 5 deletions pkg/cmd/infra/deployer/deployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import (
"github.com/golang/glog"
"github.com/spf13/cobra"

kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api"

"github.com/openshift/origin/pkg/api/latest"
"github.com/openshift/origin/pkg/cmd/util"
"github.com/openshift/origin/pkg/cmd/util/clientcmd"
deployapi "github.com/openshift/origin/pkg/deploy/api"
strategy "github.com/openshift/origin/pkg/deploy/strategy/recreate"
)

Expand Down Expand Up @@ -52,20 +54,23 @@ func NewCommandDeployer(name string) *cobra.Command {

// deploy starts the deployer
func deploy(cfg *config) error {
kClient, osClient, err := cfg.Config.Clients()
kClient, _, err := cfg.Config.Clients()
if err != nil {
return err
}
if len(cfg.DeploymentName) == 0 {
return errors.New("No deployment name was specified.")
}

var deployment *deployapi.Deployment
if deployment, err = osClient.Deployments(cfg.Namespace).Get(cfg.DeploymentName); err != nil {
var deployment *kapi.ReplicationController
if deployment, err = kClient.ReplicationControllers(cfg.Namespace).Get(cfg.DeploymentName); err != nil {
return err
}

// TODO: Choose a strategy based on some input
strategy := &strategy.DeploymentStrategy{strategy.RealReplicationController{KubeClient: kClient}}
strategy := &strategy.DeploymentStrategy{
ReplicationController: strategy.RealReplicationController{KubeClient: kClient},
Codec: latest.Codec,
}
return strategy.Deploy(deployment)
}
24 changes: 21 additions & 3 deletions pkg/cmd/server/origin/master.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,10 @@ func (c *MasterConfig) InstallAPI(container *restful.Container) []string {
oauthEtcd := oauthetcd.New(c.EtcdHelper)

deployConfigGenerator := &deployconfiggenerator.DeploymentConfigGenerator{
DeploymentInterface: deployEtcd,
DeploymentInterface: &clientDeploymentInterface{c.KubeClient},
DeploymentConfigInterface: deployEtcd,
ImageRepositoryInterface: imageEtcd,
Codec: latest.Codec,
}

defaultRegistry := env("OPENSHIFT_DEFAULT_REGISTRY", "")
Expand Down Expand Up @@ -354,6 +355,7 @@ func (c *MasterConfig) RunDeploymentController() {
factory := deploycontrollerfactory.DeploymentControllerFactory{
Client: c.OSClient,
KubeClient: c.KubeClient,
Codec: latest.Codec,
Environment: []api.EnvVar{
{Name: "KUBERNETES_MASTER", Value: c.MasterAddr},
{Name: "OPENSHIFT_MASTER", Value: c.MasterAddr},
Expand All @@ -367,13 +369,21 @@ func (c *MasterConfig) RunDeploymentController() {
}

func (c *MasterConfig) RunDeploymentConfigController() {
factory := deploycontrollerfactory.DeploymentConfigControllerFactory{Client: c.OSClient}
factory := deploycontrollerfactory.DeploymentConfigControllerFactory{
Client: c.OSClient,
KubeClient: c.KubeClient,
Codec: latest.Codec,
}
controller := factory.Create()
controller.Run()
}

func (c *MasterConfig) RunDeploymentConfigChangeController() {
factory := deploycontrollerfactory.DeploymentConfigChangeControllerFactory{Client: c.OSClient}
factory := deploycontrollerfactory.DeploymentConfigChangeControllerFactory{
Client: c.OSClient,
KubeClient: c.KubeClient,
Codec: latest.Codec,
}
controller := factory.Create()
controller.Run()
}
Expand Down Expand Up @@ -420,3 +430,11 @@ func (c ClientWebhookInterface) CreateBuild(namespace string, build *buildapi.Bu
func (c ClientWebhookInterface) GetBuildConfig(namespace, name string) (*buildapi.BuildConfig, error) {
return c.Client.BuildConfigs(namespace).Get(name)
}

type clientDeploymentInterface struct {
KubeClient kclient.Interface
}

func (c *clientDeploymentInterface) GetDeployment(ctx api.Context, id string) (*api.ReplicationController, error) {
return c.KubeClient.ReplicationControllers(api.Namespace(ctx)).Get(id)
}
Loading

0 comments on commit 0eb0234

Please sign in to comment.