| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450 |
- package provisioner
- import (
- "fmt"
- batchv1 "k8s.io/api/batch/v1"
- v1 "k8s.io/api/core/v1"
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "github.com/porter-dev/porter/internal/kubernetes/provisioner/aws"
- "github.com/porter-dev/porter/internal/kubernetes/provisioner/aws/ecr"
- "github.com/porter-dev/porter/internal/kubernetes/provisioner/aws/eks"
- "github.com/porter-dev/porter/internal/kubernetes/provisioner/do"
- "github.com/porter-dev/porter/internal/kubernetes/provisioner/do/docr"
- "github.com/porter-dev/porter/internal/kubernetes/provisioner/do/doks"
- "github.com/porter-dev/porter/internal/kubernetes/provisioner/input"
- "github.com/porter-dev/porter/internal/kubernetes/provisioner/gcp"
- "github.com/porter-dev/porter/internal/kubernetes/provisioner/gcp/gke"
- "github.com/porter-dev/porter/internal/config"
- )
- // InfraOption is a type of infrastructure that can be provisioned
- type InfraOption string
- // The list of infra options
- const (
- Test InfraOption = "test"
- ECR InfraOption = "ecr"
- EKS InfraOption = "eks"
- GCR InfraOption = "gcr"
- GKE InfraOption = "gke"
- DOCR InfraOption = "docr"
- DOKS InfraOption = "doks"
- )
- // Conf is the config required to start a provisioner container
- type Conf struct {
- Kind InfraOption
- Name string
- Namespace string
- ID string
- Redis *config.RedisConf
- Postgres *config.DBConf
- Operation ProvisionerOperation
- ProvisionerImageTag string
- LastApplied []byte
- // provider-specific configurations
- // AWS
- AWS *aws.Conf
- ECR *ecr.Conf
- EKS *eks.Conf
- // GKE
- GCP *gcp.Conf
- GKE *gke.Conf
- // DO
- DO *do.Conf
- DOCR *docr.Conf
- DOKS *doks.Conf
- }
- type ProvisionerOperation string
- const (
- Apply ProvisionerOperation = "apply"
- Destroy ProvisionerOperation = "destroy"
- )
- // GetProvisionerJobTemplate returns the manifest that should be applied to
- // create a provisioning job
- func (conf *Conf) GetProvisionerJobTemplate() (*batchv1.Job, error) {
- operation := string(conf.Operation)
- if operation == "" {
- operation = string(Apply)
- }
- env := make([]v1.EnvVar, 0)
- env = conf.attachDefaultEnv(env)
- ttl := int32(3600)
- backoffLimit := int32(1)
- labels := map[string]string{
- "app": "provisioner",
- }
- args := make([]string, 0)
- switch conf.Kind {
- case Test:
- args = []string{operation, "test", "hello"}
- case ECR:
- args = []string{operation, "ecr"}
- if len(conf.LastApplied) > 0 {
- inputConf, err := input.GetECRInput(conf.LastApplied)
- if err != nil {
- return nil, err
- }
- conf.AWS.AWSAccessKeyID = inputConf.AWSAccessKey
- conf.AWS.AWSSecretAccessKey = inputConf.AWSSecretKey
- conf.AWS.AWSRegion = inputConf.AWSRegion
- conf.ECR.ECRName = inputConf.ECRName
- } else {
- inputConf := &input.ECR{
- AWSRegion: conf.AWS.AWSRegion,
- AWSAccessKey: conf.AWS.AWSAccessKeyID,
- AWSSecretKey: conf.AWS.AWSSecretAccessKey,
- ECRName: conf.ECR.ECRName,
- }
- lastApplied, err := inputConf.GetInput()
- if err != nil {
- return nil, err
- }
- conf.LastApplied = lastApplied
- }
- env = conf.AWS.AttachAWSEnv(env)
- env = conf.ECR.AttachECREnv(env)
- case EKS:
- args = []string{operation, "eks"}
- if len(conf.LastApplied) > 0 {
- inputConf, err := input.GetEKSInput(conf.LastApplied)
- if err != nil {
- return nil, err
- }
- conf.AWS.AWSAccessKeyID = inputConf.AWSAccessKey
- conf.AWS.AWSSecretAccessKey = inputConf.AWSSecretKey
- conf.AWS.AWSRegion = inputConf.AWSRegion
- conf.EKS.ClusterName = inputConf.ClusterName
- } else {
- inputConf := &input.EKS{
- AWSRegion: conf.AWS.AWSRegion,
- AWSAccessKey: conf.AWS.AWSAccessKeyID,
- AWSSecretKey: conf.AWS.AWSSecretAccessKey,
- ClusterName: conf.EKS.ClusterName,
- }
- lastApplied, err := inputConf.GetInput()
- if err != nil {
- return nil, err
- }
- conf.LastApplied = lastApplied
- }
- env = conf.AWS.AttachAWSEnv(env)
- env = conf.EKS.AttachEKSEnv(env)
- case GCR:
- args = []string{operation, "gcr"}
- if len(conf.LastApplied) > 0 {
- inputConf, err := input.GetGCRInput(conf.LastApplied)
- if err != nil {
- return nil, err
- }
- conf.GCP.GCPKeyData = inputConf.GCPCredentials
- conf.GCP.GCPRegion = inputConf.GCPRegion
- conf.GCP.GCPProjectID = inputConf.GCPProjectID
- } else {
- inputConf := &input.GCR{
- GCPCredentials: conf.GCP.GCPKeyData,
- GCPRegion: conf.GCP.GCPRegion,
- GCPProjectID: conf.GCP.GCPProjectID,
- }
- lastApplied, err := inputConf.GetInput()
- if err != nil {
- return nil, err
- }
- conf.LastApplied = lastApplied
- }
- env = conf.GCP.AttachGCPEnv(env)
- case GKE:
- args = []string{operation, "gke"}
- if len(conf.LastApplied) > 0 {
- inputConf, err := input.GetGKEInput(conf.LastApplied)
- if err != nil {
- return nil, err
- }
- conf.GCP.GCPKeyData = inputConf.GCPCredentials
- conf.GCP.GCPRegion = inputConf.GCPRegion
- conf.GCP.GCPProjectID = inputConf.GCPProjectID
- conf.GKE.ClusterName = inputConf.ClusterName
- } else {
- inputConf := &input.GKE{
- GCPCredentials: conf.GCP.GCPKeyData,
- GCPRegion: conf.GCP.GCPRegion,
- GCPProjectID: conf.GCP.GCPProjectID,
- ClusterName: conf.GKE.ClusterName,
- }
- lastApplied, err := inputConf.GetInput()
- if err != nil {
- return nil, err
- }
- conf.LastApplied = lastApplied
- }
- env = conf.GCP.AttachGCPEnv(env)
- env = conf.GKE.AttachGKEEnv(env)
- case DOCR:
- args = []string{operation, "docr"}
- if len(conf.LastApplied) > 0 {
- inputConf, err := input.GetDOCRInput(conf.LastApplied)
- if err != nil {
- return nil, err
- }
- conf.DO.DOToken = inputConf.DOToken
- conf.DOCR.DOCRSubscriptionTier = inputConf.DOCRSubscriptionTier
- conf.DOCR.DOCRName = inputConf.DOCRName
- } else {
- inputConf := &input.DOCR{
- DOToken: conf.DO.DOToken,
- DOCRSubscriptionTier: conf.DOCR.DOCRSubscriptionTier,
- DOCRName: conf.DOCR.DOCRName,
- }
- lastApplied, err := inputConf.GetInput()
- if err != nil {
- return nil, err
- }
- conf.LastApplied = lastApplied
- }
- env = conf.DO.AttachDOEnv(env)
- env = conf.DOCR.AttachDOCREnv(env)
- case DOKS:
- args = []string{operation, "doks"}
- if len(conf.LastApplied) > 0 {
- inputConf, err := input.GetDOKSInput(conf.LastApplied)
- if err != nil {
- return nil, err
- }
- conf.DO.DOToken = inputConf.DOToken
- conf.DOKS.DORegion = inputConf.DORegion
- conf.DOKS.DOKSClusterName = inputConf.ClusterName
- } else {
- inputConf := &input.DOKS{
- DOToken: conf.DO.DOToken,
- DORegion: conf.DOKS.DORegion,
- ClusterName: conf.DOKS.DOKSClusterName,
- }
- lastApplied, err := inputConf.GetInput()
- if err != nil {
- return nil, err
- }
- conf.LastApplied = lastApplied
- }
- env = conf.DO.AttachDOEnv(env)
- env = conf.DOKS.AttachDOKSEnv(env)
- }
- return &batchv1.Job{
- ObjectMeta: metav1.ObjectMeta{
- Name: conf.Name,
- Namespace: conf.Namespace,
- Labels: labels,
- },
- Spec: batchv1.JobSpec{
- TTLSecondsAfterFinished: &ttl,
- BackoffLimit: &backoffLimit,
- Template: v1.PodTemplateSpec{
- ObjectMeta: metav1.ObjectMeta{
- Labels: labels,
- },
- Spec: v1.PodSpec{
- RestartPolicy: v1.RestartPolicyNever,
- Containers: []v1.Container{
- {
- Name: "provisioner",
- Image: "gcr.io/porter-dev-273614/provisioner:" + conf.ProvisionerImageTag,
- ImagePullPolicy: v1.PullAlways,
- Args: args,
- Env: env,
- VolumeMounts: []v1.VolumeMount{
- v1.VolumeMount{
- MountPath: "/.terraform/plugin-cache",
- Name: "tf-cache",
- ReadOnly: true,
- },
- },
- },
- },
- Volumes: []v1.Volume{
- v1.Volume{
- Name: "tf-cache",
- VolumeSource: v1.VolumeSource{
- PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
- ClaimName: "tf-cache-pvc",
- ReadOnly: true,
- },
- },
- },
- },
- },
- },
- },
- }, nil
- }
- // GetRedisStreamID returns the stream id that should be used
- func (conf *Conf) GetRedisStreamID() string {
- return conf.ID
- }
- // GetTFWorkspaceID returns the workspace id that should be used
- func (conf *Conf) GetTFWorkspaceID() string {
- return conf.ID
- }
- // attaches the env variables required by all provisioner instances
- func (conf *Conf) attachDefaultEnv(env []v1.EnvVar) []v1.EnvVar {
- env = conf.addRedisEnv(env)
- env = conf.addPostgresEnv(env)
- env = conf.addTFEnv(env)
- return env
- }
- // adds the env variables required for the Redis stream
- func (conf *Conf) addRedisEnv(env []v1.EnvVar) []v1.EnvVar {
- env = append(env, v1.EnvVar{
- Name: "REDIS_ENABLED",
- Value: "true",
- })
- env = append(env, v1.EnvVar{
- Name: "REDIS_HOST",
- Value: conf.Redis.Host,
- })
- env = append(env, v1.EnvVar{
- Name: "REDIS_PORT",
- Value: conf.Redis.Port,
- })
- env = append(env, v1.EnvVar{
- Name: "REDIS_USER",
- Value: conf.Redis.Username,
- })
- env = append(env, v1.EnvVar{
- Name: "REDIS_PASS",
- Value: conf.Redis.Password,
- // ValueFrom: &v1.EnvVarSource{
- // SecretKeyRef: &v1.SecretKeySelector{
- // LocalObjectReference: v1.LocalObjectReference{
- // Name: "redis",
- // },
- // Key: "redis-password",
- // },
- // },
- })
- env = append(env, v1.EnvVar{
- Name: "REDIS_STREAM_ID",
- Value: conf.GetRedisStreamID(),
- })
- return env
- }
- // adds the env variables required for the PG backend
- func (conf *Conf) addPostgresEnv(env []v1.EnvVar) []v1.EnvVar {
- env = append(env, v1.EnvVar{
- Name: "PG_HOST",
- Value: conf.Postgres.Host,
- })
- env = append(env, v1.EnvVar{
- Name: "PG_PORT",
- Value: fmt.Sprintf("%d", conf.Postgres.Port),
- })
- env = append(env, v1.EnvVar{
- Name: "PG_USER",
- Value: conf.Postgres.Username,
- })
- env = append(env, v1.EnvVar{
- Name: "PG_PASS",
- Value: conf.Postgres.Password,
- })
- return env
- }
- func (conf *Conf) addTFEnv(env []v1.EnvVar) []v1.EnvVar {
- env = append(env, v1.EnvVar{
- Name: "TF_DIR",
- Value: "./terraform",
- })
- env = append(env, v1.EnvVar{
- Name: "TF_PLUGIN_CACHE_DIR",
- Value: "/.terraform/plugin-cache",
- })
- env = append(env, v1.EnvVar{
- Name: "TF_PORTER_BACKEND",
- Value: "postgres",
- })
- env = append(env, v1.EnvVar{
- Name: "TF_PORTER_WORKSPACE",
- Value: conf.GetTFWorkspaceID(),
- })
- return env
- }
|