// GetReplicationController returns the most recent replication controller associated with the deploymentConfig // with the provided namespace/name combination func (c *realScalerClient) GetReplicationController(namespace, name string) (*kapi.ReplicationController, error) { dc, err := c.oc.DeploymentConfigs(namespace).Get(name) if err != nil { return nil, err } rcName = util.LatestDeploymentNameForConfig(dc) return c.kc.ReplicationControllers(namespace).Get(rcName) }
// Describe returns the description of a DeploymentConfig func (d *DeploymentConfigDescriber) Describe(namespace, name string) (string, error) { deploymentConfig, err := d.client.getDeploymentConfig(namespace, name) if err != nil { return "", err } events, err := d.client.listEvents(deploymentConfig) if err != nil { return "", err } return tabbedString(func(out *tabwriter.Writer) error { formatMeta(out, deploymentConfig.ObjectMeta) if deploymentConfig.LatestVersion == 0 { formatString(out, "Latest Version", "Not deployed") } else { formatString(out, "Latest Version", strconv.Itoa(deploymentConfig.LatestVersion)) } printTriggers(deploymentConfig.Triggers, out) formatString(out, "Strategy", deploymentConfig.Template.Strategy.Type) printStrategy(deploymentConfig.Template.Strategy, out) printReplicationControllerSpec(deploymentConfig.Template.ControllerTemplate, out) deploymentName := deployutil.LatestDeploymentNameForConfig(deploymentConfig) deployment, err := d.client.getDeployment(namespace, deploymentName) if err != nil { if kerrors.IsNotFound(err) { formatString(out, "Latest Deployment", "<none>") } else { formatString(out, "Latest Deployment", fmt.Sprintf("error: %v", err)) } } else { header := fmt.Sprintf("Deployment #%d (latest)", deployutil.DeploymentVersionFor(deployment)) printDeploymentRc(deployment, d.client, out, header, true) } deploymentsHistory, err := d.client.listDeployments(namespace, labels.Everything()) if err == nil { sorted := rcSorter{} sorted = append(sorted, deploymentsHistory.Items...) sort.Sort(sorted) for _, item := range sorted { if item.Name != deploymentName && deploymentConfig.Name == deployutil.DeploymentConfigNameFor(&item) { header := fmt.Sprintf("Deployment #%d", deployutil.DeploymentVersionFor(&item)) printDeploymentRc(&item, d.client, out, header, false) } } } if events != nil { kctl.DescribeEvents(events, out) } return nil }) }
// retry resets the status of the latest deployment to New, which will cause // the deployment to be retried. An error is returned if the deployment is not // currently in a failed state. func (c *retryDeploymentCommand) retry(config *deployapi.DeploymentConfig, out io.Writer) error { if config.LatestVersion == 0 { return fmt.Errorf("no deployments found for %s/%s", config.Namespace, config.Name) } deploymentName := deployutil.LatestDeploymentNameForConfig(config) deployment, err := c.client.GetDeployment(config.Namespace, deploymentName) if err != nil { if kerrors.IsNotFound(err) { return fmt.Errorf("Unable to find the latest deployment (#%d).\nYou can start a new deployment using the --latest option.", config.LatestVersion) } return err } if status := deployutil.DeploymentStatusFor(deployment); status != deployapi.DeploymentStatusFailed { message := fmt.Sprintf("#%d is %s; only failed deployments can be retried.\n", config.LatestVersion, status) if status == deployapi.DeploymentStatusComplete { message += fmt.Sprintf("You can start a new deployment using the --latest option.") } else { message += fmt.Sprintf("Optionally, you can cancel this deployment using the --cancel option.", config.LatestVersion) } return fmt.Errorf(message) } // Delete the deployer pod as well as the deployment hooks pods, if any pods, err := c.client.ListDeployerPodsFor(config.Namespace, deploymentName) if err != nil { return fmt.Errorf("Failed to list deployer/hook pods for deployment #%d: %v", config.LatestVersion, err) } for _, pod := range pods.Items { err := c.client.DeletePod(&pod) if err != nil { return fmt.Errorf("Failed to delete deployer/hook pod %s for deployment #%d: %v", pod.Name, config.LatestVersion, err) } } deployment.Annotations[deployapi.DeploymentStatusAnnotation] = string(deployapi.DeploymentStatusNew) // clear out the cancellation flag as well as any previous status-reason annotation delete(deployment.Annotations, deployapi.DeploymentStatusReasonAnnotation) delete(deployment.Annotations, deployapi.DeploymentCancelledAnnotation) _, err = c.client.UpdateDeployment(deployment) if err == nil { fmt.Fprintf(out, "retried #%d\n", config.LatestVersion) } return err }
// Describe returns the description of the latest deployments for a config func (d *LatestDeploymentsDescriber) Describe(namespace, name string) (string, error) { config, err := d.client.getDeploymentConfig(namespace, name) if err != nil { return "", err } var deployments []kapi.ReplicationController if d.count == -1 || d.count > 1 { list, err := d.client.listDeployments(namespace, labels.Everything()) if err != nil && !kerrors.IsNotFound(err) { return "", err } deployments = list.Items } else { deploymentName := deployutil.LatestDeploymentNameForConfig(config) deployment, err := d.client.getDeployment(config.Namespace, deploymentName) if err != nil && !kerrors.IsNotFound(err) { return "", err } if deployment != nil { deployments = []kapi.ReplicationController{*deployment} } } g := graph.New() deploy := graph.DeploymentConfig(g, config) if len(deployments) > 0 { graph.JoinDeployments(deploy.(*graph.DeploymentConfigNode), deployments) } return tabbedString(func(out *tabwriter.Writer) error { node := deploy.(*graph.DeploymentConfigNode) descriptions := describeDeployments(node, d.count) for i, description := range descriptions { descriptions[i] = fmt.Sprintf("%v %v", name, description) } printLines(out, "", 0, descriptions...) return nil }) }
// deploy launches a new deployment unless there's already a deployment // process in progress for config. func (c *deployLatestCommand) deploy(config *deployapi.DeploymentConfig, out io.Writer) error { deploymentName := deployutil.LatestDeploymentNameForConfig(config) deployment, err := c.client.GetDeployment(config.Namespace, deploymentName) if err != nil { if !kerrors.IsNotFound(err) { return err } } else { // Reject attempts to start a concurrent deployment. status := deployutil.DeploymentStatusFor(deployment) if status != deployapi.DeploymentStatusComplete && status != deployapi.DeploymentStatusFailed { return fmt.Errorf("#%d is already in progress (%s).\nOptionally, you can cancel this deployment using the --cancel option.", config.LatestVersion, status) } } config.LatestVersion++ _, err = c.client.UpdateDeploymentConfig(config) if err == nil { fmt.Fprintf(out, "deployed #%d\n", config.LatestVersion) } return err }
// Handle processes change triggers for config. func (c *DeploymentConfigChangeController) Handle(config *deployapi.DeploymentConfig) error { hasChangeTrigger := false for _, trigger := range config.Triggers { if trigger.Type == deployapi.DeploymentTriggerOnConfigChange { hasChangeTrigger = true break } } if !hasChangeTrigger { glog.V(4).Infof("Ignoring DeploymentConfig %s; no change triggers detected", deployutil.LabelForDeploymentConfig(config)) return nil } if config.LatestVersion == 0 { _, _, err := c.generateDeployment(config) if err != nil { if kerrors.IsConflict(err) { return fatalError(fmt.Sprintf("DeploymentConfig %s updated since retrieval; aborting trigger: %v", deployutil.LabelForDeploymentConfig(config), err)) } c.recorder.Eventf(config, "failedCreate", "Couldn't create initial deployment: %v", err) return fmt.Errorf("couldn't create initial Deployment for DeploymentConfig %s: %v", deployutil.LabelForDeploymentConfig(config), err) } glog.V(4).Infof("Created initial Deployment for DeploymentConfig %s", deployutil.LabelForDeploymentConfig(config)) return nil } latestDeploymentName := deployutil.LatestDeploymentNameForConfig(config) deployment, err := c.changeStrategy.getDeployment(config.Namespace, latestDeploymentName) if err != nil { // If there's no deployment for the latest config, we have no basis of // comparison. It's the responsibility of the deployment config controller // to make the deployment for the config, so return early. if kerrors.IsNotFound(err) { glog.V(2).Infof("Ignoring change for DeploymentConfig %s; no existing Deployment found", deployutil.LabelForDeploymentConfig(config)) return nil } return fmt.Errorf("couldn't retrieve Deployment for DeploymentConfig %s: %v", deployutil.LabelForDeploymentConfig(config), err) } deployedConfig, err := c.decodeConfig(deployment) if err != nil { return fatalError(fmt.Sprintf("error decoding DeploymentConfig from Deployment %s for DeploymentConfig %s: %v", deployutil.LabelForDeployment(deployment), deployutil.LabelForDeploymentConfig(config), err)) } newSpec, oldSpec := config.Template.ControllerTemplate.Template.Spec, deployedConfig.Template.ControllerTemplate.Template.Spec if kapi.Semantic.DeepEqual(oldSpec, newSpec) { glog.V(2).Infof("Ignoring DeploymentConfig change for %s (latestVersion=%d); same as Deployment %s", deployutil.LabelForDeploymentConfig(config), config.LatestVersion, deployutil.LabelForDeployment(deployment)) return nil } fromVersion, toVersion, err := c.generateDeployment(config) if err != nil { if kerrors.IsConflict(err) { return fatalError(fmt.Sprintf("DeploymentConfig %s updated since retrieval; aborting trigger: %v", deployutil.LabelForDeploymentConfig(config), err)) } return fmt.Errorf("couldn't generate deployment for DeploymentConfig %s: %v", deployutil.LabelForDeploymentConfig(config), err) } glog.V(4).Infof("Updated DeploymentConfig %s from version %d to %d for existing deployment %s", deployutil.LabelForDeploymentConfig(config), fromVersion, toVersion, deployutil.LabelForDeployment(deployment)) return nil }