in pkg/cmd/set/set_env.go [272:542]
func (o *EnvOptions) RunEnv() error {
env, remove, envFromStdin, err := envutil.ParseEnv(append(o.EnvParams, o.envArgs...), o.In)
if err != nil {
return err
}
if len(o.From) != 0 {
b := o.builder().
WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
LocalParam(o.Local).
ContinueOnError().
NamespaceParam(o.namespace).DefaultNamespace().
FilenameParam(o.enforceNamespace, &o.FilenameOptions).
Flatten()
if !o.Local {
b = b.
LabelSelectorParam(o.Selector).
ResourceTypeOrNameArgs(o.All, o.From).
Latest()
}
if envFromStdin {
b = b.StdinInUse()
}
infos, err := b.Do().Infos()
if err != nil {
return err
}
for _, info := range infos {
switch from := info.Object.(type) {
case *v1.Secret:
for key := range from.Data {
if contains(key, o.Keys) {
envVar := v1.EnvVar{
Name: keyToEnvName(key),
ValueFrom: &v1.EnvVarSource{
SecretKeyRef: &v1.SecretKeySelector{
LocalObjectReference: v1.LocalObjectReference{
Name: from.Name,
},
Key: key,
},
},
}
env = append(env, envVar)
}
}
case *v1.ConfigMap:
for key := range from.Data {
if contains(key, o.Keys) {
envVar := v1.EnvVar{
Name: keyToEnvName(key),
ValueFrom: &v1.EnvVarSource{
ConfigMapKeyRef: &v1.ConfigMapKeySelector{
LocalObjectReference: v1.LocalObjectReference{
Name: from.Name,
},
Key: key,
},
},
}
env = append(env, envVar)
}
}
default:
return fmt.Errorf("unsupported resource specified in --from")
}
}
}
if len(o.Prefix) != 0 {
for i := range env {
env[i].Name = fmt.Sprintf("%s%s", o.Prefix, env[i].Name)
}
}
b := o.builder().
WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
LocalParam(o.Local).
ContinueOnError().
NamespaceParam(o.namespace).DefaultNamespace().
FilenameParam(o.enforceNamespace, &o.FilenameOptions).
Flatten()
if !o.Local {
b.LabelSelectorParam(o.Selector).
ResourceTypeOrNameArgs(o.All, o.resources...).
Latest()
}
if envFromStdin {
b = b.StdinInUse()
}
infos, err := b.Do().Infos()
if err != nil {
return err
}
patches := CalculatePatches(infos, scheme.DefaultJSONEncoder(), func(obj runtime.Object) ([]byte, error) {
_, err := o.updatePodSpecForObject(obj, func(spec *v1.PodSpec) error {
resolutionErrorsEncountered := false
initContainers, _ := selectContainers(spec.InitContainers, o.ContainerSelector)
containers, _ := selectContainers(spec.Containers, o.ContainerSelector)
containers = append(containers, initContainers...)
objName, err := meta.NewAccessor().Name(obj)
if err != nil {
return err
}
gvks, _, err := scheme.Scheme.ObjectKinds(obj)
if err != nil {
return err
}
objKind := obj.GetObjectKind().GroupVersionKind().Kind
if len(objKind) == 0 {
for _, gvk := range gvks {
if len(gvk.Kind) == 0 {
continue
}
if len(gvk.Version) == 0 || gvk.Version == runtime.APIVersionInternal {
continue
}
objKind = gvk.Kind
break
}
}
if len(containers) == 0 {
if gvks, _, err := scheme.Scheme.ObjectKinds(obj); err == nil {
objKind := obj.GetObjectKind().GroupVersionKind().Kind
if len(objKind) == 0 {
for _, gvk := range gvks {
if len(gvk.Kind) == 0 {
continue
}
if len(gvk.Version) == 0 || gvk.Version == runtime.APIVersionInternal {
continue
}
objKind = gvk.Kind
break
}
}
fmt.Fprintf(o.ErrOut, "warning: %s/%s does not have any containers matching %q\n", objKind, objName, o.ContainerSelector)
}
return nil
}
for _, c := range containers {
if !o.Overwrite {
if err := validateNoOverwrites(c.Env, env); err != nil {
return err
}
}
c.Env = updateEnv(c.Env, env, remove)
if o.List {
resolveErrors := map[string][]string{}
store := envutil.NewResourceStore()
fmt.Fprintf(o.Out, "# %s %s, container %s\n", objKind, objName, c.Name)
for _, env := range c.Env {
// Print the simple value
if env.ValueFrom == nil {
fmt.Fprintf(o.Out, "%s=%s\n", env.Name, env.Value)
continue
}
// Print the reference version
if !o.Resolve {
fmt.Fprintf(o.Out, "# %s from %s\n", env.Name, envutil.GetEnvVarRefString(env.ValueFrom))
continue
}
value, err := envutil.GetEnvVarRefValue(o.clientset, o.namespace, store, env.ValueFrom, obj, c)
// Print the resolved value
if err == nil {
fmt.Fprintf(o.Out, "%s=%s\n", env.Name, value)
continue
}
// Print the reference version and save the resolve error
fmt.Fprintf(o.Out, "# %s from %s\n", env.Name, envutil.GetEnvVarRefString(env.ValueFrom))
errString := err.Error()
resolveErrors[errString] = append(resolveErrors[errString], env.Name)
resolutionErrorsEncountered = true
}
// Print any resolution errors
errs := []string{}
for err, vars := range resolveErrors {
sort.Strings(vars)
errs = append(errs, fmt.Sprintf("error retrieving reference for %s: %v", strings.Join(vars, ", "), err))
}
sort.Strings(errs)
for _, err := range errs {
fmt.Fprintln(o.ErrOut, err)
}
}
}
if resolutionErrorsEncountered {
return errors.New("failed to retrieve valueFrom references")
}
return nil
})
if err == nil {
return runtime.Encode(scheme.DefaultJSONEncoder(), obj)
}
return nil, err
})
if o.List {
return nil
}
allErrs := []error{}
for _, patch := range patches {
info := patch.Info
if patch.Err != nil {
name := info.ObjectName()
allErrs = append(allErrs, fmt.Errorf("error: %s %v\n", name, patch.Err))
continue
}
// no changes
if string(patch.Patch) == "{}" || len(patch.Patch) == 0 {
continue
}
if o.Local || o.dryRunStrategy == cmdutil.DryRunClient {
if err := o.PrintObj(info.Object, o.Out); err != nil {
allErrs = append(allErrs, err)
}
continue
}
if o.dryRunStrategy == cmdutil.DryRunServer {
if err := o.dryRunVerifier.HasSupport(info.Mapping.GroupVersionKind); err != nil {
allErrs = append(allErrs, err)
continue
}
}
actual, err := resource.
NewHelper(info.Client, info.Mapping).
DryRun(o.dryRunStrategy == cmdutil.DryRunServer).
WithFieldManager(o.fieldManager).
Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch, nil)
if err != nil {
allErrs = append(allErrs, fmt.Errorf("failed to patch env update to pod template: %v", err))
continue
}
// make sure arguments to set or replace environment variables are set
// before returning a successful message
if len(env) == 0 && len(o.envArgs) == 0 {
return fmt.Errorf("at least one environment variable must be provided")
}
if err := o.PrintObj(actual, o.Out); err != nil {
allErrs = append(allErrs, err)
}
}
return utilerrors.NewAggregate(allErrs)
}