-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support valueFrom syntax for build env vars #14143
Support valueFrom syntax for build env vars #14143
Conversation
[test] |
[testextended][extended:core(builds)] |
@openshift/devex ptal |
}, | ||
}, | ||
errExpected: true, | ||
errField: "env[0].valueFrom.ResourceFieldRef", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if this isn't supported, is there another way for the user to reference the memory/cpu resource limits/requests for the build?
pkg/build/api/types.go
Outdated
@@ -475,6 +475,10 @@ const ( | |||
// build pod but one was already present. | |||
StatusReasonBuildPodExists StatusReason = "BuildPodExists" | |||
|
|||
// StatusReasonInvalidValueFrom indicates that and error occurred processing | |||
// the supplied options for valueFrom in the build strategy environment | |||
StatusReasonInvalidValueFrom StatusReason = "InvalidValueFrom" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EnvValueFrom
build.Status.Reason = buildapi.StatusReasonInvalidValueFrom | ||
return err | ||
} | ||
*originalEnvVars = *processedEnvVars |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be done at the same point where we apply env from the defaults/overrides.
in fact this processing should be done after that, so it can take into account default/override values that use a valuefrom reference.
pkg/build/controller/common/util.go
Outdated
case e.Value != "": | ||
value = e.Value | ||
case e.ValueFrom.FieldRef != nil: | ||
value, err = envutil.GetEnvVarFieldRef(build, e.ValueFrom) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so would they handle a resource ref by using a field ref?
pkg/build/controller/common/util.go
Outdated
return nil, nil, utilerrors.NewAggregate(allErrs) | ||
} | ||
|
||
return inputEnv, &outputEnv, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think i see why you did it, but i think it's weird you're returning the inputenv here. i think you should just return the resolved env.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(and make the caller get a handle to the envvar array they want to overwrite with the new values)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in next push
pkg/util/env/env.go
Outdated
} | ||
} | ||
|
||
func GetEnvVarSecretRefValue(client kclientset.Interface, namespace string, store *ResourceStore, secretSelector *kapi.SecretKeySelector) (string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this function has nothing to do w/ EnvVar so don't include it in the name. find some other way to disambiguate it from the private function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in next push
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in next push
pkg/util/env/env.go
Outdated
return GetEnvVarSecretRefValue(kubeClient, namespace, store, secretSelector) | ||
} | ||
|
||
func GetEnvVarConfigMapRefValue(client kclientset.Interface, namespace string, store *ResourceStore, configMapSelector *kapi.ConfigMapKeySelector) (string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this function has nothing to do w/ EnvVar so don't include it in the name. find some other way to disambiguate it from the private function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in next push
@@ -0,0 +1,134 @@ | |||
package env |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
godoc for all the functions in this file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in next push
pkg/util/env/env.go
Outdated
return fieldpath.InternalExtractContainerResourceValue(from.ResourceFieldRef, c) | ||
} | ||
|
||
func GetEnvVarRefValue(f *clientcmd.Factory, store *ResourceStore, from *kapi.EnvVarSource, obj runtime.Object, c *kapi.Container) (string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why isn't there an equivalent of this for the build logic to call, instead of including all the switching in the build controller?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
excellent idea, refactored in next push
pkg/build/controller/common/util.go
Outdated
case e.Value != "": | ||
value = e.Value | ||
case e.ValueFrom.FieldRef != nil: | ||
value, err = envutil.GetEnvVarFieldRef(build, e.ValueFrom) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so this is how they could reference the build limits/request values?
@@ -683,7 +683,12 @@ func ValidateStrategyEnv(vars []kapi.EnvVar, fldPath *field.Path) field.ErrorLis | |||
allErrs = append(allErrs, field.Invalid(idxPath.Child("name"), ev.Name, cIdentifierErrorMsg)) | |||
} | |||
if ev.ValueFrom != nil { | |||
allErrs = append(allErrs, field.Invalid(idxPath.Child("valueFrom"), ev.ValueFrom, "valueFrom is not supported in build strategy environment variables")) | |||
if ev.Value != "" { | |||
allErrs = append(allErrs, field.Duplicate(idxPath.Child("value"), fmt.Sprintf("cannot use 'value' and 'valueFrom' together for %v", ev.Name))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAICS Kubernetes allows the user to specify value and valueFrom. If value is set, it takes precedence. I can see advantages in behaving in the same way, and I can see also advantages in being more restrictive. @bparees do you have an opinion on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jim-minter good catch. we should be matching the k8s behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in next push
if ev.Value != "" { | ||
allErrs = append(allErrs, field.Duplicate(idxPath.Child("value"), fmt.Sprintf("cannot use 'value' and 'valueFrom' together for %v", ev.Name))) | ||
} | ||
if ev.ValueFrom.ResourceFieldRef != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that we can/should remove this code in favour of ValidateEnv() from vendor/k8s.io/kubernetes/pkg/api/validation, with an additional check if we don't permit ResourceFieldRef != nil
.
@@ -710,7 +714,6 @@ type CustomBuildStrategy struct { | |||
PullSecret *kapi.LocalObjectReference | |||
|
|||
// Env contains additional environment variables you want to pass into a builder container. | |||
// ValueFrom is not supported. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please also update docs in v1/types.go
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in next push
pkg/build/controller/common/util.go
Outdated
var err error | ||
|
||
if e.Value != "" { | ||
r, err := regexp.Compile(`(\$\([A-Z_]+\))`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you have to use regexes, they should be package-level and non-exported, initialised using regex.MustCompile().
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in next push
build.Status.Reason = buildapi.StatusReasonInvalidEnvironmentVariable | ||
return err | ||
} | ||
*originalEnvVars = *processedEnvVars |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this code is mis-located. I think it is, or almost certainly will become, a problem to modify the original Build object in memory. You will need to locate this code at least after the kapi.Scheme.Copy in nextBuildPhase() and do your work on the buildCopy object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Also, I remember the discussion but not the outcome of it: was the decision definitely to update the build object with the resolved env vars as well as the resulting pod, or was it just the latter?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code for this is getting refactored with my pull #14289. At some point we'll need to reconcile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think i had a comment elsewhere that the processing of the env vars should be done in the same place/way that we're doing it for the builddefaulter/overrider.
pkg/build/controller/common/util.go
Outdated
// ProcessValueFrom supports the k8s pod syntax of allowing "valueFrom" in addition | ||
// to "value", where "valueFrom" uses the downward api to reference existing env | ||
// variables, jsonpath references to the build object, secrets, and configmaps. | ||
func ProcessValueFrom(build *buildapi.Build, client kclientset.Interface) (*[]kapi.EnvVar, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(comment applies to whole PR) I think that working with types of *[]Foo is generally an antipattern. The implementation of []Foo is that it already contains a pointer to an underlying shared array. For this PR I'd sooner see rework to use []kapi.EnvVar; perhaps this will necessitate the addition of a helper function such as PutEnvToStrategy (or something), but I think that's preferable to *[]kapi.EnvVar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
given that this is a return value and not a parameter, it should be entirely possible to just return []Foo and let the caller look up the pointer if it wants to use it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm disagreeing with the use of *[]kapi.EnvVar throughout this PR, not just as a return type here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated in next push
pkg/build/controller/common/util.go
Outdated
var err error | ||
|
||
if e.Value != "" { | ||
r, err := regexp.Compile(`(\$\([A-Z_]+\))`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This section is quite problematic. Please take a look at the use of k8s.io/kubernetes/third_party/forked/golang/expansion.Expand()
in vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods.go and use that as a model.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in next push
@@ -1,27 +0,0 @@ | |||
// This file was automatically generated by informer-gen |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the deletion of these files intentional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, ben told me to delete them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no i told you to delete the buildconfig related generated files:
you also seem to have fallen victim to the unnecessary buildconfig informer generation. delete all these generated files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
meaning the new ones your PR was introducing, not the existing ones.
pkg/build/util/util.go
Outdated
@@ -307,3 +307,19 @@ func SafeForLoggingS2IConfig(config *s2iapi.Config) *s2iapi.Config { | |||
newConfig.ScriptsURL, _ = s2iutil.SafeForLoggingURL(newConfig.ScriptsURL) | |||
return &newConfig | |||
} | |||
|
|||
// Gets the Env section of the build config regardless of the build strategy | |||
func GetEnvFromStrategy(build *buildapi.Build) *[]kapi.EnvVar { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is duplicating non-exported code at least in pkg/build/admission/buildpodutil.go, pkg/build/admission/defaults/admission.go and pkg/build/util/util.go.
If you end up adding an update equivalent, there's one already in pkg/build/generator/generator.go.
If this isn't dealt with in this PR, please could you open a follow-on issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I refactored the updateBuildEnv from generator.go into pkg/build/util/util.go in the next push, and refactored pkg/build/admission/defaults/admission.go to use the new GetBuildEnv function that I added.
If you are referring to the buildEnvVar function in buildpodutil.go, that seems to not be doing the same thing that these are?
test/extended/builds/valuefrom.go
Outdated
err := oc.Run("create").Args("-f", stiImageStreamFixture).Execute() | ||
o.Expect(err).NotTo(o.HaveOccurred()) | ||
|
||
g.By("creating test secret") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
push this and the "creating test configmap" into g.JustBeforeEach() above to save duplication of code in each g.It()?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in next push
test/extended/builds/valuefrom.go
Outdated
|
||
}) | ||
|
||
g.It("should fail processing ResourceFieldRef and value/valueFrom in s2i build strategy environment variables", func() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the negative case shouldn't require an extended test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in next push
test/extended/builds/valuefrom.go
Outdated
|
||
}) | ||
|
||
g.It("should fail processing reference $(ENV_VAR) to missing s2i build strategy environment variable", func() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(refers to this and subsequent test:) Kubernetes doesn't class an unresolvable reference as an error (it just leaves $(ENV_VAR) in the input). Should we really diverge?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in next push
test/extended/builds/valuefrom.go
Outdated
|
||
) | ||
|
||
var _ = g.Describe("[builds][valueFrom] process valueFrom in build strategy environment variables", func() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Conformance] ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in next push
test/flake #14462 |
test/flake #14353 |
pkg/build/util/util.go
Outdated
@@ -307,3 +307,41 @@ func SafeForLoggingS2IConfig(config *s2iapi.Config) *s2iapi.Config { | |||
newConfig.ScriptsURL, _ = s2iutil.SafeForLoggingURL(newConfig.ScriptsURL) | |||
return &newConfig | |||
} | |||
|
|||
// GetBuildEnv gets the build strategy environment | |||
func GetBuildEnv(build *buildapi.Build) *[]kapi.EnvVar { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be func GetBuildEnv(build *buildapi.Build) []kapi.EnvVar
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated in next push
pkg/build/controller/common/util.go
Outdated
mapEnvs[e.Name] = value | ||
} | ||
|
||
if allErrs != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if len(allErrs) > 0
is a little more robust.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated in next push
pkg/build/controller/common/util.go
Outdated
buildEnv := buildutil.GetBuildEnv(build) | ||
*buildEnv = outputEnv | ||
|
||
return buildadmission.SetBuildInPod(pod, build, version) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can SetBuildInPod be moved to pkg/build/util?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re-factor at a later date
pkg/build/controller/common/util.go
Outdated
var outputEnv []kapi.EnvVar | ||
var allErrs []error | ||
|
||
build, version, err := buildadmission.GetBuildFromPod(pod) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can GetBuildInPod be moved to pkg/build/util?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess the answer to that may be, excessive work for this PR but worth scheduling for tech debt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is probably a good candidate for re-factoring at a later date.
pkg/build/controller/common/util.go
Outdated
@@ -134,3 +140,48 @@ func HasBuildPodNameAnnotation(build *buildapi.Build) bool { | |||
_, hasAnnotation := build.Annotations[buildapi.BuildPodNameAnnotation] | |||
return hasAnnotation | |||
} | |||
|
|||
// ProcessValueFrom supports the k8s pod syntax of allowing "valueFrom" in addition |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A little more godoc might be nice - say something about what the function actually does
pkg/build/api/types.go
Outdated
@@ -475,6 +475,10 @@ const ( | |||
// build pod but one was already present. | |||
StatusReasonBuildPodExists StatusReason = "BuildPodExists" | |||
|
|||
// StatusReasonInvalidEnvironmentVariable indicates that an error occurred processing | |||
// the supplied options for environment variables in the build strategy environment | |||
StatusReasonInvalidEnvironmentVariable StatusReason = "InvalidEnvironmentVariable" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a bit of a mismatch between the name of this error and the actual reasons why ProcessValueFrom
might return - is it possible to tighten this up at all? How do other parts of origin/k8s report this type of error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jim-minter are you suggesting a name more like invalidenvironmentvariablereference or invalidenvironmentvariablefrom or something?
For my part i'm ok with this as is, but maybe an easy improvement would be "UnresolveableEnvironmentVariable"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated in next push
@@ -682,8 +682,8 @@ func ValidateStrategyEnv(vars []kapi.EnvVar, fldPath *field.Path) field.ErrorLis | |||
} else if len(kvalidation.IsCIdentifier(ev.Name)) > 0 { | |||
allErrs = append(allErrs, field.Invalid(idxPath.Child("name"), ev.Name, cIdentifierErrorMsg)) | |||
} | |||
if ev.ValueFrom != nil { | |||
allErrs = append(allErrs, field.Invalid(idxPath.Child("valueFrom"), ev.ValueFrom, "valueFrom is not supported in build strategy environment variables")) | |||
if ev.ValueFrom != nil && ev.ValueFrom.ResourceFieldRef != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ValidateStrategyEnv is called from ValidateBuildDefaultsConfig - may want to continue to prevent BuildDefaults from using ValueFrom - @bparees?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jim-minter i don't see a compelling reason to disallow ValueFrom in BuildDefaults, do you have a specific concern?
flake #14615 |
extended test failure is a known flake. |
Evaluated for origin testextended up to 8e08af2 |
Evaluated for origin test up to 8e08af2 |
lgtm, will merge on passing tests. |
continuous-integration/openshift-jenkins/test SUCCESS (https://ci.openshift.redhat.com/jenkins/job/test_pull_request_origin/2270/) (Base Commit: 84b8802) |
[merge][severity:blocker] |
continuous-integration/openshift-jenkins/testextended FAILURE (https://ci.openshift.redhat.com/jenkins/job/test_pull_request_origin_extended/634/) (Base Commit: 84b8802) (Extended Tests: core(builds)) |
Evaluated for origin merge up to 8e08af2 |
continuous-integration/openshift-jenkins/merge FAILURE (https://ci.openshift.redhat.com/jenkins/job/merge_pull_request_origin/1024/) (Base Commit: 517be84) (PR Branch Commit: 8e08af2) (Extended Tests: blocker) |
unrelated failure, has passing tests. manually merging.
|
Causing origin-gce image merge test to fail: https://ci.openshift.redhat.com/jenkins/job/zz_origin_gce_image/272/ |
@smarterclayton @bparees looks like it's because GCE doesn't build new images. I'll submit a pull request to skip those tests on gce. |
pull request #14721 submitted |
@smarterclayton what's the difference between "test_pull_request_origin_extended_conformance_gce" (which passed) and "zz_origin_gce_image" ? (I see why the other PR was created now) |
I'll just add them to the filter list for now - we can talk about an
approach that scales re: backwards compat next week.
|
} | ||
|
||
// GenEnvVarRefValue returns the value referenced by the supplied EnvVarSource given the other supplied information | ||
func GetEnvVarRefValue(f *clientcmd.Factory, kc kclientset.Interface, ns string, store *ResourceStore, from *kapi.EnvVarSource, obj runtime.Object, c *kapi.Container) (string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Things in pkg/util are not allowed to reference clientcmd.Factory. Only things in a pkg/cmd scope may do that. This needs to be refactored to not reference that from here. It's also not really appropriate to accept client interfaces into util packages unless they are much more tightly scoped. I'd have expected this package to be pkg/pod/envresolve
or similar.
} | ||
|
||
if from.SecretKeyRef != nil { | ||
return getSecretRefValue(kubeClient, namespace, store, from.SecretKeyRef) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is a security escalation attack waiting to happen. Please add specific separate tests that verify that no call outside of ns
is made, and add specific language to the call sites that doing so is not allowed.
Addresses the following comments against the first pull request (#14143): openshift/origin#14143 (review) openshift/origin#14143 (review)
Trello card: https://trello.com/c/lDxfG8GO/1062-8-support-valuefrom-syntax-for-build-env-vars-techdebt
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1402468