Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pre-flight checks #2846

Merged
merged 15 commits into from
Apr 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 48 additions & 39 deletions .github/workflows/porter_preview_env.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,50 +22,59 @@ jobs:
porter-preview:
runs-on: ubuntu-latest
steps:
- name: Checkout code
id: checkout-code
uses: actions/checkout@v3
- name: Create Porter preview env
id: preview
timeout-minutes: 30
uses: porter-dev/porter-preview-action@dev
with:
action_id: ${{ github.run_id }}
cluster: "2489"
host: https://dashboard.getporter.dev
installation_id: "18533943"
namespace: pr-${{ github.event.inputs.pr_number }}-porter
pr_branch_from: ${{ github.event.inputs.pr_branch_from }}
pr_branch_into: ${{ github.event.inputs.pr_branch_into }}
pr_id: ${{ github.event.inputs.pr_number }}
pr_name: ${{ github.event.inputs.pr_title }}
project: "6680"
repo_name: porter
repo_owner: porter-dev
token: ${{ secrets.PORTER_PREVIEW_6680_2489 }}
- name: Attach vcluster
run: |
sudo apt-get update
sudo apt-get install bash curl jq unzip
- name: Checkout monorepo code
id: checkout-monorepo-code
uses: actions/checkout@v3
- name: Checkout CCP code
id: checkout-ccp-code
uses: actions/checkout@v3
with:
repository: porter-dev/cluster-control-plane
token: ${{ secrets.PORTER_DEV_GITHUB_TOKEN }}
path: external/ccp
- name: Create Porter preview env
id: preview
timeout-minutes: 30
uses: porter-dev/porter-preview-action@dev
with:
action_id: ${{ github.run_id }}
cluster: "2489"
host: https://dashboard.getporter.dev
installation_id: "18533943"
namespace: pr-${{ github.event.inputs.pr_number }}-porter
pr_branch_from: ${{ github.event.inputs.pr_branch_from }}
pr_branch_into: ${{ github.event.inputs.pr_branch_into }}
pr_id: ${{ github.event.inputs.pr_number }}
pr_name: ${{ github.event.inputs.pr_title }}
project: "6680"
repo_name: porter
repo_owner: porter-dev
token: ${{ secrets.PORTER_PREVIEW_6680_2489 }}
env:
PORTER_APPLY_HONEYCOMB_PASSWORD: ${{ secrets.HONEYCOMB_PASSWORD_PREVIEW_ENVIRONMENTS }}
- name: Attach vcluster
run: |
sudo apt-get update
sudo apt-get install bash curl jq unzip

/bin/bash -c "$(curl -fsSL https://install.porter.run)"
/bin/bash -c "$(curl -fsSL https://install.porter.run)"

echo "$VCLUSTER_KUBECONFIG" > /tmp/vcluster_kubeconfig
echo "$VCLUSTER_KUBECONFIG" > /tmp/vcluster_kubeconfig

dashboard_domain=$(echo "$DOMAINS" | jq '.subdomains[] | select(test("porter-dashboard*"))')
dashboard_domain=$(sed -e 's/^"//' -e 's/"$//' <<<"$dashboard_domain")
dashboard_domain=$(echo "$DOMAINS" | jq '.subdomains[] | select(test("porter-dashboard*"))')
dashboard_domain=$(sed -e 's/^"//' -e 's/"$//' <<<"$dashboard_domain")

if [ -z "$dashboard_domain" ]; then
exit 1
fi
if [ -z "$dashboard_domain" ]; then
exit
fi

export PORTER_HOST="https://${dashboard_domain}"
export PORTER_HOST="https://${dashboard_domain}"

porter connect kubeconfig --kubeconfig /tmp/vcluster_kubeconfig
env:
PORTER_TOKEN: ${{ secrets.PREVIEW_DEPLOYMENT_PORTER_KEY }}
PORTER_PROJECT: 1
VCLUSTER_KUBECONFIG: ${{ secrets.VCLUSTER_KUBECONFIG }}
DOMAINS: ${{ steps.preview.outputs.domains }}
porter connect kubeconfig --kubeconfig /tmp/vcluster_kubeconfig
env:
PORTER_TOKEN: ${{ secrets.PREVIEW_DEPLOYMENT_PORTER_KEY }}
PORTER_PROJECT: 1
VCLUSTER_KUBECONFIG: ${{ secrets.VCLUSTER_KUBECONFIG }}
DOMAINS: ${{ steps.preview.outputs.domains }}
concurrency:
group: ${{ github.workflow }}-${{ github.event.inputs.pr_number }}
25 changes: 25 additions & 0 deletions .github/workflows/porter_production.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"on":
push:
branches:
- master
name: Deploy to Porter
jobs:
porter-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set Github tag
id: vars
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Update Porter App
timeout-minutes: 20
uses: porter-dev/[email protected]
with:
app: production
cluster: "8"
host: https://dashboard.internal-tools.getporter.dev
namespace: default
project: "1"
tag: ${{ steps.vars.outputs.sha_short }}
token: ${{ secrets.PORTER_TOKEN_1 }}
4 changes: 3 additions & 1 deletion api/server/handlers/project_integration/create_aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,13 @@ func (p *CreateAWSHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
SourceArn: "arn:aws:iam::108458755588:role/CAPIManagement", // hard coded as this is the final hop for a CAPI cluster
TargetAccessId: request.AWSAccessKeyID,
TargetSecretKey: request.AWSSecretAccessKey,
TargetArn: request.TargetArn,
ExternalId: request.ExternalID,
}
credResp, err := p.Config().ClusterControlPlaneClient.CreateAssumeRoleChain(ctx, connect.NewRequest(&credReq))
if err != nil {
e := fmt.Errorf("unable to create CAPI required credential: %w", err)
p.HandleAPIError(w, r, apierrors.NewErrInternal(e))
p.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(e, http.StatusPreconditionFailed, err.Error()))
return
}
res.CloudProviderCredentialIdentifier = credResp.Msg.TargetArn
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package project_integration

import (
"fmt"
"net/http"

"github.com/bufbuild/connect-go"
porterv1 "github.com/porter-dev/api-contracts/generated/go/porter/v1"
"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/models"
)

type CreatePreflightCheckAWSUsageHandler struct {
handlers.PorterHandlerReadWriter
}

func NewCreatePreflightCheckAWSUsageHandler(
config *config.Config,
decoderValidator shared.RequestDecoderValidator,
writer shared.ResultWriter,
) *CreatePreflightCheckAWSUsageHandler {
return &CreatePreflightCheckAWSUsageHandler{
PorterHandlerReadWriter: handlers.NewDefaultPorterHandler(config, decoderValidator, writer),
}
}

func (p *CreatePreflightCheckAWSUsageHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
project, _ := r.Context().Value(types.ProjectScope).(*models.Project)
ctx := r.Context()

request := &types.QuotaPreflightCheckRequest{}
if ok := p.DecodeAndValidate(w, r, request); !ok {
return
}

checkReq := porterv1.QuotaPreflightCheckRequest{
ProjectId: int64(project.ID),
TargetArn: request.TargetARN,
Region: request.Region,
}

checkResp, err := p.Config().ClusterControlPlaneClient.QuotaPreflightCheck(ctx, connect.NewRequest(&checkReq))

if err != nil {
e := fmt.Errorf("Pre-provision check failed: %w", err)
p.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(e, http.StatusPreconditionFailed, err.Error()))
return
}

p.WriteResult(w, r, checkResp)
}
28 changes: 28 additions & 0 deletions api/server/router/project_integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,34 @@ func getProjectIntegrationRoutes(
Router: r,
})

// POST /api/projects/{project_id}/integrations/aws/preflightcheck/usage -> project_integration.NewCreatePreflightCheckAWSHandler
preflightCheckAWSUsageEndpoint := factory.NewAPIEndpoint(
&types.APIRequestMetadata{
Verb: types.APIVerbCreate,
Method: types.HTTPVerbPost,
Path: &types.Path{
Parent: basePath,
RelativePath: relPath + "/aws/preflight/usage",
},
Scopes: []types.PermissionScope{
types.UserScope,
types.ProjectScope,
},
},
)

preflightCheckAWSUsageHandler := project_integration.NewCreatePreflightCheckAWSUsageHandler(
config,
factory.GetDecoderValidator(),
factory.GetResultWriter(),
)

routes = append(routes, &router.Route{
Endpoint: preflightCheckAWSUsageEndpoint,
Handler: preflightCheckAWSUsageHandler,
Router: r,
})

// GET /api/projects/{project_id}/integrations/azure -> project_integration.NewListAzureHandler
listAzureEndpoint := factory.NewAPIEndpoint(
&types.APIRequestMetadata{
Expand Down
11 changes: 11 additions & 0 deletions api/types/project_integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,23 @@ type AWSIntegration struct {

type ListAWSResponse []*AWSIntegration

type QuotaPreflightCheckRequest struct {
ProjectID uint `json:"project_id"`
TargetARN string `json:"target_arn"`
ExternalID string `json:"external_id"`
Region string `json:"region"`
}

type QuotaPreflightCheckResponse struct{}

type CreateAWSRequest struct {
AWSRegion string `json:"aws_region"`
AWSClusterID string `json:"aws_cluster_id"`
AWSAccessKeyID string `json:"aws_access_key_id"`
AWSSecretAccessKey string `json:"aws_secret_access_key"`
AWSAssumeRoleArn string `json:"aws_assume_role_arn"`
TargetArn string `json:"aws_target_arn"`
ExternalID string `json:"aws_external_id"`
}

type CreateAWSResponse struct {
Expand Down
4 changes: 3 additions & 1 deletion cli/cmd/preview/v2beta1/addon_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ func (a *AddonResource) GetName() string {
}

func (a *AddonResource) GetDependsOn() []string {
var dependsOn []string
dependsOn := []string{
"get-env",
}

if a == nil || a.DependsOn == nil {
return dependsOn
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/preview/v2beta1/app_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (a *AppResource) getV1Resource(b *Build) (*types.Resource, error) {

return &types.Resource{
Name: a.GetName(),
DependsOn: append([]string{b.GetName()}, a.GetDependsOn()...),
DependsOn: append([]string{"get-env", b.GetName()}, a.GetDependsOn()...),
Source: map[string]any{
"name": a.Chart.GetName(),
"repo": a.Chart.GetURL(),
Expand Down
11 changes: 11 additions & 0 deletions cli/cmd/preview/v2beta1/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package v2beta1
import (
"context"
"fmt"
"regexp"

api "github.com/porter-dev/porter/api/client"
"github.com/porter-dev/porter/cli/cmd/config"
Expand All @@ -28,6 +29,10 @@ type PreviewApplier struct {
}

func NewApplier(client *api.Client, raw []byte, namespace string) (*PreviewApplier, error) {
// replace all instances of ${{ porter.env.FOO }} with { .get-env.FOO }
re := regexp.MustCompile(`\$\{\{\s*porter\.env\.(.*)\s*\}\}`)
raw = re.ReplaceAll(raw, []byte("{.get-env.$1}"))

parsed := &PorterYAML{}

err := yaml.Unmarshal(raw, parsed)
Expand Down Expand Up @@ -147,6 +152,12 @@ func (a *PreviewApplier) DowngradeToV1() (*types.ResourceGroup, error) {

v1File := &types.ResourceGroup{
Version: "v1",
Resources: []*types.Resource{
{
Name: "get-env",
Driver: "os-env",
},
},
}

buildRefs := make(map[string]*Build)
Expand Down
4 changes: 4 additions & 0 deletions cli/cmd/preview/v2beta1/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ func (b *Build) getV1BuildImage() (*types.Resource, error) {
Target: map[string]any{
"app_name": b.GetName(),
},
DependsOn: []string{
"get-env",
},
Config: rawConfig,
}, nil
}
Expand All @@ -184,6 +187,7 @@ func (b *Build) getV1PushImage() (*types.Resource, error) {
Name: b.GetName(),
Driver: "push-image",
DependsOn: []string{
"get-env",
fmt.Sprintf("%s-build-image", b.GetName()),
},
Target: map[string]any{
Expand Down
Loading