Skip to content

Commit b6757ff

Browse files
committed
feat(bootstrap-gcp): Add managed services & openbao config
* Add openbao config * Add managed service config * Remove yaml infra output fixes CU-869c3kpk3 and CU-869c3kry4
1 parent 4db7095 commit b6757ff

File tree

8 files changed

+207
-11
lines changed

8 files changed

+207
-11
lines changed

cli/cmd/bootstrap_gcp.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ func AddBootstrapGcpCmd(parent *cobra.Command, opts *GlobalOptions) {
8787
flags.StringArrayVar(&bootstrapGcpCmd.CodesphereEnv.Experiments, "experiments", gcp.DefaultExperiments, "Experiments to enable in Codesphere installation (optional)")
8888
flags.StringArrayVar(&bootstrapGcpCmd.CodesphereEnv.FeatureFlags, "feature-flags", []string{}, "Feature flags to enable in Codesphere installation (optional)")
8989

90+
flags.StringVar(&bootstrapGcpCmd.CodesphereEnv.OpenBaoURI, "openbao-uri", "", "URI for OpenBao (optional)")
91+
flags.StringVar(&bootstrapGcpCmd.CodesphereEnv.OpenBaoEngine, "openbao-engine", "cs-secrets-engine", "OpenBao engine name (default: cs-secrets-engine)")
92+
flags.StringVar(&bootstrapGcpCmd.CodesphereEnv.OpenBaoUser, "openbao-user", "admin", "OpenBao username (optional)")
93+
flags.StringVar(&bootstrapGcpCmd.CodesphereEnv.OpenBaoPassword, "openbao-password", "", "OpenBao password (optional)")
94+
9095
util.MarkFlagRequired(bootstrapGcpCmd.cmd, "project-name")
9196
util.MarkFlagRequired(bootstrapGcpCmd.cmd, "billing-account")
9297
util.MarkFlagRequired(bootstrapGcpCmd.cmd, "base-domain")
@@ -143,7 +148,6 @@ func (c *BootstrapGcpCmd) BootstrapGcp() error {
143148
}
144149

145150
log.Println("\n🎉🎉🎉 GCP infrastructure bootstrapped successfully!")
146-
log.Println(envString)
147151
log.Printf("Infrastructure details written to %s", infraFilePath)
148152
log.Printf("Access the jumpbox using:\nssh-add $SSH_KEY_PATH; ssh -o StrictHostKeyChecking=no -o ForwardAgent=yes -o SendEnv=OMS_PORTAL_API_KEY root@%s", bs.Env.Jumpbox.GetExternalIP())
149153
if bs.Env.InstallVersion != "" {

cli/cmd/init_install_config.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ type InitInstallConfigOpts struct {
8888
CodesphereHostingPlanTempStorageMb int
8989
CodesphereWorkspacePlanName string
9090
CodesphereWorkspacePlanMaxReplicas int
91+
92+
CodesphereOpenBaoUri string
93+
CodesphereOpenBaoEngine string
94+
CodesphereOpenBaoUser string
95+
CodesphereOpenBaoPassword string
9196
}
9297

9398
func (c *InitInstallConfigCmd) RunE(_ *cobra.Command, args []string) error {
@@ -154,6 +159,11 @@ func AddInitInstallConfigCmd(init *cobra.Command, opts *GlobalOptions) {
154159

155160
c.cmd.Flags().StringVar(&c.Opts.CodesphereDomain, "domain", "", "Main Codesphere domain")
156161

162+
c.cmd.Flags().StringVar(&c.Opts.CodesphereOpenBaoUri, "openbao-uri", "", "URI for OpenBao (e.g., https://openbao.example.com)")
163+
c.cmd.Flags().StringVar(&c.Opts.CodesphereOpenBaoEngine, "openbao-engine", "cs-secrets-engine", "Engine for OpenBao")
164+
c.cmd.Flags().StringVar(&c.Opts.CodesphereOpenBaoUser, "openbao-user", "admin", "Username for OpenBao authentication")
165+
c.cmd.Flags().StringVar(&c.Opts.CodesphereOpenBaoPassword, "openbao-password", "", "Password for OpenBao authentication")
166+
157167
util.MarkFlagRequired(c.cmd, "config")
158168
util.MarkFlagRequired(c.cmd, "vault")
159169

@@ -448,6 +458,16 @@ func (c *InitInstallConfigCmd) updateConfigFromOpts(config *files.RootConfig) *f
448458
}
449459
}
450460

461+
if c.Opts.CodesphereOpenBaoUri != "" {
462+
if config.Codesphere.OpenBao == nil {
463+
config.Codesphere.OpenBao = &files.OpenBaoConfig{}
464+
}
465+
config.Codesphere.OpenBao.URI = c.Opts.CodesphereOpenBaoUri
466+
config.Codesphere.OpenBao.Engine = c.Opts.CodesphereOpenBaoEngine
467+
config.Codesphere.OpenBao.User = c.Opts.CodesphereOpenBaoUser
468+
config.Codesphere.OpenBao.Password = c.Opts.CodesphereOpenBaoPassword
469+
}
470+
451471
// Plans
452472
if c.Opts.CodesphereHostingPlanCPUTenth != 0 || c.Opts.CodesphereHostingPlanMemoryMb != 0 ||
453473
c.Opts.CodesphereHostingPlanStorageMb != 0 || c.Opts.CodesphereHostingPlanTempStorageMb != 0 {

internal/bootstrap/gcp/gcp.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ type CodesphereEnvironment struct {
102102
Experiments []string `json:"experiments"`
103103
FeatureFlags []string `json:"feature_flags"`
104104

105+
// OpenBao
106+
OpenBaoURI string `json:"-"`
107+
OpenBaoEngine string `json:"-"`
108+
OpenBaoUser string `json:"-"`
109+
OpenBaoPassword string `json:"-"`
110+
105111
// Config
106112
InstallConfigPath string `json:"-"`
107113
SecretsFilePath string `json:"-"`
@@ -1271,6 +1277,30 @@ func (b *GCPBootstrapper) UpdateInstallConfig() error {
12711277
}
12721278
}
12731279

1280+
b.Env.InstallConfig.Codesphere.ManagedServices = []files.ManagedServiceConfig{
1281+
{
1282+
Name: "postgres",
1283+
Version: "v1",
1284+
},
1285+
{
1286+
Name: "babelfish",
1287+
Version: "v1",
1288+
},
1289+
{
1290+
Name: "s3",
1291+
Version: "v1",
1292+
},
1293+
}
1294+
1295+
if b.Env.OpenBaoURI != "" {
1296+
b.Env.InstallConfig.Codesphere.OpenBao = &files.OpenBaoConfig{
1297+
Engine: b.Env.OpenBaoEngine,
1298+
URI: b.Env.OpenBaoURI,
1299+
User: b.Env.OpenBaoUser,
1300+
Password: b.Env.OpenBaoPassword,
1301+
}
1302+
}
1303+
12741304
if err := b.icg.WriteInstallConfig(b.Env.InstallConfigPath, true); err != nil {
12751305
return fmt.Errorf("failed to write config file: %w", err)
12761306
}

internal/bootstrap/gcp/gcp_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,6 +1137,9 @@ var _ = Describe("GCP Bootstrapper", func() {
11371137
dnsConfig := dnsIssuer["config"].(map[string]interface{})
11381138
cloudDns := dnsConfig["cloudDNS"].(map[string]interface{})
11391139
Expect(cloudDns["project"]).To(Equal(bs.Env.DNSProjectID))
1140+
1141+
Expect(bs.Env.InstallConfig.Codesphere.OpenBao).To(BeNil())
1142+
Expect(len(bs.Env.InstallConfig.Codesphere.ManagedServices)).To(Equal(3))
11401143
})
11411144
Context("When Experiments are set in CodesphereEnvironment", func() {
11421145
BeforeEach(func() {
@@ -1190,6 +1193,30 @@ var _ = Describe("GCP Bootstrapper", func() {
11901193
})
11911194

11921195
})
1196+
1197+
Context("When OpenBao config is set", func() {
1198+
BeforeEach(func() {
1199+
csEnv.OpenBaoURI = "https://openbao.example.com"
1200+
csEnv.OpenBaoPassword = "fake-password"
1201+
csEnv.OpenBaoUser = "fake-username"
1202+
csEnv.OpenBaoEngine = "fake-engine"
1203+
})
1204+
It("sets OpenBao config in install config", func() {
1205+
icg.EXPECT().GenerateSecrets().Return(nil)
1206+
icg.EXPECT().WriteInstallConfig("fake-config-file", true).Return(nil)
1207+
icg.EXPECT().WriteVault("fake-secret", true).Return(nil)
1208+
1209+
nodeClient.EXPECT().CopyFile(mock.Anything, mock.Anything, mock.Anything).Return(nil).Twice()
1210+
1211+
err := bs.UpdateInstallConfig()
1212+
Expect(err).NotTo(HaveOccurred())
1213+
1214+
Expect(bs.Env.InstallConfig.Codesphere.OpenBao.URI).To(Equal("https://openbao.example.com"))
1215+
Expect(bs.Env.InstallConfig.Codesphere.OpenBao.Password).To(Equal("fake-password"))
1216+
Expect(bs.Env.InstallConfig.Codesphere.OpenBao.User).To(Equal("fake-username"))
1217+
Expect(bs.Env.InstallConfig.Codesphere.OpenBao.Engine).To(Equal("fake-engine"))
1218+
})
1219+
})
11931220
})
11941221

11951222
Describe("Invalid cases", func() {

internal/installer/config_generator_collector.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,4 +346,24 @@ func (g *InstallConfig) collectCodesphereConfig(prompter *Prompter) {
346346
1: workspacePlan,
347347
},
348348
}
349+
350+
g.collectOpenBaoConfig(prompter)
351+
}
352+
353+
func (g *InstallConfig) collectOpenBaoConfig(prompter *Prompter) {
354+
log.Println("\n=== OpenBao Configuration (Optional) ===")
355+
hasOpenBao := prompter.Bool("Configure OpenBao integration", g.Config.Codesphere.OpenBao != nil && g.Config.Codesphere.OpenBao.URI != "")
356+
if !hasOpenBao {
357+
g.Config.Codesphere.OpenBao = nil
358+
return
359+
}
360+
361+
if g.Config.Codesphere.OpenBao == nil {
362+
g.Config.Codesphere.OpenBao = &files.OpenBaoConfig{}
363+
}
364+
365+
g.Config.Codesphere.OpenBao.URI = g.collectString(prompter, "OpenBao URI (e.g., https://openbao.example.com)", "")
366+
g.Config.Codesphere.OpenBao.Engine = g.collectString(prompter, "OpenBao engine name", "cs-secrets-engine")
367+
g.Config.Codesphere.OpenBao.User = g.collectString(prompter, "OpenBao username", "admin")
368+
g.Config.Codesphere.OpenBao.Password = g.collectString(prompter, "OpenBao password", "")
349369
}

internal/installer/config_manager.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"fmt"
88
"io"
99
"net"
10+
"net/url"
1011

1112
"github.com/codesphere-cloud/oms/internal/installer/files"
1213
"github.com/codesphere-cloud/oms/internal/util"
@@ -155,6 +156,21 @@ func (g *InstallConfig) ValidateInstallConfig() []string {
155156
errors = append(errors, "Codesphere domain is required")
156157
}
157158

159+
if g.Config.Codesphere.OpenBao != nil {
160+
if g.Config.Codesphere.OpenBao.URI == "" {
161+
errors = append(errors, "OpenBao URI is required when OpenBao integration is enabled")
162+
}
163+
if _, err := url.ParseRequestURI(g.Config.Codesphere.OpenBao.URI); err != nil {
164+
errors = append(errors, "OpenBao URI must be a valid URL")
165+
}
166+
if g.Config.Codesphere.OpenBao.Engine == "" {
167+
errors = append(errors, "OpenBao engine name is required when OpenBao integration is enabled")
168+
}
169+
if g.Config.Codesphere.OpenBao.User == "" {
170+
errors = append(errors, "OpenBao username is required when OpenBao integration is enabled")
171+
}
172+
}
173+
158174
return errors
159175
}
160176

@@ -177,6 +193,12 @@ func (g *InstallConfig) ValidateVault() []string {
177193
}
178194
}
179195

196+
if g.Config.Codesphere.OpenBao != nil {
197+
if !foundSecrets["openBaoPassword"] {
198+
errors = append(errors, "required OpenBao secret missing: openBaoPassword")
199+
}
200+
}
201+
180202
return errors
181203
}
182204

@@ -358,5 +380,12 @@ func (g *InstallConfig) MergeVaultIntoConfig() error {
358380
}
359381
}
360382

383+
// OpenBao secrets
384+
if g.Config.Codesphere.OpenBao != nil {
385+
if secret, ok := secretsMap["openBaoPassword"]; ok && secret.Fields != nil {
386+
g.Config.Codesphere.OpenBao.Password = secret.Fields.Password
387+
}
388+
}
389+
361390
return nil
362391
}

internal/installer/config_manager_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,51 @@ var _ = Describe("ConfigManager", func() {
218218
Expect(errors).To(ContainElement(ContainSubstring("postgres server address is required")))
219219
})
220220
})
221+
222+
})
223+
224+
Context("openBao validation", func() {
225+
BeforeEach(func() {
226+
configManager.Config.Codesphere.OpenBao = &files.OpenBaoConfig{
227+
URI: "https://openbao.example.com",
228+
Engine: "openbao-engine",
229+
User: "fake-user",
230+
}
231+
})
232+
233+
It("should require OpenBao URI", func() {
234+
configManager.Config.Codesphere.OpenBao.URI = ""
235+
errors := configManager.ValidateInstallConfig()
236+
Expect(errors).To(ContainElement(ContainSubstring("OpenBao URI is required")))
237+
})
238+
239+
It("should require OpenBao engine", func() {
240+
configManager.Config.Codesphere.OpenBao.Engine = ""
241+
errors := configManager.ValidateInstallConfig()
242+
Expect(errors).To(ContainElement(ContainSubstring("OpenBao engine name is required")))
243+
})
244+
245+
It("should require OpenBao user", func() {
246+
configManager.Config.Codesphere.OpenBao.User = ""
247+
errors := configManager.ValidateInstallConfig()
248+
Expect(errors).To(ContainElement(ContainSubstring("OpenBao username is required")))
249+
})
250+
251+
It("should validate OpenBao URI format", func() {
252+
configManager.Config.Codesphere.OpenBao.URI = "not-a-valid-url"
253+
errors := configManager.ValidateInstallConfig()
254+
Expect(errors).To(ContainElement(ContainSubstring("OpenBao URI must be a valid URL")))
255+
})
256+
257+
It("should require OpenBao password in vault", func() {
258+
configManager.Vault = &files.InstallVault{
259+
Secrets: []files.SecretEntry{
260+
{Name: "cephSshPrivateKey"},
261+
},
262+
}
263+
errors := configManager.ValidateVault()
264+
Expect(errors).To(ContainElement(ContainSubstring("required OpenBao secret missing: openBaoPassword")))
265+
})
221266
})
222267

223268
Context("ceph validation", func() {

internal/installer/files/config_yaml.go

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -263,11 +263,20 @@ type CodesphereConfig struct {
263263
UnderprovisionFactors *UnderprovisionFactors `yaml:"underprovisionFactors,omitempty"`
264264
GitProviders *GitProvidersConfig `yaml:"gitProviders,omitempty"`
265265
ManagedServices []ManagedServiceConfig `yaml:"managedServices,omitempty"`
266+
OpenBao *OpenBaoConfig `yaml:"openBao,omitempty"`
266267

267268
DomainAuthPrivateKey string `yaml:"-"`
268269
DomainAuthPublicKey string `yaml:"-"`
269270
}
270271

272+
type OpenBaoConfig struct {
273+
Engine string `yaml:"engine,omitempty"`
274+
URI string `yaml:"uri,omitempty"`
275+
User string `yaml:"user,omitempty"`
276+
277+
Password string `yaml:"-"`
278+
}
279+
271280
type CertIssuerType string
272281

273282
const (
@@ -417,16 +426,16 @@ type OAuthConfig struct {
417426

418427
type ManagedServiceConfig struct {
419428
Name string `yaml:"name"`
420-
API ManagedServiceAPI `yaml:"api"`
421-
Author string `yaml:"author"`
422-
Category string `yaml:"category"`
423-
ConfigSchema map[string]interface{} `yaml:"configSchema"`
424-
DetailsSchema map[string]interface{} `yaml:"detailsSchema"`
425-
SecretsSchema map[string]interface{} `yaml:"secretsSchema"`
426-
Description string `yaml:"description"`
427-
DisplayName string `yaml:"displayName"`
428-
IconURL string `yaml:"iconUrl"`
429-
Plans []ServicePlan `yaml:"plans"`
429+
API ManagedServiceAPI `yaml:"api,omitempty"`
430+
Author string `yaml:"author,omitempty"`
431+
Category string `yaml:"category,omitempty"`
432+
ConfigSchema map[string]interface{} `yaml:"configSchema,omitempty"`
433+
DetailsSchema map[string]interface{} `yaml:"detailsSchema,omitempty"`
434+
SecretsSchema map[string]interface{} `yaml:"secretsSchema,omitempty"`
435+
Description string `yaml:"description,omitempty"`
436+
DisplayName string `yaml:"displayName,omitempty"`
437+
IconURL string `yaml:"iconUrl,omitempty"`
438+
Plans []ServicePlan `yaml:"plans,omitempty"`
430439
Version string `yaml:"version"`
431440
}
432441

@@ -530,6 +539,7 @@ func (c *RootConfig) ExtractVault() *InstallVault {
530539
c.addManagedServiceSecrets(vault)
531540
c.addRegistrySecrets(vault)
532541
c.addKubeConfigSecret(vault)
542+
c.addOpenBaoSecrets(vault)
533543

534544
return vault
535545
}
@@ -744,6 +754,17 @@ func (c *RootConfig) addKubeConfigSecret(vault *InstallVault) {
744754
}
745755
}
746756

757+
func (c *RootConfig) addOpenBaoSecrets(vault *InstallVault) {
758+
if c.Codesphere.OpenBao != nil && c.Codesphere.OpenBao.Password != "" {
759+
vault.Secrets = append(vault.Secrets, SecretEntry{
760+
Name: "openBaoPassword",
761+
Fields: &SecretFields{
762+
Password: c.Codesphere.OpenBao.Password,
763+
},
764+
})
765+
}
766+
}
767+
747768
func Capitalize(s string) string {
748769
if s == "" {
749770
return ""

0 commit comments

Comments
 (0)