forked from openshift/origin
/
deployment_config_controller.go
115 lines (97 loc) · 3.94 KB
/
deployment_config_controller.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package controller
import (
kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/golang/glog"
deployapi "github.com/openshift/origin/pkg/deploy/api"
deployutil "github.com/openshift/origin/pkg/deploy/util"
)
// DeploymentConfigController is responsible for creating a Deployment when a DeploymentConfig is
// updated with a new LatestVersion. Any deployment created is correlated to a DeploymentConfig
// by setting the DeploymentConfigLabel on the deployment.
type DeploymentConfigController struct {
DeploymentInterface deploymentInterface
// Blocks until the next DeploymentConfig is available
NextDeploymentConfig func() *deployapi.DeploymentConfig
}
type deploymentInterface interface {
GetDeployment(ctx kapi.Context, id string) (*deployapi.Deployment, error)
CreateDeployment(ctx kapi.Context, deployment *deployapi.Deployment) (*deployapi.Deployment, error)
}
// Process DeploymentConfig events one at a time.
func (c *DeploymentConfigController) Run() {
go util.Forever(c.HandleDeploymentConfig, 0)
}
// Process a single DeploymentConfig event.
func (c *DeploymentConfigController) HandleDeploymentConfig() {
config := c.NextDeploymentConfig()
ctx := kapi.WithNamespace(kapi.NewContext(), config.Namespace)
deploy, err := c.shouldDeploy(ctx, config)
if err != nil {
// TODO: better error handling
glog.V(2).Infof("Error determining whether to redeploy deploymentConfig %v: %#v", config.ID, err)
return
}
if !deploy {
glog.V(4).Infof("Won't deploy from config %s", config.ID)
return
}
err = c.deploy(ctx, config)
if err != nil {
glog.V(2).Infof("Error deploying config %s: %v", config.ID, err)
}
}
// shouldDeploy returns true if the DeploymentConfig should have a new Deployment created.
func (c *DeploymentConfigController) shouldDeploy(ctx kapi.Context, config *deployapi.DeploymentConfig) (bool, error) {
if config.LatestVersion == 0 {
glog.V(4).Infof("Shouldn't deploy config %s with LatestVersion=0", config.ID)
return false, nil
}
deployment, err := c.latestDeploymentForConfig(ctx, config)
if deployment != nil {
glog.V(4).Infof("Shouldn't deploy because a deployment '%s' already exists for latest config %s", deployment.ID, config.ID)
return false, nil
}
if err != nil {
if errors.IsNotFound(err) {
glog.V(4).Infof("Should deploy config %s because there's no latest deployment", config.ID)
return true, nil
} else {
glog.V(4).Infof("Shouldn't deploy config %s because of an error looking up latest deployment", config.ID)
return false, err
}
}
// TODO: what state would this represent?
return false, nil
}
// TODO: reduce code duplication between trigger and config controllers
func (c *DeploymentConfigController) latestDeploymentForConfig(ctx kapi.Context, config *deployapi.DeploymentConfig) (*deployapi.Deployment, error) {
latestDeploymentId := deployutil.LatestDeploymentIDForConfig(config)
deployment, err := c.DeploymentInterface.GetDeployment(ctx, latestDeploymentId)
if err != nil {
// TODO: probably some error / race handling to do here
return nil, err
}
return deployment, nil
}
// deploy performs the work of actually creating a Deployment from the given DeploymentConfig.
func (c *DeploymentConfigController) deploy(ctx kapi.Context, config *deployapi.DeploymentConfig) error {
labels := make(map[string]string)
for k, v := range config.Labels {
labels[k] = v
}
labels[deployapi.DeploymentConfigLabel] = config.ID
deployment := &deployapi.Deployment{
TypeMeta: kapi.TypeMeta{
ID: deployutil.LatestDeploymentIDForConfig(config),
},
Labels: labels,
Strategy: config.Template.Strategy,
ControllerTemplate: config.Template.ControllerTemplate,
Details: config.Details,
}
glog.V(4).Infof("Creating new deployment from config %s", config.ID)
_, err := c.DeploymentInterface.CreateDeployment(ctx, deployment)
return err
}