github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/manager/resources/container/container.go (about) 1 /* 2 * Copyright contributors to the Hyperledger Fabric Operator project 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package container 20 21 import ( 22 "github.com/IBM-Blockchain/fabric-operator/pkg/util" 23 "github.com/IBM-Blockchain/fabric-operator/pkg/util/image" 24 "github.com/pkg/errors" 25 appsv1 "k8s.io/api/apps/v1" 26 corev1 "k8s.io/api/core/v1" 27 ) 28 29 type SecurityContext struct { 30 Privileged *bool 31 RunAsNonRoot *bool 32 RunAsUser *int64 33 AllowPrivilegeEscalation *bool 34 } 35 36 func New(container *corev1.Container) *Container { 37 return &Container{container} 38 } 39 40 func LoadFromDeployment(deployment *appsv1.Deployment) map[string]Container { 41 containers := map[string]Container{} 42 for i, c := range deployment.Spec.Template.Spec.Containers { 43 containers[c.Name] = Container{&deployment.Spec.Template.Spec.Containers[i]} 44 } 45 for i, c := range deployment.Spec.Template.Spec.InitContainers { 46 containers[c.Name] = Container{&deployment.Spec.Template.Spec.InitContainers[i]} 47 } 48 return containers 49 } 50 51 func LoadFromFile(file string) (*Container, error) { 52 container, err := util.GetContainerFromFile(file) 53 if err != nil { 54 return nil, errors.Wrap(err, "failed to read container file") 55 } 56 return &Container{container}, nil 57 } 58 59 type Container struct { 60 *corev1.Container 61 } 62 63 func (c *Container) DeleteEnv(name string) { 64 newEnvs := []corev1.EnvVar{} 65 for _, env := range c.Env { 66 if env.Name == name { 67 continue 68 } 69 newEnvs = append(newEnvs, env) 70 } 71 72 c.Env = newEnvs 73 } 74 75 func (c *Container) UpdateEnv(name, value string) { 76 var updated bool 77 78 newEnvs := []corev1.EnvVar{} 79 for _, env := range c.Env { 80 if env.Name == name { 81 env.Value = value 82 updated = true 83 } 84 newEnvs = append(newEnvs, env) 85 } 86 87 if updated { 88 c.Env = newEnvs 89 } else { 90 c.Env = append(newEnvs, corev1.EnvVar{Name: name, Value: value}) 91 } 92 } 93 94 func (c *Container) AppendEnvStructIfMissing(envVar corev1.EnvVar) { 95 c.Env = util.AppendEnvIfMissing(c.Env, envVar) 96 } 97 98 func (c *Container) AppendEnvIfMissing(name, value string) { 99 envVar := corev1.EnvVar{ 100 Name: name, 101 Value: value, 102 } 103 c.Env = util.AppendEnvIfMissing(c.Env, envVar) 104 } 105 106 func (c *Container) AppendEnvIfMissingOverrideIfPresent(name, value string) { 107 envVar := corev1.EnvVar{ 108 Name: name, 109 Value: value, 110 } 111 c.Env = util.AppendEnvIfMissingOverrideIfPresent(c.Env, envVar) 112 } 113 114 func (c *Container) SetImage(img, tag string) { 115 if img != "" { 116 if tag != "" { 117 c.Container.Image = image.Format(img, tag) 118 } else { 119 c.Container.Image = img + ":latest" 120 } 121 } 122 } 123 124 func (c *Container) AppendVolumeMountStructIfMissing(volumeMount corev1.VolumeMount) { 125 c.VolumeMounts = util.AppendVolumeMountIfMissing(c.VolumeMounts, volumeMount) 126 } 127 128 func (c *Container) AppendVolumeMountIfMissing(name, mountPath string) { 129 volumeMount := corev1.VolumeMount{ 130 Name: name, 131 MountPath: mountPath, 132 } 133 c.VolumeMounts = util.AppendVolumeMountIfMissing(c.VolumeMounts, volumeMount) 134 } 135 136 func (c *Container) AppendVolumeMountWithSubPathIfMissing(name, mountPath, subPath string) { 137 volumeMount := corev1.VolumeMount{ 138 Name: name, 139 MountPath: mountPath, 140 SubPath: subPath, 141 } 142 c.VolumeMounts = util.AppendVolumeMountWithSubPathIfMissing(c.VolumeMounts, volumeMount) 143 } 144 145 func (c *Container) AppendVolumeMountWithSubPath(name, mountPath, subPath string) { 146 volumeMount := corev1.VolumeMount{ 147 Name: name, 148 MountPath: mountPath, 149 SubPath: subPath, 150 } 151 c.VolumeMounts = append(c.VolumeMounts, volumeMount) 152 } 153 154 func (c *Container) SetVolumeMounts(volumeMounts []corev1.VolumeMount) { 155 c.VolumeMounts = volumeMounts 156 } 157 158 func (c *Container) UpdateResources(new *corev1.ResourceRequirements) error { 159 current := &c.Resources 160 update, err := util.GetResourcePatch(current, new) 161 if err != nil { 162 return errors.Wrap(err, "failed to get resource patch") 163 } 164 165 c.Resources = *update 166 return nil 167 } 168 169 func (c *Container) SetCommand(command []string) { 170 c.Command = command 171 } 172 173 func (c *Container) SetArgs(args []string) { 174 c.Args = args 175 } 176 177 func (c *Container) AppendConfigMapFromSourceIfMissing(name string) { 178 envFrom := corev1.EnvFromSource{ 179 ConfigMapRef: &corev1.ConfigMapEnvSource{ 180 LocalObjectReference: corev1.LocalObjectReference{ 181 Name: name, 182 }, 183 }, 184 } 185 c.EnvFrom = util.AppendConfigMapFromSourceIfMissing(c.Container.EnvFrom, envFrom) 186 } 187 188 func (c *Container) AppendEnvVarValueFromIfMissing(name string, valueFrom *corev1.EnvVarSource) { 189 envVar := corev1.EnvVar{ 190 Name: name, 191 ValueFrom: valueFrom, 192 } 193 c.Env = util.AppendEnvIfMissing(c.Container.Env, envVar) 194 } 195 196 func (c *Container) GetEnvs(reqs []string) []corev1.EnvVar { 197 envVars := []corev1.EnvVar{} 198 199 for _, env := range c.Env { 200 for _, req := range reqs { 201 if env.Name == req { 202 envVars = append(envVars, env) 203 } 204 } 205 } 206 207 return envVars 208 } 209 210 // UpdateSecurityContext will update the security context of the container 211 func (c *Container) UpdateSecurityContext(sc SecurityContext) { 212 UpdateSecurityContext(c.Container, sc) 213 } 214 215 // UpdateSecurityContext will update the security context of passed in container 216 func UpdateSecurityContext(c *corev1.Container, sc SecurityContext) { 217 if c.SecurityContext == nil { 218 c.SecurityContext = &corev1.SecurityContext{} 219 } 220 221 c.SecurityContext.Privileged = sc.Privileged 222 c.SecurityContext.RunAsNonRoot = sc.RunAsNonRoot 223 c.SecurityContext.RunAsUser = sc.RunAsUser 224 c.SecurityContext.AllowPrivilegeEscalation = sc.AllowPrivilegeEscalation 225 } 226 227 func (c *Container) SetReadinessProbe(probe *corev1.Probe) { 228 c.ReadinessProbe = probe 229 } 230 231 func (c *Container) SetLivenessProbe(probe *corev1.Probe) { 232 c.LivenessProbe = probe 233 } 234 235 func (c *Container) SetStartupProbe(probe *corev1.Probe) { 236 c.StartupProbe = probe 237 }