@leverege/build-tools 2.97.1 → 2.98.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/launch.json +40 -0
- package/package.json +5 -5
- package/src/Utils.mjs +9 -7
- package/src/chart-to-museum.mjs +3 -1
- package/src/helm-charts/prom-operator/helmup.plugin +1 -1
- package/src/helm-charts/prom-operator/prometheus-stack.yaml.ovh +3 -3
- package/src/helm-charts/prom-operator/stackdriver-exporter.yaml.ovh +1 -1
- package/src/helm-charts/valkey/valkey-local.yaml +2 -2
- package/src/helm-charts/velero/helmup.plugin +2 -2
- package/src/helmup.sh +1 -1
- package/src/init-my-chart/{leaf-chart-templates/Chart.yaml.hbs → Chart.yaml.hbs} +4 -4
- package/src/init-my-chart/Chartwright.mjs +139 -49
- package/src/init-my-chart/init-my-chart.mjs +25 -30
- package/src/init-my-chart/leaf-chart-templates/values.schema.json +213 -254
- package/src/init-my-chart/{leaf-chart-templates/values.yaml.hbs → values.yaml.hbs} +7 -36
- package/src/push-my-chart.mjs +43 -26
- package/src/init-my-chart/init-my-chart-v1.mjs +0 -124
package/.vscode/launch.json
CHANGED
|
@@ -18,6 +18,36 @@
|
|
|
18
18
|
},
|
|
19
19
|
"outputCapture": "std"
|
|
20
20
|
},
|
|
21
|
+
{
|
|
22
|
+
"name": "push-my-chart rsrc-srvr",
|
|
23
|
+
"type": "node",
|
|
24
|
+
"request": "launch",
|
|
25
|
+
"program": "${workspaceFolder}/src/push-my-chart.mjs",
|
|
26
|
+
"args": [],
|
|
27
|
+
"cwd": "/Users/john/Work/leverege/cicd/@plt/resource-server",
|
|
28
|
+
"runtimeExecutable": "node",
|
|
29
|
+
"console": "integratedTerminal"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "ingestor in monorepo",
|
|
33
|
+
"type": "node",
|
|
34
|
+
"request": "launch",
|
|
35
|
+
"program": "${workspaceFolder}/src/init-my-chart/init-my-chart.mjs",
|
|
36
|
+
"args": [],
|
|
37
|
+
"cwd": "/Users/john/Work/leverege/cicd/@kud/recovr-services/packages/recovr-ingestor",
|
|
38
|
+
"runtimeExecutable": "node",
|
|
39
|
+
"console": "integratedTerminal"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"name": "init-my-chart emailer legacy",
|
|
43
|
+
"type": "node",
|
|
44
|
+
"request": "launch",
|
|
45
|
+
"program": "${workspaceFolder}/src/init-my-chart/init-my-chart.mjs",
|
|
46
|
+
"args": [],
|
|
47
|
+
"cwd": "/Users/john/Work/leverege/cicd/@plt/emailer",
|
|
48
|
+
"runtimeExecutable": "node",
|
|
49
|
+
"console": "integratedTerminal"
|
|
50
|
+
},
|
|
21
51
|
{
|
|
22
52
|
"name": "init-my-chart pubsub-pulse",
|
|
23
53
|
"type": "node",
|
|
@@ -38,6 +68,16 @@
|
|
|
38
68
|
"runtimeExecutable": "node",
|
|
39
69
|
"console": "integratedTerminal"
|
|
40
70
|
},
|
|
71
|
+
{
|
|
72
|
+
"name": "init-my-chart in a lib",
|
|
73
|
+
"type": "node",
|
|
74
|
+
"request": "launch",
|
|
75
|
+
"program": "${workspaceFolder}/src/init-my-chart/init-my-chart.mjs",
|
|
76
|
+
"args": ["--dry-run"],
|
|
77
|
+
"cwd": "/Users/john/Work/leverege/cicd/@lev/secrets",
|
|
78
|
+
"runtimeExecutable": "node",
|
|
79
|
+
"console": "integratedTerminal"
|
|
80
|
+
},
|
|
41
81
|
{
|
|
42
82
|
"name": "service-man (launch)",
|
|
43
83
|
"type": "node",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leverege/build-tools",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.98.1",
|
|
4
4
|
"description": "A collection of build / support tools for Leverege developers",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
"build-tools": "src/build-tools.mjs",
|
|
22
22
|
"change-up": "src/change-up.sh",
|
|
23
23
|
"chart-compass": "src/chart-compass.mjs",
|
|
24
|
-
"chart-to-museum": "src/chart-to-museum.mjs",
|
|
25
24
|
"chart-to-registry": "src/chart-to-registry.mjs",
|
|
26
25
|
"circleate": "src/circleate.sh",
|
|
27
26
|
"clone-cnpg-from-snapshot": "src/clone-cnpg-from-snapshot.mjs",
|
|
@@ -83,7 +82,7 @@
|
|
|
83
82
|
"@leverege/jsdoc-template": "^1.0.1",
|
|
84
83
|
"chalk": "^5.6.2",
|
|
85
84
|
"command-line-args": "^6.0.1",
|
|
86
|
-
"command-line-usage": "^7.0.
|
|
85
|
+
"command-line-usage": "^7.0.4",
|
|
87
86
|
"commander": "^14.0.3",
|
|
88
87
|
"deepmerge": "^4.3.1",
|
|
89
88
|
"enquirer": "^2.4.1",
|
|
@@ -104,17 +103,18 @@
|
|
|
104
103
|
"readline-sync": "^1.4.10",
|
|
105
104
|
"semver": "^7.7.4",
|
|
106
105
|
"shell-quote": "^1.8.3",
|
|
107
|
-
"simple-git": "^3.
|
|
106
|
+
"simple-git": "^3.33.0",
|
|
108
107
|
"sloc": "^0.3.2",
|
|
109
108
|
"superstruct": "^2.0.2",
|
|
110
109
|
"tmp": "^0.2.5",
|
|
111
110
|
"toml": "^3.0.0",
|
|
111
|
+
"yaml": "^2.8.2",
|
|
112
112
|
"zx": "^8.8.5"
|
|
113
113
|
},
|
|
114
114
|
"devDependencies": {
|
|
115
115
|
"@leverege/eslint-config-leverege": "^5.1.2",
|
|
116
116
|
"chai": "^6.2.2",
|
|
117
117
|
"mocha": "^11.7.5",
|
|
118
|
-
"npm": "^11.
|
|
118
|
+
"npm": "^11.11.1"
|
|
119
119
|
}
|
|
120
120
|
}
|
package/src/Utils.mjs
CHANGED
|
@@ -10,6 +10,7 @@ import { glob } from 'glob'
|
|
|
10
10
|
import { packageUp } from 'package-up'
|
|
11
11
|
import { parse } from 'shell-quote'
|
|
12
12
|
import toml from 'toml'
|
|
13
|
+
import semver from 'semver'
|
|
13
14
|
import YAML from 'js-yaml'
|
|
14
15
|
|
|
15
16
|
// __dirname goes away with ESM so we take this approach instead and
|
|
@@ -530,7 +531,8 @@ export const parseHelmChart = async ( helmroot = './helm' ) => {
|
|
|
530
531
|
const chartLibrary = chartYaml?.type === 'library'
|
|
531
532
|
const chartVersion = chartYaml.version
|
|
532
533
|
const chartPackage = `${chartName}-${chartVersion}.tgz`
|
|
533
|
-
const
|
|
534
|
+
const valuesText = fs.readFileSync( `${helmroot}/values.yaml`, 'utf8' )
|
|
535
|
+
const valuesYaml = YAML.load( valuesText )
|
|
534
536
|
debug( valuesYaml, '<== helm/values.yaml' )
|
|
535
537
|
if ( !valuesYaml.image ) {
|
|
536
538
|
errorExit( 'Error: legacy helm chart detected - must upgrade to latest ignition template to proceed' )
|
|
@@ -543,15 +545,14 @@ export const parseHelmChart = async ( helmroot = './helm' ) => {
|
|
|
543
545
|
let depsOutOfSync = hasDependencies // assume unsynced if dependencies
|
|
544
546
|
if ( chartFiles.includes( 'Chart.lock' ) ) {
|
|
545
547
|
const chartLock = YAML.load( fs.readFileSync( `${helmroot}/Chart.lock`, 'utf8' ) )
|
|
546
|
-
|
|
547
|
-
const chartDeps = Object.fromEntries(
|
|
548
|
-
chartYaml.dependencies.map( d => [ d.name, d.version ] )
|
|
549
|
-
)
|
|
548
|
+
|
|
550
549
|
const lockDeps = Object.fromEntries(
|
|
551
550
|
chartLock.dependencies.map( d => [ d.name, d.version ] )
|
|
552
551
|
)
|
|
553
|
-
|
|
554
|
-
|
|
552
|
+
|
|
553
|
+
const mismatches = chartYaml.dependencies.filter( ( { name, version } ) => {
|
|
554
|
+
const lockedVersion = lockDeps[name]
|
|
555
|
+
return !lockedVersion || !semver.satisfies( lockedVersion, version )
|
|
555
556
|
} )
|
|
556
557
|
|
|
557
558
|
depsOutOfSync = mismatches.length > 0
|
|
@@ -572,6 +573,7 @@ export const parseHelmChart = async ( helmroot = './helm' ) => {
|
|
|
572
573
|
files : chartFiles,
|
|
573
574
|
Chart : chartYaml,
|
|
574
575
|
Values : valuesYaml,
|
|
576
|
+
valuesText, // in case we need to preserve formatting or comments for pushing to registry
|
|
575
577
|
yaml : { // DEPRECATED
|
|
576
578
|
'Chart.yaml' : chartYaml,
|
|
577
579
|
'values.yaml' : valuesYaml,
|
package/src/chart-to-museum.mjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
// *** DEPRECATED: this goes away when we move away from the chart museum and
|
|
3
|
+
// push-my-chart already handles this a artifact pushes
|
|
4
|
+
//
|
|
3
5
|
import chalk from 'chalk'
|
|
4
6
|
import commandLineArgs from 'command-line-args'
|
|
5
7
|
import commandLineUsage from 'command-line-usage'
|
|
@@ -8,7 +8,7 @@ showInstalling "The Prometheus Operator (kube-prometheus-stack)"
|
|
|
8
8
|
|
|
9
9
|
# https://artifacthub.io/packages/helm/prometheus-community/kube-prometheus-stack
|
|
10
10
|
OCI_CHART="oci://ghcr.io/prometheus-community/charts/kube-prometheus-stack"
|
|
11
|
-
[ -z "$PROMETHEUS_STACK_CHART_VERSION" ] && PROMETHEUS_STACK_CHART_VERSION="82.
|
|
11
|
+
[ -z "$PROMETHEUS_STACK_CHART_VERSION" ] && PROMETHEUS_STACK_CHART_VERSION="82.10.3"
|
|
12
12
|
helm upgrade $NS --install prometheus-stack $OCI_CHART \
|
|
13
13
|
--values prom-operator/prometheus-stack.yaml \
|
|
14
14
|
--version $PROMETHEUS_STACK_CHART_VERSION $HELM_WHAT
|
|
@@ -146,7 +146,7 @@ extraManifests:
|
|
|
146
146
|
- websecure
|
|
147
147
|
routes:
|
|
148
148
|
- kind: Rule
|
|
149
|
-
match: Host(`${
|
|
149
|
+
match: Host(`${PROJECT_NAME}-prometheus.${HOST}.com`)
|
|
150
150
|
middlewares:
|
|
151
151
|
- name: basic-auth
|
|
152
152
|
services:
|
|
@@ -224,7 +224,7 @@ alertmanager:
|
|
|
224
224
|
slack_configs:
|
|
225
225
|
- channel: "${SLACK_CHANNEL}"
|
|
226
226
|
api_url: "${SLACK_HOOK_URL}"
|
|
227
|
-
username: "${
|
|
227
|
+
username: "${PROJECT_NAME}"
|
|
228
228
|
send_resolved: true
|
|
229
229
|
title: '{{ .CommonLabels.alertname }} alert'
|
|
230
230
|
title_link: '#'
|
|
@@ -261,7 +261,7 @@ alertmanager:
|
|
|
261
261
|
{{- end }}
|
|
262
262
|
|
|
263
263
|
{{- if .Labels.pod }}
|
|
264
|
-
*Pod Link:* *<https://console.cloud.google.com/kubernetes/pod/${GCE_REGION}/${CLUSTER_NAME}/{{ .Labels.namespace }}/{{ .Labels.pod }}?project=${
|
|
264
|
+
*Pod Link:* *<https://console.cloud.google.com/kubernetes/pod/${GCE_REGION}/${CLUSTER_NAME}/{{ .Labels.namespace }}/{{ .Labels.pod }}?project=${PROJECT_NAME}|`{{ .Labels.pod }}`>*
|
|
265
265
|
{{- end }}
|
|
266
266
|
|
|
267
267
|
*Status:* `{{ .Status }}` | *Severity:* `{{ .Labels.severity }}` {{- if .Labels.container }} *Container:* `{{ .Labels.container }}` {{- end }}
|
|
@@ -18,7 +18,7 @@ primary:
|
|
|
18
18
|
replicaCount: 1
|
|
19
19
|
|
|
20
20
|
# https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15
|
|
21
|
-
resourcesPreset: "
|
|
21
|
+
resourcesPreset: "medium"
|
|
22
22
|
# resources:
|
|
23
23
|
# requests:
|
|
24
24
|
# cpu: 250m
|
|
@@ -54,7 +54,7 @@ replica:
|
|
|
54
54
|
replicaCount: 1
|
|
55
55
|
|
|
56
56
|
# https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15
|
|
57
|
-
resourcesPreset: "
|
|
57
|
+
resourcesPreset: "medium"
|
|
58
58
|
# resources:
|
|
59
59
|
# requests:
|
|
60
60
|
# cpu: 250m
|
|
@@ -5,8 +5,8 @@ showInstalling "Velero Backup System"
|
|
|
5
5
|
# We use a specific version for the velero chart because we need to control
|
|
6
6
|
# the version of the locally installed velero client application.
|
|
7
7
|
#
|
|
8
|
-
VELERO_CHART_VERSION="11.
|
|
9
|
-
EXPECTED_CLIENT_VERSION="v1.
|
|
8
|
+
VELERO_CHART_VERSION="11.4.0"
|
|
9
|
+
EXPECTED_CLIENT_VERSION="v1.18.0"
|
|
10
10
|
|
|
11
11
|
addHelmRepo vmware-tanzu https://vmware-tanzu.github.io/helm-charts
|
|
12
12
|
|
package/src/helmup.sh
CHANGED
|
@@ -522,7 +522,6 @@ function getServiceAndChartInfo() {
|
|
|
522
522
|
CHARTVER="$(jq -r --arg svc "$SERVICE" '.[$svc].chart // empty' "$versions_file")"
|
|
523
523
|
[[ -n "$CHARTVER" ]] && FROM_VERSIONS=1
|
|
524
524
|
fi
|
|
525
|
-
|
|
526
525
|
return 0
|
|
527
526
|
}
|
|
528
527
|
|
|
@@ -687,6 +686,7 @@ REBOOTSTRAP
|
|
|
687
686
|
transponder-*)
|
|
688
687
|
# transponders use the same chart but different deployment name
|
|
689
688
|
[ ! -d $SERVICE ] && bootstrapLocalSetup $SERVICE
|
|
689
|
+
CHARTLOC="oci://us-docker.pkg.dev/leverege-registry/stack/charts/transponder" # always use art-reg
|
|
690
690
|
HELMUP="helm upgrade --install $SERVICE $CHARTLOC --values $SERVICE/values.yaml $CHARTVER $HELM_WHAT"
|
|
691
691
|
doHelmup "$HELMUP"
|
|
692
692
|
;;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
name: {{
|
|
2
|
-
version: {{
|
|
3
|
-
appVersion: {{
|
|
1
|
+
name: {{hbsChartName}}
|
|
2
|
+
version: {{hbsChartVersion}}
|
|
3
|
+
appVersion: {{hbsChartAppVersion}}
|
|
4
4
|
description: A leaf chart that depends on the Leverege base chart
|
|
5
5
|
apiVersion: v2
|
|
6
6
|
icon: https://raw.githubusercontent.com/kubernetes/kubernetes/master/logo/logo.svg
|
|
7
7
|
dependencies:
|
|
8
8
|
- name: leverege
|
|
9
|
-
version: "^1.0.
|
|
9
|
+
version: "^1.0.1"
|
|
10
10
|
repository: "oci://us-docker.pkg.dev/leverege-registry/base-charts"
|
|
@@ -1,69 +1,159 @@
|
|
|
1
1
|
// Chartwright.mjs
|
|
2
|
+
/* eslint-disable security/detect-non-literal-fs-filename */
|
|
3
|
+
import fs from 'node:fs'
|
|
4
|
+
|
|
5
|
+
import chalk from 'chalk'
|
|
6
|
+
import Handlebars from 'handlebars'
|
|
7
|
+
import YAML from 'yaml'
|
|
8
|
+
|
|
2
9
|
import * as Utils from '../Utils.mjs'
|
|
3
10
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
11
|
+
// handlebar variables available in the templates:
|
|
12
|
+
const hbsContext = {
|
|
13
|
+
hbsChartName : '',
|
|
14
|
+
hbsChartVersion : '1.0.0',
|
|
15
|
+
hbsChartAppVersion : 'v1.0.0',
|
|
16
|
+
hbsArtifactRegistry : 'us-docker.pkg.dev/leverege-registry/FOOLDER/images',
|
|
17
|
+
hbsPartOf : '',
|
|
18
|
+
hbsServicePreemptible : true,
|
|
19
|
+
hbsRedisEnabled : true,
|
|
20
|
+
hbsAutoScalingEnabled : true
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const PRESERVE_SECTIONS = new Set( [
|
|
24
|
+
'config',
|
|
25
|
+
'resources',
|
|
26
|
+
'autoscaling',
|
|
27
|
+
'staticscaling',
|
|
28
|
+
'pdb',
|
|
29
|
+
'probes',
|
|
30
|
+
'redis',
|
|
31
|
+
] )
|
|
32
|
+
|
|
33
|
+
// Helper functions
|
|
34
|
+
const OBSOLETE_SECTIONS = [
|
|
35
|
+
'ingressRoute',
|
|
36
|
+
'loadbalancer',
|
|
37
|
+
'udploadbalancer',
|
|
38
|
+
'podAnnotations',
|
|
39
|
+
'workloadIdentity'
|
|
40
|
+
]
|
|
41
|
+
const warnDeprecatedSections = ( doc ) => {
|
|
42
|
+
let deprecationWarningShown = false
|
|
43
|
+
for ( const key of OBSOLETE_SECTIONS ) {
|
|
44
|
+
if ( !doc.has( key ) ) continue
|
|
45
|
+
Utils.log( `${chalk.yellow.bold( '⚠️ WARNING:' )} Deprecated values.yaml section detected => ${chalk.red.bold( key )}` )
|
|
46
|
+
deprecationWarningShown = true
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if ( deprecationWarningShown ) {
|
|
50
|
+
Utils.log( chalk.yellow(
|
|
51
|
+
'\nPlease remove any deprecated sections and migrate to the new configuration options as needed.'
|
|
52
|
+
) )
|
|
53
|
+
}
|
|
23
54
|
}
|
|
24
55
|
|
|
25
56
|
export class Chartwright {
|
|
26
|
-
constructor( {
|
|
27
|
-
this.
|
|
28
|
-
this.
|
|
29
|
-
this.debug = debug
|
|
57
|
+
constructor( { Container, debug = false } = {} ) {
|
|
58
|
+
this.Container = Container
|
|
59
|
+
this.helmTemplates = `${Utils.BUILD_TOOLS_ROOT}/init-my-chart/leaf-chart-templates`
|
|
60
|
+
this.debug = debug
|
|
61
|
+
this.templates = {}
|
|
62
|
+
}
|
|
30
63
|
|
|
31
|
-
|
|
32
|
-
|
|
64
|
+
// This function takes a Handlebars template string and a context object,
|
|
65
|
+
// renders the template with the context, and parses the result as YAML,
|
|
66
|
+
// returning the resulting object.
|
|
67
|
+
async renderHbsTemplate( hbsTemplateFileName, context ) {
|
|
68
|
+
// TODO: better error handling here - if the template file doesn't exist,
|
|
69
|
+
// or if the rendered template isn't valid YAML, we should handle those
|
|
70
|
+
// errors gracefully and provide useful error messages.
|
|
71
|
+
const hbsTemplate = fs.readFileSync( hbsTemplateFileName, 'utf8' )
|
|
72
|
+
const compiled = Handlebars.compile( hbsTemplate )
|
|
73
|
+
const rendered = compiled( context )
|
|
74
|
+
return rendered
|
|
33
75
|
}
|
|
34
76
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
this.
|
|
38
|
-
|
|
77
|
+
// Load the handlebars templates for Chart.yaml and values.yaml into memory.
|
|
78
|
+
async loadTemplates() {
|
|
79
|
+
this.templates.Chart = await this.renderHbsTemplate( `${Utils.BUILD_TOOLS_ROOT}/init-my-chart/Chart.yaml.hbs`, hbsContext )
|
|
80
|
+
this.templates.Values = await this.renderHbsTemplate( `${Utils.BUILD_TOOLS_ROOT}/init-my-chart/values.yaml.hbs`, hbsContext )
|
|
39
81
|
}
|
|
40
82
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
83
|
+
// Adds missing top-level keys from base into existing WITHOUT overwriting.
|
|
84
|
+
// IMPORTANT: skips PRESERVE_SECTIONS here; those are handled separately.
|
|
85
|
+
mergeTopLevelAddMissing( baseDoc, existingDoc ) {
|
|
86
|
+
const baseRoot = baseDoc.contents
|
|
87
|
+
const existingRoot = existingDoc.contents
|
|
88
|
+
|
|
89
|
+
if ( !YAML.isMap( baseRoot ) || !YAML.isMap( existingRoot ) ) return
|
|
90
|
+
|
|
91
|
+
for ( const pair of baseRoot.items ) {
|
|
92
|
+
const key = pair.key?.value ?? pair.key
|
|
93
|
+
if ( PRESERVE_SECTIONS.has( key ) ) continue
|
|
94
|
+
|
|
95
|
+
if ( !existingRoot.has( key ) ) {
|
|
96
|
+
// Push the whole Pair node to preserve comments attached to it
|
|
97
|
+
existingRoot.items.push( pair )
|
|
98
|
+
}
|
|
46
99
|
}
|
|
47
100
|
}
|
|
48
101
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
102
|
+
// Preserve sections: if existing has it, keep it untouched.
|
|
103
|
+
// If existing is missing it and base has it, copy it in (with comments).
|
|
104
|
+
applyPreserveSections( baseDoc, existingDoc ) {
|
|
105
|
+
for ( const key of PRESERVE_SECTIONS ) {
|
|
106
|
+
const existingNode = existingDoc.get( key, true )
|
|
107
|
+
if ( existingNode ) continue // keep existing exactly
|
|
52
108
|
|
|
53
|
-
|
|
54
|
-
|
|
109
|
+
const baseNode = baseDoc.get( key, true )
|
|
110
|
+
if ( baseNode ) {
|
|
111
|
+
existingDoc.set( key, baseNode ) // brings comments from base node
|
|
112
|
+
}
|
|
113
|
+
}
|
|
55
114
|
}
|
|
56
115
|
|
|
57
|
-
|
|
58
|
-
|
|
116
|
+
// Bootstraps a helm chart layout by copying the template structure and rendering the
|
|
117
|
+
// main files with the provided context. Optionally can suppress writing values.yaml
|
|
118
|
+
// if the intention is to preserve an existing one.
|
|
119
|
+
async bootstrap( { Container, suppressValues = false } ) {
|
|
120
|
+
// load the templates and render them with the context to get the initial
|
|
121
|
+
// Chart.yaml and values.yaml content
|
|
122
|
+
await this.loadTemplates()
|
|
123
|
+
|
|
124
|
+
// replicate the chart structure from the templates directory
|
|
125
|
+
fs.mkdirSync( 'helm' )
|
|
126
|
+
fs.cpSync( `${Utils.BUILD_TOOLS_ROOT}/init-my-chart/leaf-chart-templates`, 'helm', { recursive : true } )
|
|
127
|
+
fs.writeFileSync( 'helm/Chart.yaml', this.templates.Chart )
|
|
128
|
+
if ( !suppressValues ) {
|
|
129
|
+
fs.writeFileSync( 'helm/values.yaml', this.templates.Values )
|
|
130
|
+
}
|
|
59
131
|
}
|
|
60
132
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
133
|
+
// Scribes the new chart by bootstrapping the structure and then merging the existing
|
|
134
|
+
// values.yaml with the new template, preserving existing values and comments where possible.
|
|
135
|
+
// This allows us to update the chart structure and add any new configuration options without
|
|
136
|
+
// overwriting user customizations in values.yaml.
|
|
137
|
+
async scribe( { Container, Chart, Values, ValuesText, Registry } ) {
|
|
138
|
+
hbsContext.hbsChartName = Container
|
|
139
|
+
hbsContext.hbsChartVersion = Chart.version
|
|
140
|
+
hbsContext.hbsChartAppVersion = Chart.appVersion
|
|
141
|
+
hbsContext.hbsArtifactRegistry = Registry
|
|
142
|
+
hbsContext.hbsPartOf = Values.partOf
|
|
143
|
+
await this.bootstrap( { Container, suppressValues : true } )
|
|
144
|
+
|
|
145
|
+
// Now we need to smart merge the values.yaml template while preserving existing sections
|
|
146
|
+
const baseValuesDoc = YAML.parseDocument( this.templates.Values )
|
|
147
|
+
const existingValuesDoc = YAML.parseDocument( ValuesText )
|
|
148
|
+
// warn about obsolete sections
|
|
149
|
+
warnDeprecatedSections( existingValuesDoc )
|
|
150
|
+
|
|
151
|
+
// Merge legacy values.yaml with new base, preserving formatting and comments
|
|
152
|
+
this.mergeTopLevelAddMissing( baseValuesDoc, existingValuesDoc )
|
|
153
|
+
this.applyPreserveSections( baseValuesDoc, existingValuesDoc )
|
|
154
|
+
|
|
155
|
+
// Final write of the merged values.yaml, preserving formatting and comments as much as possible
|
|
156
|
+
fs.writeFileSync( 'helm/values.yaml', existingValuesDoc.toString( { lineWidth : 0, doubleQuotedAsJSON : true } ) )
|
|
68
157
|
}
|
|
69
|
-
|
|
158
|
+
|
|
159
|
+
}
|
|
@@ -2,16 +2,13 @@
|
|
|
2
2
|
/* eslint-disable security/detect-non-literal-fs-filename */
|
|
3
3
|
|
|
4
4
|
import fs from 'node:fs'
|
|
5
|
-
import path from 'node:path'
|
|
6
5
|
|
|
7
6
|
import { program } from 'commander'
|
|
8
7
|
import chalk from 'chalk'
|
|
9
|
-
import handlebars from 'handlebars'
|
|
10
8
|
|
|
11
9
|
import {
|
|
12
10
|
analyzeRepository,
|
|
13
11
|
condir,
|
|
14
|
-
debug,
|
|
15
12
|
enableDebug,
|
|
16
13
|
errorExit,
|
|
17
14
|
log,
|
|
@@ -27,54 +24,52 @@ program
|
|
|
27
24
|
.parse()
|
|
28
25
|
|
|
29
26
|
const options = program.opts()
|
|
30
|
-
|
|
27
|
+
if ( options.debug ) {
|
|
28
|
+
enableDebug() // enables debugging in the Utils functions
|
|
29
|
+
}
|
|
31
30
|
|
|
32
31
|
const repo = await analyzeRepository()
|
|
33
|
-
|
|
34
32
|
if ( !repo.isGitRepo ) {
|
|
35
33
|
errorExit( '***ERROR: This command must be run inside a git repository - run "git init" to proceed' )
|
|
36
34
|
}
|
|
35
|
+
const Container = repo.containerName
|
|
36
|
+
const chartwright = new Chartwright( { Container, debug : options.debug } )
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
// If there isn't an existing helm chart then we just bootstrap the new chart structure
|
|
39
|
+
// from the current helm template and we're done. This will most likely be the case after
|
|
40
|
+
// a new service has been bootstrapped with ignition.
|
|
42
41
|
if ( !repo.helmChart ) {
|
|
43
|
-
|
|
44
|
-
process.exit(
|
|
42
|
+
await chartwright.bootstrap( { Container } )
|
|
43
|
+
process.exit( 0 )
|
|
45
44
|
}
|
|
46
45
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if ( fs.existsSync( `${
|
|
46
|
+
// Safety First: if there is already an older helm chart, we don't want to overwrite it - we
|
|
47
|
+
// want the user to review / intervene before proceeding.
|
|
48
|
+
const packageRoot = repo.currentDir
|
|
49
|
+
if ( fs.existsSync( `${packageRoot}/helm-old` ) ) {
|
|
51
50
|
errorExit( '***ERROR: An old helm chart structure already exists - cannot proceed' )
|
|
52
51
|
}
|
|
53
52
|
|
|
54
53
|
let movedOldHelm = false
|
|
55
|
-
if ( fs.existsSync( `${
|
|
56
|
-
fs.renameSync( `${
|
|
54
|
+
if ( fs.existsSync( `${packageRoot}/helm` ) && !options.dryRun ) {
|
|
55
|
+
fs.renameSync( `${packageRoot}/helm`, `${packageRoot}/helm-old` )
|
|
57
56
|
movedOldHelm = true
|
|
58
57
|
}
|
|
59
58
|
|
|
60
|
-
|
|
59
|
+
const {
|
|
60
|
+
Chart,
|
|
61
|
+
Values,
|
|
62
|
+
valuesText : ValuesText,
|
|
63
|
+
imageRegistry : Registry,
|
|
64
|
+
} = repo.helmChart
|
|
61
65
|
|
|
62
66
|
if ( options.dryRun ) {
|
|
63
|
-
condir( { Chart, Values,
|
|
64
|
-
condir( { chartOutput, valuesOutput }, chalk.green( '=== Generated Helm Chart Outputs ===' ) )
|
|
65
|
-
chartwright.dump()
|
|
66
|
-
log( { chartOutput }, chalk.green( '=== Chart.yaml ===' ) )
|
|
67
|
-
log( { valuesOutput }, chalk.green( '=== values.yaml ===' ) )
|
|
67
|
+
condir( { repo, Container, Chart, Values, ValuesText, Registry }, chalk.green( '<== Dry Run Mode - No Changes Made' ) )
|
|
68
68
|
process.exit( 0 )
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
// going in - I want to focus on the transformation of the existing chart to
|
|
73
|
-
// the new structure, and less on the templating aspect. The templating can be
|
|
74
|
-
// a secondary step that we add after we have the transformation working. For
|
|
75
|
-
// now, I will focus on the analysis and transformation of the existing chart,
|
|
76
|
-
// and then we can add the templating aspect later.
|
|
71
|
+
await chartwright.scribe( { Container, Chart, Values, ValuesText, Registry } )
|
|
77
72
|
|
|
78
73
|
if ( movedOldHelm ) {
|
|
79
|
-
log( chalk.yellow( '
|
|
74
|
+
log( chalk.yellow( '\nAn existing helm chart was detected and moved to helm-old. Please review and migrate any customizations as needed.' ) )
|
|
80
75
|
}
|