-
Notifications
You must be signed in to change notification settings - Fork 14
/
render.go
149 lines (135 loc) · 4.04 KB
/
render.go
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
144
145
146
147
148
149
package argocd
import (
"context"
"encoding/json"
"fmt"
"path/filepath"
argoappv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
"github.com/argoproj/argo-cd/v2/reposerver/repository"
"github.com/argoproj/argo-cd/v2/util/git"
"k8s.io/apimachinery/pkg/api/resource"
"github.com/akuity/kargo-render/internal/file"
"github.com/akuity/kargo-render/internal/manifests"
)
// ConfigManagementConfig is a wrapper around more specific configuration for
// the configuration management tools. Only one of its fields may be non-nil.
type ConfigManagementConfig struct {
Path string `json:"path,omitempty"`
Helm *ApplicationSourceHelm `json:"helm,omitempty"`
Kustomize *ApplicationSourceKustomize `json:"kustomize,omitempty"`
Directory *argoappv1.ApplicationSourceDirectory `json:"directory,omitempty"`
Plugin *argoappv1.ApplicationSourcePlugin `json:"plugin,omitempty"`
}
// ApplicationSourceHelm holds configuration for Helm-based applications.
type ApplicationSourceHelm struct {
argoappv1.ApplicationSourceHelm
Namespace string `json:"namespace,omitempty"`
K8SVersion string `json:"k8sVersion,omitempty"`
APIVersions []string `json:"apiVersions,omitempty"`
RepoURL string `json:"repoURL,omitempty"`
Chart string `json:"chart,omitempty"`
}
// ApplicationSourceKustomize holds configuration for Kustomize-based
// applications.
type ApplicationSourceKustomize struct {
argoappv1.ApplicationSourceKustomize
BuildOptions string `json:"buildOptions,omitempty"`
}
func expand(item map[string]any, values []string) {
for k, v := range item {
switch value := v.(type) {
case string:
item[k] = file.ExpandPath(value, values)
case map[string]any:
expand(value, values)
case []any:
for i, v := range value {
switch v := v.(type) {
case string:
value[i] = file.ExpandPath(v, values)
case map[string]any:
expand(v, values)
}
}
}
}
}
func (c ConfigManagementConfig) Expand(
values []string,
) (ConfigManagementConfig, error) {
data, err := json.Marshal(c)
if err != nil {
return c, err
}
var cfgMap map[string]any
if err = json.Unmarshal(data, &cfgMap); err != nil {
return c, err
}
expand(cfgMap, values)
data, err = json.Marshal(cfgMap)
if err != nil {
return c, err
}
var cfg ConfigManagementConfig
if err := json.Unmarshal(data, &cfg); err != nil {
return c, err
}
return cfg, nil
}
func Render(
ctx context.Context,
repoRoot string,
cfg ConfigManagementConfig,
) ([]byte, error) {
src := argoappv1.ApplicationSource{
Plugin: cfg.Plugin,
}
var apiVersions []string
var namespace string
var k8sVersion string
if cfg.Helm != nil {
src.Helm = &cfg.Helm.ApplicationSourceHelm
apiVersions = cfg.Helm.APIVersions
namespace = cfg.Helm.Namespace
k8sVersion = cfg.Helm.K8SVersion
}
var kustomizeOptions *argoappv1.KustomizeOptions
if cfg.Kustomize != nil {
src.Kustomize = &cfg.Kustomize.ApplicationSourceKustomize
kustomizeOptions = &argoappv1.KustomizeOptions{
BuildOptions: cfg.Kustomize.BuildOptions,
}
}
res, err := repository.GenerateManifests(
ctx,
filepath.Join(repoRoot, cfg.Path),
repoRoot, // Repo root
"", // Revision -- seems ok to be empty string
&apiclient.ManifestRequest{
// Both of these fields need to be non-nil
Repo: &argoappv1.Repository{},
ApplicationSource: &src,
KustomizeOptions: kustomizeOptions,
ApiVersions: apiVersions,
Namespace: namespace,
KubeVersion: k8sVersion,
},
true,
&git.NoopCredsStore{}, // No need for this
// Allow any quantity of generated manifests
resource.MustParse("0"),
nil,
)
if err != nil {
return nil,
fmt.Errorf("error generating manifests using Argo CD repo server: %w", err)
}
// res.Manifests contains JSON manifests. We want YAML.
yamlManifests, err := manifests.JSONStringsToYAMLBytes(res.Manifests)
if err != nil {
return nil, err
}
// Glue the manifests together
return manifests.CombineYAML(yamlManifests), nil
}