Skip to content

Commit 28feda9

Browse files
committed
update
1 parent 22d5188 commit 28feda9

File tree

17 files changed

+1177
-83
lines changed

17 files changed

+1177
-83
lines changed

cmd/manageDeploymentRepo.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,16 @@ openmcp-bootstrapper manageDeploymentRepo <componentLocation> <templateResourceL
105105
return fmt.Errorf("failed to apply providers: %w", err)
106106
}
107107

108+
err = deploymentRepoManager.ApplyCustomResourceDefinitions(cmd.Context())
109+
if err != nil {
110+
return fmt.Errorf("failed to apply custom resource definitions: %w", err)
111+
}
112+
113+
err = deploymentRepoManager.UpdateResourcesKustomization()
114+
if err != nil {
115+
return fmt.Errorf("failed to update resources kustomization: %w", err)
116+
}
117+
108118
err = deploymentRepoManager.CommitAndPushChanges(cmd.Context())
109119
if err != nil {
110120
return fmt.Errorf("failed to commit and push changes: %w", err)

go.mod

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,69 @@ require (
1313
)
1414

1515
require (
16-
dario.cat/mergo v1.0.0 // indirect
16+
dario.cat/mergo v1.0.1 // indirect
17+
github.com/Masterminds/goutils v1.1.1 // indirect
18+
github.com/Masterminds/semver/v3 v3.3.0 // indirect
19+
github.com/Masterminds/sprig/v3 v3.3.0 // indirect
1720
github.com/Microsoft/go-winio v0.6.2 // indirect
1821
github.com/ProtonMail/go-crypto v1.1.6 // indirect
1922
github.com/cloudflare/circl v1.6.1 // indirect
2023
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
2124
github.com/davecgh/go-spew v1.1.1 // indirect
25+
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
2226
github.com/emirpasic/gods v1.18.1 // indirect
27+
github.com/evanphx/json-patch v0.5.2 // indirect
28+
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
29+
github.com/ghodss/yaml v1.0.0 // indirect
2330
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
31+
github.com/go-logr/logr v1.4.2 // indirect
32+
github.com/go-openapi/jsonpointer v0.21.0 // indirect
33+
github.com/go-openapi/jsonreference v0.21.0 // indirect
34+
github.com/go-openapi/spec v0.21.0 // indirect
35+
github.com/go-openapi/swag v0.23.0 // indirect
36+
github.com/gogo/protobuf v1.3.2 // indirect
2437
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
38+
github.com/google/gnostic-models v0.7.0 // indirect
39+
github.com/google/uuid v1.6.0 // indirect
40+
github.com/huandu/xstrings v1.5.0 // indirect
2541
github.com/inconshreveable/mousetrap v1.1.0 // indirect
2642
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
43+
github.com/josharian/intern v1.0.0 // indirect
44+
github.com/json-iterator/go v1.1.12 // indirect
2745
github.com/kevinburke/ssh_config v1.2.0 // indirect
46+
github.com/mailru/easyjson v0.7.7 // indirect
47+
github.com/mitchellh/copystructure v1.2.0 // indirect
48+
github.com/mitchellh/reflectwalk v1.0.2 // indirect
49+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
50+
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
2851
github.com/pjbgf/sha1cd v0.3.2 // indirect
52+
github.com/pkg/errors v0.9.1 // indirect
2953
github.com/pmezard/go-difflib v1.0.0 // indirect
3054
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
55+
github.com/shopspring/decimal v1.4.0 // indirect
3156
github.com/skeema/knownhosts v1.3.1 // indirect
57+
github.com/spf13/cast v1.7.0 // indirect
3258
github.com/spf13/pflag v1.0.6 // indirect
59+
github.com/x448/float16 v0.8.4 // indirect
3360
github.com/xanzy/ssh-agent v0.3.3 // indirect
3461
go.yaml.in/yaml/v2 v2.4.2 // indirect
62+
go.yaml.in/yaml/v3 v3.0.4 // indirect
3563
golang.org/x/crypto v0.37.0 // indirect
3664
golang.org/x/net v0.39.0 // indirect
3765
golang.org/x/sys v0.32.0 // indirect
66+
golang.org/x/text v0.24.0 // indirect
67+
google.golang.org/protobuf v1.36.5 // indirect
68+
gopkg.in/inf.v0 v0.9.1 // indirect
3869
gopkg.in/warnings.v0 v0.1.2 // indirect
70+
gopkg.in/yaml.v2 v2.4.0 // indirect
3971
gopkg.in/yaml.v3 v3.0.1 // indirect
72+
k8s.io/api v0.34.0 // indirect
73+
k8s.io/apimachinery v0.34.0 // indirect
74+
k8s.io/client-go v0.34.0 // indirect
75+
k8s.io/klog/v2 v2.130.1 // indirect
76+
k8s.io/kube-openapi v0.0.0-20250814151709-d7b6acb124c3 // indirect
77+
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
78+
sigs.k8s.io/kustomize v2.0.3+incompatible // indirect
79+
sigs.k8s.io/randfill v1.0.0 // indirect
80+
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
4081
)

go.sum

Lines changed: 112 additions & 0 deletions
Large diffs are not rendered by default.

internal/deployment-repo/deploymentRepoManager.go

Lines changed: 171 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"os"
77
"path/filepath"
88

9+
"github.com/go-git/go-billy/v5"
910
"github.com/go-git/go-git/v5"
1011

1112
gitconfig "github.com/openmcp-project/bootstrapper/internal/git-config"
@@ -15,7 +16,11 @@ import (
1516
)
1617

1718
const (
18-
openMCPOperatorComponentName = "openmcp-operator"
19+
OpenMCPOperatorComponentName = "openmcp-operator"
20+
TemplateOverlaysDir = "overlays"
21+
TemplateEnvsDir = "envs"
22+
TemplateResourcesDir = "resources"
23+
TemplateCRDsDir = "crds"
1924
)
2025

2126
// DeploymentRepoManager manages the deployment repository by applying templates and committing changes.
@@ -66,6 +71,8 @@ type DeploymentRepoManager struct {
6671
gitRepo *git.Repository
6772

6873
openMCPOperatorCV *ocmcli.ComponentVersion
74+
75+
crdFiles []string
6976
}
7077

7178
// NewDeploymentRepoManager creates a new DeploymentRepoManager with the specified parameters.
@@ -154,9 +161,61 @@ func (m *DeploymentRepoManager) Complete(ctx context.Context) (*DeploymentRepoMa
154161
return m, fmt.Errorf("failed to download templates resource: %w", err)
155162
}
156163

164+
overlaysDir := filepath.Join(m.templatesDir, "templates", TemplateOverlaysDir)
165+
if _, err = os.Stat(overlaysDir); err != nil {
166+
if os.IsNotExist(err) {
167+
return m, fmt.Errorf("no overlays directory found in templates resource")
168+
}
169+
return m, fmt.Errorf("failed to stat overlays directory: %w", err)
170+
}
171+
172+
// move overlays to <templatesDir>/envs/<deploymentRepositoryBranch>
173+
envsDir := filepath.Join(m.templatesDir, TemplateEnvsDir)
174+
err = os.Mkdir(envsDir, 0o755)
175+
if err != nil {
176+
return m, fmt.Errorf("failed to create envs directory: %w", err)
177+
}
178+
179+
err = os.Rename(overlaysDir, filepath.Join(envsDir, m.DeploymentRepositoryBranch))
180+
if err != nil {
181+
return m, fmt.Errorf("failed to move overlays to envs directory: %w", err)
182+
}
183+
184+
// move resources to <templatesDir>/resources
185+
resourcesDir := filepath.Join(m.templatesDir, "templates", TemplateResourcesDir)
186+
if _, err = os.Stat(resourcesDir); err != nil {
187+
if os.IsNotExist(err) {
188+
return m, fmt.Errorf("no resources directory found in templates resource")
189+
}
190+
return m, fmt.Errorf("failed to stat resources directory: %w", err)
191+
}
192+
193+
err = os.Rename(resourcesDir, filepath.Join(m.templatesDir, TemplateResourcesDir))
194+
if err != nil {
195+
return m, fmt.Errorf("failed to move resources to resources directory: %w", err)
196+
}
197+
198+
// remove Chart.yaml if it exists
199+
chartFile := filepath.Join(m.templatesDir, "Chart.yaml")
200+
if _, err = os.Stat(chartFile); err == nil {
201+
err = os.Remove(chartFile)
202+
if err != nil {
203+
return m, fmt.Errorf("failed to remove Chart.yaml from templates directory: %w", err)
204+
}
205+
}
206+
207+
// remove values.yaml if it exists
208+
valuesFile := filepath.Join(m.templatesDir, "values.yaml")
209+
if _, err = os.Stat(valuesFile); err == nil {
210+
err = os.Remove(valuesFile)
211+
if err != nil {
212+
return m, fmt.Errorf("failed to remove values.yaml from templates directory: %w", err)
213+
}
214+
}
215+
157216
logger.Infof("Fetching openmcp-operator component version")
158217

159-
m.openMCPOperatorCV, err = m.compGetter.GetReferencedComponentVersion(ctx, m.compGetter.RootComponentVersion(), openMCPOperatorComponentName)
218+
m.openMCPOperatorCV, err = m.compGetter.GetReferencedComponentVersion(ctx, m.compGetter.RootComponentVersion(), OpenMCPOperatorComponentName)
160219
if err != nil {
161220
logger.Infof("No openmcp-operator component version found: %v", err)
162221
} else {
@@ -167,7 +226,8 @@ func (m *DeploymentRepoManager) Complete(ctx context.Context) (*DeploymentRepoMa
167226
if err != nil {
168227
return m, fmt.Errorf("failed to parse git config: %w", err)
169228
}
170-
if err = m.gitConfig.Validate(); err != nil {
229+
err = m.gitConfig.Validate()
230+
if err != nil {
171231
return m, fmt.Errorf("invalid git config: %w", err)
172232
}
173233

@@ -211,11 +271,24 @@ func (m *DeploymentRepoManager) ApplyTemplates(ctx context.Context) error {
211271
return fmt.Errorf("no image resource found for openmcp-operator component version %s:%s", m.openMCPOperatorCV.Component.Name, m.openMCPOperatorCV.Component.Version)
212272
}
213273

274+
imageName, imageTag, imageDigest, err := util.ParseImageVersionAndTag(*imageResources[0].Access.ImageReference)
275+
if err != nil {
276+
return fmt.Errorf("failed to parse image reference %s: %w", *imageResources[0].Access.ImageReference, err)
277+
}
278+
214279
templateInput["openmcpOperator"] = map[string]interface{}{
215280
"version": m.openMCPOperatorCV.Component.Version,
216-
"image": *imageResources[0].Access.ImageReference,
281+
"image": imageName,
217282
"imagePullSecrets": m.ImagePullSecrets,
218283
}
284+
285+
if len(imageTag) > 0 {
286+
templateInput["openmcpOperator"].(map[string]interface{})["tag"] = imageTag
287+
}
288+
if len(imageDigest) > 0 {
289+
templateInput["openmcpOperator"].(map[string]interface{})["digest"] = imageDigest
290+
}
291+
219292
}
220293

221294
err := TemplateDir(m.templatesDir, templateInput, m.gitRepo)
@@ -253,7 +326,15 @@ func (m *DeploymentRepoManager) ApplyCustomResourceDefinitions(ctx context.Conte
253326

254327
logger.Infof("Applying Custom Resource Definitions to deployment repository")
255328

256-
crdsDownloadDir := filepath.Join(m.gitRepoDir, "crds")
329+
crdsDownloadDir := filepath.Join(m.gitRepoDir, TemplateResourcesDir, TemplateCRDsDir)
330+
331+
// if the CRDs directory already exists, remove it to ensure a clean state
332+
if _, err := os.Stat(crdsDownloadDir); err == nil {
333+
err = os.RemoveAll(crdsDownloadDir)
334+
if err != nil {
335+
return fmt.Errorf("failed to remove existing CRD directory: %w", err)
336+
}
337+
}
257338

258339
err := os.Mkdir(crdsDownloadDir, 0o755)
259340
if err != nil {
@@ -265,19 +346,103 @@ func (m *DeploymentRepoManager) ApplyCustomResourceDefinitions(ctx context.Conte
265346
return fmt.Errorf("failed to download CRD resource: %w", err)
266347
}
267348

349+
// List all YAML files in the CRDs download directory
350+
entries, err := os.ReadDir(crdsDownloadDir)
351+
if err != nil {
352+
return fmt.Errorf("failed to read CRD download directory: %w", err)
353+
}
354+
355+
m.crdFiles = make([]string, 0)
356+
for _, entry := range entries {
357+
if !entry.IsDir() {
358+
fileName := entry.Name()
359+
// Check if file has .yaml or .yml extension
360+
if filepath.Ext(fileName) == ".yaml" || filepath.Ext(fileName) == ".yml" {
361+
filePath := filepath.Join(crdsDownloadDir, fileName)
362+
m.crdFiles = append(m.crdFiles, filePath)
363+
logger.Tracef("Added CRD file: %s", filePath)
364+
}
365+
}
366+
}
367+
368+
logger.Infof("Found %d CRD files", len(m.crdFiles))
369+
268370
workTree, err := m.gitRepo.Worktree()
269371
if err != nil {
270372
return fmt.Errorf("failed to get worktree: %w", err)
271373
}
272374

273-
_, err = workTree.Add("crds")
375+
_, err = workTree.Add(filepath.Join(TemplateResourcesDir, TemplateCRDsDir))
274376
if err != nil {
275377
return fmt.Errorf("failed to add CRD files: %w", err)
276378
}
277379

278380
return nil
279381
}
280382

383+
func (m *DeploymentRepoManager) UpdateResourcesKustomization() error {
384+
files := make([]string, 0, len(m.PlatformServices)+len(m.ServiceProviders)+len(m.ClusterProviders)+len(m.crdFiles))
385+
386+
for _, clusterProvider := range m.ClusterProviders {
387+
files = append(files, filepath.Join("cluster-providers", clusterProvider+".yaml"))
388+
}
389+
390+
for _, serviceProvider := range m.ServiceProviders {
391+
files = append(files, filepath.Join("service-providers", serviceProvider+".yaml"))
392+
}
393+
394+
for _, platformService := range m.PlatformServices {
395+
files = append(files, filepath.Join("platform-services", platformService+".yaml"))
396+
}
397+
398+
for _, crdFile := range m.crdFiles {
399+
files = append(files, filepath.Join(TemplateCRDsDir, filepath.Base(crdFile)))
400+
}
401+
402+
// open resources root customization
403+
resourcesRootKustomizationPath := filepath.Join(TemplateResourcesDir, "kustomization.yaml")
404+
405+
workTree, err := m.gitRepo.Worktree()
406+
if err != nil {
407+
return fmt.Errorf("failed to get worktree: %w", err)
408+
}
409+
410+
fileInWorkTree, err := workTree.Filesystem.OpenFile(resourcesRootKustomizationPath, os.O_RDWR, 0644)
411+
if err != nil {
412+
return fmt.Errorf("failed to open file %s in worktree: %w", resourcesRootKustomizationPath, err)
413+
}
414+
415+
defer func(pathInRepo billy.File) {
416+
err := pathInRepo.Close()
417+
if err != nil {
418+
_, _ = fmt.Fprintf(os.Stderr, "failed to close file in worktree: %v\n", err)
419+
}
420+
}(fileInWorkTree)
421+
422+
resourcesRootKustomization, err := ParseKustomizationFromFile(fileInWorkTree)
423+
if err != nil {
424+
return fmt.Errorf("failed to parse resources root kustomization: %w", err)
425+
}
426+
427+
_, err = fileInWorkTree.Seek(0, 0)
428+
if err != nil {
429+
return fmt.Errorf("failed to seek resources root kustomization: %w", err)
430+
}
431+
432+
AddResourcesToKustomization(resourcesRootKustomization, files)
433+
434+
err = WriteKustomizationToFile(fileInWorkTree, resourcesRootKustomization)
435+
if err != nil {
436+
return fmt.Errorf("failed to write resources root kustomization: %w", err)
437+
}
438+
439+
if _, err = workTree.Add(resourcesRootKustomizationPath); err != nil {
440+
return fmt.Errorf("failed to add resources root kustomization to git index: %w", err)
441+
}
442+
443+
return nil
444+
}
445+
281446
// CommitAndPushChanges commits all changes in the deployment repository and pushes them to the remote repository.
282447
// If there are no changes to commit, it does nothing.
283448
func (m *DeploymentRepoManager) CommitAndPushChanges(_ context.Context) error {

0 commit comments

Comments
 (0)