Add pod_environment_secret secrets to be injected to all clusters.
A potential mechanism to provide secrets to custom sidecars. Right now it is WIP and only provid secrets to Spilo Pods.
This commit is contained in:
		
							parent
							
								
									16a710a99a
								
							
						
					
					
						commit
						5cef7a5b45
					
				|  | @ -15,6 +15,7 @@ import ( | ||||||
| 
 | 
 | ||||||
| 	"github.com/zalando-incubator/postgres-operator/pkg/spec" | 	"github.com/zalando-incubator/postgres-operator/pkg/spec" | ||||||
| 	"github.com/zalando-incubator/postgres-operator/pkg/util/constants" | 	"github.com/zalando-incubator/postgres-operator/pkg/util/constants" | ||||||
|  | 	"github.com/zalando-incubator/postgres-operator/pkg/util/k8sutil" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
|  | @ -319,6 +320,7 @@ func (c *Cluster) generatePodTemplate( | ||||||
| 	cloneDescription *spec.CloneDescription, | 	cloneDescription *spec.CloneDescription, | ||||||
| 	dockerImage *string, | 	dockerImage *string, | ||||||
| 	customPodEnvVars map[string]string, | 	customPodEnvVars map[string]string, | ||||||
|  | 	customPodSecrets map[string][]byte, | ||||||
| ) *v1.PodTemplateSpec { | ) *v1.PodTemplateSpec { | ||||||
| 	spiloConfiguration := c.generateSpiloJSONConfiguration(pgParameters, patroniParameters) | 	spiloConfiguration := c.generateSpiloJSONConfiguration(pgParameters, patroniParameters) | ||||||
| 
 | 
 | ||||||
|  | @ -426,11 +428,43 @@ func (c *Cluster) generatePodTemplate( | ||||||
| 				name, c.OpConfig.PodEnvironmentConfigMap) | 				name, c.OpConfig.PodEnvironmentConfigMap) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
| 	sort.Strings(names) | 	sort.Strings(names) | ||||||
| 	for _, name := range names { | 	for _, name := range names { | ||||||
| 		envVars = append(envVars, v1.EnvVar{Name: name, Value: customPodEnvVars[name]}) | 		envVars = append(envVars, v1.EnvVar{Name: name, Value: customPodEnvVars[name]}) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	//TODO: move the variable comparing and sorting code to a sepatate function
 | ||||||
|  | 	var secretVarNames []string | ||||||
|  | 	// include references to the secrets provided in the operator configuration.
 | ||||||
|  | 	// TODO: what happens with the secrets located in a different namespace?
 | ||||||
|  | 	if c.OpConfig.PodEnvironmentSecret != "" { | ||||||
|  | 		for secretVarName := range customPodSecrets { | ||||||
|  | 			// environment variable names have scricter rules than secrets
 | ||||||
|  | 			if !k8sutil.EnvironmentVariableNameIsValid(secretVarName) { | ||||||
|  | 				c.logger.Warningf("Secret key %s cannot be a name of an environment variable") | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 			if _, ok := envVarsMap[secretVarName]; !ok { | ||||||
|  | 				secretVarNames = append(secretVarNames, secretVarName) | ||||||
|  | 			} else { | ||||||
|  | 				c.logger.Warningf("variable %q value from %q is ignored: conflict with the definition from the operator", | ||||||
|  | 					secretVarNames, c.OpConfig.PodEnvironmentConfigMap) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		sort.Strings(secretVarNames) | ||||||
|  | 		for _, name := range secretVarNames { | ||||||
|  | 			envVars = append(envVars, v1.EnvVar{Name: name, ValueFrom: &v1.EnvVarSource{ | ||||||
|  | 				SecretKeyRef: &v1.SecretKeySelector{ | ||||||
|  | 					LocalObjectReference: v1.LocalObjectReference{ | ||||||
|  | 						Name: c.OpConfig.PodEnvironmentSecret, | ||||||
|  | 					}, | ||||||
|  | 					Key: name, | ||||||
|  | 				}, | ||||||
|  | 			}}) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	privilegedMode := true | 	privilegedMode := true | ||||||
| 	containerImage := c.OpConfig.DockerImage | 	containerImage := c.OpConfig.DockerImage | ||||||
| 	if dockerImage != nil && *dockerImage != "" { | 	if dockerImage != nil && *dockerImage != "" { | ||||||
|  | @ -575,7 +609,11 @@ func (c *Cluster) generateStatefulSet(spec *spec.PostgresSpec) (*v1beta1.Statefu | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, fmt.Errorf("could not generate Scalyr sidecar resource requirements: %v", err) | 		return nil, fmt.Errorf("could not generate Scalyr sidecar resource requirements: %v", err) | ||||||
| 	} | 	} | ||||||
| 	var customPodEnvVars map[string]string | 	var ( | ||||||
|  | 		customPodEnvVars map[string]string | ||||||
|  | 		customPodSecrets map[string][]byte | ||||||
|  | 	) | ||||||
|  | 	// TODO: pod environment configmaps are read from the cluster namespace
 | ||||||
| 	if c.OpConfig.PodEnvironmentConfigMap != "" { | 	if c.OpConfig.PodEnvironmentConfigMap != "" { | ||||||
| 		if cm, err := c.KubeClient.ConfigMaps(c.Namespace).Get(c.OpConfig.PodEnvironmentConfigMap, metav1.GetOptions{}); err != nil { | 		if cm, err := c.KubeClient.ConfigMaps(c.Namespace).Get(c.OpConfig.PodEnvironmentConfigMap, metav1.GetOptions{}); err != nil { | ||||||
| 			return nil, fmt.Errorf("could not read PodEnvironmentConfigMap: %v", err) | 			return nil, fmt.Errorf("could not read PodEnvironmentConfigMap: %v", err) | ||||||
|  | @ -583,7 +621,24 @@ func (c *Cluster) generateStatefulSet(spec *spec.PostgresSpec) (*v1beta1.Statefu | ||||||
| 			customPodEnvVars = cm.Data | 			customPodEnvVars = cm.Data | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	podTemplate := c.generatePodTemplate(c.Postgresql.GetUID(), resourceRequirements, resourceRequirementsScalyrSidecar, &spec.Tolerations, &spec.PostgresqlParam, &spec.Patroni, &spec.Clone, &spec.DockerImage, customPodEnvVars) | 	// TODO: pod environment secrets are read from the cluster namespace
 | ||||||
|  | 	if c.OpConfig.PodEnvironmentSecret != "" { | ||||||
|  | 		if secret, err := c.KubeClient.Secrets(c.Namespace).Get(c.OpConfig.PodEnvironmentSecret, metav1.GetOptions{}); err != nil { | ||||||
|  | 			return nil, fmt.Errorf("could not read PodEnvironmentSecret secrets", err) | ||||||
|  | 		} else { | ||||||
|  | 			customPodSecrets = secret.Data | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	podTemplate := c.generatePodTemplate(c.Postgresql.GetUID(), | ||||||
|  | 		resourceRequirements, | ||||||
|  | 		resourceRequirementsScalyrSidecar, | ||||||
|  | 		&spec.Tolerations, | ||||||
|  | 		&spec.PostgresqlParam, | ||||||
|  | 		&spec.Patroni, | ||||||
|  | 		&spec.Clone, | ||||||
|  | 		&spec.DockerImage, | ||||||
|  | 		customPodEnvVars, | ||||||
|  | 		customPodSecrets) | ||||||
| 	volumeClaimTemplate, err := generatePersistentVolumeClaimTemplate(spec.Volume.Size, spec.Volume.StorageClass) | 	volumeClaimTemplate, err := generatePersistentVolumeClaimTemplate(spec.Volume.Size, spec.Volume.StorageClass) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, fmt.Errorf("could not generate volume claim template: %v", err) | 		return nil, fmt.Errorf("could not generate volume claim template: %v", err) | ||||||
|  |  | ||||||
|  | @ -33,6 +33,7 @@ type Resources struct { | ||||||
| 	DefaultCPULimit         string            `name:"default_cpu_limit" default:"3"` | 	DefaultCPULimit         string            `name:"default_cpu_limit" default:"3"` | ||||||
| 	DefaultMemoryLimit      string            `name:"default_memory_limit" default:"1Gi"` | 	DefaultMemoryLimit      string            `name:"default_memory_limit" default:"1Gi"` | ||||||
| 	PodEnvironmentConfigMap string            `name:"pod_environment_configmap" default:""` | 	PodEnvironmentConfigMap string            `name:"pod_environment_configmap" default:""` | ||||||
|  | 	PodEnvironmentSecret    string            `name:"pod_environment_secret" default:""` | ||||||
| 	NodeReadinessLabel      map[string]string `name:"node_readiness_label" default:""` | 	NodeReadinessLabel      map[string]string `name:"node_readiness_label" default:""` | ||||||
| 	MaxInstances            int32             `name:"max_instances" default:"-1"` | 	MaxInstances            int32             `name:"max_instances" default:"-1"` | ||||||
| 	MinInstances            int32             `name:"min_instances" default:"-1"` | 	MinInstances            int32             `name:"min_instances" default:"-1"` | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ package k8sutil | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"reflect" | 	"reflect" | ||||||
|  | 	"regexp" | ||||||
| 
 | 
 | ||||||
| 	apiextclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" | 	apiextclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" | ||||||
| 	apiextbeta1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1" | 	apiextbeta1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1" | ||||||
|  | @ -22,6 +23,14 @@ import ( | ||||||
| 	"github.com/zalando-incubator/postgres-operator/pkg/util/constants" | 	"github.com/zalando-incubator/postgres-operator/pkg/util/constants" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | const ( | ||||||
|  | 	EnvironmentNameRegexpString = "[-._a-zA-Z][-._a-zA-Z0-9]*" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	environmentNameRegexp = regexp.MustCompile(EnvironmentNameRegexpString) | ||||||
|  | ) | ||||||
|  | 
 | ||||||
| // KubernetesClient describes getters for Kubernetes objects
 | // KubernetesClient describes getters for Kubernetes objects
 | ||||||
| type KubernetesClient struct { | type KubernetesClient struct { | ||||||
| 	v1core.SecretsGetter | 	v1core.SecretsGetter | ||||||
|  | @ -153,3 +162,7 @@ func SamePDB(cur, new *policybeta1.PodDisruptionBudget) (match bool, reason stri | ||||||
| 
 | 
 | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func EnvironmentVariableNameIsValid(name string) bool { | ||||||
|  | 	return environmentNameRegexp.MatchString(name) | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue