func()

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)
}