Просмотр исходного кода

(wip) add cred exchange mechanism to job config

Alexander Belanger 4 лет назад
Родитель
Сommit
d447a303d0

+ 133 - 120
api/server/handlers/infra/delete.go

@@ -1,18 +1,19 @@
 package infra
 
 import (
+	"encoding/json"
 	"net/http"
 
 	"github.com/porter-dev/porter/api/server/handlers"
+	"github.com/porter-dev/porter/api/server/handlers/provision"
 	"github.com/porter-dev/porter/api/server/shared"
 	"github.com/porter-dev/porter/api/server/shared/apierrors"
 	"github.com/porter-dev/porter/api/server/shared/config"
 	"github.com/porter-dev/porter/api/types"
 	"github.com/porter-dev/porter/internal/analytics"
-	"github.com/porter-dev/porter/internal/kubernetes"
 	"github.com/porter-dev/porter/internal/kubernetes/provisioner"
+	"github.com/porter-dev/porter/internal/kubernetes/provisioner/aws/ecr"
 	"github.com/porter-dev/porter/internal/models"
-	"github.com/porter-dev/porter/internal/repository"
 )
 
 type InfraDeleteHandler struct {
@@ -58,15 +59,15 @@ func (c *InfraDeleteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 
 	switch infra.Kind {
 	case types.InfraECR:
-		err = destroyECR(c.Repo(), c.Config(), infra, request.Name)
-	case types.InfraEKS:
-		err = destroyEKS(c.Repo(), c.Config(), infra, request.Name)
-	case types.InfraDOCR:
-		err = destroyDOCR(c.Repo(), c.Config(), infra, request.Name)
-	case types.InfraDOKS:
-		err = destroyDOKS(c.Repo(), c.Config(), infra, request.Name)
-	case types.InfraGKE:
-		err = destroyGKE(c.Repo(), c.Config(), infra, request.Name)
+		err = destroyECR(c.Config(), infra)
+		// case types.InfraEKS:
+		// 	err = destroyEKS(c.Repo(), c.Config(), infra, request.Name)
+		// case types.InfraDOCR:
+		// 	err = destroyDOCR(c.Repo(), c.Config(), infra, request.Name)
+		// case types.InfraDOKS:
+		// 	err = destroyDOKS(c.Repo(), c.Config(), infra, request.Name)
+		// case types.InfraGKE:
+		// 	err = destroyGKE(c.Repo(), c.Config(), infra, request.Name)
 	}
 
 	if err != nil {
@@ -75,132 +76,144 @@ func (c *InfraDeleteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	}
 }
 
-func destroyECR(repo repository.Repository, conf *config.Config, infra *models.Infra, name string) error {
-	awsInt, err := repo.AWSIntegration().ReadAWSIntegration(infra.ProjectID, infra.AWSIntegrationID)
+func destroyECR(conf *config.Config, infra *models.Infra) error {
+	lastAppliedECR := &types.CreateECRInfraRequest{}
 
-	if err != nil {
+	// parse infra last applied into ECR config
+	if err := json.Unmarshal(infra.LastApplied, lastAppliedECR); err != nil {
 		return err
 	}
 
-	_, err = conf.ProvisionerAgent.ProvisionECR(
-		&kubernetes.SharedProvisionOpts{
-			ProjectID:           infra.ProjectID,
-			Repo:                repo,
-			Infra:               infra,
-			Operation:           provisioner.Destroy,
-			PGConf:              conf.DBConf,
-			RedisConf:           conf.RedisConf,
-			ProvImageTag:        conf.ServerConf.ProvisionerImageTag,
-			ProvImagePullSecret: conf.ServerConf.ProvisionerImagePullSecret,
-		},
-		awsInt,
-		name,
-	)
-
-	return err
-}
-
-func destroyEKS(repo repository.Repository, conf *config.Config, infra *models.Infra, name string) error {
-	awsInt, err := repo.AWSIntegration().ReadAWSIntegration(infra.ProjectID, infra.AWSIntegrationID)
+	awsInt, err := conf.Repo.AWSIntegration().ReadAWSIntegration(infra.ProjectID, infra.AWSIntegrationID)
 
 	if err != nil {
 		return err
 	}
 
-	_, err = conf.ProvisionerAgent.ProvisionEKS(
-		&kubernetes.SharedProvisionOpts{
-			ProjectID:           infra.ProjectID,
-			Repo:                repo,
-			Infra:               infra,
-			Operation:           provisioner.Destroy,
-			PGConf:              conf.DBConf,
-			RedisConf:           conf.RedisConf,
-			ProvImageTag:        conf.ServerConf.ProvisionerImageTag,
-			ProvImagePullSecret: conf.ServerConf.ProvisionerImagePullSecret,
-		},
-		awsInt,
-		name,
-		"",
-	)
+	opts, err := provision.GetSharedProvisionerOpts(conf, infra)
 
-	return err
-}
+	vaultToken := ""
 
-func destroyDOCR(repo repository.Repository, conf *config.Config, infra *models.Infra, name string) error {
-	doInt, err := repo.OAuthIntegration().ReadOAuthIntegration(infra.ProjectID, infra.DOIntegrationID)
+	if conf.CredentialBackend != nil {
+		vaultToken, err = conf.CredentialBackend.CreateAWSToken(awsInt)
 
-	if err != nil {
-		return err
+		if err != nil {
+			return err
+		}
 	}
 
-	_, err = conf.ProvisionerAgent.ProvisionDOCR(
-		&kubernetes.SharedProvisionOpts{
-			ProjectID:           infra.ProjectID,
-			Repo:                repo,
-			Infra:               infra,
-			Operation:           provisioner.Destroy,
-			PGConf:              conf.DBConf,
-			RedisConf:           conf.RedisConf,
-			ProvImageTag:        conf.ServerConf.ProvisionerImageTag,
-			ProvImagePullSecret: conf.ServerConf.ProvisionerImagePullSecret,
-		},
-		doInt,
-		conf.DOConf,
-		name,
-		"",
-	)
-
-	return err
-}
-
-func destroyDOKS(repo repository.Repository, conf *config.Config, infra *models.Infra, name string) error {
-	doInt, err := repo.OAuthIntegration().ReadOAuthIntegration(infra.ProjectID, infra.DOIntegrationID)
-
-	if err != nil {
-		return err
+	opts.CredentialExchange.VaultToken = vaultToken
+	opts.ECR = &ecr.Conf{
+		ECRName: lastAppliedECR.ECRName,
 	}
+	opts.OperationKind = provisioner.Destroy
 
-	_, err = conf.ProvisionerAgent.ProvisionDOKS(
-		&kubernetes.SharedProvisionOpts{
-			ProjectID:           infra.ProjectID,
-			Repo:                repo,
-			Infra:               infra,
-			Operation:           provisioner.Destroy,
-			PGConf:              conf.DBConf,
-			RedisConf:           conf.RedisConf,
-			ProvImageTag:        conf.ServerConf.ProvisionerImageTag,
-			ProvImagePullSecret: conf.ServerConf.ProvisionerImagePullSecret,
-		},
-		doInt,
-		conf.DOConf,
-		"",
-		name,
-	)
+	err = conf.ProvisionerAgent.Provision(opts)
 
 	return err
 }
 
-func destroyGKE(repo repository.Repository, conf *config.Config, infra *models.Infra, name string) error {
-	gcpInt, err := repo.GCPIntegration().ReadGCPIntegration(infra.ProjectID, infra.GCPIntegrationID)
-
-	if err != nil {
-		return err
-	}
-
-	_, err = conf.ProvisionerAgent.ProvisionGKE(
-		&kubernetes.SharedProvisionOpts{
-			ProjectID:           infra.ProjectID,
-			Repo:                repo,
-			Infra:               infra,
-			Operation:           provisioner.Destroy,
-			PGConf:              conf.DBConf,
-			RedisConf:           conf.RedisConf,
-			ProvImageTag:        conf.ServerConf.ProvisionerImageTag,
-			ProvImagePullSecret: conf.ServerConf.ProvisionerImagePullSecret,
-		},
-		gcpInt,
-		name,
-	)
-
-	return err
-}
+// func destroyEKS(repo repository.Repository, conf *config.Config, infra *models.Infra, name string) error {
+// 	awsInt, err := repo.AWSIntegration().ReadAWSIntegration(infra.ProjectID, infra.AWSIntegrationID)
+
+// 	if err != nil {
+// 		return err
+// 	}
+
+// 	_, err = conf.ProvisionerAgent.ProvisionEKS(
+// 		&kubernetes.SharedProvisionOpts{
+// 			ProjectID:           infra.ProjectID,
+// 			Repo:                repo,
+// 			Infra:               infra,
+// 			Operation:           provisioner.Destroy,
+// 			PGConf:              conf.DBConf,
+// 			RedisConf:           conf.RedisConf,
+// 			ProvImageTag:        conf.ServerConf.ProvisionerImageTag,
+// 			ProvImagePullSecret: conf.ServerConf.ProvisionerImagePullSecret,
+// 		},
+// 		awsInt,
+// 		name,
+// 		"",
+// 	)
+
+// 	return err
+// }
+
+// func destroyDOCR(repo repository.Repository, conf *config.Config, infra *models.Infra, name string) error {
+// 	doInt, err := repo.OAuthIntegration().ReadOAuthIntegration(infra.ProjectID, infra.DOIntegrationID)
+
+// 	if err != nil {
+// 		return err
+// 	}
+
+// 	_, err = conf.ProvisionerAgent.ProvisionDOCR(
+// 		&kubernetes.SharedProvisionOpts{
+// 			ProjectID:           infra.ProjectID,
+// 			Repo:                repo,
+// 			Infra:               infra,
+// 			Operation:           provisioner.Destroy,
+// 			PGConf:              conf.DBConf,
+// 			RedisConf:           conf.RedisConf,
+// 			ProvImageTag:        conf.ServerConf.ProvisionerImageTag,
+// 			ProvImagePullSecret: conf.ServerConf.ProvisionerImagePullSecret,
+// 		},
+// 		doInt,
+// 		conf.DOConf,
+// 		name,
+// 		"",
+// 	)
+
+// 	return err
+// }
+
+// func destroyDOKS(repo repository.Repository, conf *config.Config, infra *models.Infra, name string) error {
+// 	doInt, err := repo.OAuthIntegration().ReadOAuthIntegration(infra.ProjectID, infra.DOIntegrationID)
+
+// 	if err != nil {
+// 		return err
+// 	}
+
+// 	_, err = conf.ProvisionerAgent.ProvisionDOKS(
+// 		&kubernetes.SharedProvisionOpts{
+// 			ProjectID:           infra.ProjectID,
+// 			Repo:                repo,
+// 			Infra:               infra,
+// 			Operation:           provisioner.Destroy,
+// 			PGConf:              conf.DBConf,
+// 			RedisConf:           conf.RedisConf,
+// 			ProvImageTag:        conf.ServerConf.ProvisionerImageTag,
+// 			ProvImagePullSecret: conf.ServerConf.ProvisionerImagePullSecret,
+// 		},
+// 		doInt,
+// 		conf.DOConf,
+// 		"",
+// 		name,
+// 	)
+
+// 	return err
+// }
+
+// func destroyGKE(repo repository.Repository, conf *config.Config, infra *models.Infra, name string) error {
+// 	gcpInt, err := repo.GCPIntegration().ReadGCPIntegration(infra.ProjectID, infra.GCPIntegrationID)
+
+// 	if err != nil {
+// 		return err
+// 	}
+
+// 	_, err = conf.ProvisionerAgent.ProvisionGKE(
+// 		&kubernetes.SharedProvisionOpts{
+// 			ProjectID:           infra.ProjectID,
+// 			Repo:                repo,
+// 			Infra:               infra,
+// 			Operation:           provisioner.Destroy,
+// 			PGConf:              conf.DBConf,
+// 			RedisConf:           conf.RedisConf,
+// 			ProvImageTag:        conf.ServerConf.ProvisionerImageTag,
+// 			ProvImagePullSecret: conf.ServerConf.ProvisionerImagePullSecret,
+// 		},
+// 		gcpInt,
+// 		name,
+// 	)
+
+// 	return err
+// }

+ 68 - 0
api/server/handlers/provision/helpers.go

@@ -0,0 +1,68 @@
+package provision
+
+import (
+	"fmt"
+	"time"
+
+	"github.com/porter-dev/porter/api/server/shared/config"
+	"github.com/porter-dev/porter/internal/kubernetes/provisioner"
+	"github.com/porter-dev/porter/internal/models"
+	"github.com/porter-dev/porter/internal/random"
+	"golang.org/x/crypto/bcrypt"
+)
+
+func CreateCEToken(conf *config.Config, infra *models.Infra) (*models.CredentialsExchangeToken, error) {
+	// convert the form to a project model
+	expiry := time.Now().Add(6 * time.Hour)
+
+	rawToken, err := random.StringWithCharset(32, "")
+
+	if err != nil {
+		return nil, err
+	}
+
+	hashedToken, err := bcrypt.GenerateFromPassword([]byte(rawToken), 8)
+
+	if err != nil {
+		return nil, err
+	}
+
+	ceToken := &models.CredentialsExchangeToken{
+		ProjectID:       infra.ProjectID,
+		Expiry:          &expiry,
+		Token:           hashedToken,
+		DOCredentialID:  infra.DOIntegrationID,
+		AWSCredentialID: infra.AWSIntegrationID,
+		GCPCredentialID: infra.GCPIntegrationID,
+	}
+
+	// handle write to the database
+	ceToken, err = conf.Repo.CredentialsExchangeToken().CreateCredentialsExchangeToken(ceToken)
+
+	if err != nil {
+		return nil, err
+	}
+
+	return ceToken, nil
+}
+
+func GetSharedProvisionerOpts(conf *config.Config, infra *models.Infra) (*provisioner.ProvisionOpts, error) {
+	ceToken, err := CreateCEToken(conf, infra)
+
+	if err != nil {
+		return nil, err
+	}
+
+	return &provisioner.ProvisionOpts{
+		DryRun:              true,
+		Infra:               infra,
+		ProvImageTag:        conf.ServerConf.ProvisionerImageTag,
+		ProvImagePullSecret: conf.ServerConf.ProvisionerImagePullSecret,
+		TFHTTPBackendURL:    conf.ServerConf.ProvisionerBackendURL,
+		CredentialExchange: &provisioner.ProvisionCredentialExchange{
+			CredExchangeEndpoint: fmt.Sprintf("%s/api/internal/credentials", conf.ServerConf.ServerURL),
+			CredExchangeToken:    string(ceToken.Token),
+			CredExchangeID:       ceToken.ID,
+		},
+	}, nil
+}

+ 83 - 91
api/server/handlers/provision/provision_docr.go

@@ -5,15 +5,7 @@ import (
 
 	"github.com/porter-dev/porter/api/server/handlers"
 	"github.com/porter-dev/porter/api/server/shared"
-	"github.com/porter-dev/porter/api/server/shared/apierrors"
 	"github.com/porter-dev/porter/api/server/shared/config"
-	"github.com/porter-dev/porter/api/types"
-	"github.com/porter-dev/porter/internal/analytics"
-	"github.com/porter-dev/porter/internal/kubernetes"
-	"github.com/porter-dev/porter/internal/kubernetes/provisioner"
-	"github.com/porter-dev/porter/internal/models"
-	"github.com/porter-dev/porter/internal/repository"
-	"gorm.io/gorm"
 )
 
 type ProvisionDOCRHandler struct {
@@ -31,87 +23,87 @@ func NewProvisionDOCRHandler(
 }
 
 func (c *ProvisionDOCRHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-	// read the user and project from context
-	user, _ := r.Context().Value(types.UserScope).(*models.User)
-	proj, _ := r.Context().Value(types.ProjectScope).(*models.Project)
-
-	request := &types.CreateDOCRInfraRequest{
-		ProjectID: proj.ID,
-	}
-
-	if ok := c.DecodeAndValidate(w, r, request); !ok {
-		return
-	}
-
-	// get the AWS integration
-	doInt, err := c.Repo().OAuthIntegration().ReadOAuthIntegration(proj.ID, request.DOIntegrationID)
-
-	if err != nil {
-		if err == gorm.ErrRecordNotFound {
-			c.HandleAPIError(w, r, apierrors.NewErrForbidden(err))
-		} else {
-			c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-		}
-
-		return
-	}
-
-	suffix, err := repository.GenerateRandomBytes(6)
-
-	if err != nil {
-		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-		return
-	}
-
-	infra := &models.Infra{
-		Kind:            types.InfraDOCR,
-		ProjectID:       proj.ID,
-		Suffix:          suffix,
-		Status:          types.StatusCreating,
-		DOIntegrationID: request.DOIntegrationID,
-		CreatedByUserID: user.ID,
-	}
-
-	// handle write to the database
-	infra, err = c.Repo().Infra().CreateInfra(infra)
-
-	if err != nil {
-		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-		return
-	}
-
-	// launch provisioning pod
-	_, err = c.Config().ProvisionerAgent.ProvisionDOCR(
-		&kubernetes.SharedProvisionOpts{
-			ProjectID:           proj.ID,
-			Repo:                c.Repo(),
-			Infra:               infra,
-			Operation:           provisioner.Apply,
-			PGConf:              c.Config().DBConf,
-			RedisConf:           c.Config().RedisConf,
-			ProvImageTag:        c.Config().ServerConf.ProvisionerImageTag,
-			ProvImagePullSecret: c.Config().ServerConf.ProvisionerImagePullSecret,
-		},
-		doInt,
-		c.Config().DOConf,
-		request.DOCRName,
-		request.DOCRSubscriptionTier,
-	)
-
-	if err != nil {
-		infra.Status = types.StatusError
-		infra, _ = c.Repo().Infra().UpdateInfra(infra)
-		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-		return
-	}
-
-	c.Config().AnalyticsClient.Track(analytics.RegistryProvisioningStartTrack(
-		&analytics.RegistryProvisioningStartTrackOpts{
-			ProjectScopedTrackOpts: analytics.GetProjectScopedTrackOpts(user.ID, proj.ID),
-			RegistryType:           types.InfraDOCR,
-			InfraID:                infra.ID,
-		},
-	))
-
-	c.WriteResult(w, r, infra.ToInfraType())
+	// // read the user and project from context
+	// user, _ := r.Context().Value(types.UserScope).(*models.User)
+	// proj, _ := r.Context().Value(types.ProjectScope).(*models.Project)
+
+	// request := &types.CreateDOCRInfraRequest{
+	// 	ProjectID: proj.ID,
+	// }
+
+	// if ok := c.DecodeAndValidate(w, r, request); !ok {
+	// 	return
+	// }
+
+	// // get the AWS integration
+	// doInt, err := c.Repo().OAuthIntegration().ReadOAuthIntegration(proj.ID, request.DOIntegrationID)
+
+	// if err != nil {
+	// 	if err == gorm.ErrRecordNotFound {
+	// 		c.HandleAPIError(w, r, apierrors.NewErrForbidden(err))
+	// 	} else {
+	// 		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+	// 	}
+
+	// 	return
+	// }
+
+	// suffix, err := repository.GenerateRandomBytes(6)
+
+	// if err != nil {
+	// 	c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+	// 	return
+	// }
+
+	// infra := &models.Infra{
+	// 	Kind:            types.InfraDOCR,
+	// 	ProjectID:       proj.ID,
+	// 	Suffix:          suffix,
+	// 	Status:          types.StatusCreating,
+	// 	DOIntegrationID: request.DOIntegrationID,
+	// 	CreatedByUserID: user.ID,
+	// }
+
+	// // handle write to the database
+	// infra, err = c.Repo().Infra().CreateInfra(infra)
+
+	// if err != nil {
+	// 	c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+	// 	return
+	// }
+
+	// // launch provisioning pod
+	// _, err = c.Config().ProvisionerAgent.ProvisionDOCR(
+	// 	&kubernetes.SharedProvisionOpts{
+	// 		ProjectID:           proj.ID,
+	// 		Repo:                c.Repo(),
+	// 		Infra:               infra,
+	// 		Operation:           provisioner.Apply,
+	// 		PGConf:              c.Config().DBConf,
+	// 		RedisConf:           c.Config().RedisConf,
+	// 		ProvImageTag:        c.Config().ServerConf.ProvisionerImageTag,
+	// 		ProvImagePullSecret: c.Config().ServerConf.ProvisionerImagePullSecret,
+	// 	},
+	// 	doInt,
+	// 	c.Config().DOConf,
+	// 	request.DOCRName,
+	// 	request.DOCRSubscriptionTier,
+	// )
+
+	// if err != nil {
+	// 	infra.Status = types.StatusError
+	// 	infra, _ = c.Repo().Infra().UpdateInfra(infra)
+	// 	c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+	// 	return
+	// }
+
+	// c.Config().AnalyticsClient.Track(analytics.RegistryProvisioningStartTrack(
+	// 	&analytics.RegistryProvisioningStartTrackOpts{
+	// 		ProjectScopedTrackOpts: analytics.GetProjectScopedTrackOpts(user.ID, proj.ID),
+	// 		RegistryType:           types.InfraDOCR,
+	// 		InfraID:                infra.ID,
+	// 	},
+	// ))
+
+	// c.WriteResult(w, r, infra.ToInfraType())
 }

+ 83 - 91
api/server/handlers/provision/provision_doks.go

@@ -5,15 +5,7 @@ import (
 
 	"github.com/porter-dev/porter/api/server/handlers"
 	"github.com/porter-dev/porter/api/server/shared"
-	"github.com/porter-dev/porter/api/server/shared/apierrors"
 	"github.com/porter-dev/porter/api/server/shared/config"
-	"github.com/porter-dev/porter/api/types"
-	"github.com/porter-dev/porter/internal/analytics"
-	"github.com/porter-dev/porter/internal/kubernetes"
-	"github.com/porter-dev/porter/internal/kubernetes/provisioner"
-	"github.com/porter-dev/porter/internal/models"
-	"github.com/porter-dev/porter/internal/repository"
-	"gorm.io/gorm"
 )
 
 type ProvisionDOKSHandler struct {
@@ -31,87 +23,87 @@ func NewProvisionDOKSHandler(
 }
 
 func (c *ProvisionDOKSHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-	// read the user and project from context
-	user, _ := r.Context().Value(types.UserScope).(*models.User)
-	proj, _ := r.Context().Value(types.ProjectScope).(*models.Project)
-
-	request := &types.CreateDOKSInfraRequest{
-		ProjectID: proj.ID,
-	}
-
-	if ok := c.DecodeAndValidate(w, r, request); !ok {
-		return
-	}
-
-	// get the AWS integration
-	doInt, err := c.Repo().OAuthIntegration().ReadOAuthIntegration(proj.ID, request.DOIntegrationID)
-
-	if err != nil {
-		if err == gorm.ErrRecordNotFound {
-			c.HandleAPIError(w, r, apierrors.NewErrForbidden(err))
-		} else {
-			c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-		}
-
-		return
-	}
-
-	suffix, err := repository.GenerateRandomBytes(6)
-
-	if err != nil {
-		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-		return
-	}
-
-	infra := &models.Infra{
-		Kind:            types.InfraDOKS,
-		ProjectID:       proj.ID,
-		Suffix:          suffix,
-		Status:          types.StatusCreating,
-		DOIntegrationID: request.DOIntegrationID,
-		CreatedByUserID: user.ID,
-	}
-
-	// handle write to the database
-	infra, err = c.Repo().Infra().CreateInfra(infra)
-
-	if err != nil {
-		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-		return
-	}
-
-	// launch provisioning pod
-	_, err = c.Config().ProvisionerAgent.ProvisionDOKS(
-		&kubernetes.SharedProvisionOpts{
-			ProjectID:           proj.ID,
-			Repo:                c.Repo(),
-			Infra:               infra,
-			Operation:           provisioner.Apply,
-			PGConf:              c.Config().DBConf,
-			RedisConf:           c.Config().RedisConf,
-			ProvImageTag:        c.Config().ServerConf.ProvisionerImageTag,
-			ProvImagePullSecret: c.Config().ServerConf.ProvisionerImagePullSecret,
-		},
-		doInt,
-		c.Config().DOConf,
-		request.DORegion,
-		request.DOKSName,
-	)
-
-	if err != nil {
-		infra.Status = types.StatusError
-		infra, _ = c.Repo().Infra().UpdateInfra(infra)
-		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-		return
-	}
-
-	c.Config().AnalyticsClient.Track(analytics.ClusterProvisioningStartTrack(
-		&analytics.ClusterProvisioningStartTrackOpts{
-			ProjectScopedTrackOpts: analytics.GetProjectScopedTrackOpts(user.ID, proj.ID),
-			ClusterType:            types.InfraDOKS,
-			InfraID:                infra.ID,
-		},
-	))
-
-	c.WriteResult(w, r, infra.ToInfraType())
+	// // read the user and project from context
+	// user, _ := r.Context().Value(types.UserScope).(*models.User)
+	// proj, _ := r.Context().Value(types.ProjectScope).(*models.Project)
+
+	// request := &types.CreateDOKSInfraRequest{
+	// 	ProjectID: proj.ID,
+	// }
+
+	// if ok := c.DecodeAndValidate(w, r, request); !ok {
+	// 	return
+	// }
+
+	// // get the AWS integration
+	// doInt, err := c.Repo().OAuthIntegration().ReadOAuthIntegration(proj.ID, request.DOIntegrationID)
+
+	// if err != nil {
+	// 	if err == gorm.ErrRecordNotFound {
+	// 		c.HandleAPIError(w, r, apierrors.NewErrForbidden(err))
+	// 	} else {
+	// 		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+	// 	}
+
+	// 	return
+	// }
+
+	// suffix, err := repository.GenerateRandomBytes(6)
+
+	// if err != nil {
+	// 	c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+	// 	return
+	// }
+
+	// infra := &models.Infra{
+	// 	Kind:            types.InfraDOKS,
+	// 	ProjectID:       proj.ID,
+	// 	Suffix:          suffix,
+	// 	Status:          types.StatusCreating,
+	// 	DOIntegrationID: request.DOIntegrationID,
+	// 	CreatedByUserID: user.ID,
+	// }
+
+	// // handle write to the database
+	// infra, err = c.Repo().Infra().CreateInfra(infra)
+
+	// if err != nil {
+	// 	c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+	// 	return
+	// }
+
+	// // launch provisioning pod
+	// _, err = c.Config().ProvisionerAgent.ProvisionDOKS(
+	// 	&kubernetes.SharedProvisionOpts{
+	// 		ProjectID:           proj.ID,
+	// 		Repo:                c.Repo(),
+	// 		Infra:               infra,
+	// 		Operation:           provisioner.Apply,
+	// 		PGConf:              c.Config().DBConf,
+	// 		RedisConf:           c.Config().RedisConf,
+	// 		ProvImageTag:        c.Config().ServerConf.ProvisionerImageTag,
+	// 		ProvImagePullSecret: c.Config().ServerConf.ProvisionerImagePullSecret,
+	// 	},
+	// 	doInt,
+	// 	c.Config().DOConf,
+	// 	request.DORegion,
+	// 	request.DOKSName,
+	// )
+
+	// if err != nil {
+	// 	infra.Status = types.StatusError
+	// 	infra, _ = c.Repo().Infra().UpdateInfra(infra)
+	// 	c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+	// 	return
+	// }
+
+	// c.Config().AnalyticsClient.Track(analytics.ClusterProvisioningStartTrack(
+	// 	&analytics.ClusterProvisioningStartTrackOpts{
+	// 		ProjectScopedTrackOpts: analytics.GetProjectScopedTrackOpts(user.ID, proj.ID),
+	// 		ClusterType:            types.InfraDOKS,
+	// 		InfraID:                infra.ID,
+	// 	},
+	// ))
+
+	// c.WriteResult(w, r, infra.ToInfraType())
 }

+ 32 - 17
api/server/handlers/provision/provision_ecr.go

@@ -1,6 +1,7 @@
 package provision
 
 import (
+	"encoding/json"
 	"net/http"
 
 	"github.com/porter-dev/porter/api/server/handlers"
@@ -9,8 +10,8 @@ import (
 	"github.com/porter-dev/porter/api/server/shared/config"
 	"github.com/porter-dev/porter/api/types"
 	"github.com/porter-dev/porter/internal/analytics"
-	"github.com/porter-dev/porter/internal/kubernetes"
 	"github.com/porter-dev/porter/internal/kubernetes/provisioner"
+	"github.com/porter-dev/porter/internal/kubernetes/provisioner/aws/ecr"
 	"github.com/porter-dev/porter/internal/models"
 	"github.com/porter-dev/porter/internal/repository"
 	"gorm.io/gorm"
@@ -43,7 +44,7 @@ func (c *ProvisionECRHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
 		return
 	}
 
-	// get the AWS integration
+	// get the AWS integration, to check that integration exists and belongs to the project
 	awsInt, err := c.Repo().AWSIntegration().ReadAWSIntegration(proj.ID, request.AWSIntegrationID)
 
 	if err != nil {
@@ -63,6 +64,14 @@ func (c *ProvisionECRHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
 		return
 	}
 
+	lastApplied, err := json.Marshal(request)
+
+	// parse infra last applied into ECR config
+	if err != nil {
+		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+		return
+	}
+
 	infra := &models.Infra{
 		Kind:             types.InfraECR,
 		ProjectID:        proj.ID,
@@ -70,6 +79,7 @@ func (c *ProvisionECRHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
 		Status:           types.StatusCreating,
 		AWSIntegrationID: request.AWSIntegrationID,
 		CreatedByUserID:  user.ID,
+		LastApplied:      lastApplied,
 	}
 
 	// handle write to the database
@@ -80,21 +90,26 @@ func (c *ProvisionECRHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
 		return
 	}
 
-	// launch provisioning pod
-	_, err = c.Config().ProvisionerAgent.ProvisionECR(
-		&kubernetes.SharedProvisionOpts{
-			ProjectID:           proj.ID,
-			Repo:                c.Repo(),
-			Infra:               infra,
-			Operation:           provisioner.Apply,
-			PGConf:              c.Config().DBConf,
-			RedisConf:           c.Config().RedisConf,
-			ProvImageTag:        c.Config().ServerConf.ProvisionerImageTag,
-			ProvImagePullSecret: c.Config().ServerConf.ProvisionerImagePullSecret,
-		},
-		awsInt,
-		request.ECRName,
-	)
+	opts, err := GetSharedProvisionerOpts(c.Config(), infra)
+
+	vaultToken := ""
+
+	if c.Config().CredentialBackend != nil {
+		vaultToken, err = c.Config().CredentialBackend.CreateAWSToken(awsInt)
+
+		if err != nil {
+			c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+			return
+		}
+	}
+
+	opts.CredentialExchange.VaultToken = vaultToken
+	opts.ECR = &ecr.Conf{
+		ECRName: request.ECRName,
+	}
+	opts.OperationKind = provisioner.Apply
+
+	err = c.Config().ProvisionerAgent.Provision(opts)
 
 	if err != nil {
 		infra.Status = types.StatusError

+ 82 - 90
api/server/handlers/provision/provision_eks.go

@@ -5,15 +5,7 @@ import (
 
 	"github.com/porter-dev/porter/api/server/handlers"
 	"github.com/porter-dev/porter/api/server/shared"
-	"github.com/porter-dev/porter/api/server/shared/apierrors"
 	"github.com/porter-dev/porter/api/server/shared/config"
-	"github.com/porter-dev/porter/api/types"
-	"github.com/porter-dev/porter/internal/analytics"
-	"github.com/porter-dev/porter/internal/kubernetes"
-	"github.com/porter-dev/porter/internal/kubernetes/provisioner"
-	"github.com/porter-dev/porter/internal/models"
-	"github.com/porter-dev/porter/internal/repository"
-	"gorm.io/gorm"
 )
 
 type ProvisionEKSHandler struct {
@@ -31,86 +23,86 @@ func NewProvisionEKSHandler(
 }
 
 func (c *ProvisionEKSHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-	// read the user and project from context
-	user, _ := r.Context().Value(types.UserScope).(*models.User)
-	proj, _ := r.Context().Value(types.ProjectScope).(*models.Project)
-
-	request := &types.CreateEKSInfraRequest{
-		ProjectID: proj.ID,
-	}
-
-	if ok := c.DecodeAndValidate(w, r, request); !ok {
-		return
-	}
-
-	// get the AWS integration
-	awsInt, err := c.Repo().AWSIntegration().ReadAWSIntegration(proj.ID, request.AWSIntegrationID)
-
-	if err != nil {
-		if err == gorm.ErrRecordNotFound {
-			c.HandleAPIError(w, r, apierrors.NewErrForbidden(err))
-		} else {
-			c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-		}
-
-		return
-	}
-
-	suffix, err := repository.GenerateRandomBytes(6)
-
-	if err != nil {
-		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-		return
-	}
-
-	infra := &models.Infra{
-		Kind:             types.InfraEKS,
-		ProjectID:        proj.ID,
-		Suffix:           suffix,
-		Status:           types.StatusCreating,
-		AWSIntegrationID: request.AWSIntegrationID,
-		CreatedByUserID:  user.ID,
-	}
-
-	// handle write to the database
-	infra, err = c.Repo().Infra().CreateInfra(infra)
-
-	if err != nil {
-		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-		return
-	}
-
-	// launch provisioning pod
-	_, err = c.Config().ProvisionerAgent.ProvisionEKS(
-		&kubernetes.SharedProvisionOpts{
-			ProjectID:           proj.ID,
-			Repo:                c.Repo(),
-			Infra:               infra,
-			Operation:           provisioner.Apply,
-			PGConf:              c.Config().DBConf,
-			RedisConf:           c.Config().RedisConf,
-			ProvImageTag:        c.Config().ServerConf.ProvisionerImageTag,
-			ProvImagePullSecret: c.Config().ServerConf.ProvisionerImagePullSecret,
-		},
-		awsInt,
-		request.EKSName,
-		request.MachineType,
-	)
-
-	if err != nil {
-		infra.Status = types.StatusError
-		infra, _ = c.Repo().Infra().UpdateInfra(infra)
-		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-		return
-	}
-
-	c.Config().AnalyticsClient.Track(analytics.ClusterProvisioningStartTrack(
-		&analytics.ClusterProvisioningStartTrackOpts{
-			ProjectScopedTrackOpts: analytics.GetProjectScopedTrackOpts(user.ID, proj.ID),
-			ClusterType:            types.InfraEKS,
-			InfraID:                infra.ID,
-		},
-	))
-
-	c.WriteResult(w, r, infra.ToInfraType())
+	// // read the user and project from context
+	// user, _ := r.Context().Value(types.UserScope).(*models.User)
+	// proj, _ := r.Context().Value(types.ProjectScope).(*models.Project)
+
+	// request := &types.CreateEKSInfraRequest{
+	// 	ProjectID: proj.ID,
+	// }
+
+	// if ok := c.DecodeAndValidate(w, r, request); !ok {
+	// 	return
+	// }
+
+	// // get the AWS integration
+	// awsInt, err := c.Repo().AWSIntegration().ReadAWSIntegration(proj.ID, request.AWSIntegrationID)
+
+	// if err != nil {
+	// 	if err == gorm.ErrRecordNotFound {
+	// 		c.HandleAPIError(w, r, apierrors.NewErrForbidden(err))
+	// 	} else {
+	// 		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+	// 	}
+
+	// 	return
+	// }
+
+	// suffix, err := repository.GenerateRandomBytes(6)
+
+	// if err != nil {
+	// 	c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+	// 	return
+	// }
+
+	// infra := &models.Infra{
+	// 	Kind:             types.InfraEKS,
+	// 	ProjectID:        proj.ID,
+	// 	Suffix:           suffix,
+	// 	Status:           types.StatusCreating,
+	// 	AWSIntegrationID: request.AWSIntegrationID,
+	// 	CreatedByUserID:  user.ID,
+	// }
+
+	// // handle write to the database
+	// infra, err = c.Repo().Infra().CreateInfra(infra)
+
+	// if err != nil {
+	// 	c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+	// 	return
+	// }
+
+	// // launch provisioning pod
+	// _, err = c.Config().ProvisionerAgent.ProvisionEKS(
+	// 	&kubernetes.SharedProvisionOpts{
+	// 		ProjectID:           proj.ID,
+	// 		Repo:                c.Repo(),
+	// 		Infra:               infra,
+	// 		Operation:           provisioner.Apply,
+	// 		PGConf:              c.Config().DBConf,
+	// 		RedisConf:           c.Config().RedisConf,
+	// 		ProvImageTag:        c.Config().ServerConf.ProvisionerImageTag,
+	// 		ProvImagePullSecret: c.Config().ServerConf.ProvisionerImagePullSecret,
+	// 	},
+	// 	awsInt,
+	// 	request.EKSName,
+	// 	request.MachineType,
+	// )
+
+	// if err != nil {
+	// 	infra.Status = types.StatusError
+	// 	infra, _ = c.Repo().Infra().UpdateInfra(infra)
+	// 	c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+	// 	return
+	// }
+
+	// c.Config().AnalyticsClient.Track(analytics.ClusterProvisioningStartTrack(
+	// 	&analytics.ClusterProvisioningStartTrackOpts{
+	// 		ProjectScopedTrackOpts: analytics.GetProjectScopedTrackOpts(user.ID, proj.ID),
+	// 		ClusterType:            types.InfraEKS,
+	// 		InfraID:                infra.ID,
+	// 	},
+	// ))
+
+	// c.WriteResult(w, r, infra.ToInfraType())
 }

+ 80 - 88
api/server/handlers/provision/provision_gcr.go

@@ -5,15 +5,7 @@ import (
 
 	"github.com/porter-dev/porter/api/server/handlers"
 	"github.com/porter-dev/porter/api/server/shared"
-	"github.com/porter-dev/porter/api/server/shared/apierrors"
 	"github.com/porter-dev/porter/api/server/shared/config"
-	"github.com/porter-dev/porter/api/types"
-	"github.com/porter-dev/porter/internal/analytics"
-	"github.com/porter-dev/porter/internal/kubernetes"
-	"github.com/porter-dev/porter/internal/kubernetes/provisioner"
-	"github.com/porter-dev/porter/internal/models"
-	"github.com/porter-dev/porter/internal/repository"
-	"gorm.io/gorm"
 )
 
 type ProvisionGCRHandler struct {
@@ -31,84 +23,84 @@ func NewProvisionGCRHandler(
 }
 
 func (c *ProvisionGCRHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-	// read the user and project from context
-	user, _ := r.Context().Value(types.UserScope).(*models.User)
-	proj, _ := r.Context().Value(types.ProjectScope).(*models.Project)
-
-	request := &types.CreateGCRInfraRequest{
-		ProjectID: proj.ID,
-	}
-
-	if ok := c.DecodeAndValidate(w, r, request); !ok {
-		return
-	}
-
-	// get the AWS integration
-	gcpInt, err := c.Repo().GCPIntegration().ReadGCPIntegration(proj.ID, request.GCPIntegrationID)
-
-	if err != nil {
-		if err == gorm.ErrRecordNotFound {
-			c.HandleAPIError(w, r, apierrors.NewErrForbidden(err))
-		} else {
-			c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-		}
-
-		return
-	}
-
-	suffix, err := repository.GenerateRandomBytes(6)
-
-	if err != nil {
-		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-		return
-	}
-
-	infra := &models.Infra{
-		Kind:             types.InfraGCR,
-		ProjectID:        proj.ID,
-		Suffix:           suffix,
-		Status:           types.StatusCreating,
-		GCPIntegrationID: request.GCPIntegrationID,
-		CreatedByUserID:  user.ID,
-	}
-
-	// handle write to the database
-	infra, err = c.Repo().Infra().CreateInfra(infra)
-
-	if err != nil {
-		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-		return
-	}
-
-	// launch provisioning pod
-	_, err = c.Config().ProvisionerAgent.ProvisionGCR(
-		&kubernetes.SharedProvisionOpts{
-			ProjectID:           proj.ID,
-			Repo:                c.Repo(),
-			Infra:               infra,
-			Operation:           provisioner.Apply,
-			PGConf:              c.Config().DBConf,
-			RedisConf:           c.Config().RedisConf,
-			ProvImageTag:        c.Config().ServerConf.ProvisionerImageTag,
-			ProvImagePullSecret: c.Config().ServerConf.ProvisionerImagePullSecret,
-		},
-		gcpInt,
-	)
-
-	if err != nil {
-		infra.Status = types.StatusError
-		infra, _ = c.Repo().Infra().UpdateInfra(infra)
-		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-		return
-	}
-
-	c.Config().AnalyticsClient.Track(analytics.RegistryProvisioningStartTrack(
-		&analytics.RegistryProvisioningStartTrackOpts{
-			ProjectScopedTrackOpts: analytics.GetProjectScopedTrackOpts(user.ID, proj.ID),
-			RegistryType:           types.InfraGCR,
-			InfraID:                infra.ID,
-		},
-	))
-
-	c.WriteResult(w, r, infra.ToInfraType())
+	// // read the user and project from context
+	// user, _ := r.Context().Value(types.UserScope).(*models.User)
+	// proj, _ := r.Context().Value(types.ProjectScope).(*models.Project)
+
+	// request := &types.CreateGCRInfraRequest{
+	// 	ProjectID: proj.ID,
+	// }
+
+	// if ok := c.DecodeAndValidate(w, r, request); !ok {
+	// 	return
+	// }
+
+	// // get the AWS integration
+	// gcpInt, err := c.Repo().GCPIntegration().ReadGCPIntegration(proj.ID, request.GCPIntegrationID)
+
+	// if err != nil {
+	// 	if err == gorm.ErrRecordNotFound {
+	// 		c.HandleAPIError(w, r, apierrors.NewErrForbidden(err))
+	// 	} else {
+	// 		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+	// 	}
+
+	// 	return
+	// }
+
+	// suffix, err := repository.GenerateRandomBytes(6)
+
+	// if err != nil {
+	// 	c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+	// 	return
+	// }
+
+	// infra := &models.Infra{
+	// 	Kind:             types.InfraGCR,
+	// 	ProjectID:        proj.ID,
+	// 	Suffix:           suffix,
+	// 	Status:           types.StatusCreating,
+	// 	GCPIntegrationID: request.GCPIntegrationID,
+	// 	CreatedByUserID:  user.ID,
+	// }
+
+	// // handle write to the database
+	// infra, err = c.Repo().Infra().CreateInfra(infra)
+
+	// if err != nil {
+	// 	c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+	// 	return
+	// }
+
+	// // launch provisioning pod
+	// _, err = c.Config().ProvisionerAgent.ProvisionGCR(
+	// 	&kubernetes.SharedProvisionOpts{
+	// 		ProjectID:           proj.ID,
+	// 		Repo:                c.Repo(),
+	// 		Infra:               infra,
+	// 		Operation:           provisioner.Apply,
+	// 		PGConf:              c.Config().DBConf,
+	// 		RedisConf:           c.Config().RedisConf,
+	// 		ProvImageTag:        c.Config().ServerConf.ProvisionerImageTag,
+	// 		ProvImagePullSecret: c.Config().ServerConf.ProvisionerImagePullSecret,
+	// 	},
+	// 	gcpInt,
+	// )
+
+	// if err != nil {
+	// 	infra.Status = types.StatusError
+	// 	infra, _ = c.Repo().Infra().UpdateInfra(infra)
+	// 	c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+	// 	return
+	// }
+
+	// c.Config().AnalyticsClient.Track(analytics.RegistryProvisioningStartTrack(
+	// 	&analytics.RegistryProvisioningStartTrackOpts{
+	// 		ProjectScopedTrackOpts: analytics.GetProjectScopedTrackOpts(user.ID, proj.ID),
+	// 		RegistryType:           types.InfraGCR,
+	// 		InfraID:                infra.ID,
+	// 	},
+	// ))
+
+	// c.WriteResult(w, r, infra.ToInfraType())
 }

+ 81 - 89
api/server/handlers/provision/provision_gke.go

@@ -5,15 +5,7 @@ import (
 
 	"github.com/porter-dev/porter/api/server/handlers"
 	"github.com/porter-dev/porter/api/server/shared"
-	"github.com/porter-dev/porter/api/server/shared/apierrors"
 	"github.com/porter-dev/porter/api/server/shared/config"
-	"github.com/porter-dev/porter/api/types"
-	"github.com/porter-dev/porter/internal/analytics"
-	"github.com/porter-dev/porter/internal/kubernetes"
-	"github.com/porter-dev/porter/internal/kubernetes/provisioner"
-	"github.com/porter-dev/porter/internal/models"
-	"github.com/porter-dev/porter/internal/repository"
-	"gorm.io/gorm"
 )
 
 type ProvisionGKEHandler struct {
@@ -31,85 +23,85 @@ func NewProvisionGKEHandler(
 }
 
 func (c *ProvisionGKEHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-	// read the user and project from context
-	user, _ := r.Context().Value(types.UserScope).(*models.User)
-	proj, _ := r.Context().Value(types.ProjectScope).(*models.Project)
-
-	request := &types.CreateGKEInfraRequest{
-		ProjectID: proj.ID,
-	}
-
-	if ok := c.DecodeAndValidate(w, r, request); !ok {
-		return
-	}
-
-	// get the AWS integration
-	gcpInt, err := c.Repo().GCPIntegration().ReadGCPIntegration(proj.ID, request.GCPIntegrationID)
-
-	if err != nil {
-		if err == gorm.ErrRecordNotFound {
-			c.HandleAPIError(w, r, apierrors.NewErrForbidden(err))
-		} else {
-			c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-		}
-
-		return
-	}
-
-	suffix, err := repository.GenerateRandomBytes(6)
-
-	if err != nil {
-		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-		return
-	}
-
-	infra := &models.Infra{
-		Kind:             types.InfraGKE,
-		ProjectID:        proj.ID,
-		Suffix:           suffix,
-		Status:           types.StatusCreating,
-		GCPIntegrationID: request.GCPIntegrationID,
-		CreatedByUserID:  user.ID,
-	}
-
-	// handle write to the database
-	infra, err = c.Repo().Infra().CreateInfra(infra)
-
-	if err != nil {
-		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-		return
-	}
-
-	// launch provisioning pod
-	_, err = c.Config().ProvisionerAgent.ProvisionGKE(
-		&kubernetes.SharedProvisionOpts{
-			ProjectID:           proj.ID,
-			Repo:                c.Repo(),
-			Infra:               infra,
-			Operation:           provisioner.Apply,
-			PGConf:              c.Config().DBConf,
-			RedisConf:           c.Config().RedisConf,
-			ProvImageTag:        c.Config().ServerConf.ProvisionerImageTag,
-			ProvImagePullSecret: c.Config().ServerConf.ProvisionerImagePullSecret,
-		},
-		gcpInt,
-		request.GKEName,
-	)
-
-	if err != nil {
-		infra.Status = types.StatusError
-		infra, _ = c.Repo().Infra().UpdateInfra(infra)
-		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-		return
-	}
-
-	c.Config().AnalyticsClient.Track(analytics.ClusterProvisioningStartTrack(
-		&analytics.ClusterProvisioningStartTrackOpts{
-			ProjectScopedTrackOpts: analytics.GetProjectScopedTrackOpts(user.ID, proj.ID),
-			ClusterType:            types.InfraGKE,
-			InfraID:                infra.ID,
-		},
-	))
-
-	c.WriteResult(w, r, infra.ToInfraType())
+	// // read the user and project from context
+	// user, _ := r.Context().Value(types.UserScope).(*models.User)
+	// proj, _ := r.Context().Value(types.ProjectScope).(*models.Project)
+
+	// request := &types.CreateGKEInfraRequest{
+	// 	ProjectID: proj.ID,
+	// }
+
+	// if ok := c.DecodeAndValidate(w, r, request); !ok {
+	// 	return
+	// }
+
+	// // get the AWS integration
+	// gcpInt, err := c.Repo().GCPIntegration().ReadGCPIntegration(proj.ID, request.GCPIntegrationID)
+
+	// if err != nil {
+	// 	if err == gorm.ErrRecordNotFound {
+	// 		c.HandleAPIError(w, r, apierrors.NewErrForbidden(err))
+	// 	} else {
+	// 		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+	// 	}
+
+	// 	return
+	// }
+
+	// suffix, err := repository.GenerateRandomBytes(6)
+
+	// if err != nil {
+	// 	c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+	// 	return
+	// }
+
+	// infra := &models.Infra{
+	// 	Kind:             types.InfraGKE,
+	// 	ProjectID:        proj.ID,
+	// 	Suffix:           suffix,
+	// 	Status:           types.StatusCreating,
+	// 	GCPIntegrationID: request.GCPIntegrationID,
+	// 	CreatedByUserID:  user.ID,
+	// }
+
+	// // handle write to the database
+	// infra, err = c.Repo().Infra().CreateInfra(infra)
+
+	// if err != nil {
+	// 	c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+	// 	return
+	// }
+
+	// // launch provisioning pod
+	// _, err = c.Config().ProvisionerAgent.ProvisionGKE(
+	// 	&kubernetes.SharedProvisionOpts{
+	// 		ProjectID:           proj.ID,
+	// 		Repo:                c.Repo(),
+	// 		Infra:               infra,
+	// 		Operation:           provisioner.Apply,
+	// 		PGConf:              c.Config().DBConf,
+	// 		RedisConf:           c.Config().RedisConf,
+	// 		ProvImageTag:        c.Config().ServerConf.ProvisionerImageTag,
+	// 		ProvImagePullSecret: c.Config().ServerConf.ProvisionerImagePullSecret,
+	// 	},
+	// 	gcpInt,
+	// 	request.GKEName,
+	// )
+
+	// if err != nil {
+	// 	infra.Status = types.StatusError
+	// 	infra, _ = c.Repo().Infra().UpdateInfra(infra)
+	// 	c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+	// 	return
+	// }
+
+	// c.Config().AnalyticsClient.Track(analytics.ClusterProvisioningStartTrack(
+	// 	&analytics.ClusterProvisioningStartTrackOpts{
+	// 		ProjectScopedTrackOpts: analytics.GetProjectScopedTrackOpts(user.ID, proj.ID),
+	// 		ClusterType:            types.InfraGKE,
+	// 		InfraID:                infra.ID,
+	// 	},
+	// ))
+
+	// c.WriteResult(w, r, infra.ToInfraType())
 }

+ 6 - 1
api/server/shared/config/config.go

@@ -15,6 +15,7 @@ import (
 	"github.com/porter-dev/porter/internal/notifier"
 	"github.com/porter-dev/porter/internal/oauth"
 	"github.com/porter-dev/porter/internal/repository"
+	"github.com/porter-dev/porter/internal/repository/credentials"
 	"golang.org/x/oauth2"
 	"gorm.io/gorm"
 )
@@ -90,8 +91,12 @@ type Config struct {
 	// WhitelistedUsers do not count toward usage limits
 	WhitelistedUsers map[uint]uint
 
-  // PowerDNSClient is a client for PowerDNS, if the Porter instance supports vanity URLs
+	// PowerDNSClient is a client for PowerDNS, if the Porter instance supports vanity URLs
 	PowerDNSClient *powerdns.Client
+
+	// CredentialBackend is the backend for credential storage, if external cred storage (like Vault)
+	// is used
+	CredentialBackend credentials.CredentialStorage
 }
 
 type ConfigLoader interface {

+ 7 - 3
api/server/shared/config/env/envconfs.go

@@ -53,11 +53,15 @@ type ServerConf struct {
 	IronPlansServerURL string `env:"IRON_PLANS_SERVER_URL"`
 	WhitelistedUsers   []uint `env:"WHITELISTED_USERS"`
 
-	DOClientID                 string `env:"DO_CLIENT_ID"`
-	DOClientSecret             string `env:"DO_CLIENT_SECRET"`
+	DOClientID     string `env:"DO_CLIENT_ID"`
+	DOClientSecret string `env:"DO_CLIENT_SECRET"`
+
+	// Options for the provisioner jobs
 	ProvisionerImageTag        string `env:"PROV_IMAGE_TAG,default=latest"`
 	ProvisionerImagePullSecret string `env:"PROV_IMAGE_PULL_SECRET"`
-	SegmentClientKey           string `env:"SEGMENT_CLIENT_KEY"`
+	ProvisionerBackendURL      string `env:"PROV_BACKEND_URL"`
+
+	SegmentClientKey string `env:"SEGMENT_CLIENT_KEY"`
 
 	// PowerDNS client API key and the host of the PowerDNS API server
 	PowerDNSAPIServerURL string `env:"POWER_DNS_API_SERVER_URL"`

+ 6 - 5
api/server/shared/config/loader/loader.go

@@ -62,11 +62,12 @@ func (e *EnvConfigLoader) LoadConfig() (res *config.Config, err error) {
 	sc := envConf.ServerConf
 
 	res = &config.Config{
-		Logger:         lr.NewConsole(sc.Debug),
-		ServerConf:     sc,
-		DBConf:         envConf.DBConf,
-		RedisConf:      envConf.RedisConf,
-		BillingManager: InstanceBillingManager,
+		Logger:            lr.NewConsole(sc.Debug),
+		ServerConf:        sc,
+		DBConf:            envConf.DBConf,
+		RedisConf:         envConf.RedisConf,
+		BillingManager:    InstanceBillingManager,
+		CredentialBackend: InstanceCredentialBackend,
 	}
 
 	res.Metadata = config.MetadataFromConf(envConf.ServerConf, e.version)

+ 9 - 273
internal/kubernetes/agent.go

@@ -15,20 +15,9 @@ import (
 
 	goerrors "errors"
 
-	"github.com/porter-dev/porter/api/server/shared/config/env"
 	"github.com/porter-dev/porter/api/server/shared/websocket"
 	"github.com/porter-dev/porter/internal/kubernetes/provisioner"
-	"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/gcp"
-	"github.com/porter-dev/porter/internal/kubernetes/provisioner/gcp/gke"
 	"github.com/porter-dev/porter/internal/models"
-	"github.com/porter-dev/porter/internal/models/integrations"
-	"github.com/porter-dev/porter/internal/oauth"
 	"github.com/porter-dev/porter/internal/registry"
 	"github.com/porter-dev/porter/internal/repository"
 	"golang.org/x/oauth2"
@@ -990,277 +979,24 @@ func (a *Agent) StreamHelmReleases(namespace string, chartList []string, selecto
 	return a.RunWebsocketTask(run)
 }
 
-type SharedProvisionOpts struct {
-	ProjectID           uint
-	Repo                repository.Repository
-	Infra               *models.Infra
-	Operation           provisioner.ProvisionerOperation
-	PGConf              *env.DBConf
-	RedisConf           *env.RedisConf
-	ProvImageTag        string
-	ProvImagePullSecret string
-}
-
-// ProvisionECR spawns a new provisioning pod that creates an ECR instance
-func (a *Agent) ProvisionECR(
-	opts *SharedProvisionOpts,
-	awsConf *integrations.AWSIntegration,
-	ecrName string,
-) (*batchv1.Job, error) {
-	id := opts.Infra.GetUniqueName()
-	prov := &provisioner.Conf{
-		ID:                  id,
-		Name:                fmt.Sprintf("prov-%s-%s", id, string(opts.Operation)),
-		Kind:                provisioner.ECR,
-		Operation:           opts.Operation,
-		Redis:               opts.RedisConf,
-		Postgres:            opts.PGConf,
-		ProvisionerImageTag: opts.ProvImageTag,
-		ImagePullSecret:     opts.ProvImagePullSecret,
-		LastApplied:         opts.Infra.LastApplied,
-		AWS: &aws.Conf{
-			AWSRegion:          awsConf.AWSRegion,
-			AWSAccessKeyID:     string(awsConf.AWSAccessKeyID),
-			AWSSecretAccessKey: string(awsConf.AWSSecretAccessKey),
-		},
-		ECR: &ecr.Conf{
-			ECRName: ecrName,
-		},
-	}
-
-	return a.provision(prov, opts.Infra, opts.Repo)
-}
-
-// ProvisionEKS spawns a new provisioning pod that creates an EKS instance
-func (a *Agent) ProvisionEKS(
-	opts *SharedProvisionOpts,
-	awsConf *integrations.AWSIntegration,
-	eksName, machineType string,
-) (*batchv1.Job, error) {
-	id := opts.Infra.GetUniqueName()
-	prov := &provisioner.Conf{
-		ID:                  id,
-		Name:                fmt.Sprintf("prov-%s-%s", id, string(opts.Operation)),
-		Kind:                provisioner.EKS,
-		Operation:           opts.Operation,
-		Redis:               opts.RedisConf,
-		Postgres:            opts.PGConf,
-		ProvisionerImageTag: opts.ProvImageTag,
-		ImagePullSecret:     opts.ProvImagePullSecret,
-		LastApplied:         opts.Infra.LastApplied,
-		AWS: &aws.Conf{
-			AWSRegion:          awsConf.AWSRegion,
-			AWSAccessKeyID:     string(awsConf.AWSAccessKeyID),
-			AWSSecretAccessKey: string(awsConf.AWSSecretAccessKey),
-		},
-		EKS: &eks.Conf{
-			ClusterName: eksName,
-			MachineType: machineType,
-		},
-	}
-
-	return a.provision(prov, opts.Infra, opts.Repo)
-}
-
-// ProvisionGCR spawns a new provisioning pod that creates a GCR instance
-func (a *Agent) ProvisionGCR(
-	opts *SharedProvisionOpts,
-	gcpConf *integrations.GCPIntegration,
-) (*batchv1.Job, error) {
-	id := opts.Infra.GetUniqueName()
-	prov := &provisioner.Conf{
-		ID:                  id,
-		Name:                fmt.Sprintf("prov-%s-%s", id, string(opts.Operation)),
-		Kind:                provisioner.GCR,
-		Operation:           opts.Operation,
-		Redis:               opts.RedisConf,
-		Postgres:            opts.PGConf,
-		ProvisionerImageTag: opts.ProvImageTag,
-		ImagePullSecret:     opts.ProvImagePullSecret,
-		LastApplied:         opts.Infra.LastApplied,
-		GCP: &gcp.Conf{
-			GCPRegion:    gcpConf.GCPRegion,
-			GCPProjectID: gcpConf.GCPProjectID,
-			GCPKeyData:   string(gcpConf.GCPKeyData),
-		},
-	}
-
-	return a.provision(prov, opts.Infra, opts.Repo)
-}
-
-// ProvisionGKE spawns a new provisioning pod that creates a GKE instance
-func (a *Agent) ProvisionGKE(
-	opts *SharedProvisionOpts,
-	gcpConf *integrations.GCPIntegration,
-	gkeName string,
-) (*batchv1.Job, error) {
-	id := opts.Infra.GetUniqueName()
-	prov := &provisioner.Conf{
-		ID:                  id,
-		Name:                fmt.Sprintf("prov-%s-%s", id, string(opts.Operation)),
-		Kind:                provisioner.GKE,
-		Operation:           opts.Operation,
-		Redis:               opts.RedisConf,
-		Postgres:            opts.PGConf,
-		ProvisionerImageTag: opts.ProvImageTag,
-		ImagePullSecret:     opts.ProvImagePullSecret,
-		LastApplied:         opts.Infra.LastApplied,
-		GCP: &gcp.Conf{
-			GCPRegion:    gcpConf.GCPRegion,
-			GCPProjectID: gcpConf.GCPProjectID,
-			GCPKeyData:   string(gcpConf.GCPKeyData),
-		},
-		GKE: &gke.Conf{
-			ClusterName: gkeName,
-		},
-	}
-
-	return a.provision(prov, opts.Infra, opts.Repo)
-}
-
-// ProvisionDOCR spawns a new provisioning pod that creates a DOCR instance
-func (a *Agent) ProvisionDOCR(
-	opts *SharedProvisionOpts,
-	doConf *integrations.OAuthIntegration,
-	doAuth *oauth2.Config,
-	docrName, docrSubscriptionTier string,
-) (*batchv1.Job, error) {
-	// get the token
-	oauthInt, err := opts.Repo.OAuthIntegration().ReadOAuthIntegration(
-		opts.ProjectID,
-		opts.Infra.DOIntegrationID,
-	)
-
-	if err != nil {
-		return nil, err
-	}
-
-	tok, _, err := oauth.GetAccessToken(oauthInt.SharedOAuthModel, doAuth, oauth.MakeUpdateOAuthIntegrationTokenFunction(oauthInt, opts.Repo))
+func (a *Agent) Provision(
+	opts *provisioner.ProvisionOpts,
+) error {
+	// get the provisioner job template
+	job, err := provisioner.GetProvisionerJobTemplate(opts)
 
 	if err != nil {
-		return nil, err
-	}
-
-	id := opts.Infra.GetUniqueName()
-	prov := &provisioner.Conf{
-		ID:                  id,
-		Name:                fmt.Sprintf("prov-%s-%s", id, string(opts.Operation)),
-		Kind:                provisioner.DOCR,
-		Operation:           opts.Operation,
-		Redis:               opts.RedisConf,
-		Postgres:            opts.PGConf,
-		ProvisionerImageTag: opts.ProvImageTag,
-		ImagePullSecret:     opts.ProvImagePullSecret,
-		LastApplied:         opts.Infra.LastApplied,
-		DO: &do.Conf{
-			DOToken: tok,
-		},
-		DOCR: &docr.Conf{
-			DOCRName:             docrName,
-			DOCRSubscriptionTier: docrSubscriptionTier,
-		},
-	}
-
-	return a.provision(prov, opts.Infra, opts.Repo)
-}
-
-// ProvisionDOKS spawns a new provisioning pod that creates a DOKS instance
-func (a *Agent) ProvisionDOKS(
-	opts *SharedProvisionOpts,
-	doConf *integrations.OAuthIntegration,
-	doAuth *oauth2.Config,
-	doRegion, doksClusterName string,
-) (*batchv1.Job, error) {
-	// get the token
-	oauthInt, err := opts.Repo.OAuthIntegration().ReadOAuthIntegration(
-		opts.ProjectID,
-		opts.Infra.DOIntegrationID,
-	)
-
-	if err != nil {
-		return nil, err
-	}
-
-	tok, _, err := oauth.GetAccessToken(oauthInt.SharedOAuthModel, doAuth, oauth.MakeUpdateOAuthIntegrationTokenFunction(oauthInt, opts.Repo))
-
-	if err != nil {
-		return nil, err
-	}
-
-	id := opts.Infra.GetUniqueName()
-	prov := &provisioner.Conf{
-		ID:                  id,
-		Name:                fmt.Sprintf("prov-%s-%s", id, string(opts.Operation)),
-		Kind:                provisioner.DOKS,
-		Operation:           opts.Operation,
-		Redis:               opts.RedisConf,
-		Postgres:            opts.PGConf,
-		LastApplied:         opts.Infra.LastApplied,
-		ProvisionerImageTag: opts.ProvImageTag,
-		ImagePullSecret:     opts.ProvImagePullSecret,
-		DO: &do.Conf{
-			DOToken: tok,
-		},
-		DOKS: &doks.Conf{
-			DORegion:        doRegion,
-			DOKSClusterName: doksClusterName,
-		},
-	}
-
-	return a.provision(prov, opts.Infra, opts.Repo)
-}
-
-// ProvisionTest spawns a new provisioning pod that tests provisioning
-func (a *Agent) ProvisionTest(
-	opts *SharedProvisionOpts,
-) (*batchv1.Job, error) {
-	id := opts.Infra.GetUniqueName()
-
-	prov := &provisioner.Conf{
-		ID:                  id,
-		Name:                fmt.Sprintf("prov-%s-%s", id, string(opts.Operation)),
-		Operation:           opts.Operation,
-		Kind:                provisioner.Test,
-		Redis:               opts.RedisConf,
-		Postgres:            opts.PGConf,
-		ProvisionerImageTag: opts.ProvImageTag,
-		ImagePullSecret:     opts.ProvImagePullSecret,
-	}
-
-	return a.provision(prov, opts.Infra, opts.Repo)
-}
-
-func (a *Agent) provision(
-	prov *provisioner.Conf,
-	infra *models.Infra,
-	repo repository.Repository,
-) (*batchv1.Job, error) {
-	prov.Namespace = "default"
-
-	job, err := prov.GetProvisionerJobTemplate()
-
-	if err != nil {
-		return nil, err
+		return err
 	}
 
-	job, err = a.Clientset.BatchV1().Jobs(prov.Namespace).Create(
+	// apply the provisioner job template
+	_, err = a.Clientset.BatchV1().Jobs("default").Create(
 		context.TODO(),
 		job,
 		metav1.CreateOptions{},
 	)
 
-	if err != nil {
-		return nil, err
-	}
-
-	infra.LastApplied = prov.LastApplied
-	infra, err = repo.Infra().UpdateInfra(infra)
-
-	if err != nil {
-		return nil, err
-	}
-
-	return job, nil
+	return err
 }
 
 // CreateImagePullSecrets will create the required image pull secrets and

+ 72 - 352
internal/kubernetes/provisioner/provisioner.go

@@ -3,67 +3,18 @@ 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/api/server/shared/config/env"
-	"github.com/porter-dev/porter/internal/kubernetes/provisioner/aws"
+	"github.com/porter-dev/porter/api/types"
 	"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/models"
+	batchv1 "k8s.io/api/batch/v1"
+	v1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
-// 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               *env.RedisConf
-	Postgres            *env.DBConf
-	Operation           ProvisionerOperation
-	ProvisionerImageTag string
-	ImagePullSecret     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 (
@@ -71,237 +22,68 @@ const (
 	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)
+type ProvisionCredentialExchange struct {
+	CredExchangeEndpoint string
+	CredExchangeToken    string
+	CredExchangeID       uint
 
-	ttl := int32(3600)
+	VaultToken string
+}
 
-	backoffLimit := int32(1)
+type ProvisionOpts struct {
+	DryRun              bool
+	Infra               *models.Infra
+	ProvImageTag        string
+	ProvImagePullSecret string
+	TFHTTPBackendURL    string
+	CredentialExchange  *ProvisionCredentialExchange
+	OperationKind       ProvisionerOperation
+
+	// resource-specific opts
+	ECR  *ecr.Conf
+	EKS  *eks.Conf
+	GKE  *gke.Conf
+	DOCR *docr.Conf
+	DOKS *doks.Conf
+}
 
+func GetProvisionerJobTemplate(opts *ProvisionOpts) (*batchv1.Job, error) {
 	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
-		}
+	ttl := int32(3600)
 
-		env = conf.DO.AttachDOEnv(env)
-		env = conf.DOKS.AttachDOKSEnv(env)
-	}
+	backoffLimit := int32(1)
 
 	imagePullSecrets := []v1.LocalObjectReference{}
 
-	if conf.ImagePullSecret != "" {
+	if opts.ProvImagePullSecret != "" {
 		imagePullSecrets = append(imagePullSecrets, v1.LocalObjectReference{
-			Name: conf.ImagePullSecret,
+			Name: opts.ProvImagePullSecret,
 		})
 	}
 
+	env := GetTFEnv(opts)
+
+	// add resource-specific env
+	switch opts.Infra.Kind {
+	case types.InfraECR:
+		env = opts.ECR.AttachECREnv(env)
+	case types.InfraEKS:
+		env = opts.EKS.AttachEKSEnv(env)
+	case types.InfraGKE:
+		env = opts.GKE.AttachGKEEnv(env)
+	case types.InfraDOCR:
+		env = opts.DOCR.AttachDOCREnv(env)
+	case types.InfraDOKS:
+		env = opts.DOKS.AttachDOKSEnv(env)
+	}
+
 	return &batchv1.Job{
 		ObjectMeta: metav1.ObjectMeta{
-			Name:      conf.Name,
-			Namespace: conf.Namespace,
+			Name:      opts.Infra.GetUniqueName(),
+			Namespace: "default",
 			Labels:    labels,
 		},
 		Spec: batchv1.JobSpec{
@@ -317,10 +99,13 @@ func (conf *Conf) GetProvisionerJobTemplate() (*batchv1.Job, error) {
 					Containers: []v1.Container{
 						{
 							Name:            "provisioner",
-							Image:           "gcr.io/porter-dev-273614/provisioner:" + conf.ProvisionerImageTag,
+							Image:           "gcr.io/porter-dev-273614/provisioner:" + opts.ProvImageTag,
 							ImagePullPolicy: v1.PullAlways,
-							Args:            args,
-							Env:             env,
+							Args: []string{
+								string(opts.OperationKind),
+								string(opts.Infra.Kind),
+							},
+							Env: env,
 						},
 					},
 				},
@@ -329,107 +114,42 @@ func (conf *Conf) GetProvisionerJobTemplate() (*batchv1.Job, error) {
 	}, 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
-}
+func GetTFEnv(opts *ProvisionOpts) []v1.EnvVar {
+	env := make([]v1.EnvVar, 0)
 
-// 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,
+		Name:  "TF_DIR",
+		Value: "./terraform",
 	})
 
 	env = append(env, v1.EnvVar{
-		Name:  "PG_PORT",
-		Value: fmt.Sprintf("%d", conf.Postgres.Port),
+		Name:  "TF_ORG_ID",
+		Value: opts.Infra.GetUniqueName(),
 	})
 
 	env = append(env, v1.EnvVar{
-		Name:  "PG_USER",
-		Value: conf.Postgres.Username,
+		Name:  "TF_BACKEND_URL",
+		Value: opts.TFHTTPBackendURL,
 	})
 
 	env = append(env, v1.EnvVar{
-		Name:  "PG_PASS",
-		Value: conf.Postgres.Password,
+		Name:  "CRED_EXCHANGE_ENDPOINT",
+		Value: opts.CredentialExchange.CredExchangeEndpoint,
 	})
 
-	return env
-}
-
-func (conf *Conf) addTFEnv(env []v1.EnvVar) []v1.EnvVar {
 	env = append(env, v1.EnvVar{
-		Name:  "TF_DIR",
-		Value: "./terraform",
+		Name:  "CRED_EXCHANGE_ID",
+		Value: fmt.Sprintf("%d", opts.CredentialExchange.CredExchangeID),
 	})
 
 	env = append(env, v1.EnvVar{
-		Name:  "TF_PORTER_BACKEND",
-		Value: "postgres",
+		Name:  "CRED_EXCHANGE_TOKEN",
+		Value: opts.CredentialExchange.CredExchangeToken,
 	})
 
 	env = append(env, v1.EnvVar{
-		Name:  "TF_PORTER_WORKSPACE",
-		Value: conf.GetTFWorkspaceID(),
+		Name:  "VAULT_TOKEN",
+		Value: opts.CredentialExchange.VaultToken,
 	})
 
 	return env

+ 3 - 0
internal/repository/credentials/credentials.go

@@ -36,8 +36,11 @@ type AWSCredential struct {
 type CredentialStorage interface {
 	WriteOAuthCredential(oauthIntegration *integrations.OAuthIntegration, data *OAuthCredential) error
 	GetOAuthCredential(oauthIntegration *integrations.OAuthIntegration) (*OAuthCredential, error)
+	CreateOAuthToken(oauthIntegration *integrations.OAuthIntegration) (string, error)
 	WriteGCPCredential(gcpIntegration *integrations.GCPIntegration, data *GCPCredential) error
 	GetGCPCredential(gcpIntegration *integrations.GCPIntegration) (*GCPCredential, error)
+	CreateGCPToken(gcpIntegration *integrations.GCPIntegration) (string, error)
 	WriteAWSCredential(awsIntegration *integrations.AWSIntegration, data *AWSCredential) error
 	GetAWSCredential(awsIntegration *integrations.AWSIntegration) (*AWSCredential, error)
+	CreateAWSToken(awsIntegration *integrations.AWSIntegration) (string, error)
 }