@leverege/build-tools 2.98.0 → 2.99.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.
@@ -18,6 +18,26 @@
18
18
  },
19
19
  "outputCapture": "std"
20
20
  },
21
+ {
22
+ "name": "overwhelm tst-dense",
23
+ "type": "node",
24
+ "request": "launch",
25
+ "program": "${workspaceFolder}/src/overwhelm.mjs",
26
+ "args": [],
27
+ "cwd": "/Users/john/Work/leverege/k8s/tst-dense",
28
+ "runtimeExecutable": "node",
29
+ "console": "integratedTerminal"
30
+ },
31
+ {
32
+ "name": "push-my-chart rsrc-srvr",
33
+ "type": "node",
34
+ "request": "launch",
35
+ "program": "${workspaceFolder}/src/push-my-chart.mjs",
36
+ "args": [],
37
+ "cwd": "/Users/john/Work/leverege/cicd/@plt/resource-server",
38
+ "runtimeExecutable": "node",
39
+ "console": "integratedTerminal"
40
+ },
21
41
  {
22
42
  "name": "ingestor in monorepo",
23
43
  "type": "node",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leverege/build-tools",
3
- "version": "2.98.0",
3
+ "version": "2.99.0",
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",
@@ -93,7 +92,7 @@
93
92
  "googleapis": "^171.4.0",
94
93
  "handlebars": "^4.7.8",
95
94
  "ignore": "^7.0.5",
96
- "inquirer": "^13.3.0",
95
+ "inquirer": "^13.3.2",
97
96
  "js-yaml": "^4.1.1",
98
97
  "jsdoc": "^4.0.5",
99
98
  "ms": "^2.1.3",
@@ -104,7 +103,7 @@
104
103
  "readline-sync": "^1.4.10",
105
104
  "semver": "^7.7.4",
106
105
  "shell-quote": "^1.8.3",
107
- "simple-git": "^3.32.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",
@@ -116,6 +115,6 @@
116
115
  "@leverege/eslint-config-leverege": "^5.1.2",
117
116
  "chai": "^6.2.2",
118
117
  "mocha": "^11.7.5",
119
- "npm": "^11.11.0"
118
+ "npm": "^11.11.1"
120
119
  }
121
120
  }
package/src/Docker.mjs CHANGED
@@ -24,8 +24,8 @@ const DIRNAME = path.dirname( url.fileURLToPath( import.meta.url ) )
24
24
  //
25
25
  // See the latest docker images here => https://hub.docker.com/_/node
26
26
  //
27
- const dockerfileNodeVersion = process.env.DOCKER_BUILD_NODE_VERSION || '24.12.0-alpine3.23'
28
- const dockerfileNpmVersion = process.env.DOCKER_BUILD_NPM_VERSION || '11.6.0'
27
+ const dockerfileNodeVersion = process.env.DOCKER_BUILD_NODE_VERSION || '24.14.0-alpine3.23'
28
+ const dockerfileNpmVersion = process.env.DOCKER_BUILD_NPM_VERSION || '11.9.0'
29
29
 
30
30
  // The contents of these variables were initially located in files that live in
31
31
  // the build-tools repository, but it just became simpler to pull the contents
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
@@ -544,15 +545,14 @@ export const parseHelmChart = async ( helmroot = './helm' ) => {
544
545
  let depsOutOfSync = hasDependencies // assume unsynced if dependencies
545
546
  if ( chartFiles.includes( 'Chart.lock' ) ) {
546
547
  const chartLock = YAML.load( fs.readFileSync( `${helmroot}/Chart.lock`, 'utf8' ) )
547
- // Using Object.fromEntries will be able to handle multiple dependencies if ever needed
548
- const chartDeps = Object.fromEntries(
549
- chartYaml.dependencies.map( d => [ d.name, d.version ] )
550
- )
548
+
551
549
  const lockDeps = Object.fromEntries(
552
550
  chartLock.dependencies.map( d => [ d.name, d.version ] )
553
551
  )
554
- const mismatches = Object.entries( chartDeps ).filter( ( [ name, version ] ) => {
555
- return lockDeps[name] !== version
552
+
553
+ const mismatches = chartYaml.dependencies.filter( ( { name, version } ) => {
554
+ const lockedVersion = lockDeps[name]
555
+ return !lockedVersion || !semver.satisfies( lockedVersion, version )
556
556
  } )
557
557
 
558
558
  depsOutOfSync = mismatches.length > 0
package/src/bash-funcs CHANGED
@@ -5,14 +5,22 @@
5
5
  # and can now be easily added to a script via bash sourcing:
6
6
  # . `build-tools --bashfun`
7
7
 
8
+ # If the script is being run in an interactive terminal, we want to make sure to
9
+ # reset the terminal settings on exit. This is especially important if the script
10
+ # is killed while running a command that changes the terminal settings (like stty raw).
11
+ if [[ -t 0 ]]; then
12
+ STTY_SAVE=$(stty -g)
13
+ trap 'stty "$STTY_SAVE"' EXIT
14
+ fi
15
+
8
16
  # Typically /dev/null is used to redirect the noise but sometimes we need to
9
17
  # see exactly what certain commands are complaining about. Running any of the
10
18
  # build-tools with BUILD_TOOLS_DEBUG=1 will redirect the noise to stdout.
11
19
  DEVNULL="/dev/null"
12
20
  if [[ -n "${BUILD_TOOLS_DEBUG:-}" ]];
13
21
  then
14
- DEVNULL="/dev/stdout"
15
- printf "\n***BUILD_TOOLS_DEBUG DEVNULL=>$DEVNULL\n"
22
+ DEVNULL="/dev/stderr"
23
+ printf "\n***BUILD_TOOLS_DEBUG DEVNULL=>$DEVNULL\n" >&2
16
24
  fi
17
25
 
18
26
  GITTOP=`git rev-parse --show-toplevel`
@@ -35,7 +43,7 @@ YELO_WARN="`color y '***WARNING:'`"
35
43
  GREEN_INFO=`color g '***INFO:'`
36
44
 
37
45
  function clearScreen() {
38
- [ "$BUILD_TOOLS_DEBUG" != "1" ] && clear
46
+ [[ -z "${BUILD_TOOLS_DEBUG:-}" ]] && clear
39
47
  }
40
48
 
41
49
  function clearlyWarn() {
@@ -71,7 +79,7 @@ function exitOnError() {
71
79
 
72
80
  function yesOrSkipToContinue() {
73
81
  printf "\n Enter \"`color g yes`\" ${1}, \"`color y skip`\" to skip this step, or anything else to exit.\n\n"
74
- read ANS
82
+ read -e ANS
75
83
  [ "$ANS" == 'yes' ] && return 0
76
84
  [ "$ANS" == 'skip' ] && return 2
77
85
  exit 1
@@ -79,12 +87,12 @@ function yesOrSkipToContinue() {
79
87
 
80
88
  function yesToContinue() {
81
89
  printf "\n Enter \"`color g yes`\" ${1}, or anything else to exit.\n\n"
82
- read ANS
90
+ read -e ANS
83
91
  [ "$ANS" != 'yes' ] && exit 1
84
92
  }
85
93
 
86
94
  function proceedOnEnter() {
87
- printf " Hit `color g return` to proceed\n\n" && read ANS
95
+ printf " Hit `color g return` to proceed\n\n" && read -e ANS
88
96
  }
89
97
 
90
98
  function setOrUnset() {
@@ -109,13 +117,13 @@ function getManagedSecret() {
109
117
  printf "Returned =>[$SECRET]\n\n"
110
118
  exit 1
111
119
  fi
112
- echo $SECRET
120
+ echo "$SECRET"
113
121
  }
114
122
 
115
123
  function getProjectIdFromK8sContext() {
116
124
  local currContext=`kubectl config current-context`
117
125
 
118
- IFS='_'
126
+ local IFS='_'
119
127
  read -ra ADDR <<< "$currContext"
120
128
 
121
129
  echo ${ADDR[1]} # project id is the second string split by _
@@ -273,7 +281,7 @@ function ifPluggedIn() {
273
281
  local PLUGIN=
274
282
  HELMUP="helm upgrade --install $SERVICE $CHARTLOC -f $SERVICE/values.yaml $CHARTVER $HELM_WHAT"
275
283
  case "$INVOKED_AS" in
276
- "helmup"|"helmwhat"|"helmcycle" )
284
+ "helmup"|"helmwhat"|"helmcycle"|"helminit" )
277
285
  PLUGIN="$1/helmup.plugin"
278
286
  ;;
279
287
  "helmdn" )
@@ -323,4 +331,4 @@ function commandChecker() {
323
331
  done
324
332
  }
325
333
 
326
- commandChecker git helm jq kubectl service-man
334
+ commandChecker git helm jq kubectl
@@ -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'
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env node
2
+ /* eslint-disable */ // for now, we can relax this rule since ...
3
+ /* eslint-disable security/detect-non-literal-fs-filename */
4
+ import fs from 'node:fs'
5
+
6
+ import { program } from 'commander'
7
+ import chalk from 'chalk'
8
+
9
+ import {
10
+ analyzeRepository,
11
+ condir,
12
+ enableDebug,
13
+ errorExit,
14
+ log,
15
+ } from '../Utils.mjs'
16
+
17
+ program
18
+ .name( 'circle-orb' )
19
+ .description( 'updates a .circle/circle.yml to use the leverge orb' )
20
+ .option( '--debug', 'Enable debug logging - use BUILD_TOOLS_DEBUG=1 for global' )
21
+ .parse()
22
+
23
+ const options = program.opts()
24
+ if ( options.debug ) {
25
+ enableDebug() // enables debugging in the Utils functions
26
+ }
27
+
28
+ const repo = await analyzeRepository()
29
+ if ( !repo.isGitRepo ) {
30
+ errorExit( '***ERROR: This command must be run inside a git repository - run "git init" to proceed' )
31
+ }
32
+ const Container = repo.containerName
33
+ const chartwright = new Chartwright( { Container, debug : options.debug } )
34
+
35
+ // If there isn't an existing helm chart then we just bootstrap the new chart structure
36
+ // from the current helm template and we're done. This will most likely be the case after
37
+ // a new service has been bootstrapped with ignition.
38
+ if ( !repo.helmChart ) {
39
+ await chartwright.bootstrap( { Container } )
40
+ process.exit( 0 )
41
+ }
42
+
43
+ // Safety First: if there is already an older helm chart, we don't want to overwrite it - we
44
+ // want the user to review / intervene before proceeding.
45
+ const packageRoot = repo.currentDir
46
+ if ( fs.existsSync( `${packageRoot}/helm-old` ) ) {
47
+ errorExit( '***ERROR: An old helm chart structure already exists - cannot proceed' )
48
+ }
49
+
50
+ const {
51
+ Chart,
52
+ Values,
53
+ valuesText : ValuesText,
54
+ imageRegistry : Registry,
55
+ } = repo.helmChart
@@ -0,0 +1,24 @@
1
+ # See => https://bitbucket.org/leverege/circle-nodejs-ci/src/development/
2
+ version: 2.1
3
+
4
+ orbs:
5
+ leverege: leverege/circle-nodejs-ci@0.3.0
6
+
7
+ workflows:
8
+ build-and-verify:
9
+ jobs:
10
+ - leverege/install-dependencies:
11
+ context: npm
12
+ - leverege/code-analysis:
13
+ requires:
14
+ - leverege/install-dependencies
15
+ - leverege/code-coverage:
16
+ coverage-threshold: 70
17
+ context: leverege-gcp # 👈 attaches the secure secrets access to GCP_SA_KEY_JSON
18
+ enable-redis: false
19
+ cache-config: '{"type":"inMemory"}' # '{"type":"redis"}'
20
+ requires:
21
+ - leverege/install-dependencies
22
+ - leverege/generate-docs:
23
+ requires:
24
+ - leverege/install-dependencies
@@ -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.9.0"
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
@@ -109,7 +109,7 @@ prometheus:
109
109
  accessModes: ["ReadWriteOnce"]
110
110
  resources:
111
111
  requests:
112
- storage: 50Gi # Adjust size as needed
112
+ storage: 64Gi # Adjust size as needed
113
113
 
114
114
  # External access to prometheus may be enabled by creating an htpasswd secret
115
115
  # by running this example command:
@@ -146,7 +146,7 @@ extraManifests:
146
146
  - websecure
147
147
  routes:
148
148
  - kind: Rule
149
- match: Host(`${PROJECT_ID}-prometheus.${HOST}.com`)
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: "${PROJECT_ID}"
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=${PROJECT_ID}|`{{ .Labels.pod }}`>*
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 }}
@@ -90,14 +90,14 @@ spec:
90
90
  summary: "Postgresql high rollback rate on {{ $labels.release }} - {{ $labels.datname }}"
91
91
  description: "Ratio of transactions being aborted compared to committed is > 2 %"
92
92
 
93
- - alert: PostgresqlCommitRateLow
94
- expr: rate(pg_stat_database_xact_commit[1m]) < 10
95
- for: 5m
96
- labels:
97
- severity: error
98
- annotations:
99
- summary: "Postgresql commit rate low on {{ $labels.release }} - {{ $labels.datname }}"
100
- description: "Postgres seems to be processing very few transactions"
93
+ # - alert: PostgresqlCommitRateLow
94
+ # expr: rate(pg_stat_database_xact_commit[1m]) < 10
95
+ # for: 5m
96
+ # labels:
97
+ # severity: error
98
+ # annotations:
99
+ # summary: "Postgresql commit rate low on {{ $labels.release }} - {{ $labels.datname }}"
100
+ # description: "Postgres seems to be processing very few transactions"
101
101
 
102
102
  - alert: PostgresqlLowXidConsumption
103
103
  expr: rate(pg_txid_current[1m]) < 5
@@ -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: "small"
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: "micro"
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.3.2"
9
- EXPECTED_CLIENT_VERSION="v1.17.2"
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
@@ -5,10 +5,62 @@
5
5
  # indicator to the bash-funcs ifNotFromHelmup function
6
6
  export _FROM_HELMUP_="true"
7
7
 
8
+ INVOKED_AS=`basename $0`
9
+
8
10
  # Load the standard helper functions
9
11
  . `build-tools --bashfun`
10
12
 
11
- if [[ ! -z "$BUILD_TOOLS_DEBUG" ]]; then
13
+ function giveHelp() {
14
+ cat<<HELP
15
+ `color c "Helm Deployment Orchestrator"`
16
+
17
+ Usage: `color g "$INVOKED_AS <service> [service...] [options]"`
18
+
19
+ Options:
20
+ `color g "--dry-run"` Show what helm would do without applying changes
21
+ `color g "--debug"` Enable verbose debug output
22
+ `color g "--help"` Show this help message
23
+
24
+ Invocation Modes:
25
+ `color g "helmup"` Deploy / upgrade one or more services
26
+ `color g "helmdn"` Tear down one or more services
27
+ `color g "helmwhat"` Dry-run a deployment (same as --dry-run)
28
+ `color g "helminit"` Run init scripts for a service
29
+ `color g "helmboot"` Re-run the boot scripts for a service
30
+ `color g "helmcycle"` Cycle (down + up) one or more services
31
+
32
+ Examples:
33
+ `color g "helmup api-server"` # deploy a single service
34
+ `color g "helmup api-server scheduler"` # deploy multiple services
35
+ `color g "helmup transponder-*"` # deploy by glob pattern
36
+ `color g "helmup transponder-rt/5.1.0"` # deploy a specific chart version
37
+ `color g "helmup platform"` # deploy all platform services
38
+ `color g "helmup api-server --dry-run"` # dry run without applying
39
+ `color g "helmdn api-server"` # tear down a service
40
+ `color g "helmcycle api-server"` # helmdn / helmup a service
41
+ HELP
42
+ }
43
+
44
+ # command line parsing is handled in getServiceAndChartInfo which allows us to pull the chart
45
+ for arg in "$@"; do
46
+ case "$arg" in
47
+ --help|-h)
48
+ giveHelp && exit 0
49
+ ;;
50
+ --debug)
51
+ export BUILD_TOOLS_DEBUG=1
52
+ ;;
53
+ --dry-run)
54
+ export HELM_WHAT="--dry-run --debug"
55
+ export K8S_WHAT="--dry-run=server -o yaml"
56
+ ;;
57
+ *)
58
+ SERVICES+=("$arg")
59
+ ;;
60
+ esac
61
+ done
62
+
63
+ if [[ ! -z "$BUILD_TOOLS_DEBUG_XXX" ]]; then
12
64
  cat<<BAD_IDEA
13
65
 
14
66
  `color y "***WARNING: enabling debugging for helmup is a bad idea..."`
@@ -22,8 +74,6 @@ BAD_IDEA
22
74
  exit 1
23
75
  fi
24
76
 
25
- SHELMUP_ARGS=("$*")
26
-
27
77
  # artifact-registry => https://console.cloud.google.com/artifacts?project=leverege-registry
28
78
  REGISTRY_DOMAIN="us-docker.pkg.dev"
29
79
  # open container initiative (oci) => https://opencontainers.org/
@@ -44,7 +94,6 @@ PLATFORM=(
44
94
  imagine
45
95
  message-processor
46
96
  messenger
47
- reason
48
97
  resource-server
49
98
  rule-engine
50
99
  scheduler
@@ -58,10 +107,11 @@ AUXILIARY=(
58
107
  fota-server
59
108
  geotile-server
60
109
  overdose
61
- pgbouncer,
110
+ pgbouncer
62
111
  pubsub-pulse
63
112
  push-notifier
64
113
  pusher
114
+ reason
65
115
  transponder-dh
66
116
  vin-decoder-server
67
117
  )
@@ -237,7 +287,7 @@ function bootstrapLocalSetup() {
237
287
 
238
288
  if [ ! -d "$SERVICE" ];
239
289
  then
240
- mkdir $SERVICE
290
+ mkdir "$SERVICE"
241
291
  else
242
292
  # If the service dir already exists but the helmup.plugin file is missing
243
293
  # then this is most likely a legacy setup - for example, an older setup for
@@ -261,13 +311,13 @@ MISSING_HELMUP_PLUGIN
261
311
 
262
312
  if [ ! -d "$SERVICE_CHART" ];
263
313
  then
264
- rm -rf $SERVICE
314
+ rm -rf "$SERVICE"
265
315
  errorExit "Missing $SERVICE chart => $(color y $SERVICE_CHART)"
266
316
  fi
267
317
 
268
- cp -a $SERVICE_CHART .
318
+ cp -a "$SERVICE_CHART" .
269
319
  # because npm tends to not allow .gitinore files the easy way...
270
- find $SERVICE -type f -name "gitignore" -execdir mv {} .gitignore \;
320
+ find "$SERVICE" -type f -name "gitignore" -execdir mv {} .gitignore \;
271
321
  overwhelm --genvals
272
322
  FIRST_RUN="$SERVICE/helmup.bootstrap"
273
323
  if [ -f "$FIRST_RUN" ];
@@ -286,8 +336,8 @@ SERVICE_BOOTSTRAP
286
336
  exit 1
287
337
  fi
288
338
  fi
289
- git add $SERVICE
290
- ifPluggedIn $SERVICE
339
+ git add "$SERVICE"
340
+ ifPluggedIn "$SERVICE"
291
341
  }
292
342
 
293
343
  # If the service is already plugged in the go - otherwise if this is a first
@@ -318,17 +368,15 @@ function installDefaultConfigs() {
318
368
  INSTALLDEFAULTCONFIGS
319
369
  yesToContinue "to apply the default-configs to the cluster"
320
370
 
321
- kubecmd="kubectl apply -f default-configs.yaml"
322
-
323
- printf "\nRunning => `color y \"$kubecmd\"`\n\n"
324
- eval $kubecmd
325
- sendToSlack "$kubecmd"
371
+ printf "\n`color y \"*** Updating the Default Configs!!!\"` \n\n"
372
+ kubectl apply -f default-configs.yaml
373
+ sendToSlack "Updated the Default ConfigMap!"
326
374
  }
327
375
 
328
376
  function errorIfMissingSecret() {
329
377
  SECRET="$1"
330
378
  kubectl get secret $SECRET &> $DEVNULL
331
- if [[ $? = 1 || SECRET = "" ]];
379
+ if [[ $? = 1 || "${SECRET}" = "" ]];
332
380
  then
333
381
  errorExit "missing secret `color y $SECRET` - did you `color g 'service-man --new-k8s'` ?"
334
382
  fi
@@ -522,7 +570,6 @@ function getServiceAndChartInfo() {
522
570
  CHARTVER="$(jq -r --arg svc "$SERVICE" '.[$svc].chart // empty' "$versions_file")"
523
571
  [[ -n "$CHARTVER" ]] && FROM_VERSIONS=1
524
572
  fi
525
-
526
573
  return 0
527
574
  }
528
575
 
@@ -564,17 +611,32 @@ HELMUP_BANNER
564
611
  }
565
612
 
566
613
  function doHelmup() {
567
- local culprit="--set helmup.culprit=\"$(gcloud config get account)\""
568
- local deployT="--set helmup.deployT=\"$(date -u +'%Y-%m-%dT%H:%M:%SZ')\""
569
- local helmup="$@"
570
- local doing="Helming => `color g \"$helmup\"`"
614
+ local culprit="$(gcloud config get account)"
615
+ local deployT="$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
616
+ local doing="Helming => `color g \"$*\"`"
571
617
  local from=
572
618
  [ ! -z "$FROM_VERSIONS" ] && from="`color y \"<= from Versions.json\"`"
573
619
  printf "$doing $from\n"
574
- eval "$helmup $culprit $deployT"
620
+ "$@" --set "helmup.culprit=$culprit" --set "helmup.deployT=$deployT"
621
+
622
+ # usually the helm command will run without error but a common failure is caused
623
+ # by the lack of use of our protonVPN profile which causes the i/o timeout from helm
624
+ if [[ $? -ne 0 ]];
625
+ then
626
+ cat<<HELMUP_FAIL
627
+
628
+ $RED_ERROR helmup failed for => `color y "$SERVICE"`
629
+
630
+ `color y "Please investigate the issue, and if it isn't obvious then check your VPN connectivity!"`
631
+
632
+ HELMUP_FAIL
633
+
634
+ exit 1
635
+ fi
636
+
575
637
  case "$INVOKED_AS" in
576
638
  "helmup"|"helmdn")
577
- sendToSlack "$helmup"
639
+ sendToSlack "$*"
578
640
  ;;
579
641
  *)
580
642
  ;;
@@ -589,7 +651,17 @@ FROM_VERSIONS=
589
651
 
590
652
  function doInstall() {
591
653
 
592
- helm repo update &> $DEVNULL
654
+ # we used to do a Chartmuseum update here which means that we incur the cost of
655
+ # updating the index and pulling the charts down every time we install a service
656
+ # which is a lot of overhead for a process that is already pretty slow
657
+ #
658
+ # helm repo update &> $DEVNULL <===DEPRECATED
659
+ #
660
+ # the chart museum is now updated in the background when helmup runs, just before
661
+ # the overwhelm step, so we get the benefits of the updated charts without the
662
+ # overhead on every install - this is, of course, a race condition, but this will
663
+ # all go away once we move to artifact registry and can pull the charts directly
664
+ # from there without the need for a local repo update
593
665
 
594
666
  for PARAM in "$@";
595
667
  do
@@ -599,7 +671,6 @@ function doInstall() {
599
671
  # slap additional helm syntax in there if the version is set
600
672
  [ ! -z "$CHARTVER" ] && CHARTVER="--version $CHARTVER"
601
673
 
602
- INVOKED_AS=`basename $0`
603
674
  # set the dry-run flag on what
604
675
  [ "$INVOKED_AS" == "helmwhat" ] && HELM_WHAT="--dry-run --debug" && K8S_WHAT="--dry-run=server -o yaml"
605
676
 
@@ -687,8 +758,9 @@ REBOOTSTRAP
687
758
  transponder-*)
688
759
  # transponders use the same chart but different deployment name
689
760
  [ ! -d $SERVICE ] && bootstrapLocalSetup $SERVICE
761
+ CHARTLOC="oci://us-docker.pkg.dev/leverege-registry/stack/charts/transponder" # always use art-reg
690
762
  HELMUP="helm upgrade --install $SERVICE $CHARTLOC --values $SERVICE/values.yaml $CHARTVER $HELM_WHAT"
691
- doHelmup "$HELMUP"
763
+ doHelmup $HELMUP
692
764
  ;;
693
765
 
694
766
  *)
@@ -711,17 +783,6 @@ REBOOTSTRAP
711
783
  fi
712
784
 
713
785
  printf "\n--------------------------------------------------------------\nCharting $SERVICE\n"
714
- if [ ! -x "$(command -v service-man)" ];
715
- then
716
- cat<<NO_SERVICE_MAN
717
-
718
- $RED_ERROR The Leverege service-man utility is missing - install and rerun helmup
719
-
720
- `color g "npm i -g @leverege/service-man"`
721
-
722
- NO_SERVICE_MAN
723
- exit 1
724
- fi
725
786
 
726
787
  if [[ "$SERVICE" == *-canary ]];
727
788
  then
@@ -734,22 +795,7 @@ NO_SERVICE_MAN
734
795
 
735
796
  HELMUP="helm upgrade --install $SERVICE $CHARTLOC -f $SERVICE/values.yaml $CHARTVER $HELM_WHAT"
736
797
 
737
- doHelmup $HELMUP
738
- SAVERR=$?
739
- if [ $SAVERR -ne 0 ];
740
- then
741
- cat<<NOTRUNNING
742
-
743
- $RED_ERROR helm exited with error status: $SAVERR
744
-
745
- $RED_ERROR The $SERVICE chart failed to upgrade or install. There may be an
746
- issue with the service's helm charts, or you may have to follow
747
- the instructions on the wiki under `color g "Helm Charts via Chartmuseum"`
748
- in the `color y "Using the Public Endpoint"` section.
749
-
750
- NOTRUNNING
751
- exit 1
752
- fi
798
+ doHelmup $HELMUP # will exit on failure, otherwise will continue to the next service
753
799
  ;;
754
800
  esac
755
801
  done
@@ -758,7 +804,7 @@ NOTRUNNING
758
804
  }
759
805
 
760
806
  # ---------- helmup MAIN ----------
761
- GITTOP=`git rev-parse --show-toplevel`
807
+ helm repo update &>/dev/null & # see comments in the doInstall function for rationale
762
808
 
763
809
  overwhelm
764
810
  [ $? -ne 0 ] && printf "\n\n***Aborting helmup...\n\n" && exit 1
@@ -768,6 +814,6 @@ export GCP_PROJECT_ID="$(getProjectIdFromK8sContext)"
768
814
  # Same for the region, but not as prevalent
769
815
  export GCE_REGION=`overwhelm -k GCE_REGION`
770
816
 
771
- doInstall $@
817
+ doInstall "${SERVICES[@]}"
772
818
 
773
819
  displayBanner
@@ -31,9 +31,16 @@ const PRESERVE_SECTIONS = new Set( [
31
31
  ] )
32
32
 
33
33
  // Helper functions
34
- const warnDeprecatedSections = ( doc, sections ) => {
34
+ const OBSOLETE_SECTIONS = [
35
+ 'ingressRoute',
36
+ 'loadbalancer',
37
+ 'udploadbalancer',
38
+ 'podAnnotations',
39
+ 'workloadIdentity'
40
+ ]
41
+ const warnDeprecatedSections = ( doc ) => {
35
42
  let deprecationWarningShown = false
36
- for ( const key of sections ) {
43
+ for ( const key of OBSOLETE_SECTIONS ) {
37
44
  if ( !doc.has( key ) ) continue
38
45
  Utils.log( `${chalk.yellow.bold( '⚠️ WARNING:' )} Deprecated values.yaml section detected => ${chalk.red.bold( key )}` )
39
46
  deprecationWarningShown = true
@@ -138,10 +145,10 @@ export class Chartwright {
138
145
  // Now we need to smart merge the values.yaml template while preserving existing sections
139
146
  const baseValuesDoc = YAML.parseDocument( this.templates.Values )
140
147
  const existingValuesDoc = YAML.parseDocument( ValuesText )
141
- // prune obsolete sections and write the merged values.yaml back to disk, preserving formatting and comments
142
- const OBSOLETE_SECTIONS = [ 'ingressRoute', 'loadbalancer', 'udploadbalancer' ]
143
- warnDeprecatedSections( existingValuesDoc, OBSOLETE_SECTIONS )
144
-
148
+ // warn about obsolete sections
149
+ warnDeprecatedSections( existingValuesDoc )
150
+
151
+ // Merge legacy values.yaml with new base, preserving formatting and comments
145
152
  this.mergeTopLevelAddMissing( baseValuesDoc, existingValuesDoc )
146
153
  this.applyPreserveSections( baseValuesDoc, existingValuesDoc )
147
154
 
@@ -104,7 +104,3 @@ affinity: {}
104
104
  tolerations: []
105
105
 
106
106
  nodeSelector: {}
107
-
108
- podAnnotations: {}
109
-
110
- workloadIdentity: {}
package/src/overwhelm.mjs CHANGED
@@ -51,6 +51,15 @@ const deprecated = ( deprecation ) => {
51
51
  log( `${chalk.yellow.bold( '***DEPRECATED:' )} ${deprecation}\n` )
52
52
  }
53
53
 
54
+ if ( !fs.existsSync( 'overwhelm.yaml' ) ) {
55
+ log( chalk.red.bold( `
56
+
57
+ ***ERROR overwhelm => missing the overwhelm.yaml file - this command expects
58
+ to execute from within a platform-k8s branch
59
+ ` ) )
60
+ process.exit( 1 )
61
+ }
62
+
54
63
  // See if we are in a monorepo, which changes some of the rules.
55
64
  const gitTop = await shellCmd( 'git rev-parse --show-toplevel' )
56
65
 
@@ -65,17 +74,8 @@ const gitBranch = await shellCmd( 'git rev-parse --abbrev-ref HEAD' )
65
74
 
66
75
  const context = args.context || monoTop || gitBranch
67
76
 
68
- if ( context === 'master' ) {
69
- log( '***ERROR: master context is forbidden; change to a different branch\n\n' )
70
- process.exit( 1 )
71
- }
72
-
73
- if ( !fs.existsSync( 'overwhelm.yaml' ) ) {
74
- log( chalk.red.bold( `
75
-
76
- ***ERROR overwhelm => missing the overwhelm.yaml file - this command expects
77
- to execute from within a platform-k8s branch
78
- ` ) )
77
+ if ( context.match( /^(main|master)$/ ) ) {
78
+ log( `***ERROR: ${context} context is forbidden; change to a different branch\n\n` )
79
79
  process.exit( 1 )
80
80
  }
81
81
 
@@ -92,32 +92,15 @@ if ( !args.key && !args.fetchctx && !args.matchk8s && fs.existsSync( 'values-def
92
92
  }
93
93
  }
94
94
 
95
- // Avoid race condition when running overwhelm for the first time on a new
96
- // cluster and the default-configs.yaml file has yet to be created.
97
- const defaultConfigs = 'default-configs.yaml'
98
- if ( !fs.existsSync( defaultConfigs ) ) {
99
- fs.closeSync( fs.openSync( defaultConfigs, 'w' ) ) // same as unix touch
100
- }
101
-
102
- // Load the default values and then overlay with the project specific yaml
103
- // values. This supports the notion of this type of approach in the
104
- // overwhelm yaml settings:
105
- // default:
106
- // GCE_MACHINE : "n1-standard-2"
107
- //
108
- // my-project:
109
- // GCE_MACHINE : "n1-highcpu-8"
110
- //
111
- // fashion, but it is advised not to set a default region with this
112
- // approach in order to keep us cognizant of exactly where a cluster is
113
- // being formed.
114
- //
95
+ // Load the overwhelm.yaml file with the project specific settings to be rendered
96
+ // into the helm values.yaml files. The overwhelm.yaml file is expected to have a
97
+ // default section and one or more context-specific sections.
115
98
  const yaml = YAML.load( fs.readFileSync( 'overwhelm.yaml', 'utf-8' ) )
116
99
  const over = yaml.default
117
100
 
118
101
  debug( { over, yaml, }, '<==Contents of the over and yaml structs' )
119
102
 
120
- let cfgs = yaml[context]
103
+ const cfgs = yaml[context]
121
104
 
122
105
  // If we just need to check context return 0 if cfgs exists, else error.
123
106
  if ( args.checkctx ) { process.exit( !cfgs ? 1 : 0 ) }
@@ -132,18 +115,7 @@ if ( !cfgs ) {
132
115
  process.exit( 1 )
133
116
  }
134
117
 
135
- // Check to see if we are deriving from another configuration.
136
- if ( cfgs.PROJECT_BASE ) {
137
- const baseName = cfgs.PROJECT_BASE
138
- const tempCfgs = cfgs
139
- cfgs = yaml[baseName]
140
- Object.keys( tempCfgs ).forEach( ( key ) => { cfgs[key] = tempCfgs[key] } )
141
- log( 'PROJECT_BASE still under evaluation' )
142
- log( '\n cfgs=', cfgs )
143
- process.exit( 1 ) // XXX HERE
144
- }
145
-
146
- Object.keys( cfgs ).forEach( ( key ) => { over[key] = cfgs[key] || over[key] } )
118
+ Object.keys( cfgs ).forEach( ( key ) => { over[key] = cfgs[key] ?? over[key] } )
147
119
 
148
120
  // Expand any variables that reference other variable settings. A perfect
149
121
  // example of where this is useful is in the setting of a PROJECT_NAME and
@@ -163,6 +135,11 @@ const varErrors = []
163
135
  Object.keys( over ).forEach( ( key ) => {
164
136
  if ( !over[key] ) return // no value to work with - skip it
165
137
 
138
+ if ( !isString( over[key] ) ) {
139
+ varErrors.push( `${key} : ${over[key]} is not a string` )
140
+ return
141
+ }
142
+
166
143
  // Look for something in the form of "thing-${VAR1}-${VAR2}-${VARn}-stuff"
167
144
  const matches = over[key].match( /\$\{\w+\}/g )
168
145
  if ( !matches ) return
@@ -182,9 +159,9 @@ Object.keys( over ).forEach( ( key ) => {
182
159
  } )
183
160
 
184
161
  if ( varErrors.length > 0 ) {
185
- log( '***ERROR: unkown variable reference(s) in overwhelm.yaml:\n' )
162
+ log( chalk.red.bold( '\n***ERROR: unkown variable reference(s) in overwhelm.yaml:\n' ) )
186
163
  varErrors.forEach( ( error ) => {
187
- log( ` ${error}` )
164
+ log( ` ${chalk.yellow.bold( error )}` )
188
165
  } )
189
166
  log( '' )
190
167
  process.exit( 1 )
@@ -194,8 +171,8 @@ if ( varErrors.length > 0 ) {
194
171
  const yams = glob.sync( 'values-*.yaml' )
195
172
 
196
173
  // A function to apply the replacements to all of the matching yaml which
197
- // will error out if it runs into an unknown OVH<tag>.
198
- const doReplacements = ( yamls, replacements, fileName = 'default-config.yaml' ) => {
174
+ // will error out if it runs into an unknown ${TAG}
175
+ const doReplacements = ( yamls, replacements, fileName = 'unknown-file' ) => {
199
176
  let replYaml = yamls
200
177
 
201
178
  // wrap special chars with quotes if needed, like "#---incident-alerts---"
@@ -217,16 +194,23 @@ const doReplacements = ( yamls, replacements, fileName = 'default-config.yaml' )
217
194
  }
218
195
  } )
219
196
 
220
- // Verify all replaceables have been handled, or error out.
221
- const missed = replYaml.match( /OVH:<(.*)>/g )
222
-
223
- if ( missed ) {
224
- log( '\n***ERROR: missing replacements in overwhelm.yaml for these tags:\n' )
225
- missed.forEach( ( miss ) => {
226
- log( ` TAG: ${miss.match( /OVH:<(.*)>/ )[1]}` )
227
- } )
228
- log( '' )
229
- process.exit( 1 )
197
+ // this feels brittle because we have to treat the default-configs.yaml.ovh file
198
+ // differently due to variables like ${shard} which gets expanded by api-server -
199
+ // it feels brittle because there could be other yaml files that have similar
200
+ // variables that are not meant to be replaced by overwhelm - I might eventually
201
+ // just rip this out ...
202
+ if ( fileName !== 'default-configs.yaml.ovh' ) {
203
+ // Verify all replaceables have been handled, or error out.
204
+ const missed = replYaml.match( /OVH:<(.*)>|\${(.*)}/g )
205
+
206
+ if ( missed ) {
207
+ log( chalk.red.bold( `\n***ERROR: missing replacements in ${fileName} for these tags:\n` ) )
208
+ missed.forEach( ( miss ) => {
209
+ log( ` TAG: ${chalk.yellow.bold( miss )}` )
210
+ } )
211
+ log( '' )
212
+ process.exit( 1 )
213
+ }
230
214
  }
231
215
 
232
216
  // Eat any doubly double quoted values such that
@@ -241,8 +225,7 @@ const doReplacements = ( yamls, replacements, fileName = 'default-config.yaml' )
241
225
 
242
226
  // Collect all of the yaml from the yams...
243
227
  const buildYaml = ( yamls, replacements ) => {
244
- const always = [ defaultConfigs ]
245
- const values = [ ...always, ...yamls ]
228
+ const values = [ ...yamls ]
246
229
  const loaded = []
247
230
  let allYamls = ''
248
231
 
@@ -260,7 +243,7 @@ const buildYaml = ( yamls, replacements ) => {
260
243
  } )
261
244
 
262
245
  // Now apply all of the replacements from the overwhelm file.
263
- return doReplacements( allYamls, replacements )
246
+ return doReplacements( allYamls, replacements, 'from-buildYaml' )
264
247
  }
265
248
 
266
249
  // Call buildYaml to replace the OVH strings in the yaml files.
@@ -280,7 +263,7 @@ if ( args.key ) {
280
263
  }
281
264
 
282
265
  // Find all of the potential target dirs. Utilize .gitignore to ignore files
283
- const ahoy = getDirectories( process.cwd() )
266
+ const ahoy = getDirectories( { path : process.cwd(), respectGitignore : true } )
284
267
 
285
268
  // Verifies that all values in a config block are quoted
286
269
  const validValuesLocalConfig = ( vlf ) => {
@@ -307,7 +290,7 @@ const validValuesLocalConfig = ( vlf ) => {
307
290
  ahoy.forEach( ( dir ) => {
308
291
  if ( !fs.existsSync( `${dir}/.nohelm` ) && !dir.match( /^\..*/ ) ) {
309
292
  // debug( { dir }, 'Generating values' ) // eslint-disable-line no-unused-expressions
310
- let valuesOut = [] // An accumulator for all of the output values.
293
+ let valuesOut = '' // An accumulator for all of the output values.
311
294
 
312
295
  // Add support for localized values for things like keel (or whatever)
313
296
  const valuesLocal = `${dir}/values-local.yaml`
@@ -342,7 +325,7 @@ ahoy.forEach( ( dir ) => {
342
325
 
343
326
  // we can also apply replaceables to all .ovh files in the project
344
327
  glob.sync( '**/*.ovh' ).forEach( ( cfgmap ) => {
345
- const target = cfgmap.replace( /.ovh$/, '' )
328
+ const target = cfgmap.replace( /\.ovh$/, '' )
346
329
  deprecated( `rename deprecated ${cfgmap} OVH file to ${target}` )
347
330
  let valuesOut = fs.readFileSync( cfgmap, { encoding : 'utf-8' } )
348
331
  valuesOut = doReplacements( valuesOut, over, cfgmap )
@@ -3,9 +3,14 @@
3
3
  import chalk from 'chalk'
4
4
  import commandLineArgs from 'command-line-args'
5
5
  import commandLineUsage from 'command-line-usage'
6
- import { lt as semverLt } from 'semver'
7
6
 
8
- import { debug, log, shellCmd } from './Utils.mjs'
7
+ import {
8
+ debug,
9
+ errorExit,
10
+ log,
11
+ parseHelmChart,
12
+ shellCmd
13
+ } from './Utils.mjs'
9
14
 
10
15
  const commandLineOptions = [
11
16
  {
@@ -48,34 +53,46 @@ if ( args.help ) {
48
53
  process.exit( 0 )
49
54
  }
50
55
 
51
- const pushItGood = async () => {
52
- const version = await shellCmd( 'helm version --short' )
53
- const pusher = ( semverLt( version, '3.7.0' ) ? 'push' : 'cm-push' )
56
+ const {
57
+ chartName,
58
+ chartVersion,
59
+ depsOutOfSync,
60
+ } = await parseHelmChart( args.chart )
54
61
 
55
- let museumStatus = 0
62
+ log( chalk.green( `Chart => ${chalk.bold.yellow( chartName )}` ) )
63
+ log( chalk.green( `Version => ${chalk.bold.yellow( chartVersion )}` ) )
64
+
65
+ if ( depsOutOfSync ) {
56
66
  try {
57
- log( chalk.green( 'Pushing chart to the Chartmuseum\n' ) )
58
- const museum = await shellCmd( `helm ${pusher} ${args.chart} leverege` )
59
- debug( { museum }, '<==output from helm push' )
60
- } catch ( ex ) {
61
- log( ex.stderr )
62
- museumStatus = 1
67
+ log( chalk.yellow.bold( '\nChart dependedencies are out of sync - updating...\n' ) )
68
+ await shellCmd( 'helm dependency update ./helm', { stdio : 'inherit' } )
69
+ } catch ( error ) {
70
+ errorExit( error )
63
71
  }
72
+ }
64
73
 
65
- if ( args.noRegistry ) {
66
- log( `${chalk.bold.yellow( '\nskipping the chart push to the artifact registry' )}` )
67
- process.exit( museumStatus )
68
- }
74
+ let museumStatus = 0
75
+ try {
76
+ log( chalk.green( ' ... pushing to the Museum' ) )
77
+ const museum = await shellCmd( `helm cm-push ${args.chart} leverege` )
78
+ debug( { museum }, '<==output from helm push' )
79
+ } catch ( ex ) {
80
+ // log( ex.stderr )
81
+ log( ex.message )
82
+ museumStatus = 1
83
+ }
69
84
 
70
- try {
71
- log( chalk.green( 'Pushing chart to the Artifact Registry\n' ) )
72
- const registry = await shellCmd( `chart-to-registry --chart ${args.chart}` )
73
- debug( { registry }, '<==chart-to-registry' )
74
- process.exit( museumStatus )
75
- } catch ( ex ) {
76
- log( ex.stderr )
77
- process.exit( museumStatus + 1 )
78
- }
85
+ if ( args.noRegistry ) {
86
+ log( `${chalk.bold.yellow( '\nskipping the chart push to the artifact registry' )}` )
87
+ process.exit( museumStatus )
79
88
  }
80
89
 
81
- pushItGood()
90
+ try {
91
+ log( chalk.green( ' ... pushing to the Artifact Registry' ) )
92
+ const registry = await shellCmd( `chart-to-registry --chart ${args.chart}` )
93
+ debug( { registry }, '<==chart-to-registry' )
94
+ process.exit( museumStatus )
95
+ } catch ( ex ) {
96
+ log( ex.stderr )
97
+ process.exit( museumStatus + 1 )
98
+ }