diff --git a/proxy/doc.go b/proxy/doc.go new file mode 100644 index 0000000..c860758 --- /dev/null +++ b/proxy/doc.go @@ -0,0 +1,33 @@ +// Copyright 2021 The Operator-SDK Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* +Package proxy implements helper functions to facilitate making operators proxy-aware. + +This package assumes that proxy environment variables `HTTPS_PROXY`, +`HTTP_PROXY`, and/or `NO_PROXY` are set in the Operator environment, typically +via the Operator deployment. + +Proxy-aware operators can use the ReadProxyVarsFromEnv to retrieve these values +as a slice of corev1 EnvVars. Each of the proxy variables are duplicated in +upper and lower case to support applications that use either. In their +reconcile functions, Operator authors are then responsible for setting these +variables in the Container Envs that must use the proxy, For example: + + // Pods with Kubernetes < 1.22 + for _, cSpec := range (myPod.Spec.Containers) { + cSpec.Env = append(defaultEnv(), ReadProxyVarsFromEnv()) + } +*/ +package proxy diff --git a/proxy/proxy.go b/proxy/proxy.go new file mode 100644 index 0000000..fc9b9a8 --- /dev/null +++ b/proxy/proxy.go @@ -0,0 +1,45 @@ +// Copyright 2021 The Operator-SDK Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package proxy + +import ( + "os" + "strings" + + corev1 "k8s.io/api/core/v1" +) + +// ProxyEnvNames are standard environment variables for proxies +var ProxyEnvNames = []string{"HTTP_PROXY", "HTTPS_PROXY", "NO_PROXY"} + +// ReadProxyVarsFromEnv retrieves the standard proxy-related environment +// variables from the running environment and returns a slice of corev1 EnvVar +// containing upper and lower case versions of those variables. +func ReadProxyVarsFromEnv() []corev1.EnvVar { + envVars := []corev1.EnvVar{} + for _, s := range ProxyEnvNames { + value, isSet := os.LookupEnv(s) + if isSet { + envVars = append(envVars, corev1.EnvVar{ + Name: s, + Value: value, + }, corev1.EnvVar{ + Name: strings.ToLower(s), + Value: value, + }) + } + } + return envVars +} diff --git a/proxy/proxy_suite_test.go b/proxy/proxy_suite_test.go new file mode 100644 index 0000000..f70e49b --- /dev/null +++ b/proxy/proxy_suite_test.go @@ -0,0 +1,27 @@ +// Copyright 2021 The Operator-SDK Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package proxy_test + +import ( + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func TestProxy(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Proxy Suite") +} diff --git a/proxy/proxy_test.go b/proxy/proxy_test.go new file mode 100644 index 0000000..a051f13 --- /dev/null +++ b/proxy/proxy_test.go @@ -0,0 +1,71 @@ +// Copyright 2021 The Operator-SDK Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package proxy + +import ( + "errors" + "os" + "strings" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" +) + +func checkValueFromEnvObj(name string, envVars []corev1.EnvVar) (string, error) { + for i := range envVars { + if envVars[i].Name == name { + return envVars[i].Value, nil + } + } + return "", errors.New("empty name") + +} + +var _ = Describe("Retrieving", func() { + Describe("proxy environment variables", func() { + It("returns a slice of environment variables that were set", func() { + os.Setenv("HTTPS_PROXY", "https_proxy_test") + os.Setenv("HTTP_PROXY", "http_proxy_test") + os.Setenv("NO_PROXY", "no_proxy_test") + envVars := ReadProxyVarsFromEnv() + Expect(len(envVars)).To(Equal(6)) + }) + It("does not return unset variables", func() { + envVars := ReadProxyVarsFromEnv() + Expect(len(envVars)).To(Equal(0)) + }) + + It("creates upper and lower case environment variables with the same value", func() { + os.Setenv("HTTPS_PROXY", "https_proxy_test") + os.Setenv("HTTP_PROXY", "http_proxy_test") + os.Setenv("NO_PROXY", "no_proxy_test") + envVars := ReadProxyVarsFromEnv() + + for _, envName := range ProxyEnvNames { + upperValue, err := checkValueFromEnvObj(envName, envVars) + Expect(err).To(BeNil()) + lowerValue, err := checkValueFromEnvObj(strings.ToLower(envName), envVars) + Expect(err).To(BeNil()) + Expect(upperValue).To(Equal(lowerValue)) + } + }) + AfterEach(func() { + _ = os.Unsetenv("HTTPS_PROXY") + _ = os.Unsetenv("HTTP_PROXY") + _ = os.Unsetenv("NO_PROXY") + }) + }) +})