@leverege/build-tools 2.110.0 → 2.111.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leverege/build-tools",
3
- "version": "2.110.0",
3
+ "version": "2.111.0",
4
4
  "description": "A collection of build / support tools for Leverege developers",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -98,7 +98,7 @@
98
98
  "googleapis": "^173.0.0",
99
99
  "handlebars": "^4.7.9",
100
100
  "ignore": "^7.0.5",
101
- "inquirer": "14.0.2",
101
+ "inquirer": "^14.0.2",
102
102
  "js-yaml": "^4.2.0",
103
103
  "jsdoc": "^4.0.5",
104
104
  "ms": "^2.1.3",
@@ -107,7 +107,7 @@
107
107
  "p-limit": "^7.3.0",
108
108
  "package-up": "^5.0.0",
109
109
  "readline-sync": "^1.4.10",
110
- "semver": "7.8.4",
110
+ "semver": "^7.8.4",
111
111
  "shell-quote": "^1.8.4",
112
112
  "simple-git": "^3.36.0",
113
113
  "sloc": "^0.3.2",
@@ -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="85.3.3"
11
+ [ -z "$PROMETHEUS_STACK_CHART_VERSION" ] && PROMETHEUS_STACK_CHART_VERSION="86.2.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
@@ -342,7 +342,7 @@ alertmanager:
342
342
  - alertname="GKEMaintenanceInProgress"
343
343
  - maintenance="true"
344
344
  target_matchers:
345
- - alertname=~"KubernetesNodeNotReady|KubernetesPodNotHealthy|KubernetesPodCrashLooping|frequent_app_restarts"
345
+ - alertname=~"KubernetesNodeNotReady|KubernetesPodNotHealthy|KubernetesPodCrashLooping|frequent_app_restarts|KubernetesStatefulsetDown|KubernetesDaemonsetMisscheduled"
346
346
 
347
347
  route:
348
348
  receiver: slack # default for everything
@@ -68,7 +68,7 @@ spec:
68
68
  summary: Checks the number of database conflicts
69
69
  expr: |-
70
70
  rate(cnpg_pg_stat_database_deadlocks[5m]) > 0
71
- for: 1m
71
+ for: 3m
72
72
  labels:
73
73
  severity: warning
74
74
  - alert: ReplicaFailingReplication
@@ -77,7 +77,7 @@ spec:
77
77
  summary: Checks if the replica is failing to replicate
78
78
  expr: |-
79
79
  cnpg_pg_replication_in_recovery > cnpg_pg_replication_is_wal_receiver_up
80
- for: 1m
80
+ for: 3m
81
81
  labels:
82
82
  severity: warning
83
83
  #
@@ -85,7 +85,7 @@ spec:
85
85
  #
86
86
  - alert: PostgresqlDown
87
87
  expr: cnpg_collector_up == 0
88
- for: 1m
88
+ for: 3m
89
89
  labels:
90
90
  severity: critical
91
91
  annotations:
@@ -94,9 +94,9 @@ spec:
94
94
 
95
95
  - alert: PostgresqlRestarted
96
96
  expr: time() - cnpg_pg_postmaster_start_time < 60
97
- for: 2m
97
+ for: 0m
98
98
  labels:
99
- severity: critical
99
+ severity: warning
100
100
  annotations:
101
101
  summary: Postgresql restarted (instance {{ $labels.instance }})
102
102
  description: "Postgresql restarted\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"
@@ -76,7 +76,7 @@ spec:
76
76
  LABELS = {{ $labels }}
77
77
  - alert: ElasticsearchHealthyNodes
78
78
  expr: elasticsearch_cluster_health_number_of_nodes < 3
79
- for: 0m
79
+ for: 5m
80
80
  labels:
81
81
  severity: critical
82
82
  annotations:
@@ -87,7 +87,7 @@ spec:
87
87
  LABELS = {{ $labels }}
88
88
  - alert: ElasticsearchHealthyDataNodes
89
89
  expr: elasticsearch_cluster_health_number_of_data_nodes < 3
90
- for: 0m
90
+ for: 5m
91
91
  labels:
92
92
  severity: critical
93
93
  annotations:
@@ -142,7 +142,7 @@ spec:
142
142
  LABELS = {{ $labels }}
143
143
  - alert: ElasticsearchUnassignedShards
144
144
  expr: elasticsearch_cluster_health_unassigned_shards > 0
145
- for: 0m
145
+ for: 5m
146
146
  labels:
147
147
  severity: critical
148
148
  annotations:
@@ -154,7 +154,7 @@ spec:
154
154
  LABELS = {{ $labels }}
155
155
  - alert: KubernetesStatefulsetDown
156
156
  expr: kube_statefulset_replicas != kube_statefulset_status_replicas_ready > 0
157
- for: 3m # awesome was 1m
157
+ for: 5m # awesome was 1m; bumped to 3m, then 5m for GKE rolling updates
158
158
  labels:
159
159
  severity: critical
160
160
  annotations:
@@ -228,8 +228,11 @@ spec:
228
228
  VALUE = {{ $value }}
229
229
  LABELS = {{ $labels }}
230
230
  - alert: KubernetesReplicasetReplicasMismatch
231
- expr: kube_replicaset_spec_replicas != kube_replicaset_status_ready_replicas
232
- for: 15m # awesome was => 10m
231
+ expr: |
232
+ (kube_replicaset_spec_replicas != kube_replicaset_status_ready_replicas)
233
+ * on (namespace, replicaset) group_left()
234
+ kube_replicaset_owner{owner_kind!="Deployment"}
235
+ for: 15m # awesome was => 10m; Deployment-owned RSes excluded (covered by KubernetesDeploymentReplicasMismatch)
233
236
  labels:
234
237
  severity: warning
235
238
  annotations:
@@ -306,7 +309,7 @@ spec:
306
309
  LABELS = {{ $labels }}
307
310
  - alert: KubernetesDaemonsetMisscheduled
308
311
  expr: kube_daemonset_status_number_misscheduled > 0
309
- for: 1m
312
+ for: 5m
310
313
  labels:
311
314
  severity: critical
312
315
  annotations:
@@ -339,7 +342,7 @@ spec:
339
342
  LABELS = {{ $labels }}
340
343
  - alert: KubernetesApiServerErrors
341
344
  expr: sum(rate(apiserver_request_total{job="apiserver",code=~"(?:5..)"}[1m])) by (instance, job) / sum(rate(apiserver_request_total{job="apiserver"}[1m])) by (instance, job) * 100 > 3
342
- for: 2m
345
+ for: 5m
343
346
  labels:
344
347
  severity: critical
345
348
  annotations:
@@ -10,7 +10,7 @@ spec:
10
10
  rules:
11
11
  - alert: RedisDown
12
12
  expr: redis_up == 0
13
- for: 0m
13
+ for: 2m
14
14
  labels:
15
15
  severity: critical
16
16
  annotations:
@@ -21,7 +21,7 @@ spec:
21
21
  LABELS = {{ $labels }}
22
22
  - alert: RedisMissingMaster
23
23
  expr: (count(redis_instance_info{role="master"}) or vector(0)) < 1
24
- for: 0m
24
+ for: 2m
25
25
  labels:
26
26
  severity: critical
27
27
  annotations:
@@ -43,7 +43,7 @@ spec:
43
43
  LABELS = {{ $labels }}
44
44
  - alert: RedisDisconnectedSlaves
45
45
  expr: count without (instance, job) (redis_connected_slaves) - sum without (instance, job) (redis_connected_slaves) - 1 > 0
46
- for: 0m
46
+ for: 2m
47
47
  labels:
48
48
  severity: critical
49
49
  annotations:
@@ -54,7 +54,7 @@ spec:
54
54
  LABELS = {{ $labels }}
55
55
  - alert: RedisReplicationBroken
56
56
  expr: delta(redis_connected_slaves[1m]) < 0
57
- for: 0m
57
+ for: 2m
58
58
  labels:
59
59
  severity: critical
60
60
  annotations:
@@ -10,7 +10,7 @@ spec:
10
10
  rules:
11
11
  - alert: TraefikServiceDown
12
12
  expr: count(traefik_service_server_up) by (service) == 0
13
- for: 0m
13
+ for: 2m
14
14
  labels:
15
15
  severity: critical
16
16
  annotations:
@@ -0,0 +1,12 @@
1
+ #!/bin/bash
2
+ #
3
+ # The network policy sets:
4
+ #
5
+ # ingressNSMatchLabels: # this is why default ns gets labelled
6
+ # redis: external
7
+ #
8
+ # which should be specifically set in redis client service helm charts but
9
+ # for now we set it hear without being forced to upgraed al of the legacy
10
+ # helm charts. This setting will eventually end up in the leverege base chart.
11
+ #
12
+ kubectl label namespace default redis=external
@@ -1,7 +1,7 @@
1
1
  image:
2
2
  registry: us-docker.pkg.dev
3
3
  repository: leverege-registry/bitnami-mirror/images/valkey
4
- # tag: 8.1.3-devian-12-r1
4
+ # tag: 8.1.3-debian-12-r1
5
5
 
6
6
  global:
7
7
  security:
@@ -14,6 +14,14 @@ auth:
14
14
  enabled: false
15
15
  sentinel: true
16
16
 
17
+ networkPolicy:
18
+ enabled: true
19
+ allowExternal: false
20
+ ingressNSMatchLabels: # this is why default ns gets labelled
21
+ redis: external
22
+ ingressNSPodMatchLabels:
23
+ redis-client: true
24
+
17
25
  primary:
18
26
  replicaCount: 1
19
27
 
@@ -11,7 +11,7 @@ function installVeleroEnvironment() {
11
11
  gcloud config set project $GCP_PROJECT_ID
12
12
 
13
13
  ## The major chart version will determine the bucket suffix
14
- [ -z "$VELERO_CHART_VERSION" ] && VELERO_CHART_VERSION="11"
14
+ [ -z "$VELERO_CHART_VERSION" ] && VELERO_CHART_VERSION="12"
15
15
 
16
16
  ## Create a bucket
17
17
  BUCKET="$GCP_PROJECT_ID-velero-$VELERO_CHART_VERSION"
@@ -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.4.0"
9
- EXPECTED_CLIENT_VERSION="v1.18.0"
8
+ VELERO_CHART_VERSION="12.0.3"
9
+ EXPECTED_CLIENT_VERSION="v1.18.1"
10
10
 
11
11
  addHelmRepo vmware-tanzu https://vmware-tanzu.github.io/helm-charts
12
12
 
package/src/overwhelm.mjs CHANGED
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // XXX console.log( `TOP=>[${process.cwd()}] PWD=[${process.env.PWD}]` )
4
3
  /* eslint-disable security/detect-non-literal-fs-filename */
5
4
 
6
5
  import path from 'node:path'
@@ -8,7 +7,6 @@ import fs from 'node:fs'
8
7
 
9
8
  import chalk from 'chalk'
10
9
  import cliArgs from 'command-line-args'
11
- // const cliHelp = require( 'command-line-usage' )
12
10
  import deepmerge from 'deepmerge'
13
11
  import { glob } from 'glob'
14
12
  import ask from 'readline-sync'
@@ -1,55 +0,0 @@
1
- #!/usr/bin/env node
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
- //
5
- import chalk from 'chalk'
6
- import commandLineArgs from 'command-line-args'
7
- import commandLineUsage from 'command-line-usage'
8
- import { lt as semverLt } from 'semver'
9
-
10
- import { log, shellCmd } from './Utils.mjs'
11
-
12
- const commandLineOptions = [
13
- {
14
- name : 'help',
15
- type : Boolean,
16
- description : '{green display this help screen}',
17
- },
18
- ]
19
-
20
- const sections = [
21
- {
22
- header : 'Leverege Helm Chart Museum Pusher',
23
- content : `{green This legacy tool acts as a simple method for assembling and storing a local
24
- helm chart structure on the Leverege Chart Museum using Google Cloud Storage.
25
- This approach is considered legacy since we have transitioned to using the
26
- Google Artifact Registry for distributing helm charts.
27
- }`
28
- },
29
- { header : 'Options',
30
- optionList : commandLineOptions,
31
- },
32
- ]
33
-
34
- const args = commandLineArgs( commandLineOptions, { camelCase : true, partial : true } )
35
- const usage = commandLineUsage( sections )
36
-
37
- if ( args.help ) {
38
- log( usage )
39
- process.exit( 0 )
40
- }
41
-
42
- const pushItGood = async () => {
43
- const version = await shellCmd( 'helm version --short' )
44
- const pusher = ( semverLt( version, '3.7.0' ) ? 'push' : 'cm-push' )
45
-
46
- try {
47
- const museum = await shellCmd( `helm ${pusher} helm leverege` )
48
- log( chalk.green( museum ) )
49
- } catch ( ex ) {
50
- log( chalk.red( ex.stderr ) )
51
- process.exit( 1 )
52
- }
53
- }
54
-
55
- pushItGood()
@@ -1,75 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import fs from 'node:fs'
4
- import path from 'node:path'
5
-
6
- import yaml from 'js-yaml'
7
- import { Command } from 'commander'
8
- import chalk from 'chalk'
9
-
10
- import { log, err } from './Utils.mjs'
11
-
12
- const program = new Command()
13
-
14
- program
15
- .name( 'fetch-alerts' )
16
- .description( 'Fetch a Prometheus alert YAML file and convert it to a PrometheusRule CRD.' )
17
- .argument( '<sourceFile>', 'YAML filename to fetch from awesome-prometheus' )
18
- .option( '-o, --output <outputFile>', 'Output file name', 'converted-alerts.yaml' )
19
- .option( '-n, --name <customName>', 'Override metadata.name in the PrometheusRule' )
20
- .option( '--dry-run', 'Print output to console instead of writing to file' )
21
- .parse()
22
-
23
- const [ sourceFile ] = program.args
24
- const { output : outputFile, dryRun, name : customName } = program.opts()
25
-
26
- const BASE_URL = 'https://raw.githubusercontent.com/samber/awesome-prometheus-alerts/master/dist/rules'
27
- const SOURCE_URL = `${BASE_URL}/${sourceFile}`
28
-
29
- const defaultName = path.basename( sourceFile ).replace( /\.(yaml|yml)$/, '' )
30
- const metadataName = customName || defaultName
31
-
32
- async function fetchAndConvert() {
33
- try {
34
- log( chalk.blueBright( `🔍 Fetching YAML from ${SOURCE_URL}...` ) )
35
- const response = await fetch( SOURCE_URL )
36
- if ( !response.ok ) throw new Error( `Failed to fetch: ${response.statusText}` )
37
-
38
- const rawYaml = await response.text()
39
- const parsedYaml = yaml.load( rawYaml )
40
- if ( !parsedYaml.groups ) throw new Error( 'Invalid YAML structure, missing "groups"' )
41
-
42
- const prometheusRule = {
43
- apiVersion : 'monitoring.coreos.com/v1',
44
- kind : 'PrometheusRule',
45
- metadata : {
46
- name : metadataName,
47
- namespace : 'prometheus',
48
- },
49
- spec : {
50
- groups : parsedYaml.groups.map( group => ( {
51
- name : `${group.name}-rules`,
52
- rules : group.rules,
53
- } ) ),
54
- },
55
- }
56
-
57
- const formattedYaml = yaml.dump( prometheusRule, {
58
- noRefs : true,
59
- indent : 2,
60
- lineWidth : -1,
61
- } )
62
-
63
- if ( dryRun ) {
64
- log( chalk.green( `\nđŸŸĸ Dry Run Output for: ${chalk.yellow( metadataName )}\n` ) )
65
- log( formattedYaml )
66
- } else {
67
- fs.writeFileSync( outputFile, formattedYaml, 'utf8' ) // eslint-disable-line security/detect-non-literal-fs-filename
68
- log( chalk.green( `✅ Converted YAML written to ${chalk.cyan( outputFile )}` ) )
69
- }
70
- } catch ( error ) {
71
- err( chalk.red( '❌ Error:' ), error.message )
72
- }
73
- }
74
-
75
- fetchAndConvert()
@@ -1,85 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { Command } from 'commander'
4
-
5
- import { shellCmd, log, warning, errorExit } from './Utils.mjs'
6
-
7
- const program = new Command()
8
-
9
- program
10
- .requiredOption( '--project <projectId>', 'GCP project ID of the GSA' )
11
- .requiredOption( '--bucket <bucketName>', 'GCS bucket name (no gs:// prefix)' )
12
- .requiredOption( '--gsa <gsaName>', 'Service account name, e.g. my-service' )
13
- .requiredOption( '--role <roleId>', 'Custom role ID', 'leveregeStorageObjectReader' )
14
- .option( '--org', 'Treat as GCP organizational level role' )
15
- .option( '--add', 'Add IAM binding (default)' )
16
- .option( '--remove', 'Remove IAM binding' )
17
- .option( '--dry-run', 'Show command without executing' )
18
-
19
- program.parse( process.argv )
20
-
21
- const opts = program.opts()
22
-
23
- // Validate mutually exclusive add/remove
24
- if ( opts.add && opts.remove ) {
25
- errorExit( 'You cannot specify both --add and --remove.' )
26
- }
27
-
28
- const action = opts.remove ? 'remove' : 'add'
29
-
30
- const {
31
- project,
32
- org,
33
- bucket,
34
- gsa,
35
- role,
36
- dryRun
37
- } = opts
38
-
39
- const orgId = await shellCmd( 'gcloud organizations list --format="value(ID)"' )
40
- const gsaEmail = `${gsa}@${project}.iam.gserviceaccount.com`
41
- const fullRole = org ? `organizations/${orgId}/roles/${role}` : `roles/${role}`
42
- const bucketUri = `gs://${bucket}`
43
-
44
- const iamMember = `serviceAccount:${gsaEmail}:${fullRole}`
45
-
46
- const command = action === 'add' ?
47
- [ 'gsutil', 'iam', 'ch', iamMember, bucketUri ] :
48
- [ 'gsutil', 'iam', 'ch', '-d', iamMember, bucketUri ]
49
-
50
- log( `🔧 ${action === 'add' ? 'Granting' : 'Removing'} ${fullRole} for ${gsaEmail} on ${bucketUri}...` )
51
-
52
- if ( dryRun ) {
53
- warning( '💡 DRY RUN mode — no commands executed.' )
54
- log( `🔗 Command:\n$ ${command.join( ' ' )}` )
55
- process.exit( 0 )
56
- }
57
-
58
- try {
59
- const result = await shellCmd( command )
60
- log( `✅ IAM ${action} successful:\n${result}` )
61
- } catch ( err ) {
62
- errorExit( `❌ Failed to ${action} IAM binding: ${err.message}` )
63
- }
64
-
65
- // === Post-change audit ===
66
- log( '🔍 Verifying IAM policy for this GSA on the bucket...\n' )
67
-
68
- try {
69
- const policyRaw = await shellCmd( [ 'gsutil', 'iam', 'get', bucketUri ] )
70
- const policy = JSON.parse( policyRaw )
71
-
72
- const matchingRoles = policy.bindings.filter(
73
- b => b.members.includes( `serviceAccount:${gsaEmail}` )
74
- )
75
-
76
- if ( matchingRoles.length === 0 ) {
77
- log( `â„šī¸ No IAM bindings found for ${gsaEmail} on ${bucketUri}.` )
78
- } else {
79
- for ( const binding of matchingRoles ) {
80
- log( `🔐 ${gsaEmail} has role: ${binding.role}` )
81
- }
82
- }
83
- } catch ( err ) {
84
- warning( `âš ī¸ Failed to retrieve or parse IAM policy: ${err.message}` )
85
- }
package/src/test.json DELETED
@@ -1,4 +0,0 @@
1
- {
2
- "name": "@leverege/packagename",
3
- "main": "lib/index.js"
4
- }
@@ -1,12 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import {
4
- establishOauthAccess,
5
- log,
6
- } from './Utils.mjs'
7
-
8
- // simple test program for oauth nonsense
9
-
10
- const results = await establishOauthAccess()
11
-
12
- log( { results }, '<==after establishOauthAccess' )
package/src/unleash.mjs DELETED
@@ -1,57 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import SimpleGit from 'simple-git'
4
-
5
- import { shellCmd } from './Utils.mjs'
6
-
7
- const git = new SimpleGit()
8
-
9
- const getCurrentBranchName = async () => {
10
- const branchInfo = await git.branch()
11
-
12
- // first check to see if there are no branches - new repo?
13
- if ( Object.keys( branchInfo.branches ).length === 0 ) { return '' }
14
-
15
- return Object
16
- .entries( branchInfo.branches )
17
- .find( ( [ name, info ] ) => ( info.current ) )[0]
18
- }
19
-
20
- const isProtected = async () => {
21
- const theBranch = await getCurrentBranchName()
22
-
23
- const protectedBranches = [ 'main', 'master', 'development' ]
24
- const additionalProtectedBranches = [ ...process.argv.slice( 2 ) ]
25
-
26
- // Check if the current branch starts with any of the additional
27
- // protected branch name
28
- let matchesAdditionalBranch = false
29
- for ( let i = 0; i < additionalProtectedBranches.length; i++ ) {
30
- matchesAdditionalBranch = matchesAdditionalBranch ||
31
- theBranch.startsWith( additionalProtectedBranches[i] )
32
- }
33
-
34
- return protectedBranches.includes( theBranch ) || matchesAdditionalBranch
35
- }
36
-
37
- const npmRunner = async ( script ) => {
38
- try {
39
- const cmd = `npm run ${script}`
40
- const results = await shellCmd( cmd, { stdio : 'inherit' } )
41
- return results
42
- } catch ( err ) { // eslint-disable-line no-unused-vars
43
- process.exit( 1 )
44
- }
45
- return undefined
46
- }
47
-
48
- ( async () => {
49
- if ( await isProtected() ) {
50
- const script = [ 'test', 'lint' ]
51
- for ( let i = 0; i < script.length; i++ ) {
52
- await npmRunner( script[i] ) // eslint-disable-line no-await-in-loop
53
- }
54
- } else {
55
- process.exit( 0 )
56
- }
57
- } )()