Skip to content

Commit

Permalink
Merge branch 'master' into validate-apply-with-overrides
Browse files Browse the repository at this point in the history
  • Loading branch information
ianedwards authored Sep 28, 2023
2 parents d026b1b + 1b0e2dc commit 3da8cbd
Show file tree
Hide file tree
Showing 21 changed files with 318 additions and 121 deletions.
7 changes: 4 additions & 3 deletions api/server/handlers/porter_app/analytics.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ func TrackStackBuildStatus(
stackName string,
errorMessage string,
status types.PorterAppEventStatus,
validateApplyV2 bool,
) error {
_, span := telemetry.NewSpan(ctx, "track-build-status")
defer span.End()
Expand All @@ -126,7 +127,7 @@ func TrackStackBuildStatus(
FirstName: user.FirstName,
LastName: user.LastName,
CompanyName: user.CompanyName,
ValidateApplyV2: project.ValidateApplyV2,
ValidateApplyV2: validateApplyV2,
}))
}

Expand All @@ -138,7 +139,7 @@ func TrackStackBuildStatus(
FirstName: user.FirstName,
LastName: user.LastName,
CompanyName: user.CompanyName,
ValidateApplyV2: project.ValidateApplyV2,
ValidateApplyV2: validateApplyV2,
}))
}

Expand All @@ -151,7 +152,7 @@ func TrackStackBuildStatus(
FirstName: user.FirstName,
LastName: user.LastName,
CompanyName: user.CompanyName,
ValidateApplyV2: project.ValidateApplyV2,
ValidateApplyV2: validateApplyV2,
}))
}

Expand Down
7 changes: 4 additions & 3 deletions api/server/handlers/porter_app/create_and_update_events.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ func (p *CreateUpdatePorterAppEventHandler) ServeHTTP(w http.ResponseWriter, r *
)

if request.Type == types.PorterAppEventType_Build {
reportBuildStatus(ctx, request, p.Config(), user, project, appName)
validateApplyV2 := project.GetFeatureFlag(models.ValidateApplyV2, p.Config().LaunchDarklyClient)
reportBuildStatus(ctx, request, p.Config(), user, project, appName, validateApplyV2)
}

if request.ID == "" {
Expand All @@ -88,7 +89,7 @@ func (p *CreateUpdatePorterAppEventHandler) ServeHTTP(w http.ResponseWriter, r *
p.WriteResult(w, r, event)
}

func reportBuildStatus(ctx context.Context, request *types.CreateOrUpdatePorterAppEventRequest, config *config.Config, user *models.User, project *models.Project, stackName string) {
func reportBuildStatus(ctx context.Context, request *types.CreateOrUpdatePorterAppEventRequest, config *config.Config, user *models.User, project *models.Project, stackName string, validateApplyV2 bool) {
ctx, span := telemetry.NewSpan(ctx, "report-build-status")
defer span.End()

Expand All @@ -113,7 +114,7 @@ func reportBuildStatus(ctx context.Context, request *types.CreateOrUpdatePorterA
}
}

_ = TrackStackBuildStatus(ctx, config, user, project, stackName, errStr, request.Status)
_ = TrackStackBuildStatus(ctx, config, user, project, stackName, errStr, request.Status, validateApplyV2)
}

// createNewAppEvent will create a new app event for the given porter app name. If the app event is an agent event, then it will be created only if there is no existing event which has the agent ID. In the case that an existing event is found, that will be returned instead
Expand Down
8 changes: 5 additions & 3 deletions api/server/handlers/porter_app/list_events.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ func (p *PorterAppEventListHandler) updateExistingAppEvent(

// TODO: get rid of this block and related methods if still here after 08-04-2023
if appEvent.Type == string(types.PorterAppEventType_Build) && appEvent.TypeExternalSource == "GITHUB" {
err = p.updateBuildEvent_Github(ctx, &event, user, project, stackName)
validateApplyV2 := project.GetFeatureFlag(models.ValidateApplyV2, p.Config().LaunchDarklyClient)
err = p.updateBuildEvent_Github(ctx, &event, user, project, stackName, validateApplyV2)
if err != nil {
return appEvent, telemetry.Error(ctx, span, err, "error updating porter app event for github build")
}
Expand All @@ -158,6 +159,7 @@ func (p *PorterAppEventListHandler) updateBuildEvent_Github(
user *models.User,
project *models.Project,
stackName string,
validateApplyV2 bool,
) error {
ctx, span := telemetry.NewSpan(ctx, "update-porter-app-build-event")
defer span.End()
Expand Down Expand Up @@ -220,10 +222,10 @@ func (p *PorterAppEventListHandler) updateBuildEvent_Github(
if *actionRun.Status == "completed" {
if *actionRun.Conclusion == "success" {
event.Status = string(types.PorterAppEventStatus_Success)
_ = TrackStackBuildStatus(ctx, p.Config(), user, project, stackName, "", types.PorterAppEventStatus_Success)
_ = TrackStackBuildStatus(ctx, p.Config(), user, project, stackName, "", types.PorterAppEventStatus_Success, validateApplyV2)
} else {
event.Status = string(types.PorterAppEventStatus_Failed)
_ = TrackStackBuildStatus(ctx, p.Config(), user, project, stackName, "", types.PorterAppEventStatus_Failed)
_ = TrackStackBuildStatus(ctx, p.Config(), user, project, stackName, "", types.PorterAppEventStatus_Failed, validateApplyV2)
}
event.Metadata["end_time"] = actionRun.GetUpdatedAt().Time
}
Expand Down
48 changes: 31 additions & 17 deletions cli/cmd/v2/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,53 +175,61 @@ func Apply(ctx context.Context, inp ApplyInput) error {
eventID, _ := createBuildEvent(ctx, client, appName, cliConf.Project, cliConf.Cluster, deploymentTargetID)

if commitSHA == "" {
_ = reportBuildFailure(ctx, client, appName, cliConf, deploymentTargetID, applyResp.AppRevisionId, eventID)
return errors.New("Build is required but commit SHA cannot be identified. Please set the PORTER_COMMIT_SHA environment variable or run apply in git repository with access to the git CLI.")
err := errors.New("Build is required but commit SHA cannot be identified. Please set the PORTER_COMMIT_SHA environment variable or run apply in git repository with access to the git CLI.")
_ = reportBuildFailure(ctx, client, appName, cliConf, deploymentTargetID, applyResp.AppRevisionId, eventID, err)
return err
}

buildSettings, err := buildSettingsFromBase64AppProto(base64AppProto)
if err != nil {
_ = reportBuildFailure(ctx, client, appName, cliConf, deploymentTargetID, applyResp.AppRevisionId, eventID)
return fmt.Errorf("error building settings from base64 app proto: %w", err)
err := fmt.Errorf("error getting build settings from base64 app proto: %w", err)
_ = reportBuildFailure(ctx, client, appName, cliConf, deploymentTargetID, applyResp.AppRevisionId, eventID, err)
return err
}

currentAppRevisionResp, err := client.CurrentAppRevision(ctx, cliConf.Project, cliConf.Cluster, appName, deploymentTargetID)
if err != nil {
_ = reportBuildFailure(ctx, client, appName, cliConf, deploymentTargetID, applyResp.AppRevisionId, eventID)
return fmt.Errorf("error getting current app revision: %w", err)
err := fmt.Errorf("error getting current app revision: %w", err)
_ = reportBuildFailure(ctx, client, appName, cliConf, deploymentTargetID, applyResp.AppRevisionId, eventID, err)
return err
}

if currentAppRevisionResp == nil {
_ = reportBuildFailure(ctx, client, appName, cliConf, deploymentTargetID, applyResp.AppRevisionId, eventID)
return errors.New("current app revision is nil")
err := errors.New("current app revision is nil")
_ = reportBuildFailure(ctx, client, appName, cliConf, deploymentTargetID, applyResp.AppRevisionId, eventID, err)
return err
}

appRevision := currentAppRevisionResp.AppRevision
if appRevision.B64AppProto == "" {
_ = reportBuildFailure(ctx, client, appName, cliConf, deploymentTargetID, applyResp.AppRevisionId, eventID)
return errors.New("current app revision b64 app proto is empty")
err := errors.New("current app revision b64 app proto is empty")
_ = reportBuildFailure(ctx, client, appName, cliConf, deploymentTargetID, applyResp.AppRevisionId, eventID, err)
return err
}

currentImageTag, err := imageTagFromBase64AppProto(appRevision.B64AppProto)
if err != nil {
_ = reportBuildFailure(ctx, client, appName, cliConf, deploymentTargetID, applyResp.AppRevisionId, eventID)
return fmt.Errorf("error getting image tag from current app revision: %w", err)
err := fmt.Errorf("error getting image tag from current app revision: %w", err)
_ = reportBuildFailure(ctx, client, appName, cliConf, deploymentTargetID, applyResp.AppRevisionId, eventID, err)
return err
}

buildSettings.CurrentImageTag = currentImageTag
buildSettings.ProjectID = cliConf.Project

buildEnv, err := client.GetBuildEnv(ctx, cliConf.Project, cliConf.Cluster, appName, appRevision.ID)
if err != nil {
_ = reportBuildFailure(ctx, client, appName, cliConf, deploymentTargetID, applyResp.AppRevisionId, eventID)
return fmt.Errorf("error getting build env: %w", err)
err := fmt.Errorf("error getting build env: %w", err)
_ = reportBuildFailure(ctx, client, appName, cliConf, deploymentTargetID, applyResp.AppRevisionId, eventID, err)
return err
}
buildSettings.Env = buildEnv.BuildEnvVariables

err = build(ctx, client, buildSettings)
if err != nil {
_ = reportBuildFailure(ctx, client, appName, cliConf, deploymentTargetID, applyResp.AppRevisionId, eventID)
return fmt.Errorf("error building app: %w", err)
err := fmt.Errorf("error building app: %w", err)
_ = reportBuildFailure(ctx, client, appName, cliConf, deploymentTargetID, applyResp.AppRevisionId, eventID, err)
return err
}

color.New(color.FgGreen).Printf("Successfully built image (tag: %s)\n", buildSettings.ImageTag) // nolint:errcheck,gosec
Expand Down Expand Up @@ -501,9 +509,15 @@ func updateEnvGroupsInProto(ctx context.Context, base64AppProto string, envGroup
return editedB64AppProto, nil
}

func reportBuildFailure(ctx context.Context, client api.Client, appName string, cliConf config.CLIConfig, deploymentTargetID string, appRevisionID string, eventID string) error {
func reportBuildFailure(ctx context.Context, client api.Client, appName string, cliConf config.CLIConfig, deploymentTargetID string, appRevisionID string, eventID string, buildError error) error {
buildMetadata := make(map[string]interface{})
buildMetadata["end_time"] = time.Now().UTC()

// the below is a temporary solution until we can report build errors via telemetry from the CLI
errorStringMap := make(map[string]string)
errorStringMap["build-error"] = fmt.Sprintf("%+v", buildError)
buildMetadata["errors"] = errorStringMap

err := updateExistingEvent(ctx, client, appName, cliConf.Project, cliConf.Cluster, deploymentTargetID, types.PorterAppEventType_Build, eventID, types.PorterAppEventStatus_Failed, buildMetadata)
if err != nil {
return err
Expand Down
14 changes: 7 additions & 7 deletions dashboard/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"@loadable/component": "^5.15.2",
"@material-ui/core": "^4.11.3",
"@material-ui/lab": "^4.0.0-alpha.61",
"@porter-dev/api-contracts": "^0.1.7",
"@porter-dev/api-contracts": "^0.2.1",
"@react-spring/web": "^9.6.1",
"@sentry/react": "^6.13.2",
"@sentry/tracing": "^6.13.2",
Expand Down
46 changes: 39 additions & 7 deletions dashboard/src/components/ProvisionerSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ import {
EKSLogging,
EKSPreflightValues,
PreflightCheckRequest,
GKE
AWSClusterNetwork,
} from "@porter-dev/api-contracts";

import { ClusterType } from "shared/types";
import Button from "./porter/Button";
import Error from "./porter/Error";
Expand Down Expand Up @@ -78,13 +79,25 @@ const machineTypeOptions = [
{ value: "c6i.2xlarge", label: "c6i.2xlarge" },
{ value: "c6i.4xlarge", label: "c6i.4xlarge" },
{ value: "c6i.8xlarge", label: "c6i.8xlarge" },
{ value: "r6i.large", label: "r6i.large" },
{ value: "r6i.xlarge", label: "r6i.xlarge" },
{ value: "r6i.2xlarge", label: "r6i.2xlarge" },
{ value: "r6i.4xlarge", label: "r6i.4xlarge" },
{ value: "r6i.8xlarge", label: "r6i.8xlarge" },
{ value: "r6i.12xlarge", label: "r6i.12xlarge" },
{ value: "r6i.16xlarge", label: "r6i.16xlarge" },
{ value: "r6i.24xlarge", label: "r6i.24xlarge" },
{ value: "r6i.32xlarge", label: "r6i.32xlarge" },
{ value: "g4dn.xlarge", label: "g4dn.xlarge" },
];

const clusterVersionOptions = [
{ value: "v1.24.0", label: "1.24.0" },
];

const defaultCidrVpc = "10.78.0.0/16"
const defaultCidrServices = "172.20.0.0/16"

type Props = RouteComponentProps & {
selectedClusterVersion?: Contract;
provisionerError?: string;
Expand Down Expand Up @@ -125,7 +138,8 @@ const ProvisionerSettings: React.FC<Props> = (props) => {
const [additionalNodePolicies, setAdditionalNodePolicies] = useState<
string[]
>([]);
const [cidrRange, setCidrRange] = useState("10.78.0.0/16");
const [cidrRangeVPC, setCidrRangeVPC] = useState(defaultCidrVpc);
const [cidrRangeServices, setCidrRangeServices] = useState(defaultCidrServices);
const [clusterVersion, setClusterVersion] = useState("v1.24.0");
const [isReadOnly, setIsReadOnly] = useState(false);
const [errorMessage, setErrorMessage] = useState<string>(undefined);
Expand Down Expand Up @@ -286,12 +300,16 @@ const ProvisionerSettings: React.FC<Props> = (props) => {
value: new EKS({
clusterName,
clusterVersion: clusterVersion || "v1.24.0",
cidrRange: cidrRange || "10.78.0.0/16",
cidrRange: cidrRangeVPC || defaultCidrVpc, // deprecated in favour of network.cidrRangeVPC: can be removed after december 2023
region: awsRegion,
loadBalancer: loadBalancerObj,
logging: controlPlaneLogs,
enableGuardDuty: guardDutyEnabled,
enableKmsEncryption: kmsEncryptionEnabled,
network: new AWSClusterNetwork({
vpcCidr: cidrRangeVPC || defaultCidrVpc,
serviceCidr: cidrRangeServices || defaultCidrServices,
}),
nodeGroups: [
new EKSNodeGroup({
instanceType: "t3.medium",
Expand Down Expand Up @@ -441,7 +459,11 @@ const ProvisionerSettings: React.FC<Props> = (props) => {
setClusterName(eksValues.clusterName);
setAwsRegion(eksValues.region);
setClusterVersion(eksValues.clusterVersion);
setCidrRange(eksValues.cidrRange);
setCidrRangeVPC(eksValues.cidrRange);
if (eksValues.network != null) {
setCidrRangeVPC(eksValues.network?.vpcCidr || defaultCidrVpc);
setCidrRangeServices(eksValues.network?.serviceCidr || defaultCidrServices);
}
if (eksValues.loadBalancer != null) {
setIPAllowList(eksValues.loadBalancer.allowlistIpRanges);
setWildCardDomain(eksValues.loadBalancer.wildcardDomain);
Expand Down Expand Up @@ -609,12 +631,22 @@ const ProvisionerSettings: React.FC<Props> = (props) => {
<Input
width="350px"
type="string"
value={cidrRange}
value={cidrRangeVPC}
disabled={!user.isPorterUser}
setValue={(x: string) => setCidrRange(x)}
label="VPC CIDR range"
setValue={(x: string) => setCidrRangeVPC(x)}
label="CIDR range for AWS VPC"
placeholder="ex: 10.78.0.0/16"
/>
<Spacer y={1} />
<Input
width="350px"
type="string"
value={cidrRangeServices}
disabled={!user.isPorterUser}
setValue={(x: string) => setCidrRangeServices(x)}
label="CIDR range for Kubernetes internal services"
placeholder="ex: 172.20.0.0/16"
/>
{!currentProject.simplified_view_enabled && (
<>
<Spacer y={1} />
Expand Down
18 changes: 10 additions & 8 deletions dashboard/src/lib/hooks/useAppValidation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ import api from "shared/api";
import { match } from "ts-pattern";
import { z } from "zod";

export type AppValidationResult = {
validatedAppProto: PorterApp;
variables: Record<string, string>;
secrets: Record<string, string>;
};

export const useAppValidation = ({
deploymentTargetID,
creating = false,
Expand All @@ -19,13 +25,6 @@ export const useAppValidation = ({
}) => {
const { currentProject, currentCluster } = useContext(Context);

const removedEnvKeys = (
current: Record<string, string>,
previous: Record<string, string>
) => {
return Object.keys(previous).filter((key) => !current[key]);
};

const getBranchHead = async ({
projectID,
source,
Expand Down Expand Up @@ -62,7 +61,10 @@ export const useAppValidation = ({
};

const validateApp = useCallback(
async (data: PorterAppFormData, prevRevision?: PorterApp) => {
async (
data: PorterAppFormData,
prevRevision?: PorterApp
): Promise<AppValidationResult> => {
if (!currentProject || !currentCluster) {
throw new Error("No project or cluster selected");
}
Expand Down
1 change: 1 addition & 0 deletions dashboard/src/lib/porter-apps/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export const porterAppFormValidator = z.object({
app: clientAppValidator,
source: sourceValidator,
deletions: deletionValidator,
redeployOnSave: z.boolean().default(false),
});
export type PorterAppFormData = z.infer<typeof porterAppFormValidator>;

Expand Down
Loading

0 comments on commit 3da8cbd

Please sign in to comment.