-
Notifications
You must be signed in to change notification settings - Fork 146
Expand file tree
/
Copy pathdeployer.go
More file actions
143 lines (127 loc) · 5.01 KB
/
Copy pathdeployer.go
File metadata and controls
143 lines (127 loc) · 5.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package deployer
import (
"context"
"fmt"
"os"
"scripts/camunda-core/pkg/docker"
"scripts/camunda-core/pkg/helm"
"scripts/camunda-core/pkg/kube"
"scripts/camunda-core/pkg/logging"
"scripts/camunda-core/pkg/utils"
"scripts/camunda-deployer/pkg/types"
)
func Deploy(ctx context.Context, o types.Options) error {
// Render-only mode: do not touch the cluster or docker; just render templates
if o.RenderTemplates {
return renderTemplates(ctx, o)
}
if !o.SkipDockerLogin {
if o.EnsureDockerHub {
if err := docker.EnsureDockerHubLogin(ctx, o.DockerHubUsername, o.DockerHubPassword); err != nil {
return fmt.Errorf("failed to ensure Docker Hub login: %w", err)
}
}
if o.EnsureDockerRegistry {
if err := docker.EnsureHarborLogin(ctx, o.DockerRegistryUsername, o.DockerRegistryPassword); err != nil {
return fmt.Errorf("failed to ensure Harbor login: %w", err)
}
}
}
if !o.SkipDependencyUpdate {
if err := helm.DependencyUpdate(ctx, o.ChartPath); err != nil {
return err
}
}
kubeClient, err := kube.NewClient(o.Kubeconfig, o.KubeContext)
if err != nil {
return fmt.Errorf("failed to create kube client: %w", err)
}
if err := kubeClient.EnsureNamespace(ctx, o.Namespace); err != nil {
return err
}
if err := labelAndAnnotateNamespace(ctx, kubeClient, o.Namespace, o.Identifier, o.CIMetadata.Flow, o.TTL, o.CIMetadata.GithubRunID, o.CIMetadata.GithubJobID, o.CIMetadata.GithubOrg, o.CIMetadata.GithubRepo, o.CIMetadata.WorkflowURL); err != nil {
// Non-fatal: namespace labels are CI housekeeping metadata (TTL, GitHub run IDs).
// On some clusters (e.g., EKS via Teleport) the user may lack namespace PATCH RBAC.
logging.Logger.Warn().Err(err).Str("namespace", o.Namespace).
Msg("failed to label/annotate namespace (continuing without CI metadata)")
}
if o.EnsureDockerRegistry {
// Resolve Harbor registry credentials from flags or environment fallbacks
username := o.DockerRegistryUsername
password := o.DockerRegistryPassword
if username == "" {
username = utils.FirstNonEmpty(os.Getenv("HARBOR_USERNAME"), os.Getenv("TEST_DOCKER_USERNAME_CAMUNDA_CLOUD"), os.Getenv("NEXUS_USERNAME"))
}
if password == "" {
password = utils.FirstNonEmpty(os.Getenv("HARBOR_PASSWORD"), os.Getenv("TEST_DOCKER_PASSWORD_CAMUNDA_CLOUD"), os.Getenv("NEXUS_PASSWORD"))
}
if err := kubeClient.EnsureDockerRegistrySecret(ctx, o.Namespace, username, password); err != nil {
return err
}
}
if o.EnsureDockerHub {
// Resolve Docker Hub credentials from flags or environment fallbacks
username := o.DockerHubUsername
password := o.DockerHubPassword
if username == "" {
username = utils.FirstNonEmpty(os.Getenv("DOCKERHUB_USERNAME"), os.Getenv("TEST_DOCKER_USERNAME"))
}
if password == "" {
password = utils.FirstNonEmpty(os.Getenv("DOCKERHUB_PASSWORD"), os.Getenv("TEST_DOCKER_PASSWORD"))
}
if err := kubeClient.EnsureDockerHubSecret(ctx, o.Namespace, username, password); err != nil {
return err
}
}
if o.ExternalSecretsEnabled {
if err := kube.ApplyExternalSecretsAndCerts(ctx, o.Kubeconfig, o.KubeContext, o.Platform, o.RepoRoot, o.ChartPath, o.Namespace, o.NamespacePrefix, o.ExternalSecretsStore); err != nil {
return err
}
}
if o.ApplyIntegrationCreds {
if err := applyIntegrationTestCredentials(ctx, kubeClient, o.Namespace); err != nil {
return err
}
}
if o.VaultSecretPath != "" {
data, err := os.ReadFile(o.VaultSecretPath)
if err != nil {
return fmt.Errorf("failed to read vault secret file: %w", err)
}
if err := kubeClient.ApplyManifest(ctx, o.Namespace, data); err != nil {
return fmt.Errorf("failed to apply vault secret: %w", err)
}
}
// Run pre-install hooks (e.g., OIDC credential secret creation).
// These run after the namespace is guaranteed to exist and all standard
// secrets are in place, but before the helm upgrade/install.
for i, hook := range o.PreInstallHooks {
if err := hook(ctx); err != nil {
return fmt.Errorf("pre-install hook [%d] failed: %w", i, err)
}
}
// Deploy companion charts (e.g., OpenSearch) as separate Helm releases
// in the same namespace. Each chart is deployed with --wait to ensure
// it is ready before the main Camunda chart deployment begins.
for i, cc := range o.CompanionCharts {
logging.Logger.Info().
Str("chart", cc.ChartRef).
Str("version", cc.Version).
Str("release", cc.ReleaseName).
Str("namespace", o.Namespace).
Msg("Deploying companion chart")
if err := deployCompanionChart(ctx, cc, o); err != nil {
return fmt.Errorf("companion chart [%d] %q failed: %w", i, cc.ReleaseName, err)
}
}
// Run post-infra hooks after the companion charts (external infrastructure)
// are deployed and ready, but before the main Camunda chart. This is the
// point to act on freshly-provisioned infrastructure — e.g. migrating data
// from a prior release's bundled backends onto the companion services.
for i, hook := range o.PostInfraHooks {
if err := hook(ctx); err != nil {
return fmt.Errorf("post-infra hook [%d] failed: %w", i, err)
}
}
return upgradeInstall(ctx, o)
}