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  }