@leverege/build-tools 2.94.0 → 2.95.0

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.
Files changed (87) hide show
  1. package/.vscode/launch.json +14 -0
  2. package/package.json +5 -2
  3. package/src/Docker.mjs +3 -2
  4. package/src/Utils.mjs +53 -6
  5. package/src/artifacts/Utils.mjs +1 -1
  6. package/src/bash-funcs +1 -1
  7. package/src/git-tar.sh +1 -1
  8. package/src/helm-charts/emailer/values-local.yaml +1 -8
  9. package/src/helm-charts/prom-operator/helmup.plugin +1 -1
  10. package/src/helm-charts/traefik/helmup.plugin +1 -1
  11. package/src/helm-charts/velero/README.md +135 -0
  12. package/src/helm-charts/velero/helmup.bootstrap +1 -0
  13. package/src/helm-charts/velero/helmup.plugin +29 -2
  14. package/src/helm-charts/velero/values-local.yaml +1 -1
  15. package/src/helmup.sh +49 -41
  16. package/src/service-man/ServiceMan.mjs +75 -0
  17. package/src/service-man/config/CommandLine.mjs +199 -0
  18. package/src/service-man/config/Config.mjs +203 -0
  19. package/src/service-man/config/VersionCheck.mjs +79 -0
  20. package/src/service-man/config/iam-roles/leveregeBigQueryReader.json +10 -0
  21. package/src/service-man/config/iam-roles/leveregeBigQueryWriter.json +13 -0
  22. package/src/service-man/config/iam-roles/leveregeCloudFunctionsManager.json +12 -0
  23. package/src/service-man/config/iam-roles/leveregeFirebaseHosting.json +9 -0
  24. package/src/service-man/config/iam-roles/leveregeFirebaseMessaging.json +13 -0
  25. package/src/service-man/config/iam-roles/leveregeFirebaseUpdates.json +10 -0
  26. package/src/service-man/config/iam-roles/leveregeLogsViewer.json +8 -0
  27. package/src/service-man/config/iam-roles/leveregePubSub.json +13 -0
  28. package/src/service-man/config/iam-roles/leveregeSecretsViewer.json +9 -0
  29. package/src/service-man/config/iam-roles/leveregeStorageObjectAdmin.json +21 -0
  30. package/src/service-man/config/iam-roles/leveregeStorageObjectReader.json +13 -0
  31. package/src/service-man/config/iam-roles/leveregeSvcAcctActor.json +8 -0
  32. package/src/service-man/config/iam-roles/leveregeSvcAcctTokenCreator.json +8 -0
  33. package/src/service-man/config/index.mjs +7 -0
  34. package/src/service-man/config/secrets/authz-jwt.json +6 -0
  35. package/src/service-man/config/secrets/authz-postgres.json +7 -0
  36. package/src/service-man/config/secrets/db-timescale-dense.json +8 -0
  37. package/src/service-man/config/secrets/jwt-options.json +7 -0
  38. package/src/service-man/config/secrets/mail-gun-api-key.json +6 -0
  39. package/src/service-man/config/secrets/npmrc.json +6 -0
  40. package/src/service-man/config/secrets/oidc-client-secret.json +6 -0
  41. package/src/service-man/config/secrets/postgresql-password.json +8 -0
  42. package/src/service-man/config/secrets/session-secret.json +6 -0
  43. package/src/service-man/config/secrets/twilio.json +8 -0
  44. package/src/service-man/config/service-accounts/api-server.json +12 -0
  45. package/src/service-man/config/service-accounts/authz-server.json +5 -0
  46. package/src/service-man/config/service-accounts/db-curator.json +8 -0
  47. package/src/service-man/config/service-accounts/emailer.json +7 -0
  48. package/src/service-man/config/service-accounts/fota-server.json +6 -0
  49. package/src/service-man/config/service-accounts/geotile-server.json +8 -0
  50. package/src/service-man/config/service-accounts/imagine.json +6 -0
  51. package/src/service-man/config/service-accounts/message-processor.json +6 -0
  52. package/src/service-man/config/service-accounts/messenger.json +7 -0
  53. package/src/service-man/config/service-accounts/pubsub-pulse.json +6 -0
  54. package/src/service-man/config/service-accounts/push-notifier.json +8 -0
  55. package/src/service-man/config/service-accounts/reason.json +5 -0
  56. package/src/service-man/config/service-accounts/resource-server.json +9 -0
  57. package/src/service-man/config/service-accounts/rule-engine.json +7 -0
  58. package/src/service-man/config/service-accounts/scheduler.json +6 -0
  59. package/src/service-man/config/service-accounts/transponder.json +15 -0
  60. package/src/service-man/gcloud-k8s/RolesManager.mjs +41 -0
  61. package/src/service-man/gcloud-k8s/SecretsManager.mjs +182 -0
  62. package/src/service-man/gcloud-k8s/ServiceAccountManager.mjs +246 -0
  63. package/src/service-man/gcloud-k8s/VersionManager.mjs +114 -0
  64. package/src/service-man/gcloud-k8s/index.mjs +11 -0
  65. package/src/service-man/service-man.mjs +18 -0
  66. package/src/service-man/utils/index.mjs +83 -0
  67. package/leverege-build-tools-2.21.13.tgz +0 -0
  68. package/lib/server/build-tools.js +0 -138
  69. package/lib/server/firebaseDeploy.js +0 -195
  70. package/lib/server/firebaseServe.js +0 -116
  71. package/lib/server/getfbcfg.js +0 -25
  72. package/lib/server/getjson.js +0 -70
  73. package/lib/server/overwhelm.js +0 -447
  74. package/lib/server/push-my-chart.js +0 -18
  75. package/lib/server/refresh-npm-token.js +0 -135
  76. package/lib/server/tag-release.js +0 -681
  77. package/lib/server/unleash.js +0 -50
  78. package/lib/web/build-tools.js +0 -138
  79. package/lib/web/firebaseDeploy.js +0 -195
  80. package/lib/web/firebaseServe.js +0 -116
  81. package/lib/web/getfbcfg.js +0 -25
  82. package/lib/web/getjson.js +0 -70
  83. package/lib/web/overwhelm.js +0 -447
  84. package/lib/web/push-my-chart.js +0 -18
  85. package/lib/web/refresh-npm-token.js +0 -135
  86. package/lib/web/tag-release.js +0 -681
  87. package/lib/web/unleash.js +0 -50
@@ -17,6 +17,20 @@
17
17
  "env": {
18
18
  },
19
19
  "outputCapture": "std"
20
+ },
21
+ {
22
+ "name": "service-man (launch)",
23
+ "type": "node",
24
+ "request": "launch",
25
+ "program": "${workspaceFolder}/src/service-man/service-man.mjs",
26
+ "args": ["--dump-configs","dbg-cfgs"],
27
+ "cwd": "/Users/john/Work/leverege/k8s/tst-builder",
28
+ "runtimeExecutable": "node",
29
+ "console": "integratedTerminal",
30
+ "skipFiles": ["<node_internals>/**"],
31
+ "env": {
32
+ "NODE_ENV": "development"
33
+ }
20
34
  }
21
35
  ]
22
36
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leverege/build-tools",
3
- "version": "2.94.0",
3
+ "version": "2.95.0",
4
4
  "description": "A collection of build / support tools for Leverege developers",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -40,6 +40,7 @@
40
40
  "getjson": "src/getjson.mjs",
41
41
  "git-tar": "src/git-tar.sh",
42
42
  "helm-audit": "src/helm-audit.mjs",
43
+ "helmboot": "src/helmup.sh",
43
44
  "helmcycle": "src/helmup.sh",
44
45
  "helmdn": "src/helmdn.sh",
45
46
  "helminit": "src/helmup.sh",
@@ -64,6 +65,7 @@
64
65
  "refresh-npm-token": "src/refresh-npm-token.mjs",
65
66
  "refresh-py-idx": "src/refresh-py-idx.sh",
66
67
  "send-to-slack": "src/send-to-slack.mjs",
68
+ "service-man": "src/service-man/service-man.mjs",
67
69
  "snapshot-cnpg": "src/snapshot-cnpg.mjs",
68
70
  "tag-release": "src/tag-release.mjs",
69
71
  "unleash": "src/unleash.mjs",
@@ -99,12 +101,13 @@
99
101
  "simple-git": "^3.30.0",
100
102
  "sloc": "^0.3.2",
101
103
  "superstruct": "^2.0.2",
104
+ "tmp": "^0.2.5",
102
105
  "toml": "^3.0.0",
103
106
  "zx": "^8.8.5"
104
107
  },
105
108
  "devDependencies": {
106
109
  "@leverege/eslint-config-leverege": "^5.1.1",
107
- "chai": "^6.2.1",
110
+ "chai": "^6.2.2",
108
111
  "mocha": "^11.7.5",
109
112
  "npm": "^11.7.0"
110
113
  }
package/src/Docker.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ /* eslint-disable security/detect-non-literal-fs-filename */
1
2
  import fs from 'node:fs'
2
3
  import path from 'node:path'
3
4
  import url from 'node:url'
@@ -23,7 +24,7 @@ const DIRNAME = path.dirname( url.fileURLToPath( import.meta.url ) )
23
24
  //
24
25
  // See the latest docker images here => https://hub.docker.com/_/node
25
26
  //
26
- const dockerfileNodeVersion = process.env.DOCKER_BUILD_NODE_VERSION || '22.21.1-alpine3.23' // TODO: 1/1/26 => '24.12.0-alpine3.23'
27
+ const dockerfileNodeVersion = process.env.DOCKER_BUILD_NODE_VERSION || '24.12.0-alpine3.23'
27
28
  const dockerfileNpmVersion = process.env.DOCKER_BUILD_NPM_VERSION || '11.6.0'
28
29
 
29
30
  // The contents of these variables were initially located in files that live in
@@ -83,7 +84,7 @@ const generateDockerfile = async ( options ) => {
83
84
  const gitReference = await shellCmd( 'git rev-parse --short HEAD' )
84
85
  const settings = { gitReference, ...defaultSettings, ...options }
85
86
  const dockerTemplate = options.isNodeJsProject ? 'dockerfileTemplateNodeJs' : 'dockerfileTemplatePython'
86
- const dockerfileTemplate = fs.readFileSync( path.join( DIRNAME, `./templates/${dockerTemplate}.hbs` ), 'utf8' ) // eslint-disable-line security/detect-non-literal-fs-filename
87
+ const dockerfileTemplate = fs.readFileSync( path.join( DIRNAME, `./templates/${dockerTemplate}.hbs` ), 'utf8' )
87
88
 
88
89
  // defaults to the current "official" version of node unless it gets
89
90
  // overridden in the leverege.nodeimg package.json stanza
package/src/Utils.mjs CHANGED
@@ -39,11 +39,42 @@ export const warning = ( warningText ) => {
39
39
  console.error( `\n${chalk.yellow.bold( fullWarning )}` )
40
40
  }
41
41
 
42
- export const errorExit = ( error, opts = {} ) => {
43
- const { errorCode = 1 } = opts
44
- console.error( `\n${chalk.red.bold( error )}\n` )
45
- process.exit( errorCode )
42
+ export const errorExit = ( arg, opts = {} ) => {
43
+ const exitCode =
44
+ typeof opts.exitCode === 'number' ? opts.exitCode :
45
+ ( arg && typeof arg.exitCode === 'number' ) ? arg.exitCode : 1
46
+
47
+ // lets figure out what to print
48
+ let message
49
+ let details
50
+
51
+ if ( arg instanceof Error ) {
52
+ message = arg.message || 'Error'
53
+ details = arg.stack
54
+ } else if ( typeof arg === 'string' ) {
55
+ message = arg
56
+ } else if ( arg && typeof arg === 'object' ) {
57
+ message = 'Error'
58
+ details = JSON.stringify( arg, null, 2 )
59
+ } else if ( arg != null ) {
60
+ message = String( arg )
61
+ }
62
+
63
+ console.error( `\n${chalk.red.bold( message )}\n` )
64
+ if ( details && details !== message ) {
65
+ console.error( `${details}\n` )
66
+ }
67
+
68
+ process.exit( exitCode )
69
+ }
70
+
71
+ /**
72
+ * Clears the screen and optionally homes the cursor.
73
+ */
74
+ export const clear = ( home = true ) => {
75
+ log( `${home ? '\x1B[0f' : ''}\x1B[2J` )
46
76
  }
77
+
47
78
  /* eslint-enable no-console */
48
79
 
49
80
  export const isHex = ( hex ) => {
@@ -54,6 +85,22 @@ export const isString = ( s ) => {
54
85
  return typeof s === 'string' || s instanceof String
55
86
  }
56
87
 
88
+ /**
89
+ * * Sets first char to Upper
90
+ * */
91
+ export const capitalize = ( norm ) => {
92
+ return norm.charAt( 0 ).toUpperCase() + norm.slice( 1 )
93
+ }
94
+
95
+ /**
96
+ * A simple mS sleep delay.
97
+ */
98
+ export const sleep = ( ms = 0 ) => {
99
+ return new Promise( ( resolve ) => {
100
+ setTimeout( resolve, ms )
101
+ } )
102
+ }
103
+
57
104
  /**
58
105
  * General "yes" to proceed function.
59
106
  */
@@ -226,7 +273,7 @@ export const gitRepoIsDirty = async () => {
226
273
 
227
274
  export const parseYamlFile = async ( filePath ) => {
228
275
  try {
229
- const fileContent = await fs.promises.readFile( filePath, 'utf8' )
276
+ const fileContent = await fs.promises.readFile( filePath, 'utf8' ) /* eslint-disable-line security/detect-non-literal-fs-filename */
230
277
  return YAML.load( fileContent )
231
278
  } catch ( error ) {
232
279
  throw new Error( `Failed to parse YAML file ${filePath}: ${error.message}` )
@@ -538,7 +585,7 @@ export const getRepositoryDescr = async () => {
538
585
  const helmChart = await parseHelmChart()
539
586
  const rootPackageJson = await parseJsonFile( `${gitRoot}/package.json` )
540
587
  const rootPyProjectToml = await parsePyProjectToml( `${gitRoot}/pyproject.toml` )
541
- const isYarnProject = fs.existsSync( path.join( gitRoot, 'yarn.lock' ) ) || fs.existsSync( path.join( gitRoot, '.yarn' ) )
588
+ const isYarnProject = fs.existsSync( path.join( gitRoot, 'yarn.lock' ) ) || fs.existsSync( path.join( gitRoot, '.yarn' ) ) /* eslint-disable-line security/detect-non-literal-fs-filename */
542
589
 
543
590
  return {
544
591
  currentDir : process.cwd(),
@@ -1,6 +1,6 @@
1
1
  import fs from 'node:fs'
2
2
  import path from 'node:path'
3
- import crypto from 'crypto'
3
+ import crypto from 'node:crypto'
4
4
 
5
5
  import { validate } from 'superstruct'
6
6
 
package/src/bash-funcs CHANGED
@@ -322,4 +322,4 @@ function commandChecker() {
322
322
  done
323
323
  }
324
324
 
325
- commandChecker git helm kubectl service-man
325
+ commandChecker git helm jq kubectl service-man
package/src/git-tar.sh CHANGED
@@ -3,7 +3,7 @@
3
3
  # Load the standard helper functions
4
4
  . `build-tools --bashfun`
5
5
 
6
- # If it isn't already set use the default ~/work/.gitar
6
+ # If it isn't already set use the default ~/.gitar
7
7
  #
8
8
  [ -z $GITAR ] && GITAR="${HOME}/.gitar"
9
9
 
@@ -1,12 +1,5 @@
1
1
  image:
2
- tag: # v3.7.0
2
+ tag: # v5.1.0
3
3
 
4
4
  config:
5
5
  LOG_CONFIG: '{"type":"pino","level":"warn"}'
6
-
7
- API_UI_URL: "${PROJECT_ID}.web.app"
8
- MAIL_GUN_DOMAIN: "${MAIL_GUN_DOMAIN}"
9
- MAIL_GUN_DEFAULT_SENDER: "no-reply@${MAIL_GUN_DOMAIN}"
10
-
11
- serviceMonitor:
12
- enabled: true
@@ -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="80.4.1"
11
+ [ -z "$PROMETHEUS_STACK_CHART_VERSION" ] && PROMETHEUS_STACK_CHART_VERSION="80.11.0"
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
@@ -17,7 +17,7 @@ TRAEFIK_NAMESPACE="traefik"
17
17
 
18
18
  addHelmRepo traefik https://helm.traefik.io/traefik
19
19
 
20
- [ -z "$TRAEFIK_CHART_VERSION" ] && TRAEFIK_CHART_VERSION="37"
20
+ [ -z "$TRAEFIK_CHART_VERSION" ] && TRAEFIK_CHART_VERSION="38"
21
21
  helm upgrade --install traefik traefik/traefik \
22
22
  --namespace $TRAEFIK_NAMESPACE --create-namespace \
23
23
  --values traefik/values.yaml \
@@ -0,0 +1,135 @@
1
+ # Velero Deployment Notes
2
+
3
+ ## Why this document exists
4
+
5
+ This document explains **why we had to change the Velero deployment process** and how we now safely manage **CRDs and Helm upgrades** without relying on Bitnami images or brittle Helm hook jobs.
6
+
7
+ These changes were driven by:
8
+ - Removal / breakage of Bitnami `kubectl` images referenced by the `vmware-tanzu/velero` Helm chart
9
+ - Broadcom’s changes to Bitnami image access and licensing
10
+ - The need for **deterministic, version-safe CRD management** on new and existing GKE clusters
11
+
12
+ ---
13
+
14
+ ## Background: What broke
15
+
16
+ The Velero Helm chart (`vmware-tanzu/velero` >= 11.x) includes a Helm **hook job** that attempts to install or upgrade CRDs using an initContainer based on:
17
+
18
+ ```
19
+ docker.io/bitnamilegacy/kubectl:<k8s-version>
20
+ ```
21
+
22
+ On Kubernetes 1.34+ clusters, this image **no longer exists**, causing installs to fail with errors such as:
23
+
24
+ ```
25
+ ErrImagePull: bitnamilegacy/kubectl:1.34 not found
26
+ ```
27
+
28
+ Attempts to substitute other kubectl images failed due to hard assumptions in the hook job (e.g. `/tmp/sh`, shell paths, filesystem layout).
29
+
30
+ Because this hook runs **before Helm considers the release successful**, it blocks both fresh installs and upgrades.
31
+
32
+ ---
33
+
34
+ ## Why we disabled Helm-based CRD upgrades
35
+
36
+ Helm does not natively manage CRD upgrades well:
37
+ - CRDs in `crds/` directories are only installed once
38
+ - Schema upgrades require hooks or out-of-band logic
39
+ - Hook jobs are fragile and opaque when they fail
40
+
41
+ The Velero chart’s CRD hook job is effectively doing:
42
+
43
+ ```
44
+ velero install --crds-only | kubectl apply
45
+ ```
46
+
47
+ …but wrapped in a container that is now broken due to image dependencies.
48
+
49
+ **Conclusion:** We disable the Helm CRD hook entirely and manage CRDs explicitly.
50
+
51
+ ---
52
+
53
+ ## Our current approach (high-level)
54
+
55
+ 1. **CRDs are managed explicitly**, outside Helm
56
+ 2. **CRDs are generated from the exact Velero version being deployed**
57
+ 3. Helm is used only for deploying/upgrading the Velero controller and configuration
58
+ 4. Helm CRD hooks are disabled (`upgradeCRDs=false`)
59
+
60
+ This makes installs:
61
+ - Reproducible
62
+ - Debuggable
63
+ - Independent of third-party image publishing decisions
64
+
65
+ ---
66
+
67
+ ## Version alignment is critical
68
+
69
+ The command:
70
+
71
+ ```bash
72
+ velero install --crds-only --dry-run -o yaml
73
+ ```
74
+
75
+ **uses the local `velero` CLI version** to generate CRDs.
76
+
77
+ If the CLI version does not match the Velero server version deployed by Helm, you can:
78
+ - Apply incompatible CRD schemas
79
+ - Introduce validation failures on existing custom resources
80
+
81
+ ### Our safeguard
82
+
83
+ `helmup.plugin` now:
84
+ - Reads the chart `appVersion` directly from Helm
85
+ - Verifies the local `velero` CLI version matches exactly
86
+ - Fails fast if versions are mismatched
87
+
88
+ This guarantees CRDs and controllers stay in lockstep.
89
+
90
+ ---
91
+
92
+ ## When CRDs are applied
93
+
94
+ CRDs are **not applied on every deploy**.
95
+
96
+ They are applied only when:
97
+ - Bootstrapping a new cluster
98
+ - Upgrading the Velero chart to a version with a new `appVersion`
99
+
100
+ This is controlled explicitly via:
101
+
102
+ ```bash
103
+ VELERO_APPLY_CRDS=1 helmup velero
104
+ ```
105
+
106
+ Normal configuration-only updates do **not** touch CRDs.
107
+
108
+ ---
109
+
110
+ ## Summary of changes
111
+
112
+ | Area | Old behavior | New behavior |
113
+ |-----|-------------|-------------|
114
+ | CRD management | Helm hook job | Explicit, pinned CRD apply |
115
+ | kubectl dependency | Bitnami legacy image | None |
116
+ | Version safety | Implicit | Enforced |
117
+ | Failure mode | Late, opaque | Early, explicit |
118
+ | New cluster installs | Unreliable | Deterministic |
119
+
120
+ ---
121
+
122
+ ## Key takeaways
123
+
124
+ - **CRDs are part of the API, not application config** — they must be versioned and applied intentionally
125
+ - Helm hooks are not a reliable mechanism for critical cluster-scoped resources
126
+ - Pinning tool versions eliminates an entire class of upgrade failures
127
+ - This approach aligns with GitOps and production-safe Kubernetes practices
128
+
129
+ ---
130
+
131
+ ## References
132
+
133
+ - Velero documentation: https://velero.io/docs/
134
+ - Velero Helm charts: https://github.com/vmware-tanzu/helm-charts
135
+ - Kubernetes CRD management: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/
@@ -4,6 +4,7 @@
4
4
  function installVeleroEnvironment() {
5
5
  # Follows instructions => https://github.com/vmware-tanzu/velero-plugin-for-gcp
6
6
  showInstalling "Velero Backup Management"
7
+
7
8
  createNamespaceIfNeeded velero
8
9
 
9
10
  # Do we need to => gcloud auth application-default
@@ -2,10 +2,36 @@
2
2
  #
3
3
  showInstalling "Velero Backup System"
4
4
 
5
+ # We use a specific version for the velero chart because we need to control
6
+ # the version of the locally installed velero client application.
7
+ #
8
+ VELERO_CHART_VERSION="11.3.1"
9
+ EXPECTED_CLIENT_VERSION="v1.17.1"
10
+
5
11
  addHelmRepo vmware-tanzu https://vmware-tanzu.github.io/helm-charts
6
12
 
7
- [ -z "$VELERO_CHART_VERSION" ] && VELERO_CHART_VERSION="11"
13
+ commandChecker velero # verify the velero client is installed
14
+
15
+ local client_version="$(velero version --client-only 2>/dev/null | awk -F': ' '/Version:/ {print $2; exit}')"
16
+
17
+ if [[ "$client_version" != "$EXPECTED_CLIENT_VERSION" ]]; then
18
+ cat<<WRONG_VELERO_APP_VERSION
19
+
20
+ ERROR: velero CLI version mismatch.
21
+ Expected: `color g "${EXPECTED_CLIENT_VERSION}"`
22
+ Found: `color r "${client_version}"`
23
+
24
+ Fix => `color y "install velero ${EXPECTED_CLIENT_VERSION}"`
25
+ WRONG_VELERO_APP_VERSION
26
+ exit 1
27
+ fi
28
+
29
+ # If the CRDs need to be updated set VELERO_APPLY_CRDS!
8
30
  #
31
+ if [[ "${VELERO_APPLY_CRDS:-0}" == "1" ]]; then
32
+ velero install --crds-only --dry-run -o yaml | kubectl apply -f - --validate=false
33
+ fi
34
+
9
35
  # Build the bucket, region and SA email variables and use --set to mod the
10
36
  # chart values as opposed to using an ${label} approach. This eliminates
11
37
  # the need for an overwhelm generated values.yaml file which also contains
@@ -13,7 +39,7 @@ addHelmRepo vmware-tanzu https://vmware-tanzu.github.io/helm-charts
13
39
  #
14
40
  # Note: GCP_PROJECT_ID is passed down from helmup's environment.
15
41
  #
16
- GCE_BUCKET="$GCP_PROJECT_ID-velero-$VELERO_CHART_VERSION"
42
+ GCE_BUCKET="$GCP_PROJECT_ID-velero-${VELERO_CHART_VERSION%%.*}"
17
43
  GCE_REGION=`overwhelm -k GCE_REGION`
18
44
  GCE_SA_EMAIL="velero@${GCP_PROJECT_ID}.iam.gserviceaccount.com"
19
45
 
@@ -27,6 +53,7 @@ helm upgrade \
27
53
  --namespace velero --create-namespace \
28
54
  --values velero/values-local.yaml \
29
55
  --version $VELERO_CHART_VERSION $HELM_WHAT \
56
+ --set upgradeCRDs=false \
30
57
  --set configuration.backupStorageLocation[0].bucket="$GCE_BUCKET" \
31
58
  --set configuration.backupStorageLocation[0].config.serviceAccount="$GCE_SA_EMAIL" \
32
59
  --set configuration.volumeSnapshotLocation[0].config.snapshotLocation="$GCE_REGION"
@@ -137,7 +137,7 @@ nodeSelector: {}
137
137
  # See => https://github.com/vmware-tanzu/velero-plugin-for-gcp
138
138
  initContainers:
139
139
  - name: velero-plugin-for-gcp
140
- image: velero/velero-plugin-for-gcp:v1.10.0
140
+ image: velero/velero-plugin-for-gcp:v1.13.1
141
141
  volumeMounts:
142
142
  - mountPath: /target
143
143
  name: plugins
package/src/helmup.sh CHANGED
@@ -447,35 +447,50 @@ BAD_SECRETS
447
447
  fi
448
448
  }
449
449
 
450
- function getServiceAndChartVersion() {
450
+ function findChartLocation() {
451
+ local service_name="$1"
452
+ local output
453
+
454
+ # check the compass for a chart location
455
+ if output="$(chart-compass --service "$service_name")";
456
+ then
457
+ # chart exists in local chart-compass.yaml
458
+ local chart_location="oci://$output"
459
+ else
460
+ # nope - fallback to using the legacy museum location
461
+ local chart_location="leverege/$service_name"
462
+ fi
463
+
464
+ echo "$chart_location"
465
+ }
466
+
467
+ function getServiceAndChartInfo() {
451
468
  SERVICE=
469
+ CHARTLOC=
452
470
  CHARTVER=
453
471
  FROM_VERSIONS=
472
+
473
+ local input="${1:-}"
474
+ local versions_file="./Versions.json"
475
+
454
476
  # Allows chart version from command line via <deployment>/<x.y.z>
455
477
  IFS="/" read SERVICE CHARTVER <<< "$1"
456
478
 
457
- # Allows chart version as <deployment>/Chart-x.y.z*>
458
- [ ! -z "$CHARTVER" ] && return # service and chart version from CLI
479
+ [[ -z "$SERVICE" ]] && return 1
459
480
 
460
- # force the move away from the old approach
461
- LCL_CHART=`compgen -G $SERVICE/Chart-?*.?*.?*` &> $DEVNULL
462
- if [ ! -z "$LCL_CHART" ];
463
- then
464
- CHARTVER=${LCL_CHART#*/Chart-}
465
- cat<<DEPRECATED_CHART
466
- $YELO_WARN The use of $SERVICE/$LCL_CHART to lock the chart version has
467
- been deprecated. Create a top level `color g "Versions.json"` file instead:
481
+ CHARTLOC="$(findChartLocation $SERVICE)"
468
482
 
469
- DEPRECATED_CHART
470
- exit 1
483
+ # Allows chart version as <deployment>/x.y.z>
484
+ if [[ -n "$CHARTVER" ]]; then
485
+ return 0 # service and chart version from CLI
471
486
  fi
472
487
 
473
488
  # check for the top level Versions.json file
474
- local VERSIONS="./Versions.json"
475
- if [ -f "$VERSIONS" ];
476
- then
477
- CHARTVER=`node -e "charts=require('$VERSIONS');console.log( charts['$SERVICE']?.chart || '' )"`
478
- [ ! -z "${CHARTVER}" ] && FROM_VERSIONS=1
489
+ if [[ -f "$versions_file" ]]; then
490
+ CHARTVER=$(jq -r --arg svc "$SERVICE" '.[$svc].chart // ""' "$versions_file")
491
+ if [[ -n "$CHARTVER" ]]; then
492
+ FROM_VERSIONS=1
493
+ fi
479
494
  fi
480
495
  }
481
496
 
@@ -516,23 +531,6 @@ $BANNER_TXT
516
531
  HELMUP_BANNER
517
532
  }
518
533
 
519
- findChartLocation() {
520
- local service_name="$1"
521
- local output
522
-
523
- # check the compass for a chart location
524
- if output="$(chart-compass --service "$service_name")";
525
- then
526
- # chart exists in local chart-compass.yaml
527
- local chart_location="oci://$output"
528
- else
529
- # nope - fallback to using the legacy museum location
530
- local chart_location="leverege/$service_name"
531
- fi
532
-
533
- echo "$chart_location"
534
- }
535
-
536
534
  function doHelmup() {
537
535
  local culprit="--set helmup.culprit=\"$(gcloud config get account)\""
538
536
  local deployT="--set helmup.deployT=\"$(date -u +'%Y-%m-%dT%H:%M:%SZ')\""
@@ -551,8 +549,9 @@ function doHelmup() {
551
549
  esac
552
550
  }
553
551
 
554
- # not a fan of global vars but bash forced me to - set by getServiceAndChartVersion
552
+ # not a fan of global vars but bash forced me to - set by getServiceAndChartInfo
555
553
  SERVICE=
554
+ CHARTLOC=
556
555
  CHARTVER=
557
556
  FROM_VERSIONS=
558
557
  function doInstall() {
@@ -562,7 +561,7 @@ function doInstall() {
562
561
  for PARAM in "$@";
563
562
  do
564
563
  # Allows chart version from command line via <deployment>/<x.y.z>
565
- getServiceAndChartVersion "$PARAM"
564
+ getServiceAndChartInfo "$PARAM"
566
565
  #printf "SVC=[$SERVICE] CHT=[$CHARTVER]\n"
567
566
 
568
567
  # slap additional helm syntax in there if the version is set
@@ -593,6 +592,17 @@ CATBACKUP
593
592
  fi
594
593
  fi
595
594
 
595
+ if [[ "$INVOKED_AS" == "helmboot" ]]; then
596
+ local BOOTSTRAP="$SERVICE/helmup.bootstrap"
597
+ cat<<REBOOTSTRAP
598
+
599
+ Rerunning service bootstrap script => `color g "$BOOTSTRAP"`
600
+
601
+ REBOOTSTRAP
602
+ [[ -x "$BOOTSTRAP" ]] && . "$BOOTSTRAP"
603
+ exit 0
604
+ fi
605
+
596
606
  if [ "$INVOKED_AS" == "helmcycle" ];
597
607
  then
598
608
  helmdn $SERVICE
@@ -602,8 +612,6 @@ CATBACKUP
602
612
  # during initial install then do so here
603
613
  ifPluggedInOrBootstrapped $SERVICE && continue
604
614
 
605
- local CHART_LOCATION="$(findChartLocation $SERVICE)"
606
-
607
615
  case "$SERVICE" in
608
616
  "platform")
609
617
  doPlatormPreInstallChecks
@@ -647,7 +655,7 @@ CATBACKUP
647
655
  transponder-*)
648
656
  # transponders use the same chart but different deployment name
649
657
  [ ! -d $SERVICE ] && bootstrapLocalSetup $SERVICE
650
- HELMUP="helm upgrade --install $SERVICE leverege/transponder --values $SERVICE/values.yaml $CHARTVER $HELM_WHAT"
658
+ HELMUP="helm upgrade --install $SERVICE $CHARTLOC --values $SERVICE/values.yaml $CHARTVER $HELM_WHAT"
651
659
  doHelmup "$HELMUP"
652
660
  ;;
653
661
 
@@ -692,7 +700,7 @@ NO_SERVICE_MAN
692
700
 
693
701
  checkUpgradeNotes $SERVICE
694
702
 
695
- HELMUP="helm upgrade --install $SERVICE $CHART_LOCATION -f $SERVICE/values.yaml $CHARTVER $HELM_WHAT"
703
+ HELMUP="helm upgrade --install $SERVICE $CHARTLOC -f $SERVICE/values.yaml $CHARTVER $HELM_WHAT"
696
704
 
697
705
  doHelmup $HELMUP
698
706
  SAVERR=$?
@@ -0,0 +1,75 @@
1
+ import chalk from 'chalk'
2
+
3
+ import { log, } from '../Utils.mjs'
4
+
5
+ import { CommandLine, Config, } from './config/index.mjs'
6
+ import {
7
+ RolesManager,
8
+ SecretsManager,
9
+ ServiceAccountManager,
10
+ VersionManager,
11
+ } from './gcloud-k8s/index.mjs'
12
+
13
+ const showKubernetesConfig = ( svcCfg ) => {
14
+ log( chalk.green`
15
+ Current k8s / gcloud settings:
16
+
17
+ Project => `, chalk.yellow( svcCfg.getK8sProject() ), chalk.green`
18
+ Cluster => `, chalk.yellow( svcCfg.getK8sCluster() ), `
19
+ `
20
+ )
21
+ }
22
+
23
+ const start = async ( options ) => {
24
+
25
+ const CLI = await new CommandLine( options ).init()
26
+ const serviceManCfg = await new Config( options ).init( CLI )
27
+
28
+ // also let user know which gke/gcp context is going to be used
29
+ showKubernetesConfig( serviceManCfg )
30
+
31
+ if ( CLI.args.dumpConfigs ) {
32
+ await serviceManCfg.dump( CLI.args.dumpConfigs )
33
+ process.exit( 0 )
34
+ }
35
+
36
+ // create an unbound service account
37
+ if ( CLI.args.createSa ) {
38
+ await new ServiceAccountManager( serviceManCfg ).createServiceAccount( CLI.args.createSa, serviceManCfg.k8sProject )
39
+ }
40
+
41
+ // check for a service account and create it if needed
42
+ if ( CLI.args.createService ) {
43
+ await new ServiceAccountManager( serviceManCfg ).createBoundServiceAccount( CLI.args.createService )
44
+ }
45
+
46
+ // retrieve image and chart versions of all deployments on the cluster
47
+ if ( CLI.args.fetchVersions ) {
48
+ await new VersionManager( serviceManCfg ).start()
49
+ process.exit( 0 )
50
+ }
51
+
52
+ // create or update the custom IAM roles on the project
53
+ if ( CLI.args.setupRoles ) {
54
+ await new RolesManager( serviceManCfg ).start()
55
+ }
56
+
57
+ // build the service accounts
58
+ if ( CLI.args.setupServices ) {
59
+ await new ServiceAccountManager( serviceManCfg ).start( CLI )
60
+ }
61
+
62
+ // inject the randomly generated secrets
63
+ if ( CLI.args.setupSecrets ) {
64
+ await new SecretsManager( serviceManCfg ).start()
65
+ }
66
+
67
+ // synchronize a secret manager secret to its k8s secret counterpart
68
+ if ( CLI.args.syncSecrets ) {
69
+ await new SecretsManager( serviceManCfg ).synchronize()
70
+ }
71
+ }
72
+
73
+ export default {
74
+ start
75
+ }