Skip to content

Commit

Permalink
apps: move deployer controller to external types
Browse files Browse the repository at this point in the history
  • Loading branch information
mfojtik committed Jul 23, 2018
1 parent 4271e4f commit 2208e68
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 136 deletions.
204 changes: 100 additions & 104 deletions pkg/apps/controller/deployer/deployer_controller.go

Large diffs are not rendered by default.

32 changes: 21 additions & 11 deletions pkg/apps/util/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ const (
// DefaultRecreateTimeoutSeconds is the default TimeoutSeconds for RecreateDeploymentStrategyParams.
// Used by strategies:
DefaultRecreateTimeoutSeconds int64 = 10 * 60
DefaultRollingTimeoutSeconds int64 = 10 * 60

// PreHookPodSuffix is the suffix added to all pre hook pods
PreHookPodSuffix = "hook-pre"
Expand All @@ -76,18 +77,27 @@ const (

// Used only internally by utils:

// deploymentStatusReasonAnnotation represents the reason for deployment being in a given state
// DeploymentStatusReasonAnnotation represents the reason for deployment being in a given state
// Used for specifying the reason for cancellation or failure of a deployment
deploymentStatusReasonAnnotation = "openshift.io/deployment.status-reason"
deploymentCancelledAnnotation = "openshift.io/deployment.cancelled"
deploymentCancelledByUser = "cancelled by the user"
DeploymentStatusReasonAnnotation = "openshift.io/deployment.status-reason"
DeploymentIgnorePodAnnotation = "deploy.openshift.io/deployer-pod.ignore"
DeploymentPodAnnotation = "openshift.io/deployer-pod.name"
DeployerPodCreatedAtAnnotation = "openshift.io/deployer-pod.created-at"
DeployerPodStartedAtAnnotation = "openshift.io/deployer-pod.started-at"
DeployerPodCompletedAtAnnotation = "openshift.io/deployer-pod.completed-at"
DeploymentReplicasAnnotation = "openshift.io/deployment.replicas"
DesiredReplicasAnnotation = "kubectl.kubernetes.io/desired-replicas"
DeploymentAnnotation = "openshift.io/deployment.name"
DeploymentConfigAnnotation = "openshift.io/deployment-config.name"

DeploymentFailedUnrelatedDeploymentExists = "unrelated pod with the same name as this deployment is already running"
DeploymentFailedUnableToCreateDeployerPod = "unable to create deployer pod"
DeploymentFailedDeployerPodNoLongerExists = "deployer pod no longer exists"

deploymentCancelledAnnotation = "openshift.io/deployment.cancelled"
deploymentCancelledByUser = "cancelled by the user"

deploymentIgnorePodAnnotation = "deploy.openshift.io/deployer-pod.ignore"
deploymentEncodedConfigAnnotation = "openshift.io/encoded-deployment-config"
deploymentPodAnnotation = "openshift.io/deployer-pod.name"
deploymentAnnotation = "openshift.io/deployment.name"
desiredReplicasAnnotation = "kubectl.kubernetes.io/desired-replicas"
deploymentReplicasAnnotation = "openshift.io/deployment.replicas"
deploymentConfigAnnotation = "openshift.io/deployment-config.name"
deploymentVersionAnnotation = "openshift.io/deployment-config.latest-version"

deploymentVersionAnnotation = "openshift.io/deployment-config.latest-version"
)
18 changes: 9 additions & 9 deletions pkg/apps/util/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func MakeDeployment(config *appsv1.DeploymentConfig) (*v1.ReplicationController,
// Correlate the deployment with the config.
// TODO: Using the annotation constant for now since the value is correct
// but we could consider adding a new constant to the public types.
controllerLabels[deploymentConfigAnnotation] = config.Name
controllerLabels[DeploymentConfigAnnotation] = config.Name

// Ensure that pods created by this deployment controller can be safely associated back
// to the controller, and that multiple deployment controllers for the same config don't
Expand All @@ -80,8 +80,8 @@ func MakeDeployment(config *appsv1.DeploymentConfig) (*v1.ReplicationController,
for k, v := range config.Spec.Template.Annotations {
podAnnotations[k] = v
}
podAnnotations[deploymentAnnotation] = deploymentName
podAnnotations[deploymentConfigAnnotation] = config.Name
podAnnotations[DeploymentAnnotation] = deploymentName
podAnnotations[DeploymentConfigAnnotation] = config.Name
podAnnotations[deploymentVersionAnnotation] = strconv.FormatInt(config.Status.LatestVersion, 10)

controllerRef := newControllerRef(config)
Expand All @@ -91,13 +91,13 @@ func MakeDeployment(config *appsv1.DeploymentConfig) (*v1.ReplicationController,
Name: deploymentName,
Namespace: config.Namespace,
Annotations: map[string]string{
deploymentConfigAnnotation: config.Name,
DeploymentConfigAnnotation: config.Name,
deploymentEncodedConfigAnnotation: string(encodedConfig),
DeploymentStatusAnnotation: string(DeploymentStatusNew),
deploymentVersionAnnotation: strconv.FormatInt(config.Status.LatestVersion, 10),
// This is the target replica count for the new deployment.
desiredReplicasAnnotation: strconv.Itoa(int(config.Spec.Replicas)),
deploymentReplicasAnnotation: strconv.Itoa(0),
DesiredReplicasAnnotation: strconv.Itoa(int(config.Spec.Replicas)),
DeploymentReplicasAnnotation: strconv.Itoa(0),
},
Labels: controllerLabels,
OwnerReferences: []metav1.OwnerReference{*controllerRef},
Expand All @@ -117,10 +117,10 @@ func MakeDeployment(config *appsv1.DeploymentConfig) (*v1.ReplicationController,
},
}
if config.Status.Details != nil && len(config.Status.Details.Message) > 0 {
deployment.Annotations[deploymentStatusReasonAnnotation] = config.Status.Details.Message
deployment.Annotations[DeploymentStatusReasonAnnotation] = config.Status.Details.Message
}
if value, ok := config.Annotations[deploymentIgnorePodAnnotation]; ok {
deployment.Annotations[deploymentIgnorePodAnnotation] = value
if value, ok := config.Annotations[DeploymentIgnorePodAnnotation]; ok {
deployment.Annotations[DeploymentIgnorePodAnnotation] = value
}

return deployment, nil
Expand Down
80 changes: 72 additions & 8 deletions pkg/apps/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"reflect"
"strconv"
"strings"
"time"

"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
Expand Down Expand Up @@ -60,6 +61,42 @@ func DecodeDeploymentConfig(controller metav1.ObjectMetaAccessor) (*appsv1.Deplo
return externalConfig, nil
}

// RolloutExceededTimeoutSeconds returns true if the current deployment exceeded
// the timeoutSeconds defined for its strategy.
// Note that this is different than activeDeadlineSeconds which is the timeout
// set for the deployer pod. In some cases, the deployer pod cannot be created
// (like quota, etc...). In that case deployer controller use this function to
// measure if the created deployment (RC) exceeded the timeout.
func RolloutExceededTimeoutSeconds(config *appsv1.DeploymentConfig, latestRC *v1.ReplicationController) bool {
timeoutSeconds := GetTimeoutSecondsForStrategy(config)
// If user set the timeoutSeconds to 0, we assume there should be no timeout.
if timeoutSeconds <= 0 {
return false
}
return int64(time.Since(latestRC.CreationTimestamp.Time).Seconds()) > timeoutSeconds
}

// GetTimeoutSecondsForStrategy returns the timeout in seconds defined in the
// deployment config strategy.
func GetTimeoutSecondsForStrategy(config *appsv1.DeploymentConfig) int64 {
var timeoutSeconds int64
switch config.Spec.Strategy.Type {
case appsv1.DeploymentStrategyTypeRolling:
timeoutSeconds = DefaultRollingTimeoutSeconds
if t := config.Spec.Strategy.RollingParams.TimeoutSeconds; t != nil {
timeoutSeconds = *t
}
case appsv1.DeploymentStrategyTypeRecreate:
timeoutSeconds = DefaultRecreateTimeoutSeconds
if t := config.Spec.Strategy.RecreateParams.TimeoutSeconds; t != nil {
timeoutSeconds = *t
}
case appsv1.DeploymentStrategyTypeCustom:
timeoutSeconds = DefaultRecreateTimeoutSeconds
}
return timeoutSeconds
}

func NewReplicationControllerScaler(client kubernetes.Interface) kubectl.Scaler {
return kubectl.NewScaler(NewReplicationControllerScaleClient(client))
}
Expand All @@ -80,7 +117,7 @@ func LabelForDeployment(deployment *v1.ReplicationController) string {

// DeploymentDesiredReplicas returns number of desired replica for the given replication controller
func DeploymentDesiredReplicas(obj runtime.Object) (int32, bool) {
return int32AnnotationFor(obj, desiredReplicasAnnotation)
return int32AnnotationFor(obj, DesiredReplicasAnnotation)
}

// LatestDeploymentNameForConfig returns a stable identifier for deployment config
Expand All @@ -94,25 +131,25 @@ func LatestDeploymentNameForConfigAndVersion(name string, version int64) string
}

func DeployerPodNameFor(obj runtime.Object) string {
return AnnotationFor(obj, deploymentPodAnnotation)
return AnnotationFor(obj, DeploymentPodAnnotation)
}

func DeploymentConfigNameFor(obj runtime.Object) string {
return AnnotationFor(obj, deploymentConfigAnnotation)
return AnnotationFor(obj, DeploymentConfigAnnotation)
}

func DeploymentStatusReasonFor(obj runtime.Object) string {
return AnnotationFor(obj, deploymentStatusReasonAnnotation)
return AnnotationFor(obj, DeploymentStatusReasonAnnotation)
}

func DeleteStatusReasons(rc *v1.ReplicationController) {
delete(rc.Annotations, deploymentStatusReasonAnnotation)
delete(rc.Annotations, DeploymentStatusReasonAnnotation)
delete(rc.Annotations, deploymentCancelledAnnotation)
}

func SetCancellationReasons(rc *v1.ReplicationController) {
rc.Annotations[deploymentCancelledAnnotation] = "true"
rc.Annotations[deploymentStatusReasonAnnotation] = deploymentCancelledByUser
rc.Annotations[DeploymentStatusReasonAnnotation] = deploymentCancelledByUser
}

// HasSynced checks if the provided deployment config has been noticed by the deployment
Expand Down Expand Up @@ -203,7 +240,7 @@ func ActiveDeployment(input []*v1.ReplicationController) *v1.ReplicationControll
// TODO: Using the annotation constant for now since the value is correct
// but we could consider adding a new constant to the public types.
func ConfigSelector(name string) labels.Selector {
return labels.SelectorFromValidatedSet(labels.Set{deploymentConfigAnnotation: name})
return labels.SelectorFromValidatedSet(labels.Set{DeploymentConfigAnnotation: name})
}

// IsCompleteDeployment returns true if the passed deployment is in state complete.
Expand Down Expand Up @@ -246,7 +283,7 @@ func DeploymentVersionFor(obj runtime.Object) int64 {
}

func DeploymentNameFor(obj runtime.Object) string {
return AnnotationFor(obj, deploymentAnnotation)
return AnnotationFor(obj, DeploymentAnnotation)
}

// GetDeploymentCondition returns the condition with the provided type.
Expand Down Expand Up @@ -319,6 +356,33 @@ func HasImageChangeTrigger(config *appsv1.DeploymentConfig) bool {
return false
}

// CanTransitionPhase returns whether it is allowed to go from the current to the next phase.
func CanTransitionPhase(current, next DeploymentStatus) bool {
switch current {
case DeploymentStatusNew:
switch next {
case DeploymentStatusPending,
DeploymentStatusRunning,
DeploymentStatusFailed,
DeploymentStatusComplete:
return true
}
case DeploymentStatusPending:
switch next {
case DeploymentStatusRunning,
DeploymentStatusFailed,
DeploymentStatusComplete:
return true
}
case DeploymentStatusRunning:
switch next {
case DeploymentStatusFailed, DeploymentStatusComplete:
return true
}
}
return false
}

func int32AnnotationFor(obj runtime.Object, key string) (int32, bool) {
s := AnnotationFor(obj, key)
if len(s) == 0 {
Expand Down
3 changes: 1 addition & 2 deletions pkg/oc/cli/deploy/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,6 @@ func (o DeployOptions) RunDeploy() error {
if o.follow {
return o.getLogs(config)
}
// TODO: HERE
describer := describe.NewLatestDeploymentsDescriber(o.appsClient, o.kubeClient, -1)
desc, err := describer.Describe(config.Namespace, config.Name)
if err != nil {
Expand Down Expand Up @@ -343,7 +342,7 @@ func (o DeployOptions) retry(config *appsv1.DeploymentConfig) error {
}
}

deployment.Annotations[appsutil.DeploymentStatusAnnotation] = "New"
deployment.Annotations[appsutil.DeploymentStatusAnnotation] = string(appsutil.DeploymentStatusNew)
// clear out the cancellation flag as well as any previous status-reason annotation
appsutil.DeleteStatusReasons(deployment)
_, err = o.kubeClient.CoreV1().ReplicationControllers(deployment.Namespace).Update(deployment)
Expand Down
3 changes: 1 addition & 2 deletions pkg/oc/cli/rollout/cancel.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,7 @@ func (o CancelOptions) Run() error {
}

func (o CancelOptions) forEachControllerInConfig(namespace, name string, mutateFunc func(*corev1.ReplicationController) bool) ([]*corev1.ReplicationController, bool, error) {
deploymentList, err := o.KubeClient.CoreV1().ReplicationControllers(namespace).List(metav1.ListOptions{LabelSelector: appsutil.ConfigSelector(
name).String()})
deploymentList, err := o.KubeClient.CoreV1().ReplicationControllers(namespace).List(metav1.ListOptions{LabelSelector: appsutil.ConfigSelector(name).String()})
if err != nil {
return nil, false, err
}
Expand Down
1 change: 1 addition & 0 deletions pkg/oc/lib/describe/deployments_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ func TestDeploymentConfigDescriber(t *testing.T) {
}

podList.Items = []corev1.Pod{*mkV1Pod(corev1.PodRunning, 0)}
// TODO: re-enable when we switch describer to external client
/*
substr := "Autoscaling:\tbetween 1 and 3 replicas"
if !strings.Contains(out, substr) {
Expand Down

0 comments on commit 2208e68

Please sign in to comment.