github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/caas/containers.go (about)

     1  // Copyright 2018 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package caas
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
     9  )
    10  
    11  // FileSet defines a set of files to mount
    12  // into the container.
    13  type FileSet struct {
    14  	Name      string            `yaml:"name" json:"name"`
    15  	MountPath string            `yaml:"mountPath" json:"mountPath"`
    16  	Files     map[string]string `yaml:"files" json:"files"`
    17  }
    18  
    19  // ContainerPort defines a port on a container.
    20  type ContainerPort struct {
    21  	Name          string `yaml:"name,omitempty" json:"name,omitempty"`
    22  	ContainerPort int32  `yaml:"containerPort" json:"containerPort"`
    23  	Protocol      string `yaml:"protocol" json:"protocol"`
    24  }
    25  
    26  // ImageDetails defines all details required to pull a docker image from any registry
    27  type ImageDetails struct {
    28  	ImagePath string `yaml:"imagePath" json:"imagePath"`
    29  	Username  string `yaml:"username,omitempty" json:"username,omitempty"`
    30  	Password  string `yaml:"password,omitempty" json:"password,omitempty"`
    31  }
    32  
    33  // ProviderContainer defines a provider specific container.
    34  type ProviderContainer interface {
    35  	Validate() error
    36  }
    37  
    38  // ContainerSpec defines the data values used to configure
    39  // a container on the CAAS substrate.
    40  type ContainerSpec struct {
    41  	Name string `yaml:"name"`
    42  	// Image is deprecated in preference to using ImageDetails.
    43  	Image        string          `yaml:"image,omitempty"`
    44  	ImageDetails ImageDetails    `yaml:"imageDetails"`
    45  	Ports        []ContainerPort `yaml:"ports,omitempty"`
    46  
    47  	Command    []string `yaml:"command,omitempty"`
    48  	Args       []string `yaml:"args,omitempty"`
    49  	WorkingDir string   `yaml:"workingDir,omitempty"`
    50  
    51  	Config map[string]interface{} `yaml:"config,omitempty"`
    52  	Files  []FileSet              `yaml:"files,omitempty"`
    53  
    54  	// ProviderContainer defines config which is specific to a substrate, eg k8s
    55  	ProviderContainer `yaml:"-"`
    56  }
    57  
    58  // PodSpec defines the data values used to configure
    59  // a pod on the CAAS substrate.
    60  type PodSpec struct {
    61  	Containers                []ContainerSpec            `yaml:"-"`
    62  	OmitServiceFrontend       bool                       `yaml:"omitServiceFrontend"`
    63  	CustomResourceDefinitions []CustomResourceDefinition `yaml:"customResourceDefinition,omitempty"`
    64  
    65  	// ProviderPod defines config which is specific to a substrate, eg k8s
    66  	ProviderPod `yaml:"-"`
    67  }
    68  
    69  // ProviderPod defines a provider specific pod.
    70  type ProviderPod interface {
    71  	Validate() error
    72  }
    73  
    74  // CustomResourceDefinitionValidation defines the custom resource definition validation schema.
    75  type CustomResourceDefinitionValidation struct {
    76  	Properties map[string]apiextensionsv1beta1.JSONSchemaProps `yaml:"properties"`
    77  }
    78  
    79  // CustomResourceDefinition defines the custom resource definition template and content format in podspec.
    80  type CustomResourceDefinition struct {
    81  	Kind       string                             `yaml:"kind"`
    82  	Group      string                             `yaml:"group"`
    83  	Version    string                             `yaml:"version"`
    84  	Scope      string                             `yaml:"scope"`
    85  	Validation CustomResourceDefinitionValidation `yaml:"validation,omitempty"`
    86  }
    87  
    88  // Validate returns an error if the crd is not valid.
    89  func (crd *CustomResourceDefinition) Validate() error {
    90  	if crd.Kind == "" {
    91  		return errors.NotValidf("missing kind")
    92  	}
    93  	if crd.Group == "" {
    94  		return errors.NotValidf("missing group")
    95  	}
    96  	if crd.Version == "" {
    97  		return errors.NotValidf("missing version")
    98  	}
    99  	if crd.Scope == "" {
   100  		return errors.NotValidf("missing scope")
   101  	}
   102  	return nil
   103  }
   104  
   105  // Validate returns an error if the spec is not valid.
   106  func (spec *PodSpec) Validate() error {
   107  	for _, c := range spec.Containers {
   108  		if err := c.Validate(); err != nil {
   109  			return errors.Trace(err)
   110  		}
   111  	}
   112  	for _, crd := range spec.CustomResourceDefinitions {
   113  		if err := crd.Validate(); err != nil {
   114  			return errors.Trace(err)
   115  		}
   116  	}
   117  	if spec.ProviderPod != nil {
   118  		return spec.ProviderPod.Validate()
   119  	}
   120  	return nil
   121  }
   122  
   123  // Validate is defined on ProviderContainer.
   124  func (spec *ContainerSpec) Validate() error {
   125  	if spec.Name == "" {
   126  		return errors.New("spec name is missing")
   127  	}
   128  	if spec.Image == "" && spec.ImageDetails.ImagePath == "" {
   129  		return errors.New("spec image details is missing")
   130  	}
   131  	for _, fs := range spec.Files {
   132  		if fs.Name == "" {
   133  			return errors.New("file set name is missing")
   134  		}
   135  		if fs.MountPath == "" {
   136  			return errors.Errorf("mount path is missing for file set %q", fs.Name)
   137  		}
   138  	}
   139  	if spec.ProviderContainer != nil {
   140  		return spec.ProviderContainer.Validate()
   141  	}
   142  	return nil
   143  }