github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/caas/kubernetes/provider/k8stypes_test.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package provider_test 5 6 import ( 7 jc "github.com/juju/testing/checkers" 8 gc "gopkg.in/check.v1" 9 core "k8s.io/api/core/v1" 10 apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" 11 "k8s.io/apimachinery/pkg/util/intstr" 12 13 "github.com/juju/juju/caas" 14 "github.com/juju/juju/caas/kubernetes/provider" 15 "github.com/juju/juju/testing" 16 ) 17 18 type ContainersSuite struct { 19 testing.BaseSuite 20 } 21 22 var _ = gc.Suite(&ContainersSuite{}) 23 24 func (s *ContainersSuite) TestParse(c *gc.C) { 25 26 specStr := ` 27 omitServiceFrontend: true 28 activeDeadlineSeconds: 10 29 serviceAccountName: serviceAccount 30 restartPolicy: OnFailure 31 terminationGracePeriodSeconds: 20 32 automountServiceAccountToken: true 33 securityContext: 34 runAsNonRoot: true 35 hostname: host 36 subdomain: sub 37 priorityClassName: top 38 priority: 30 39 dnsConfig: 40 nameservers: [ns1, ns2] 41 readinessGates: 42 - conditionType: PodScheduled 43 containers: 44 - name: gitlab 45 image: gitlab/latest 46 imagePullPolicy: Always 47 command: ["sh", "-c"] 48 args: ["doIt", "--debug"] 49 workingDir: "/path/to/here" 50 ports: 51 - containerPort: 80 52 name: fred 53 protocol: TCP 54 - containerPort: 443 55 name: mary 56 livenessProbe: 57 initialDelaySeconds: 10 58 httpGet: 59 path: /ping 60 port: 8080 61 readinessProbe: 62 initialDelaySeconds: 10 63 httpGet: 64 path: /pingReady 65 port: www 66 config: 67 attr: foo=bar; name['fred']='blogs'; 68 foo: bar 69 restricted: 'yes' 70 switch: on 71 files: 72 - name: configuration 73 mountPath: /var/lib/foo 74 files: 75 file1: | 76 [config] 77 foo: bar 78 - name: gitlab-helper 79 image: gitlab-helper/latest 80 ports: 81 - containerPort: 8080 82 protocol: TCP 83 - name: secret-image-user 84 imageDetails: 85 imagePath: staging.registry.org/testing/testing-image@sha256:deed-beef 86 username: docker-registry 87 password: hunter2 88 - name: just-image-details 89 imageDetails: 90 imagePath: testing/no-secrets-needed@sha256:deed-beef 91 customResourceDefinition: 92 - group: kubeflow.org 93 version: v1alpha2 94 scope: Namespaced 95 kind: TFJob 96 validation: 97 properties: 98 tfReplicaSpecs: 99 properties: 100 Worker: 101 properties: 102 replicas: 103 type: integer 104 minimum: 1 105 PS: 106 properties: 107 replicas: 108 type: integer 109 minimum: 1 110 Chief: 111 properties: 112 replicas: 113 type: integer 114 minimum: 1 115 maximum: 1 116 `[1:] 117 118 expectedFileContent := ` 119 [config] 120 foo: bar 121 `[1:] 122 123 spec, err := provider.ParseK8sPodSpec(specStr) 124 c.Assert(err, jc.ErrorIsNil) 125 c.Assert(spec, jc.DeepEquals, &caas.PodSpec{ 126 OmitServiceFrontend: true, 127 ProviderPod: &provider.K8sPodSpec{ 128 ActiveDeadlineSeconds: int64Ptr(10), 129 ServiceAccountName: "serviceAccount", 130 RestartPolicy: core.RestartPolicyOnFailure, 131 TerminationGracePeriodSeconds: int64Ptr(20), 132 AutomountServiceAccountToken: boolPtr(true), 133 SecurityContext: &core.PodSecurityContext{ 134 RunAsNonRoot: boolPtr(true), 135 }, 136 Hostname: "host", 137 Subdomain: "sub", 138 PriorityClassName: "top", 139 Priority: int32Ptr(30), 140 DNSConfig: &core.PodDNSConfig{ 141 Nameservers: []string{"ns1", "ns2"}, 142 }, 143 ReadinessGates: []core.PodReadinessGate{ 144 {ConditionType: core.PodScheduled}, 145 }, 146 }, 147 Containers: []caas.ContainerSpec{{ 148 Name: "gitlab", 149 Image: "gitlab/latest", 150 Command: []string{"sh", "-c"}, 151 Args: []string{"doIt", "--debug"}, 152 WorkingDir: "/path/to/here", 153 Ports: []caas.ContainerPort{ 154 {ContainerPort: 80, Protocol: "TCP", Name: "fred"}, 155 {ContainerPort: 443, Name: "mary"}, 156 }, 157 Config: map[string]interface{}{ 158 "attr": "foo=bar; name['fred']='blogs';", 159 "foo": "bar", 160 "restricted": "'yes'", 161 "switch": true, 162 }, 163 Files: []caas.FileSet{ 164 { 165 Name: "configuration", 166 MountPath: "/var/lib/foo", 167 Files: map[string]string{ 168 "file1": expectedFileContent, 169 }, 170 }, 171 }, 172 ProviderContainer: &provider.K8sContainerSpec{ 173 ImagePullPolicy: "Always", 174 LivenessProbe: &core.Probe{ 175 InitialDelaySeconds: 10, 176 Handler: core.Handler{ 177 HTTPGet: &core.HTTPGetAction{ 178 Path: "/ping", 179 Port: intstr.IntOrString{IntVal: 8080}, 180 }, 181 }, 182 }, 183 ReadinessProbe: &core.Probe{ 184 InitialDelaySeconds: 10, 185 Handler: core.Handler{ 186 HTTPGet: &core.HTTPGetAction{ 187 Path: "/pingReady", 188 Port: intstr.IntOrString{StrVal: "www", Type: 1}, 189 }, 190 }, 191 }, 192 }, 193 }, { 194 Name: "gitlab-helper", 195 Image: "gitlab-helper/latest", 196 Ports: []caas.ContainerPort{ 197 {ContainerPort: 8080, Protocol: "TCP"}, 198 }, 199 }, { 200 Name: "secret-image-user", 201 ImageDetails: caas.ImageDetails{ 202 ImagePath: "staging.registry.org/testing/testing-image@sha256:deed-beef", 203 Username: "docker-registry", 204 Password: "hunter2", 205 }, 206 }, { 207 Name: "just-image-details", 208 ImageDetails: caas.ImageDetails{ 209 ImagePath: "testing/no-secrets-needed@sha256:deed-beef", 210 }, 211 }}, 212 CustomResourceDefinitions: []caas.CustomResourceDefinition{ 213 { 214 Kind: "TFJob", 215 Group: "kubeflow.org", 216 Version: "v1alpha2", 217 Scope: "Namespaced", 218 Validation: caas.CustomResourceDefinitionValidation{ 219 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 220 "tfReplicaSpecs": { 221 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 222 "PS": { 223 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 224 "replicas": { 225 Type: "integer", Minimum: float64Ptr(1), 226 }, 227 }, 228 }, 229 "Chief": { 230 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 231 "replicas": { 232 Type: "integer", 233 Minimum: float64Ptr(1), 234 Maximum: float64Ptr(1), 235 }, 236 }, 237 }, 238 "Worker": { 239 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 240 "replicas": { 241 Type: "integer", 242 Minimum: float64Ptr(1), 243 }, 244 }, 245 }, 246 }, 247 }, 248 }, 249 }, 250 }, 251 }, 252 }) 253 } 254 255 func float64Ptr(f float64) *float64 { 256 return &f 257 } 258 259 func int32Ptr(i int32) *int32 { 260 return &i 261 } 262 263 func int64Ptr(i int64) *int64 { 264 return &i 265 } 266 267 func boolPtr(b bool) *bool { 268 return &b 269 } 270 271 func (s *ContainersSuite) TestValidateMissingContainers(c *gc.C) { 272 273 specStr := ` 274 containers: 275 `[1:] 276 277 _, err := provider.ParseK8sPodSpec(specStr) 278 c.Assert(err, gc.ErrorMatches, "require at least one container spec") 279 } 280 281 func (s *ContainersSuite) TestValidateMissingName(c *gc.C) { 282 283 specStr := ` 284 containers: 285 - image: gitlab/latest 286 `[1:] 287 288 spec, err := provider.ParseK8sPodSpec(specStr) 289 c.Assert(err, jc.ErrorIsNil) 290 err = spec.Validate() 291 c.Assert(err, gc.ErrorMatches, "spec name is missing") 292 } 293 294 func (s *ContainersSuite) TestValidateMissingImage(c *gc.C) { 295 296 specStr := ` 297 containers: 298 - name: gitlab 299 `[1:] 300 301 spec, err := provider.ParseK8sPodSpec(specStr) 302 c.Assert(err, jc.ErrorIsNil) 303 err = spec.Validate() 304 c.Assert(err, gc.ErrorMatches, "spec image details is missing") 305 } 306 307 func (s *ContainersSuite) TestValidateFileSetPath(c *gc.C) { 308 309 specStr := ` 310 containers: 311 - name: gitlab 312 image: gitlab/latest 313 files: 314 - files: 315 file1: |- 316 [config] 317 foo: bar 318 `[1:] 319 320 spec, err := provider.ParseK8sPodSpec(specStr) 321 c.Assert(err, jc.ErrorIsNil) 322 err = spec.Validate() 323 c.Assert(err, gc.ErrorMatches, `file set name is missing`) 324 } 325 326 func (s *ContainersSuite) TestValidateMissingMountPath(c *gc.C) { 327 328 specStr := ` 329 containers: 330 - name: gitlab 331 image: gitlab/latest 332 files: 333 - name: configuration 334 files: 335 file1: |- 336 [config] 337 foo: bar 338 `[1:] 339 340 spec, err := provider.ParseK8sPodSpec(specStr) 341 c.Assert(err, jc.ErrorIsNil) 342 err = spec.Validate() 343 c.Assert(err, gc.ErrorMatches, `mount path is missing for file set "configuration"`) 344 }