// Complete fills CreateBasicAuthSecretOptions fields with data and checks for mutual exclusivity // between flags from different option groups. func (o *CreateBasicAuthSecretOptions) Complete(f kcmdutil.Factory, args []string) error { if len(args) != 1 { return errors.New("must have exactly one argument: secret name") } o.SecretName = args[0] if o.PromptForPassword { if len(o.Password) != 0 { return errors.New("must provide either --prompt or --password flag") } if !kterm.IsTerminal(o.Reader) { return errors.New("provided reader is not a terminal") } o.Password = term.PromptForPasswordString(o.Reader, o.Out, "Password: "******"password must be provided") } } if f != nil { client, err := f.ClientSet() if err != nil { return err } namespace, _, err := f.DefaultNamespace() if err != nil { return err } o.SecretsInterface = client.Core().Secrets(namespace) } return nil }
func execute(f cmdutil.Factory, cmd *cobra.Command, options *ExecOptions) error { if len(options.Namespace) == 0 { namespace, _, err := f.DefaultNamespace() if err != nil { return err } options.Namespace = namespace } container := cmdutil.GetFlagString(cmd, "container") if len(container) > 0 { options.ContainerName = container } config, err := f.ClientConfig() if err != nil { return err } options.Config = config clientset, err := f.ClientSet() if err != nil { return err } options.PodClient = clientset.Core() if err := options.Validate(); err != nil { return err } if err := options.Run(); err != nil { return err } return nil }
// createSecret extracts the kubeconfig for a given cluster and populates // a secret with that kubeconfig. func createSecret(hostFactory cmdutil.Factory, clientConfig *clientcmdapi.Config, namespace, contextName, secretName string, dryRun bool) (runtime.Object, error) { // Minify the kubeconfig to ensure that there is only information // relevant to the cluster we are registering. newClientConfig, err := minifyConfig(clientConfig, contextName) if err != nil { glog.V(2).Infof("Failed to minify the kubeconfig for the given context %q: %v", contextName, err) return nil, err } // Flatten the kubeconfig to ensure that all the referenced file // contents are inlined. err = clientcmdapi.FlattenConfig(newClientConfig) if err != nil { glog.V(2).Infof("Failed to flatten the kubeconfig for the given context %q: %v", contextName, err) return nil, err } // Boilerplate to create the secret in the host cluster. clientset, err := hostFactory.ClientSet() if err != nil { glog.V(2).Infof("Failed to serialize the kubeconfig for the given context %q: %v", contextName, err) return nil, err } return util.CreateKubeconfigSecret(clientset, newClientConfig, namespace, secretName, dryRun) }
func RunVersion(f cmdutil.Factory, out io.Writer, cmd *cobra.Command) error { v := fmt.Sprintf("%#v", version.Get()) if cmdutil.GetFlagBool(cmd, "short") { v = version.Get().GitVersion } fmt.Fprintf(out, "Client Version: %s\n", v) if cmdutil.GetFlagBool(cmd, "client") { return nil } clientset, err := f.ClientSet() if err != nil { return err } serverVersion, err := clientset.Discovery().ServerVersion() if err != nil { return err } v = fmt.Sprintf("%#v", *serverVersion) if cmdutil.GetFlagBool(cmd, "short") { v = serverVersion.GitVersion } fmt.Fprintf(out, "Server Version: %s\n", v) return nil }
// deleteSecret deletes the secret with the given name from the host // cluster. func deleteSecret(hostFactory cmdutil.Factory, name, namespace string) error { clientset, err := hostFactory.ClientSet() if err != nil { return err } return clientset.Core().Secrets(namespace).Delete(name, &api.DeleteOptions{}) }
// Complete verifies command line arguments and loads data from the command environment func (p *AttachOptions) Complete(f *cmdutil.Factory, cmd *cobra.Command, argsIn []string) error { if len(argsIn) == 0 { return cmdutil.UsageError(cmd, "POD is required for attach") } if len(argsIn) > 1 { return cmdutil.UsageError(cmd, fmt.Sprintf("expected a single argument: POD, saw %d: %s", len(argsIn), argsIn)) } p.PodName = argsIn[0] namespace, _, err := f.DefaultNamespace() if err != nil { return err } p.Namespace = namespace config, err := f.ClientConfig() if err != nil { return err } p.Config = config clientset, err := f.ClientSet() if err != nil { return err } p.PodClient = clientset.Core() if p.CommandName == "" { p.CommandName = cmd.CommandPath() } return nil }
func handleAttachPod(f *cmdutil.Factory, c *client.Client, ns, name string, opts *AttachOptions, quiet bool) error { pod, err := waitForPodRunning(c, ns, name, opts.Out, quiet) if err != nil { return err } ctrName, err := opts.GetContainerName(pod) if err != nil { return err } if pod.Status.Phase == api.PodSucceeded || pod.Status.Phase == api.PodFailed { req, err := f.LogsForObject(pod, &api.PodLogOptions{Container: ctrName}) if err != nil { return err } readCloser, err := req.Stream() if err != nil { return err } defer readCloser.Close() _, err = io.Copy(opts.Out, readCloser) return err } clientset, err := f.ClientSet() if err != nil { return nil } opts.PodClient = clientset.Core() opts.PodName = name opts.Namespace = ns // TODO: opts.Run sets opts.Err to nil, we need to find a better way stderr := opts.Err if err := opts.Run(); err != nil { fmt.Fprintf(stderr, "Error attaching, falling back to logs: %v\n", err) req, err := f.LogsForObject(pod, &api.PodLogOptions{Container: ctrName}) if err != nil { return err } readCloser, err := req.Stream() if err != nil { return err } defer readCloser.Close() _, err = io.Copy(opts.Out, readCloser) return err } return nil }
// Complete verifies command line arguments and loads data from the command environment func (p *ExecOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn []string, argsLenAtDash int) error { // Let kubectl exec follow rules for `--`, see #13004 issue if len(p.PodName) == 0 && (len(argsIn) == 0 || argsLenAtDash == 0) { return cmdutil.UsageError(cmd, execUsageStr) } if len(p.PodName) != 0 { printDeprecationWarning("exec POD_NAME", "-p POD_NAME") if len(argsIn) < 1 { return cmdutil.UsageError(cmd, execUsageStr) } p.Command = argsIn } else { p.PodName = argsIn[0] p.Command = argsIn[1:] if len(p.Command) < 1 { return cmdutil.UsageError(cmd, execUsageStr) } } cmdParent := cmd.Parent() if cmdParent != nil { p.FullCmdName = cmdParent.CommandPath() } if len(p.FullCmdName) > 0 && cmdutil.IsSiblingCommandExists(cmd, "describe") { p.SuggestedCmdUsage = fmt.Sprintf("Use '%s describe pod/%s' to see all of the containers in this pod.", p.FullCmdName, p.PodName) } namespace, _, err := f.DefaultNamespace() if err != nil { return err } p.Namespace = namespace config, err := f.ClientConfig() if err != nil { return err } p.Config = config clientset, err := f.ClientSet() if err != nil { return err } p.PodClient = clientset.Core() return nil }
func (o *TopNodeOptions) Complete(f *cmdutil.Factory, cmd *cobra.Command, args []string, out io.Writer) error { var err error if len(args) == 1 { o.ResourceName = args[0] } else if len(args) > 1 { return cmdutil.UsageError(cmd, cmd.Use) } clientset, err := f.ClientSet() if err != nil { return err } o.NodeClient = clientset.Core() o.Client = metricsutil.DefaultHeapsterMetricsClient(clientset.Core()) o.Printer = metricsutil.NewTopCmdPrinter(out) return nil }
func RunVersion(f cmdutil.Factory, out io.Writer, cmd *cobra.Command) error { kubectl.GetClientVersion(out) if cmdutil.GetFlagBool(cmd, "client") { return nil } clientset, err := f.ClientSet() if err != nil { return err } serverVersion, err := clientset.Discovery().ServerVersion() if err != nil { return err } fmt.Fprintf(out, "Server Version: %#v\n", *serverVersion) return nil }
// Complete verifies command line arguments and loads data from the command environment func (p *ExecOptions) Complete(f *cmdutil.Factory, cmd *cobra.Command, argsIn []string, argsLenAtDash int) error { if len(p.FullCmdName) == 0 { p.FullCmdName = "kubectl" } // Let kubectl exec follow rules for `--`, see #13004 issue if len(p.PodName) == 0 && (len(argsIn) == 0 || argsLenAtDash == 0) { return cmdutil.UsageError(cmd, execUsageStr) } if len(p.PodName) != 0 { printDeprecationWarning("exec POD_NAME", "-p POD_NAME") if len(argsIn) < 1 { return cmdutil.UsageError(cmd, execUsageStr) } p.Command = argsIn } else { p.PodName = argsIn[0] p.Command = argsIn[1:] if len(p.Command) < 1 { return cmdutil.UsageError(cmd, execUsageStr) } } namespace, _, err := f.DefaultNamespace() if err != nil { return err } p.Namespace = namespace config, err := f.ClientConfig() if err != nil { return err } p.Config = config clientset, err := f.ClientSet() if err != nil { return err } p.PodClient = clientset.Core() return nil }
func RunApiVersions(f cmdutil.Factory, w io.Writer) error { if len(os.Args) > 1 && os.Args[1] == "apiversions" { printDeprecationWarning("api-versions", "apiversions") } clientset, err := f.ClientSet() if err != nil { return err } groupList, err := clientset.Discovery().ServerGroups() if err != nil { return fmt.Errorf("Couldn't get available api versions from server: %v\n", err) } apiVersions := unversioned.ExtractGroupVersions(groupList) sort.Strings(apiVersions) for _, v := range apiVersions { fmt.Fprintln(w, v) } return nil }
func (o *TopPodOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string, out io.Writer) error { var err error if len(args) == 1 { o.ResourceName = args[0] } else if len(args) > 1 { return cmdutil.UsageError(cmd, cmd.Use) } o.Namespace, _, err = f.DefaultNamespace() if err != nil { return err } clientset, err := f.ClientSet() if err != nil { return err } o.PodClient = clientset.Core() o.Client = metricsutil.NewHeapsterMetricsClient(clientset.Core(), o.HeapsterOptions.Namespace, o.HeapsterOptions.Scheme, o.HeapsterOptions.Service, o.HeapsterOptions.Port) o.Printer = metricsutil.NewTopCmdPrinter(out) return nil }
// Complete completes all the required options for port-forward cmd. func (o *PortForwardOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string, cmdOut io.Writer, cmdErr io.Writer) error { var err error o.PodName = cmdutil.GetFlagString(cmd, "pod") if len(o.PodName) == 0 && len(args) == 0 { return cmdutil.UsageError(cmd, "POD is required for port-forward") } if len(o.PodName) != 0 { printDeprecationWarning("port-forward POD", "-p POD") o.Ports = args } else { o.PodName = args[0] o.Ports = args[1:] } o.Namespace, _, err = f.DefaultNamespace() if err != nil { return err } clientset, err := f.ClientSet() if err != nil { return err } o.PodClient = clientset.Core() o.Config, err = f.ClientConfig() if err != nil { return err } o.RESTClient, err = f.RESTClient() if err != nil { return err } o.StopChannel = make(chan struct{}, 1) o.ReadyChannel = make(chan struct{}) return nil }
func (options *CertificateOptions) modifyCertificateCondition(f cmdutil.Factory, out io.Writer, modify func(csr *certificates.CertificateSigningRequest) (*certificates.CertificateSigningRequest, string)) error { var found int mapper, typer := f.Object() c, err := f.ClientSet() if err != nil { return err } r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ContinueOnError(). FilenameParam(false, &options.FilenameOptions). ResourceNames("certificatesigningrequest", options.csrNames...). RequireObject(true). Flatten(). Latest(). Do() err = r.Visit(func(info *resource.Info, err error) error { if err != nil { return err } csr := info.Object.(*certificates.CertificateSigningRequest) csr, verb := modify(csr) csr, err = c.Certificates(). CertificateSigningRequests(). UpdateApproval(csr) if err != nil { return err } found++ cmdutil.PrintSuccess(mapper, options.outputStyle == "name", out, info.Mapping.Resource, info.Name, false, verb) return nil }) if found == 0 { fmt.Fprintf(out, "No resources found\n") } return err }
// Complete Parses the command line arguments and populates SecretOptions func (o *SecretOptions) Complete(f kcmdutil.Factory, args []string) error { if len(args) < 2 { return errors.New("must have service account name and at least one secret name") } o.TargetName = args[0] o.SecretNames = args[1:] var err error kubeClientSet, err := f.ClientSet() if err != nil { return err } o.KubeCoreClient = kubeClientSet.Core() o.Namespace, _, err = f.DefaultNamespace() if err != nil { return err } o.Mapper, o.Typer = f.Object() o.ClientMapper = resource.ClientMapperFunc(f.ClientForMapping) return nil }
func Run(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cobra.Command, args []string, argsLenAtDash int) error { if len(os.Args) > 1 && os.Args[1] == "run-container" { printDeprecationWarning("run", "run-container") } // Let kubectl run follow rules for `--`, see #13004 issue if len(args) == 0 || argsLenAtDash == 0 { return cmdutil.UsageError(cmd, "NAME is required for run") } // validate image name imageName := cmdutil.GetFlagString(cmd, "image") validImageRef := reference.ReferenceRegexp.MatchString(imageName) if !validImageRef { return fmt.Errorf("Invalid image name %q: %v", imageName, reference.ErrReferenceInvalidFormat) } interactive := cmdutil.GetFlagBool(cmd, "stdin") tty := cmdutil.GetFlagBool(cmd, "tty") if tty && !interactive { return cmdutil.UsageError(cmd, "-i/--stdin is required for containers with -t/--tty=true") } replicas := cmdutil.GetFlagInt(cmd, "replicas") if interactive && replicas != 1 { return cmdutil.UsageError(cmd, fmt.Sprintf("-i/--stdin requires that replicas is 1, found %d", replicas)) } namespace, _, err := f.DefaultNamespace() if err != nil { return err } restartPolicy, err := getRestartPolicy(cmd, interactive) if err != nil { return err } if restartPolicy != api.RestartPolicyAlways && replicas != 1 { return cmdutil.UsageError(cmd, fmt.Sprintf("--restart=%s requires that --replicas=1, found %d", restartPolicy, replicas)) } attachFlag := cmd.Flags().Lookup("attach") attach := cmdutil.GetFlagBool(cmd, "attach") if !attachFlag.Changed && interactive { attach = true } remove := cmdutil.GetFlagBool(cmd, "rm") if !attach && remove { return cmdutil.UsageError(cmd, "--rm should only be used for attached containers") } if attach && cmdutil.GetDryRunFlag(cmd) { return cmdutil.UsageError(cmd, "--dry-run can't be used with attached containers options (--attach, --stdin, or --tty)") } if err := verifyImagePullPolicy(cmd); err != nil { return err } generatorName := cmdutil.GetFlagString(cmd, "generator") schedule := cmdutil.GetFlagString(cmd, "schedule") if len(schedule) != 0 && len(generatorName) == 0 { generatorName = "cronjob/v2alpha1" } if len(generatorName) == 0 { clientset, err := f.ClientSet() if err != nil { return err } resourcesList, err := clientset.Discovery().ServerResources() // ServerResources ignores errors for old servers do not expose discovery if err != nil { return fmt.Errorf("failed to discover supported resources: %v", err) } switch restartPolicy { case api.RestartPolicyAlways: if contains(resourcesList, v1beta1.SchemeGroupVersion.WithResource("deployments")) { generatorName = "deployment/v1beta1" } else { generatorName = "run/v1" } case api.RestartPolicyOnFailure: if contains(resourcesList, batchv1.SchemeGroupVersion.WithResource("jobs")) { generatorName = "job/v1" } else if contains(resourcesList, v1beta1.SchemeGroupVersion.WithResource("jobs")) { generatorName = "job/v1beta1" } else { generatorName = "run-pod/v1" } case api.RestartPolicyNever: generatorName = "run-pod/v1" } } if generatorName == "job/v1beta1" { fmt.Fprintf(cmdErr, "DEPRECATED: --generator=job/v1beta1 is deprecated, use job/v1 instead.\n") } generators := f.Generators("run") generator, found := generators[generatorName] if !found { return cmdutil.UsageError(cmd, fmt.Sprintf("generator %q not found.", generatorName)) } names := generator.ParamNames() params := kubectl.MakeParams(cmd, names) params["name"] = args[0] if len(args) > 1 { params["args"] = args[1:] } params["env"] = cmdutil.GetFlagStringSlice(cmd, "env") obj, _, mapper, mapping, err := createGeneratedObject(f, cmd, generator, names, params, cmdutil.GetFlagString(cmd, "overrides"), namespace) if err != nil { return err } if cmdutil.GetFlagBool(cmd, "expose") { serviceGenerator := cmdutil.GetFlagString(cmd, "service-generator") if len(serviceGenerator) == 0 { return cmdutil.UsageError(cmd, fmt.Sprintf("No service generator specified")) } if err := generateService(f, cmd, args, serviceGenerator, params, namespace, cmdOut); err != nil { return err } } if attach { quiet := cmdutil.GetFlagBool(cmd, "quiet") opts := &AttachOptions{ StreamOptions: StreamOptions{ In: cmdIn, Out: cmdOut, Err: cmdErr, Stdin: interactive, TTY: tty, Quiet: quiet, }, CommandName: cmd.Parent().CommandPath() + " attach", Attach: &DefaultRemoteAttach{}, } config, err := f.ClientConfig() if err != nil { return err } opts.Config = config clientset, err := f.ClientSet() if err != nil { return err } opts.PodClient = clientset.Core() attachablePod, err := f.AttachablePodForObject(obj) if err != nil { return err } err = handleAttachPod(f, clientset.Core(), attachablePod.Namespace, attachablePod.Name, opts, quiet) if err != nil { return err } var pod *api.Pod leaveStdinOpen := cmdutil.GetFlagBool(cmd, "leave-stdin-open") waitForExitCode := !leaveStdinOpen && restartPolicy == api.RestartPolicyNever if waitForExitCode { pod, err = waitForPodTerminated(clientset.Core(), attachablePod.Namespace, attachablePod.Name, opts.Out, quiet) if err != nil { return err } } if remove { namespace, err = mapping.MetadataAccessor.Namespace(obj) if err != nil { return err } var name string name, err = mapping.MetadataAccessor.Name(obj) if err != nil { return err } _, typer := f.Object() r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ContinueOnError(). NamespaceParam(namespace).DefaultNamespace(). ResourceNames(mapping.Resource, name). Flatten(). Do() // Note: we pass in "true" for the "quiet" parameter because // ReadResult will only print one thing based on the "quiet" // flag, and that's the "pod xxx deleted" message. If they // asked for us to remove the pod (via --rm) then telling them // its been deleted is unnecessary since that's what they asked // for. We should only print something if the "rm" fails. err = ReapResult(r, f, cmdOut, true, true, 0, -1, false, false, mapper, true) if err != nil { return err } } // after removal is done, return successfully if we are not interested in the exit code if !waitForExitCode { return nil } switch pod.Status.Phase { case api.PodSucceeded: return nil case api.PodFailed: unknownRcErr := fmt.Errorf("pod %s/%s failed with unknown exit code", pod.Namespace, pod.Name) if len(pod.Status.ContainerStatuses) == 0 || pod.Status.ContainerStatuses[0].State.Terminated == nil { return unknownRcErr } // assume here that we have at most one status because kubectl-run only creates one container per pod rc := pod.Status.ContainerStatuses[0].State.Terminated.ExitCode if rc == 0 { return unknownRcErr } return uexec.CodeExitError{ Err: fmt.Errorf("pod %s/%s terminated", pod.Namespace, pod.Name), Code: int(rc), } default: return fmt.Errorf("pod %s/%s left in phase %s", pod.Namespace, pod.Name, pod.Status.Phase) } } outputFormat := cmdutil.GetFlagString(cmd, "output") if outputFormat != "" || cmdutil.GetDryRunFlag(cmd) { return f.PrintObject(cmd, mapper, obj, cmdOut) } cmdutil.PrintSuccess(mapper, false, cmdOut, mapping.Resource, args[0], cmdutil.GetDryRunFlag(cmd), "created") return nil }
func RunRollingUpdate(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error { if len(os.Args) > 1 && os.Args[1] == "rollingupdate" { printDeprecationWarning("rolling-update", "rollingupdate") } err := validateArguments(cmd, options.Filenames, args) if err != nil { return err } deploymentKey := cmdutil.GetFlagString(cmd, "deployment-label-key") filename := "" image := cmdutil.GetFlagString(cmd, "image") pullPolicy := cmdutil.GetFlagString(cmd, "image-pull-policy") oldName := args[0] rollback := cmdutil.GetFlagBool(cmd, "rollback") period := cmdutil.GetFlagDuration(cmd, "update-period") interval := cmdutil.GetFlagDuration(cmd, "poll-interval") timeout := cmdutil.GetFlagDuration(cmd, "timeout") dryrun := cmdutil.GetDryRunFlag(cmd) outputFormat := cmdutil.GetFlagString(cmd, "output") container := cmdutil.GetFlagString(cmd, "container") if len(options.Filenames) > 0 { filename = options.Filenames[0] } cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } clientset, err := f.ClientSet() if err != nil { return err } coreClient := clientset.Core() var newRc *api.ReplicationController // fetch rc oldRc, err := coreClient.ReplicationControllers(cmdNamespace).Get(oldName, metav1.GetOptions{}) if err != nil { if !errors.IsNotFound(err) || len(image) == 0 || len(args) > 1 { return err } // We're in the middle of a rename, look for an RC with a source annotation of oldName newRc, err := kubectl.FindSourceController(coreClient, cmdNamespace, oldName) if err != nil { return err } return kubectl.Rename(coreClient, newRc, oldName) } var keepOldName bool var replicasDefaulted bool mapper, typer := f.Object() if len(filename) != 0 { schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"), cmdutil.GetFlagString(cmd, "schema-cache-dir")) if err != nil { return err } request := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). Schema(schema). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, &resource.FilenameOptions{Recursive: false, Filenames: []string{filename}}). Do() obj, err := request.Object() if err != nil { return err } var ok bool // Handle filename input from stdin. The resource builder always returns an api.List // when creating resource(s) from a stream. if list, ok := obj.(*api.List); ok { if len(list.Items) > 1 { return cmdutil.UsageError(cmd, "%s specifies multiple items", filename) } if len(list.Items) == 0 { return cmdutil.UsageError(cmd, "please make sure %s exists and is not empty", filename) } obj = list.Items[0] } newRc, ok = obj.(*api.ReplicationController) if !ok { if gvks, _, err := typer.ObjectKinds(obj); err == nil { return cmdutil.UsageError(cmd, "%s contains a %v not a ReplicationController", filename, gvks[0]) } glog.V(4).Infof("Object %#v is not a ReplicationController", obj) return cmdutil.UsageError(cmd, "%s does not specify a valid ReplicationController", filename) } infos, err := request.Infos() if err != nil || len(infos) != 1 { glog.V(2).Infof("was not able to recover adequate information to discover if .spec.replicas was defaulted") } else { replicasDefaulted = isReplicasDefaulted(infos[0]) } } // If the --image option is specified, we need to create a new rc with at least one different selector // than the old rc. This selector is the hash of the rc, with a suffix to provide uniqueness for // same-image updates. if len(image) != 0 { codec := api.Codecs.LegacyCodec(clientset.CoreClient.RESTClient().APIVersion()) keepOldName = len(args) == 1 newName := findNewName(args, oldRc) if newRc, err = kubectl.LoadExistingNextReplicationController(coreClient, cmdNamespace, newName); err != nil { return err } if newRc != nil { if inProgressImage := newRc.Spec.Template.Spec.Containers[0].Image; inProgressImage != image { return cmdutil.UsageError(cmd, "Found existing in-progress update to image (%s).\nEither continue in-progress update with --image=%s or rollback with --rollback", inProgressImage, inProgressImage) } fmt.Fprintf(out, "Found existing update in progress (%s), resuming.\n", newRc.Name) } else { config := &kubectl.NewControllerConfig{ Namespace: cmdNamespace, OldName: oldName, NewName: newName, Image: image, Container: container, DeploymentKey: deploymentKey, } if oldRc.Spec.Template.Spec.Containers[0].Image == image { if len(pullPolicy) == 0 { return cmdutil.UsageError(cmd, "--image-pull-policy (Always|Never|IfNotPresent) must be provided when --image is the same as existing container image") } config.PullPolicy = api.PullPolicy(pullPolicy) } newRc, err = kubectl.CreateNewControllerFromCurrentController(coreClient, codec, config) if err != nil { return err } } // Update the existing replication controller with pointers to the 'next' controller // and adding the <deploymentKey> label if necessary to distinguish it from the 'next' controller. oldHash, err := api.HashObject(oldRc, codec) if err != nil { return err } // If new image is same as old, the hash may not be distinct, so add a suffix. oldHash += "-orig" oldRc, err = kubectl.UpdateExistingReplicationController(coreClient, coreClient, oldRc, cmdNamespace, newRc.Name, deploymentKey, oldHash, out) if err != nil { return err } } if rollback { keepOldName = len(args) == 1 newName := findNewName(args, oldRc) if newRc, err = kubectl.LoadExistingNextReplicationController(coreClient, cmdNamespace, newName); err != nil { return err } if newRc == nil { return cmdutil.UsageError(cmd, "Could not find %s to rollback.\n", newName) } } if oldName == newRc.Name { return cmdutil.UsageError(cmd, "%s cannot have the same name as the existing ReplicationController %s", filename, oldName) } updater := kubectl.NewRollingUpdater(newRc.Namespace, coreClient, coreClient) // To successfully pull off a rolling update the new and old rc have to differ // by at least one selector. Every new pod should have the selector and every // old pod should not have the selector. var hasLabel bool for key, oldValue := range oldRc.Spec.Selector { if newValue, ok := newRc.Spec.Selector[key]; ok && newValue != oldValue { hasLabel = true break } } if !hasLabel { return cmdutil.UsageError(cmd, "%s must specify a matching key with non-equal value in Selector for %s", filename, oldName) } // TODO: handle scales during rolling update if replicasDefaulted { newRc.Spec.Replicas = oldRc.Spec.Replicas } if dryrun { oldRcData := &bytes.Buffer{} newRcData := &bytes.Buffer{} if outputFormat == "" { oldRcData.WriteString(oldRc.Name) newRcData.WriteString(newRc.Name) } else { if err := f.PrintObject(cmd, mapper, oldRc, oldRcData); err != nil { return err } if err := f.PrintObject(cmd, mapper, newRc, newRcData); err != nil { return err } } fmt.Fprintf(out, "Rolling from:\n%s\nTo:\n%s\n", string(oldRcData.Bytes()), string(newRcData.Bytes())) return nil } updateCleanupPolicy := kubectl.DeleteRollingUpdateCleanupPolicy if keepOldName { updateCleanupPolicy = kubectl.RenameRollingUpdateCleanupPolicy } config := &kubectl.RollingUpdaterConfig{ Out: out, OldRc: oldRc, NewRc: newRc, UpdatePeriod: period, Interval: interval, Timeout: timeout, CleanupPolicy: updateCleanupPolicy, MaxUnavailable: intstr.FromInt(0), MaxSurge: intstr.FromInt(1), } if rollback { err = kubectl.AbortRollingUpdate(config) if err != nil { return err } coreClient.ReplicationControllers(config.NewRc.Namespace).Update(config.NewRc) } err = updater.Update(config) if err != nil { return err } message := "rolling updated" if keepOldName { newRc.Name = oldName } else { message = fmt.Sprintf("rolling updated to %q", newRc.Name) } newRc, err = coreClient.ReplicationControllers(cmdNamespace).Get(newRc.Name, metav1.GetOptions{}) if err != nil { return err } if outputFormat != "" { return f.PrintObject(cmd, mapper, newRc, out) } kinds, _, err := api.Scheme.ObjectKinds(newRc) if err != nil { return err } _, res := meta.KindToResource(kinds[0]) cmdutil.PrintSuccess(mapper, false, out, res.Resource, oldName, dryrun, message) return nil }
func dumpClusterInfo(f cmdutil.Factory, cmd *cobra.Command, args []string, out io.Writer) error { clientset, err := f.ClientSet() if err != nil { return err } printer, _, err := kubectl.GetPrinter("json", "", false, true) if err != nil { return err } nodes, err := clientset.Core().Nodes().List(api.ListOptions{}) if err != nil { return err } if err := printer.PrintObj(nodes, setupOutputWriter(cmd, out, "nodes.json")); err != nil { return err } var namespaces []string if cmdutil.GetFlagBool(cmd, "all-namespaces") { namespaceList, err := clientset.Core().Namespaces().List(api.ListOptions{}) if err != nil { return err } for ix := range namespaceList.Items { namespaces = append(namespaces, namespaceList.Items[ix].Name) } } else { namespaces = cmdutil.GetFlagStringSlice(cmd, "namespaces") if len(namespaces) == 0 { cmdNamespace, _, err := f.DefaultNamespace() if err != nil { return err } namespaces = []string{ api.NamespaceSystem, cmdNamespace, } } } for _, namespace := range namespaces { // TODO: this is repetitive in the extreme. Use reflection or // something to make this a for loop. events, err := clientset.Core().Events(namespace).List(api.ListOptions{}) if err != nil { return err } if err := printer.PrintObj(events, setupOutputWriter(cmd, out, path.Join(namespace, "events.json"))); err != nil { return err } rcs, err := clientset.Core().ReplicationControllers(namespace).List(api.ListOptions{}) if err != nil { return err } if err := printer.PrintObj(rcs, setupOutputWriter(cmd, out, path.Join(namespace, "replication-controllers.json"))); err != nil { return err } svcs, err := clientset.Core().Services(namespace).List(api.ListOptions{}) if err != nil { return err } if err := printer.PrintObj(svcs, setupOutputWriter(cmd, out, path.Join(namespace, "services.json"))); err != nil { return err } sets, err := clientset.Extensions().DaemonSets(namespace).List(api.ListOptions{}) if err != nil { return err } if err := printer.PrintObj(sets, setupOutputWriter(cmd, out, path.Join(namespace, "daemonsets.json"))); err != nil { return err } deps, err := clientset.Extensions().Deployments(namespace).List(api.ListOptions{}) if err != nil { return err } if err := printer.PrintObj(deps, setupOutputWriter(cmd, out, path.Join(namespace, "deployments.json"))); err != nil { return err } rps, err := clientset.Extensions().ReplicaSets(namespace).List(api.ListOptions{}) if err != nil { return err } if err := printer.PrintObj(rps, setupOutputWriter(cmd, out, path.Join(namespace, "replicasets.json"))); err != nil { return err } pods, err := clientset.Core().Pods(namespace).List(api.ListOptions{}) if err != nil { return err } if err := printer.PrintObj(pods, setupOutputWriter(cmd, out, path.Join(namespace, "pods.json"))); err != nil { return err } for ix := range pods.Items { pod := &pods.Items[ix] writer := setupOutputWriter(cmd, out, path.Join(namespace, pod.Name, "logs.txt")) writer.Write([]byte(fmt.Sprintf("==== START logs for %s/%s ====\n", pod.Namespace, pod.Name))) request, err := f.LogsForObject(pod, &api.PodLogOptions{}) if err != nil { return err } data, err := request.DoRaw() if err != nil { return err } writer.Write(data) writer.Write([]byte(fmt.Sprintf("==== END logs for %s/%s ====\n", pod.Namespace, pod.Name))) } } dir := cmdutil.GetFlagString(cmd, "output-directory") if len(dir) == 0 { dir = "." } if dir != "-" { fmt.Fprintf(out, "Cluster info dumped to %s", dir) } return nil }