3180f050 |
package rollout
import (
"errors"
"fmt"
"io"
|
6267dded |
"github.com/openshift/origin/pkg/cmd/templates" |
3180f050 |
"github.com/spf13/cobra"
kerrors "k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/meta"
kclient "k8s.io/kubernetes/pkg/client/unversioned"
kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/runtime"
"github.com/openshift/origin/pkg/client"
"github.com/openshift/origin/pkg/cmd/util/clientcmd"
deployapi "github.com/openshift/origin/pkg/deploy/api"
deployutil "github.com/openshift/origin/pkg/deploy/util"
)
|
6267dded |
var (
rolloutLatestLong = templates.LongDesc(`
Start a new rollout for a deployment config with the latest state from its triggers |
3180f050 |
|
6267dded |
This command is appropriate for running manual rollouts. If you want full control over
running new rollouts, use "oc set triggers --manual" to disable all triggers in your
deployment config and then whenever you want to run a new deployment process, use this
command in order to pick up the latest images found in the cluster that are pointed by
your image change triggers.`) |
3180f050 |
|
6267dded |
rolloutLatestExample = templates.Examples(`
# Start a new rollout based on the latest images defined in the image change triggers.
%[1]s rollout latest dc/nginx`) |
3180f050 |
)
// RolloutLatestOptions holds all the options for the `rollout latest` command.
type RolloutLatestOptions struct {
mapper meta.RESTMapper
typer runtime.ObjectTyper
infos []*resource.Info
|
7a2339f4 |
DryRun bool |
14b40ee5 |
out io.Writer
output string
again bool |
3180f050 |
oc client.Interface
kc kclient.Interface
baseCommandName string
}
// NewCmdRolloutLatest implements the oc rollout latest subcommand.
func NewCmdRolloutLatest(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command {
opts := &RolloutLatestOptions{
baseCommandName: fullName,
}
cmd := &cobra.Command{
Use: "latest DEPLOYMENTCONFIG",
Short: "Start a new rollout for a deployment config with the latest state from its triggers",
Long: rolloutLatestLong,
Example: fmt.Sprintf(rolloutLatestExample, fullName),
Run: func(cmd *cobra.Command, args []string) {
err := opts.Complete(f, cmd, args, out)
kcmdutil.CheckErr(err)
if err := opts.Validate(); err != nil {
kcmdutil.CheckErr(kcmdutil.UsageError(cmd, err.Error()))
}
err = opts.RunRolloutLatest()
kcmdutil.CheckErr(err)
}, |
442adafd |
ValidArgs: []string{"deploymentconfig"}, |
3180f050 |
}
|
7a2339f4 |
kcmdutil.AddPrinterFlags(cmd)
kcmdutil.AddDryRunFlag(cmd) |
cc7cbc20 |
cmd.Flags().Bool("again", false, "Deploy the current pod template without updating state from triggers") |
3180f050 |
return cmd
}
func (o *RolloutLatestOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, args []string, out io.Writer) error {
if len(args) != 1 {
return errors.New("one deployment config name is needed as argument.")
}
namespace, _, err := f.DefaultNamespace()
if err != nil {
return err
}
|
7a2339f4 |
o.DryRun = kcmdutil.GetFlagBool(cmd, "dry-run")
|
3180f050 |
o.oc, o.kc, err = f.Clients()
if err != nil {
return err
}
o.mapper, o.typer = f.Object(false)
o.infos, err = resource.NewBuilder(o.mapper, o.typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
NamespaceParam(namespace).
ResourceNames("deploymentconfigs", args[0]).
SingleResourceType().
Do().Infos()
if err != nil {
return err
}
o.out = out |
14b40ee5 |
o.output = kcmdutil.GetFlagString(cmd, "output") |
cc7cbc20 |
o.again = kcmdutil.GetFlagBool(cmd, "again") |
3180f050 |
return nil
}
func (o RolloutLatestOptions) Validate() error {
if len(o.infos) != 1 {
return errors.New("a deployment config name is required.")
}
return nil
}
func (o RolloutLatestOptions) RunRolloutLatest() error {
info := o.infos[0]
config, ok := info.Object.(*deployapi.DeploymentConfig)
if !ok {
return fmt.Errorf("%s is not a deployment config", info.Name)
}
// TODO: Consider allowing one-off deployments for paused configs
// See https://github.com/openshift/origin/issues/9903
if config.Spec.Paused {
return fmt.Errorf("cannot deploy a paused deployment config")
}
deploymentName := deployutil.LatestDeploymentNameForConfig(config)
deployment, err := o.kc.ReplicationControllers(config.Namespace).Get(deploymentName)
switch {
case err == nil:
// Reject attempts to start a concurrent deployment.
if !deployutil.IsTerminatedDeployment(deployment) {
status := deployutil.DeploymentStatusFor(deployment)
return fmt.Errorf("#%d is already in progress (%s).", config.Status.LatestVersion, status)
}
case !kerrors.IsNotFound(err):
return err
}
|
7a2339f4 |
dc := config
if !o.DryRun {
request := &deployapi.DeploymentRequest{
Name: config.Name,
Latest: !o.again,
Force: true,
} |
3180f050 |
|
7a2339f4 |
dc, err = o.oc.DeploymentConfigs(config.Namespace).Instantiate(request)
// Pre 1.4 servers don't support the instantiate endpoint. Fallback to incrementing
// latestVersion on them.
if kerrors.IsNotFound(err) || kerrors.IsForbidden(err) {
config.Status.LatestVersion++
dc, err = o.oc.DeploymentConfigs(config.Namespace).Update(config)
} |
3180f050 |
|
7a2339f4 |
if err != nil {
return err
}
info.Refresh(dc, true)
} |
3180f050 |
|
14b40ee5 |
if o.output == "revision" {
fmt.Fprintf(o.out, fmt.Sprintf("%d", dc.Status.LatestVersion))
return nil
}
|
7a2339f4 |
kcmdutil.PrintSuccess(o.mapper, o.output == "name", o.out, info.Mapping.Resource, info.Name, o.DryRun, "rolled out") |
3180f050 |
return nil
} |