github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/caas/kubernetes/provider/k8stypes.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package provider 5 6 import ( 7 "fmt" 8 "strings" 9 10 "github.com/juju/collections/set" 11 "github.com/juju/errors" 12 "gopkg.in/yaml.v2" 13 core "k8s.io/api/core/v1" 14 k8syaml "k8s.io/apimachinery/pkg/util/yaml" 15 16 "github.com/juju/juju/caas" 17 ) 18 19 type caasContainerSpec caas.ContainerSpec 20 21 type k8sContainer struct { 22 caasContainerSpec `json:",inline"` 23 *K8sContainerSpec `json:",inline"` 24 } 25 26 type k8sContainers struct { 27 Containers []k8sContainer `json:"containers"` 28 } 29 30 // K8sContainerSpec is a subset of v1.Container which defines 31 // attributes we expose for charms to set. 32 type K8sContainerSpec struct { 33 LivenessProbe *core.Probe `json:"livenessProbe,omitempty"` 34 ReadinessProbe *core.Probe `json:"readinessProbe,omitempty"` 35 ImagePullPolicy core.PullPolicy `json:"imagePullPolicy,omitempty"` 36 } 37 38 // Validate is defined on ProviderContainer. 39 func (*K8sContainerSpec) Validate() error { 40 return nil 41 } 42 43 type caasPodSpec caas.PodSpec 44 45 type k8sPod struct { 46 caasPodSpec `json:",inline"` 47 *K8sPodSpec `json:",inline"` 48 } 49 50 // K8sPodSpec is a subset of v1.PodSpec which defines 51 // attributes we expose for charms to set. 52 type K8sPodSpec struct { 53 ServiceAccountName string `json:"serviceAccountName,omitempty"` 54 RestartPolicy core.RestartPolicy `json:"restartPolicy,omitempty"` 55 TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty"` 56 ActiveDeadlineSeconds *int64 `json:"activeDeadlineSeconds,omitempty"` 57 DNSPolicy core.DNSPolicy `json:"dnsPolicy,omitempty"` 58 AutomountServiceAccountToken *bool `json:"automountServiceAccountToken,omitempty"` 59 SecurityContext *core.PodSecurityContext `json:"securityContext,omitempty"` 60 Hostname string `json:"hostname,omitempty"` 61 Subdomain string `json:"subdomain,omitempty"` 62 PriorityClassName string `json:"priorityClassName,omitempty"` 63 Priority *int32 `json:"priority,omitempty"` 64 DNSConfig *core.PodDNSConfig `json:"dnsConfig,omitempty"` 65 ReadinessGates []core.PodReadinessGate `json:"readinessGates,omitempty"` 66 } 67 68 // Validate is defined on ProviderPod. 69 func (*K8sPodSpec) Validate() error { 70 return nil 71 } 72 73 var boolValues = set.NewStrings( 74 strings.Split("y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF", "|")...) 75 76 // parseK8sPodSpec parses a YAML file which defines how to 77 // configure a CAAS pod. We allow for generic container 78 // set up plus k8s select specific features. 79 func parseK8sPodSpec(in string) (*caas.PodSpec, error) { 80 // Do the common fields. 81 var spec caas.PodSpec 82 if err := yaml.Unmarshal([]byte(in), &spec); err != nil { 83 return nil, errors.Trace(err) 84 } 85 86 // Do the k8s pod attributes. 87 var pod k8sPod 88 decoder := k8syaml.NewYAMLOrJSONDecoder(strings.NewReader(in), len(in)) 89 if err := decoder.Decode(&pod); err != nil { 90 return nil, errors.Trace(err) 91 } 92 if pod.K8sPodSpec != nil { 93 spec.ProviderPod = pod.K8sPodSpec 94 } 95 96 // Do the k8s containers. 97 var containers k8sContainers 98 decoder = k8syaml.NewYAMLOrJSONDecoder(strings.NewReader(in), len(in)) 99 if err := decoder.Decode(&containers); err != nil { 100 return nil, errors.Trace(err) 101 } 102 103 if len(containers.Containers) == 0 { 104 return nil, errors.New("require at least one container spec") 105 } 106 107 // Any string config values that could be interpreted as bools need to be quoted. 108 for _, container := range containers.Containers { 109 for k, v := range container.Config { 110 strValue, ok := v.(string) 111 if !ok { 112 continue 113 } 114 if boolValues.Contains(strValue) { 115 container.Config[k] = fmt.Sprintf("'%s'", strValue) 116 } 117 } 118 } 119 120 // Compose the result. 121 spec.Containers = make([]caas.ContainerSpec, len(containers.Containers)) 122 for i, c := range containers.Containers { 123 if err := c.Validate(); err != nil { 124 return nil, errors.Trace(err) 125 } 126 spec.Containers[i] = caas.ContainerSpec{ 127 ImageDetails: c.ImageDetails, 128 Name: c.Name, 129 Image: c.Image, 130 Ports: c.Ports, 131 Command: c.Command, 132 Args: c.Args, 133 WorkingDir: c.WorkingDir, 134 Config: c.Config, 135 Files: c.Files, 136 } 137 if c.K8sContainerSpec != nil { 138 spec.Containers[i].ProviderContainer = c.K8sContainerSpec 139 } 140 } 141 return &spec, nil 142 }