Skip to content

Commit 076b7cc

Browse files
committed
feat: Update templates for production components and v0.9.2
- Add workload-identity and gke-network-policy components to production skaffold profile - These components are required for production deployments - Ensures future regenerations include necessary production configuration
1 parent f8c481c commit 076b7cc

5 files changed

Lines changed: 124 additions & 10 deletions

File tree

Dockerfile

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,28 @@
1-
# Start from the google cloud SDK image which supports multiple architectures
1+
# Multi-stage build for compliance-cli
2+
# Build stage compiles the Go binary for the target architecture
3+
FROM golang:1.21-alpine AS builder
4+
5+
# Install build dependencies
6+
RUN apk add --no-cache git
7+
8+
# Set working directory
9+
WORKDIR /build
10+
11+
# Copy go mod files
12+
COPY go.mod go.sum ./
13+
14+
# Download dependencies
15+
RUN go mod download
16+
17+
# Copy source code
18+
COPY . .
19+
20+
# Build for the target architecture
21+
# Docker automatically sets TARGETARCH based on the platform being built
22+
ARG TARGETARCH
23+
RUN GOOS=linux GOARCH=${TARGETARCH} go build -o compliance-cli ./cmd/deploy
24+
25+
# Final stage - Start from the google cloud SDK image which supports multiple architectures
226
FROM gcr.io/google.com/cloudsdktool/google-cloud-cli:stable
327

428
# Install additional useful tools
@@ -8,17 +32,19 @@ RUN apt-get update && apt-get install -y \
832
git \
933
&& rm -rf /var/lib/apt/lists/*
1034

11-
# Install yq separately
12-
RUN curl -L https://github.com/mikefarah/yq/releases/download/v4.40.5/yq_linux_amd64 -o /usr/local/bin/yq \
13-
&& chmod +x /usr/local/bin/yq
35+
# Install yq for the correct architecture
36+
ARG TARGETARCH
37+
RUN if [ "${TARGETARCH}" = "arm64" ]; then \
38+
curl -L https://github.com/mikefarah/yq/releases/download/v4.40.5/yq_linux_arm64 -o /usr/local/bin/yq; \
39+
else \
40+
curl -L https://github.com/mikefarah/yq/releases/download/v4.40.5/yq_linux_amd64 -o /usr/local/bin/yq; \
41+
fi && \
42+
chmod +x /usr/local/bin/yq
1443

15-
# Add the compliance-cli binary
16-
COPY compliance-cli /usr/local/bin/compliance-cli
44+
# Copy the compliance-cli binary from builder
45+
COPY --from=builder /build/compliance-cli /usr/local/bin/compliance-cli
1746
RUN chmod +x /usr/local/bin/compliance-cli
1847

19-
# Add any other custom tools your org uses
20-
# COPY other-tool /usr/local/bin/other-tool
21-
2248
# Set workdir
2349
WORKDIR /workspace
2450

internal/deploy/preview.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ func NewPreviewCommand(appConfig *config.AppConfig) *cobra.Command {
4242
}
4343

4444
previewName := fmt.Sprintf("pr%s", prNumber)
45+
deployConfig.PRNumber = prNumber
4546

4647
// Set preview-specific configuration using app config
4748
deployConfig.Pipeline = fmt.Sprintf("%s-preview-pipeline", appConfig.App)

internal/generate/templates/cloudbuild/preview-destroy.yaml.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ steps:
1212
env:
1313
- 'PROJECT_ID=${_PROJECT_ID}'
1414
- 'REGION=${_REGION}'
15-
- 'PR_NUMBER=${_PR_NUMBER}'
15+
- '_PR_NUMBER=${_PR_NUMBER}'
1616

1717
options:
1818
logging: CLOUD_LOGGING_ONLY

internal/generate/templates/skaffold.yaml.tmpl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,7 @@ profiles:
7171
kustomize:
7272
paths:
7373
- ../k8s/app/resources/prod
74+
- ../k8s/components/security/workload-identity
75+
- ../k8s/components/networking/gke-network-policy
7476
buildArgs:
7577
- --load-restrictor=LoadRestrictionsNone

internal/preview/destroy.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ Removes:
6464
log.Printf("Warning: Failed to destroy Cloud Deploy releases: %v", err)
6565
}
6666

67+
// Destroy AlloyDB Omni DBClusters first (if any)
68+
if err := destroyPRDBClusters(ctx, appConfig, projectID, region, prNumber, dryRun); err != nil {
69+
log.Printf("Warning: Failed to destroy AlloyDB Omni DBClusters: %v", err)
70+
}
71+
6772
// Destroy Kubernetes namespace
6873
if err := destroyPRNamespace(ctx, appConfig, projectID, region, prNumber, dryRun); err != nil {
6974
log.Printf("Warning: Failed to destroy Kubernetes namespace: %v", err)
@@ -153,6 +158,86 @@ func destroyPRReleases(ctx context.Context, appConfig *config.AppConfig, project
153158
return nil
154159
}
155160

161+
func destroyPRDBClusters(ctx context.Context, appConfig *config.AppConfig, projectID, region, prNumber string, dryRun bool) error {
162+
log.Printf("🗄️ Destroying AlloyDB Omni DBClusters for PR #%s...", prNumber)
163+
164+
// Get cluster credentials
165+
credsCmd := exec.CommandContext(ctx, "gcloud", "container", "clusters", "get-credentials",
166+
fmt.Sprintf("%s-cluster", appConfig.App),
167+
"--region="+region,
168+
"--project="+projectID,
169+
)
170+
if err := credsCmd.Run(); err != nil {
171+
// If we can't get credentials, skip DBCluster cleanup
172+
log.Printf(" Warning: Could not get cluster credentials: %v", err)
173+
return nil
174+
}
175+
176+
namespaceName := fmt.Sprintf("%s-preview-pr%s", appConfig.App, prNumber)
177+
178+
// Check if namespace exists
179+
checkCmd := exec.CommandContext(ctx, "kubectl", "get", "namespace", namespaceName)
180+
if err := checkCmd.Run(); err != nil {
181+
// Namespace doesn't exist, nothing to do
182+
return nil
183+
}
184+
185+
// List DBClusters in the namespace
186+
listCmd := exec.CommandContext(ctx, "kubectl", "get", "dbclusters.alloydbomni.dbadmin.goog",
187+
"-n", namespaceName,
188+
"-o", "jsonpath={.items[*].metadata.name}",
189+
)
190+
191+
output, err := listCmd.Output()
192+
if err != nil {
193+
// DBClusters CRD might not exist or no DBClusters in namespace
194+
if strings.Contains(err.Error(), "error validating data") ||
195+
strings.Contains(err.Error(), "the server doesn't have a resource type") {
196+
log.Printf(" No DBClusters CRD or no DBClusters found")
197+
return nil
198+
}
199+
log.Printf(" Warning: Could not list DBClusters: %v", err)
200+
return nil
201+
}
202+
203+
dbClusters := strings.TrimSpace(string(output))
204+
if dbClusters == "" {
205+
log.Printf(" No DBClusters found in namespace")
206+
return nil
207+
}
208+
209+
// Mark each DBCluster for deletion
210+
for _, dbCluster := range strings.Fields(dbClusters) {
211+
log.Printf(" 🗑️ Marking DBCluster '%s' for deletion", dbCluster)
212+
213+
if !dryRun {
214+
// Set isDeleted=true to trigger graceful deletion
215+
patchCmd := exec.CommandContext(ctx, "kubectl", "patch",
216+
"dbclusters.alloydbomni.dbadmin.goog", dbCluster,
217+
"-n", namespaceName,
218+
"--type=merge",
219+
"-p", `{"spec":{"isDeleted":true}}`,
220+
)
221+
222+
if err := patchCmd.Run(); err != nil {
223+
log.Printf(" ⚠️ Failed to mark DBCluster %s for deletion: %v", dbCluster, err)
224+
} else {
225+
log.Printf(" ✓ DBCluster %s marked for deletion", dbCluster)
226+
}
227+
}
228+
}
229+
230+
// Wait a bit for the operator to start processing the deletion
231+
if !dryRun && dbClusters != "" {
232+
log.Printf(" ⏳ Waiting for AlloyDB Omni operator to process deletions...")
233+
// Sleep for 10 seconds to give the operator time to start cleanup
234+
// This helps avoid namespace getting stuck in Terminating state
235+
exec.CommandContext(ctx, "sleep", "10").Run()
236+
}
237+
238+
return nil
239+
}
240+
156241
func destroyPRNamespace(ctx context.Context, appConfig *config.AppConfig, projectID, region, prNumber string, dryRun bool) error {
157242
log.Printf("☸️ Destroying Kubernetes namespace for PR #%s...", prNumber)
158243

0 commit comments

Comments
 (0)