diff --git a/pkg/kubectl/cmd/set/set_image.go b/pkg/kubectl/cmd/set/set_image.go index 885b824eeb6ac..339bc965e5081 100644 --- a/pkg/kubectl/cmd/set/set_image.go +++ b/pkg/kubectl/cmd/set/set_image.go @@ -34,21 +34,22 @@ import ( // ImageOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of // referencing the cmd.Flags() type ImageOptions struct { - Mapper meta.RESTMapper - Typer runtime.ObjectTyper - Infos []*resource.Info - Encoder runtime.Encoder - Selector string - Out io.Writer - Err io.Writer - Filenames []string - Recursive bool - ShortOutput bool - All bool - Record bool - ChangeCause string - Local bool - Cmd *cobra.Command + Mapper meta.RESTMapper + Typer runtime.ObjectTyper + Infos []*resource.Info + Encoder runtime.Encoder + Selector string + Out io.Writer + Err io.Writer + Filenames []string + Recursive bool + ShortOutput bool + All bool + Record bool + ChangeCause string + Local bool + ResolveImage func(in string) (string, error) + Cmd *cobra.Command PrintObject func(cmd *cobra.Command, mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error UpdatePodSpecForObject func(obj runtime.Object, fn func(*api.PodSpec) error) (bool, error) @@ -75,7 +76,7 @@ var ( # Update image of all containers of daemonset abc to 'nginx:1.9.1' kubectl set image daemonset abc *=nginx:1.9.1 - # Print result (in yaml format) of updating nginx container image from local file, without hitting the server + # Print result (in yaml format) of updating nginx container image from local file, without hitting the server kubectl set image -f path/to/file.yaml nginx=nginx:1.9.1 --local -o yaml`) ) @@ -115,6 +116,7 @@ func (o *ImageOptions) Complete(f *cmdutil.Factory, cmd *cobra.Command, args []s o.Record = cmdutil.GetRecordFlag(cmd) o.ChangeCause = f.Command() o.PrintObject = f.PrintObject + o.ResolveImage = f.ResolveImage o.Cmd = cmd cmdNamespace, enforceNamespace, err := f.DefaultNamespace() @@ -165,12 +167,22 @@ func (o *ImageOptions) Run() error { transformed := false _, err := o.UpdatePodSpecForObject(info.Object, func(spec *api.PodSpec) error { for name, image := range o.ContainerImages { - containerFound := false + var ( + containerFound bool + err error + resolved string + ) // Find the container to update, and update its image for i, c := range spec.Containers { if c.Name == name || name == "*" { - spec.Containers[i].Image = image containerFound = true + if len(resolved) == 0 { + if resolved, err = o.ResolveImage(image); err != nil { + allErrs = append(allErrs, fmt.Errorf("error: unable to resolve image %q for container %q: %v", image, name, err)) + continue + } + } + spec.Containers[i].Image = resolved // Perform updates transformed = true } diff --git a/pkg/kubectl/cmd/util/factory.go b/pkg/kubectl/cmd/util/factory.go index f603e46fbdd6b..f26b41876c9bd 100644 --- a/pkg/kubectl/cmd/util/factory.go +++ b/pkg/kubectl/cmd/util/factory.go @@ -134,6 +134,10 @@ type Factory struct { PauseObject func(object runtime.Object) (bool, error) // ResumeObject resumes a paused object ie. it will be reconciled by its controller. ResumeObject func(object runtime.Object) (bool, error) + // ResolveImage resolves the image names. For kubernetes this function is just + // passthrough but it allows to perform more sophisticated image name resolving for + // third-party vendors. + ResolveImage func(imageName string) (string, error) // Returns a schema that can validate objects stored on disk. Validator func(validate bool, cacheDir string) (validation.Schema, error) // SwaggerSchema returns the schema declaration for the provided group version kind. @@ -671,6 +675,9 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory { return false, fmt.Errorf("cannot resume %v", gvks[0]) } }, + ResolveImage: func(imageName string) (string, error) { + return imageName, nil + }, Scaler: func(mapping *meta.RESTMapping) (kubectl.Scaler, error) { mappingVersion := mapping.GroupVersionKind.GroupVersion() client, err := clients.ClientForVersion(&mappingVersion)