func (o *RetryOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, out io.Writer, args []string) error { if len(args) == 0 && len(o.Filenames) == 0 { return kcmdutil.UsageError(cmd, cmd.Use) } o.Mapper, o.Typer = f.Object(false) o.Encoder = f.JSONEncoder() o.Out = out cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } _, _, o.Clientset, err = f.Clients() if err != nil { return err } r := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, o.Recursive, o.Filenames...). ResourceTypeOrNameArgs(true, args...). ContinueOnError(). Latest(). Flatten(). Do() err = r.Err() if err != nil { return err } o.Infos, err = r.Infos() return err }
func (o *TriggersOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, args []string) error { cmdNamespace, explicit, err := f.DefaultNamespace() if err != nil { return err } if !cmd.Flags().Lookup("from-github").Changed { o.FromGitHub = nil } if !cmd.Flags().Lookup("from-webhook").Changed { o.FromWebHook = nil } if !cmd.Flags().Lookup("from-webhook-allow-env").Changed { o.FromWebHookAllowEnv = nil } if len(o.FromImage) > 0 { ref, err := imageapi.ParseDockerImageReference(o.FromImage) if err != nil { return fmt.Errorf("the value of --from-image does not appear to be a valid reference to an image: %v", err) } if len(ref.Registry) > 0 || len(ref.ID) > 0 { return fmt.Errorf("the value of --from-image must point to an image stream tag on this server") } if len(ref.Tag) == 0 { return fmt.Errorf("the value of --from-image must include the tag you wish to pull from") } o.FromImage = ref.NameString() o.FromImageNamespace = defaultNamespace(ref.Namespace, cmdNamespace) } count := o.count() o.Reset = count == 0 && (o.Auto || o.Manual) switch { case count == 0 && !o.Remove && !o.RemoveAll && !o.Auto && !o.Manual: o.PrintTable = true case !o.RemoveAll && !o.Auto && !o.Manual: o.Auto = true } mapper, typer := f.Object(false) o.Builder = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), kapi.Codecs.UniversalDecoder()). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(explicit, false, o.Filenames...). SelectorParam(o.Selector). ResourceTypeOrNameArgs(o.All, args...). Flatten() output := kcmdutil.GetFlagString(cmd, "output") if len(output) != 0 { o.PrintObject = func(obj runtime.Object) error { return f.PrintObject(cmd, mapper, obj, o.Out) } } o.Encoder = f.JSONEncoder() o.ShortOutput = kcmdutil.GetFlagString(cmd, "output") == "name" o.Mapper = mapper return nil }
func (v *VolumeOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, out, errOut io.Writer) error { clientConfig, err := f.ClientConfig() if err != nil { return err } v.OutputVersion, err = kcmdutil.OutputVersion(cmd, clientConfig.GroupVersion) if err != nil { return err } _, kc, err := f.Clients() if err != nil { return err } v.Client = kc cmdNamespace, explicit, err := f.DefaultNamespace() if err != nil { return err } mapper, typer := f.Object(false) v.DefaultNamespace = cmdNamespace v.ExplicitNamespace = explicit v.Out = out v.Err = errOut v.Mapper = mapper v.Typer = typer v.RESTClientFactory = f.Factory.ClientForMapping v.UpdatePodSpecForObject = f.UpdatePodSpecForObject v.Encoder = f.JSONEncoder() // In case of volume source ignore the default volume type if len(v.AddOpts.Source) > 0 { v.AddOpts.Type = "" } if len(v.AddOpts.ClaimSize) > 0 { v.AddOpts.CreateClaim = true if len(v.AddOpts.ClaimName) == 0 { v.AddOpts.ClaimName = kapi.SimpleNameGenerator.GenerateName("pvc-") } q, err := kresource.ParseQuantity(v.AddOpts.ClaimSize) if err != nil { return fmt.Errorf("--claim-size is not valid: %v", err) } v.AddOpts.ClaimSize = q.String() } switch strings.ToLower(v.AddOpts.ClaimMode) { case strings.ToLower(string(kapi.ReadOnlyMany)), "rom": v.AddOpts.ClaimMode = string(kapi.ReadOnlyMany) case strings.ToLower(string(kapi.ReadWriteOnce)), "rwo": v.AddOpts.ClaimMode = string(kapi.ReadWriteOnce) case strings.ToLower(string(kapi.ReadWriteMany)), "rwm": v.AddOpts.ClaimMode = string(kapi.ReadWriteMany) case "": default: return errors.New("--claim-mode must be one of ReadWriteOnce (rwo), ReadWriteMany (rwm), or ReadOnlyMany (rom)") } return nil }
// Complete takes command line information to fill out BackendOptions or returns an error. func (o *BackendsOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, args []string) error { cmdNamespace, explicit, err := f.DefaultNamespace() if err != nil { return err } clientConfig, err := f.ClientConfig() if err != nil { return err } o.OutputVersion, err = kcmdutil.OutputVersion(cmd, clientConfig.GroupVersion) if err != nil { return err } var resources []string for _, arg := range args { if !strings.Contains(arg, "=") { resources = append(resources, arg) continue } input, err := ParseBackendInput(arg) if err != nil { return fmt.Errorf("invalid argument %q: %v", arg, err) } o.Transform.Inputs = append(o.Transform.Inputs, *input) } o.PrintTable = o.Transform.Empty() mapper, typer := f.Object(false) o.Builder = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), kapi.Codecs.UniversalDecoder()). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(explicit, false, o.Filenames...). SelectorParam(o.Selector). SelectAllParam(o.All). ResourceNames("route", resources...). Flatten() if len(resources) == 0 { o.Builder.ResourceTypes("routes") } output := kcmdutil.GetFlagString(cmd, "output") if len(output) != 0 { o.PrintObject = func(obj runtime.Object) error { return f.PrintObject(cmd, mapper, obj, o.Out) } } o.Encoder = f.JSONEncoder() o.ShortOutput = kcmdutil.GetFlagString(cmd, "output") == "name" o.Mapper = mapper return nil }
func (o *BuildHookOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, args []string) error { resources := args if i := cmd.ArgsLenAtDash(); i != -1 { resources = args[:i] o.Command = args[i:] } if len(o.Filenames) == 0 && len(args) < 1 { return kcmdutil.UsageError(cmd, "one or more build configs must be specified as <name> or <resource>/<name>") } cmdNamespace, explicit, err := f.DefaultNamespace() if err != nil { return err } clientConfig, err := f.ClientConfig() if err != nil { return err } o.OutputVersion, err = kcmdutil.OutputVersion(cmd, clientConfig.GroupVersion) if err != nil { return err } mapper, typer := f.Object(false) o.Builder = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), kapi.Codecs.UniversalDecoder()). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(explicit, false, o.Filenames...). SelectorParam(o.Selector). ResourceNames("buildconfigs", resources...). Flatten() if o.All { o.Builder.ResourceTypes("buildconfigs").SelectAllParam(o.All) } output := kcmdutil.GetFlagString(cmd, "output") if len(output) != 0 { o.PrintObject = func(infos []*resource.Info) error { return f.PrintResourceInfos(cmd, infos, o.Out) } } o.Encoder = f.JSONEncoder() o.ShortOutput = kcmdutil.GetFlagString(cmd, "output") == "name" o.Mapper = mapper return nil }
func (o *ProbeOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, args []string) error { resources := args if i := cmd.ArgsLenAtDash(); i != -1 { resources = args[:i] o.Command = args[i:] } if len(o.Filenames) == 0 && len(args) < 1 { return kcmdutil.UsageError(cmd, "one or more resources must be specified as <resource> <name> or <resource>/<name>") } cmdNamespace, explicit, err := f.DefaultNamespace() if err != nil { return err } clientConfig, err := f.ClientConfig() if err != nil { return err } o.OutputVersion, err = kcmdutil.OutputVersion(cmd, clientConfig.GroupVersion) if err != nil { return err } mapper, typer := f.Object(false) o.Builder = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), kapi.Codecs.UniversalDecoder()). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(explicit, false, o.Filenames...). SelectorParam(o.Selector). ResourceTypeOrNameArgs(o.All, resources...). Flatten() output := kcmdutil.GetFlagString(cmd, "output") if len(output) != 0 { o.PrintObject = func(obj runtime.Object) error { return f.PrintObject(cmd, mapper, obj, o.Out) } } o.Encoder = f.JSONEncoder() o.UpdatePodSpecForObject = f.UpdatePodSpecForObject o.ShortOutput = kcmdutil.GetFlagString(cmd, "output") == "name" o.Mapper = mapper if !cmd.Flags().Lookup("initial-delay-seconds").Changed { o.InitialDelaySeconds = nil } if !cmd.Flags().Lookup("timeout-seconds").Changed { o.TimeoutSeconds = nil } if !cmd.Flags().Lookup("period-seconds").Changed { o.PeriodSeconds = nil } if !cmd.Flags().Lookup("success-threshold").Changed { o.SuccessThreshold = nil } if !cmd.Flags().Lookup("failure-threshold").Changed { o.FailureThreshold = nil } if len(o.HTTPGet) > 0 { url, err := url.Parse(o.HTTPGet) if err != nil { return fmt.Errorf("--get-url could not be parsed as a valid URL: %v", err) } var host, port string if strings.Contains(url.Host, ":") { if host, port, err = net.SplitHostPort(url.Host); err != nil { return fmt.Errorf("--get-url did not have a valid port specification: %v", err) } } if host == "localhost" { host = "" } o.HTTPGetAction = &kapi.HTTPGetAction{ Scheme: kapi.URIScheme(strings.ToUpper(url.Scheme)), Host: host, Port: intOrString(port), Path: url.Path, } } return nil }
// RunIdle runs the idling command logic, taking a list of resources or services in a file, scaling the associated // scalable resources to zero, and annotating the associated endpoints objects with the scalable resources to unidle // when they receive traffic. func (o *IdleOptions) RunIdle(f *clientcmd.Factory) error { hadError := false nowTime := time.Now().UTC() // figure out which endpoints and resources we need to idle byService, byScalable, err := o.calculateIdlableAnnotationsByService(f) if err != nil { if len(byService) == 0 || len(byScalable) == 0 { return fmt.Errorf("no valid scalable resources found to idle: %v", err) } fmt.Fprintf(o.errOut, "warning: continuing on for valid scalable resources, but an error occurred while finding scalable resources to idle: %v", err) } oclient, _, kclient, err := f.Clients() if err != nil { return err } delegScaleGetter := osclient.NewDelegatingScaleNamespacer(oclient, kclient.Extensions()) dcGetter := deployclient.New(oclient.RESTClient) scaleAnnotater := utilunidling.NewScaleAnnotater(delegScaleGetter, dcGetter, kclient.Core(), func(currentReplicas int32, annotations map[string]string) { annotations[unidlingapi.IdledAtAnnotation] = nowTime.UTC().Format(time.RFC3339) annotations[unidlingapi.PreviousScaleAnnotation] = fmt.Sprintf("%v", currentReplicas) }) replicas := make(map[unidlingapi.CrossGroupObjectReference]int32, len(byScalable)) toScale := make(map[unidlingapi.CrossGroupObjectReference]scaleInfo) mapper, typer := f.Object(false) // first, collect the scale info for scaleRef, svcName := range byScalable { obj, scale, err := scaleAnnotater.GetObjectWithScale(svcName.Namespace, scaleRef) if err != nil { fmt.Fprintf(o.errOut, "error: unable to get scale for %s %s/%s, not marking that scalable as idled: %v\n", scaleRef.Kind, svcName.Namespace, scaleRef.Name, err) svcInfo := byService[svcName] delete(svcInfo.scaleRefs, scaleRef) hadError = true continue } replicas[scaleRef] = scale.Spec.Replicas toScale[scaleRef] = scaleInfo{scale: scale, obj: obj, namespace: svcName.Namespace} } // annotate the endpoints objects to indicate which scalable resources need to be unidled on traffic for serviceName, info := range byService { if info.obj.Annotations == nil { info.obj.Annotations = make(map[string]string) } refsWithScale, err := pairScalesWithScaleRefs(serviceName, info.obj.Annotations, info.scaleRefs, replicas) if err != nil { fmt.Fprintf(o.errOut, "error: unable to mark service %s as idled: %v", serviceName.String(), err) continue } if !o.dryRun { if len(info.scaleRefs) == 0 { fmt.Fprintf(o.errOut, "error: no scalable resources marked as idled for service %s, not marking as idled\n", serviceName.String()) hadError = true continue } metadata, err := meta.Accessor(info.obj) if err != nil { fmt.Fprintf(o.errOut, "error: unable to mark service %s as idled: %v", serviceName.String(), err) hadError = true continue } gvks, _, err := typer.ObjectKinds(info.obj) if err != nil { fmt.Fprintf(o.errOut, "error: unable to mark service %s as idled: %v", serviceName.String(), err) hadError = true continue } oldData, err := json.Marshal(info.obj) if err != nil { fmt.Fprintf(o.errOut, "error: unable to mark service %s as idled: %v", serviceName.String(), err) hadError = true continue } mapping, err := mapper.RESTMapping(gvks[0].GroupKind(), gvks[0].Version) if err != nil { fmt.Fprintf(o.errOut, "error: unable to mark service %s as idled: %v", serviceName.String(), err) hadError = true continue } if err = setIdleAnnotations(serviceName, info.obj.Annotations, refsWithScale, nowTime); err != nil { fmt.Fprintf(o.errOut, "error: unable to mark service %s as idled: %v", serviceName.String(), err) hadError = true continue } if _, err := patchObj(info.obj, metadata, oldData, mapping, f); err != nil { fmt.Fprintf(o.errOut, "error: unable to mark service %s as idled: %v", serviceName.String(), err) hadError = true continue } } for _, scaleRef := range refsWithScale { fmt.Fprintf(o.out, "Marked service %s to unidle resource %s %s/%s (unidle to %v replicas)\n", serviceName.String(), scaleRef.Kind, serviceName.Namespace, scaleRef.Name, scaleRef.Replicas) } } // actually "idle" the scalable resources by scaling them down to zero // (scale down to zero *after* we've applied the annotation so that we don't miss any traffic) for scaleRef, info := range toScale { idled := "" if !o.dryRun { info.scale.Spec.Replicas = 0 scaleUpdater := utilunidling.NewScaleUpdater(f.JSONEncoder(), info.namespace, dcGetter, kclient.Core()) if err := scaleAnnotater.UpdateObjectScale(scaleUpdater, info.namespace, scaleRef, info.obj, info.scale); err != nil { fmt.Fprintf(o.errOut, "error: unable to scale %s %s/%s to 0, but still listed as target for unidling: %v\n", scaleRef.Kind, info.namespace, scaleRef.Name, err) hadError = true continue } } else { idled = "(dry run)" } fmt.Fprintf(o.out, "Idled %s %s/%s %s\n", scaleRef.Kind, info.namespace, scaleRef.Name, idled) } if hadError { return cmdutil.ErrExit } return nil }
func (o *DeploymentHookOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, args []string) error { resources := args if i := cmd.ArgsLenAtDash(); i != -1 { resources = args[:i] o.Command = args[i:] } if len(o.Filenames) == 0 && len(args) < 1 { return kcmdutil.UsageError(cmd, "one or more deployment configs must be specified as <name> or dc/<name>") } cmdNamespace, explicit, err := f.DefaultNamespace() if err != nil { return err } clientConfig, err := f.ClientConfig() if err != nil { return err } o.OutputVersion, err = kcmdutil.OutputVersion(cmd, clientConfig.GroupVersion) if err != nil { return err } mapper, typer := f.Object(false) o.Builder = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), kapi.Codecs.UniversalDecoder()). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(explicit, false, o.Filenames...). Flatten() if !o.Local { o.Builder = o.Builder. ResourceNames("deploymentconfigs", resources...). SelectorParam(o.Selector). Latest() if o.All { o.Builder.ResourceTypes("deploymentconfigs").SelectAllParam(o.All) } } output := kcmdutil.GetFlagString(cmd, "output") if len(output) != 0 || o.Local { o.PrintObject = func(infos []*resource.Info) error { return f.PrintResourceInfos(cmd, infos, o.Out) } } o.Encoder = f.JSONEncoder() o.ShortOutput = kcmdutil.GetFlagString(cmd, "output") == "name" o.Mapper = mapper failurePolicyString := kcmdutil.GetFlagString(cmd, "failure-policy") if len(failurePolicyString) > 0 { switch failurePolicyString { case "abort": o.FailurePolicy = deployapi.LifecycleHookFailurePolicyAbort case "ignore": o.FailurePolicy = deployapi.LifecycleHookFailurePolicyIgnore case "retry": o.FailurePolicy = deployapi.LifecycleHookFailurePolicyRetry default: return kcmdutil.UsageError(cmd, "valid values for --failure-policy are: abort, retry, ignore") } } return nil }
func (o *BuildSecretOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, args []string) error { var secretArg string if !o.Remove { if len(args) < 1 { return kcmdutil.UsageError(cmd, "a secret name must be specified") } secretArg = args[len(args)-1] args = args[:len(args)-1] } resources := args if len(resources) == 0 && len(o.Selector) == 0 && len(o.Filenames) == 0 && !o.All { return kcmdutil.UsageError(cmd, "one or more build configs must be specified as <name> or <resource>/<name>") } cmdNamespace, explicit, err := f.DefaultNamespace() if err != nil { return err } clientConfig, err := f.ClientConfig() if err != nil { return err } o.OutputVersion, err = kcmdutil.OutputVersion(cmd, clientConfig.GroupVersion) if err != nil { return err } mapper, typer := f.Object(false) if len(secretArg) > 0 { o.Secret, err = o.secretFromArg(f, mapper, typer, cmdNamespace, secretArg) if err != nil { return err } } o.Builder = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), kapi.Codecs.UniversalDecoder()). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(explicit, false, o.Filenames...). Flatten() if !o.Local { o.Builder = o.Builder. ResourceNames("buildconfigs", resources...). SelectorParam(o.Selector). Latest() if o.All { o.Builder.ResourceTypes(supportedBuildTypes...).SelectAllParam(o.All) } } output := kcmdutil.GetFlagString(cmd, "output") if len(output) > 0 || o.Local { o.PrintObject = func(infos []*resource.Info) error { return f.PrintResourceInfos(cmd, infos, o.Out) } } o.Encoder = f.JSONEncoder() o.ShortOutput = kcmdutil.GetFlagString(cmd, "output") == "name" o.Mapper = mapper return nil }