@leverege/build-tools 2.45.0-mono.1 → 2.45.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 +1 -4
- package/src/Utils.mjs +13 -192
- package/src/dirty-git.sh +1 -1
- package/src/helm-charts/db-timescale-plain/.nohelm +0 -0
- package/src/helm-charts/db-timescale-plain/.nohelmdn +0 -0
- package/src/helm-charts/db-timescale-plain/db-timescale-plain.yaml.ovh +120 -0
- package/src/helm-charts/db-timescale-plain/gitignore +1 -0
- package/src/helm-charts/db-timescale-plain/helmdn.plugin +3 -0
- package/src/helm-charts/db-timescale-plain/helmup.plugin +3 -0
- package/src/helm-charts/redis/helmup.plugin +1 -1
- package/src/helm-charts/timescale-db/timescale-db-local.yaml +10 -10
- package/src/k8x.sh +57 -6
- package/src/Docker.mjs +0 -252
- package/src/docker-to-registry.mjs +0 -71
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leverege/build-tools",
|
|
3
|
-
"version": "2.45.0
|
|
3
|
+
"version": "2.45.0",
|
|
4
4
|
"description": "A collection of build / support tools for Leverege developers",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -60,12 +60,9 @@
|
|
|
60
60
|
"enquirer": "^2.4.1",
|
|
61
61
|
"execa": "^8.0.1",
|
|
62
62
|
"glob": "^10.3.10",
|
|
63
|
-
"handlebars": "^4.7.8",
|
|
64
|
-
"inquirer": "^9.2.14",
|
|
65
63
|
"js-yaml": "^4.1.0",
|
|
66
64
|
"ms": "^2.1.3",
|
|
67
65
|
"npm-registry-fetch": "^16.1.0",
|
|
68
|
-
"package-up": "^5.0.0",
|
|
69
66
|
"parse-gitignore": "^2.0.0",
|
|
70
67
|
"read-pkg": "^9.0.1",
|
|
71
68
|
"readline-sync": "^1.4.10",
|
package/src/Utils.mjs
CHANGED
|
@@ -2,9 +2,6 @@ import { existsSync, readdirSync, readFileSync } from 'node:fs'
|
|
|
2
2
|
|
|
3
3
|
import chalk from 'chalk'
|
|
4
4
|
import { $ } from 'execa'
|
|
5
|
-
import inquirer from 'inquirer'
|
|
6
|
-
import { glob } from 'glob'
|
|
7
|
-
import { packageUp } from 'package-up'
|
|
8
5
|
import YAML from 'js-yaml'
|
|
9
6
|
|
|
10
7
|
const debugEnabled = process.env.BUILD_TOOLS_DEBUG === '1'
|
|
@@ -22,34 +19,12 @@ export const condir = ( obj, text = '' ) => {
|
|
|
22
19
|
export const debug = ( obj, text ) => {
|
|
23
20
|
if ( debugEnabled ) { condir( obj, text ) }
|
|
24
21
|
}
|
|
25
|
-
export const warning = ( warningText ) => {
|
|
26
|
-
const fullWarning = `***WARNING: ${warningText}`
|
|
27
|
-
console.error( `\n${chalk.yellow.bold( fullWarning )}` )
|
|
28
|
-
}
|
|
29
|
-
|
|
30
22
|
export const errorExit = ( error, opts = { errorCode : 1 } ) => {
|
|
31
23
|
console.error( `\n${chalk.red.bold( error )}\n` )
|
|
32
24
|
if ( opts?.errorCode ) { process.exit( opts.errorCode ) }
|
|
33
25
|
}
|
|
34
26
|
/* eslint-enable no-console */
|
|
35
27
|
|
|
36
|
-
/**
|
|
37
|
-
* General "yes" to proceed function.
|
|
38
|
-
*/
|
|
39
|
-
export const proceed = async ( query = 'Do you wish to proceed?' ) => {
|
|
40
|
-
await inquirer.prompt( [
|
|
41
|
-
{
|
|
42
|
-
type : 'confirm',
|
|
43
|
-
name : 'proceed',
|
|
44
|
-
message : query,
|
|
45
|
-
default : true,
|
|
46
|
-
}
|
|
47
|
-
]
|
|
48
|
-
).then( ( answer ) => {
|
|
49
|
-
if ( !answer.proceed ) { process.exit( 0 ) }
|
|
50
|
-
} )
|
|
51
|
-
}
|
|
52
|
-
|
|
53
28
|
export const shellCmd = async ( cmdstr, opts = {} ) => {
|
|
54
29
|
try {
|
|
55
30
|
// due to the escaping rules we pull apart the cmdstr and invoke $ using
|
|
@@ -110,22 +85,15 @@ export const parseJsonFile = async ( jsonFile ) => {
|
|
|
110
85
|
throw new Error( `${error} in ${jsonFile}` )
|
|
111
86
|
}
|
|
112
87
|
}
|
|
113
|
-
throw new Error( `
|
|
88
|
+
throw new Error( `File ${jsonFile} does not exist` )
|
|
114
89
|
/* eslint-enable security/detect-non-literal-fs-filename */
|
|
115
90
|
}
|
|
116
91
|
|
|
117
92
|
// Parses the ./package.json file and verifies there is a properly formatted
|
|
118
93
|
// leverege.registry section present.
|
|
119
|
-
const deprecated = ( opts ) => {
|
|
120
|
-
log( chalk.red.bold( `\n ***DEPRECATED: ${opts.deprecationError}` ) )
|
|
121
|
-
log( chalk.white( opts.deprecationInfo ) )
|
|
122
|
-
process.exit( 1 )
|
|
123
|
-
}
|
|
124
|
-
|
|
125
94
|
export const parsePackageJson = async ( packageFileName ) => {
|
|
126
95
|
const packageJson = await parseJsonFile( packageFileName )
|
|
127
96
|
|
|
128
|
-
// deprecation checks are here to ease the pain of upgrading older repos
|
|
129
97
|
const leveregeClauseError = `leverege.registry statement, it should
|
|
130
98
|
resemble something like:
|
|
131
99
|
|
|
@@ -134,116 +102,25 @@ export const parsePackageJson = async ( packageFileName ) => {
|
|
|
134
102
|
},
|
|
135
103
|
|
|
136
104
|
`
|
|
137
|
-
|
|
138
|
-
if ( !registry ) {
|
|
105
|
+
|
|
106
|
+
if ( !packageJson?.leverege?.registry ) {
|
|
139
107
|
errorExit( `Error: package.json is missing a proper ${leveregeClauseError}` )
|
|
140
108
|
}
|
|
141
109
|
|
|
142
|
-
const
|
|
143
|
-
if (
|
|
110
|
+
const artifacts = packageJson.leverege.registry.split( '/' )
|
|
111
|
+
if ( artifacts.length !== 3 ) {
|
|
144
112
|
errorExit( `Error: package.json has a malformed ${leveregeClauseError}` )
|
|
145
113
|
}
|
|
146
114
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
const deprecationInfo = `
|
|
156
|
-
Setting the project in the package.json leverege section was used for builds
|
|
157
|
-
being stored in the deprecated GCP container registry. Remove the deprecated
|
|
158
|
-
leverege.project setting from package.json and try again.
|
|
159
|
-
|
|
160
|
-
"leverege": {
|
|
161
|
-
${chalk.red.bold( removeLine )}
|
|
162
|
-
...
|
|
163
|
-
}
|
|
164
|
-
`
|
|
165
|
-
deprecated( { deprecationError, deprecationInfo } )
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// DEPRECATED: leverege.container
|
|
169
|
-
if ( packageJson?.leverege?.container ) {
|
|
170
|
-
const removeLine = `"container": "${packageJson.leverege.container}",`
|
|
171
|
-
|
|
172
|
-
const deprecationError = 'leverege.container is no longer supported'
|
|
173
|
-
const deprecationInfo = `
|
|
174
|
-
Setting the container name explicitly from the package.json leverge block
|
|
175
|
-
is no longer supported. The container name will be automatically derived
|
|
176
|
-
from the git repository's remote root, which is the default behavior. Remove
|
|
177
|
-
the container line from the leverege section in package.json and try again.
|
|
178
|
-
|
|
179
|
-
"leverege": {
|
|
180
|
-
${chalk.red.bold( removeLine )}
|
|
181
|
-
...
|
|
182
|
-
}
|
|
183
|
-
`
|
|
184
|
-
deprecated( { deprecationError, deprecationInfo } )
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// DEPRECATED: leverege.nodeimg
|
|
188
|
-
if ( packageJson?.leverege?.nodeimg ) {
|
|
189
|
-
const removeLine = `"nodeimg": "${packageJson.leverege.nodeimg}",`
|
|
190
|
-
|
|
191
|
-
const deprecationError = 'leverege.nodeimg is no longer supported'
|
|
192
|
-
const deprecationInfo = `
|
|
193
|
-
Setting the node base image using the nodeimg statement in package.json is no
|
|
194
|
-
longer supported. By default the actual node image version will be defaulted
|
|
195
|
-
by this script and will rarely need to be a specific version. Remove the
|
|
196
|
-
nodeimg line from the leverege section in package.json and try again.
|
|
197
|
-
|
|
198
|
-
"leverege": {
|
|
199
|
-
${chalk.red.bold( removeLine )}
|
|
200
|
-
...
|
|
201
|
-
}
|
|
202
|
-
`
|
|
203
|
-
deprecated( { deprecationError, deprecationInfo } )
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// DEPRECATED: leverege.artifact
|
|
207
|
-
if ( packageJson?.leverege?.artifact ) {
|
|
208
|
-
const removeLine = `"artifact": "${packageJson.leverege.artifact}",`
|
|
209
|
-
const replaceLine = `"registry": "us-docker.pkg.dev/leverege-registry/${packageJson.leverege.artifact}",`
|
|
210
|
-
|
|
211
|
-
const deprecationError = 'leverege.artifact is no longer supported'
|
|
212
|
-
const deprecationInfo = `
|
|
213
|
-
Setting the registry folder via the ${chalk.yellow.bold( 'artifact' )} statement is no longer supported.
|
|
214
|
-
Instead use the ${chalk.green.bold( 'leverege.registry' )} setting to specify the full artifact registry
|
|
215
|
-
and folder used for storing the docker image. Replace the artifact line with the
|
|
216
|
-
full registry path in package.json and try again.
|
|
217
|
-
|
|
218
|
-
"leverege": {
|
|
219
|
-
${chalk.red.bold( removeLine )}
|
|
220
|
-
${chalk.green.bold( replaceLine )}
|
|
221
|
-
...
|
|
222
|
-
}
|
|
223
|
-
`
|
|
224
|
-
deprecated( { deprecationError, deprecationInfo } )
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// DEPRECATED: leverege.nodeops
|
|
228
|
-
if ( packageJson?.leverege?.nodeops ) {
|
|
229
|
-
const removeLine = `"nodeops": "${packageJson.leverege.nodeops}",`
|
|
230
|
-
|
|
231
|
-
const deprecationError = 'leverege.nodeops is no longer supported'
|
|
232
|
-
const deprecationInfo = `
|
|
233
|
-
Setting the hard coded node options on the image is no longer supported. The
|
|
234
|
-
better approach is to add ${chalk.green.bold( 'NODE_OPTIONS' )} to the config section of the chart's
|
|
235
|
-
values.yaml to allow downstream users to easily tune the options as needed.
|
|
236
|
-
Remove the nodeops line from the leverege section in package.json and try again.
|
|
237
|
-
|
|
238
|
-
"leverege": {
|
|
239
|
-
${chalk.red.bold( removeLine )}
|
|
240
|
-
...
|
|
241
|
-
}
|
|
242
|
-
`
|
|
243
|
-
deprecated( { deprecationError, deprecationInfo } )
|
|
115
|
+
return {
|
|
116
|
+
artifactRegistry : {
|
|
117
|
+
registry : packageJson.leverege.registry,
|
|
118
|
+
region : artifacts[0],
|
|
119
|
+
project : artifacts[1],
|
|
120
|
+
repository : artifacts[2],
|
|
121
|
+
},
|
|
122
|
+
...packageJson,
|
|
244
123
|
}
|
|
245
|
-
|
|
246
|
-
return { artifactRegistry, ...packageJson }
|
|
247
124
|
}
|
|
248
125
|
|
|
249
126
|
export const parseHelmChart = async ( helmroot ) => {
|
|
@@ -260,59 +137,3 @@ export const parseHelmChart = async ( helmroot ) => {
|
|
|
260
137
|
}
|
|
261
138
|
} )
|
|
262
139
|
}
|
|
263
|
-
|
|
264
|
-
export const describeRepository = async () => {
|
|
265
|
-
const gitRoot = await getGitRootDirectory()
|
|
266
|
-
const subPkgs = await glob( `${gitRoot}/packages/**/package.json`, { ignore : '/**/node_modules/**' } )
|
|
267
|
-
|
|
268
|
-
let rootPackageJson
|
|
269
|
-
try {
|
|
270
|
-
rootPackageJson = await parseJsonFile( `${gitRoot}/package.json` )
|
|
271
|
-
} catch ( error ) {
|
|
272
|
-
rootPackageJson = { inValid : true, error : 'invalid or non-existent root package.json file' }
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
log( chalk.green.bold( '\nParsing and analyzing the package.json file\n' ) )
|
|
276
|
-
let closestPackageJson
|
|
277
|
-
try {
|
|
278
|
-
closestPackageJson = await parsePackageJson( './package.json' )
|
|
279
|
-
} catch ( error ) {
|
|
280
|
-
errorExit( error )
|
|
281
|
-
}
|
|
282
|
-
const containerName = closestPackageJson.name
|
|
283
|
-
const artifactProject = closestPackageJson.artifactRegistry.project
|
|
284
|
-
const artifactRegistry = closestPackageJson.leverege.registry
|
|
285
|
-
|
|
286
|
-
const currentDir = process.cwd()
|
|
287
|
-
const closestPkg = await packageUp()
|
|
288
|
-
|
|
289
|
-
// get the name of the current workspace, if we're in one
|
|
290
|
-
let wsName
|
|
291
|
-
try {
|
|
292
|
-
wsName = await shellCmd( 'npm exec -c pwd -ws' )
|
|
293
|
-
} catch ( err ) { }
|
|
294
|
-
|
|
295
|
-
let gitRemote
|
|
296
|
-
try {
|
|
297
|
-
gitRemote = await shellCmd( 'git config --get remote.origin.url' )
|
|
298
|
-
} catch ( err ) { }
|
|
299
|
-
|
|
300
|
-
// TODO: Add in Define VERBOSE_DOCKREATE_NPM="yes" for verbose build logging
|
|
301
|
-
// TODO: Validity check for version and package.json
|
|
302
|
-
|
|
303
|
-
return {
|
|
304
|
-
artifactProject,
|
|
305
|
-
artifactRegistry,
|
|
306
|
-
containerName,
|
|
307
|
-
currentDir,
|
|
308
|
-
closestPkg,
|
|
309
|
-
gitRoot,
|
|
310
|
-
gitRemote,
|
|
311
|
-
isMonoRepo : subPkgs?.length > 0,
|
|
312
|
-
isNpmWorkspace : rootPackageJson?.workspaces?.length > 0,
|
|
313
|
-
rootPackageJson,
|
|
314
|
-
closestPackageJson,
|
|
315
|
-
subPkgs,
|
|
316
|
-
wsName,
|
|
317
|
-
}
|
|
318
|
-
}
|
package/src/dirty-git.sh
CHANGED
|
@@ -36,7 +36,7 @@ do
|
|
|
36
36
|
fi
|
|
37
37
|
fi
|
|
38
38
|
[ -f "Versions.json" ] && locked="$LOCKD" || locked=" "
|
|
39
|
-
[ ! -d "elasticsearch8" ] && elastic="$ELAS7" || elastic=" "
|
|
39
|
+
[ ! -d "elasticsearch8" ] && [ -d "elasticsearch" ] && elastic="$ELAS7" || elastic=" "
|
|
40
40
|
cd - &>/dev/null
|
|
41
41
|
printf "${status} %-28s ${stash}${ahead}${locked}${elastic} %s\n" $dir $branch
|
|
42
42
|
done
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Artifact Chart => https://artifacthub.io/packages/helm/cloudnative-pg/cloudnative-pg
|
|
2
|
+
# Examples Charts => https://cloudnative-pg.io/documentation/current/samples/
|
|
3
|
+
apiVersion: postgresql.cnpg.io/v1
|
|
4
|
+
kind: Cluster
|
|
5
|
+
metadata:
|
|
6
|
+
name: db-timescale-plain
|
|
7
|
+
namespace: cnpg-operands
|
|
8
|
+
spec:
|
|
9
|
+
instances: 1
|
|
10
|
+
logLevel: debug
|
|
11
|
+
|
|
12
|
+
description: "Leverege Plain Timescale DB"
|
|
13
|
+
imageName: us-docker.pkg.dev/leverege-registry/system/images/leverege-pgsql:16.1-cnpg-tsdb2-beta.6
|
|
14
|
+
bootstrap:
|
|
15
|
+
initdb:
|
|
16
|
+
postInitTemplateSQL:
|
|
17
|
+
- CREATE EXTENSION timescaledb;
|
|
18
|
+
- CREATE EXTENSION jsquery;
|
|
19
|
+
database: imagine
|
|
20
|
+
owner: imagine
|
|
21
|
+
secret:
|
|
22
|
+
name: db-timescale-plain-imagine-pw # imagine db pw
|
|
23
|
+
|
|
24
|
+
enableSuperuserAccess: true
|
|
25
|
+
superuserSecret:
|
|
26
|
+
name: db-timescale-plain-postgres-pw # postgres db pw
|
|
27
|
+
|
|
28
|
+
affinity:
|
|
29
|
+
# enablePodAntiAffinity: true
|
|
30
|
+
# topologyKey: failure-domain.beta.kubernetes.io/zone
|
|
31
|
+
tolerations:
|
|
32
|
+
- key: "database"
|
|
33
|
+
operator: "Equal"
|
|
34
|
+
value: "true"
|
|
35
|
+
effect: "NoSchedule"
|
|
36
|
+
|
|
37
|
+
# Parameters and pg_hba configuration will be append
|
|
38
|
+
# to the default ones to make the cluster work
|
|
39
|
+
postgresql:
|
|
40
|
+
shared_preload_libraries:
|
|
41
|
+
- timescaledb
|
|
42
|
+
- jsquery
|
|
43
|
+
parameters:
|
|
44
|
+
# max_worker_processes: "60"
|
|
45
|
+
max_worker_processes: "8"
|
|
46
|
+
max_parallel_workers: "8"
|
|
47
|
+
shared_buffers: 2GB
|
|
48
|
+
effective_cache_size: 6GB
|
|
49
|
+
maintenance_work_mem: 1GB
|
|
50
|
+
work_mem: 20MB
|
|
51
|
+
pg_hba:
|
|
52
|
+
# To access through TCP/IP you will need to get username
|
|
53
|
+
# and password from the secret cluster-example-custom-app
|
|
54
|
+
- host all all all md5
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
# Example of rolling update strategy:
|
|
58
|
+
# - unsupervised: automated update of the primary once all
|
|
59
|
+
# replicas have been upgraded (default)
|
|
60
|
+
# - supervised: requires manual supervision to perform
|
|
61
|
+
# the switchover of the primary
|
|
62
|
+
primaryUpdateStrategy: unsupervised
|
|
63
|
+
|
|
64
|
+
serviceAccountTemplate:
|
|
65
|
+
metadata:
|
|
66
|
+
annotations:
|
|
67
|
+
iam.gke.io/gcp-service-account: cnpg-operands-sa@OVH:<PROJECT_ID>.iam.gserviceaccount.com
|
|
68
|
+
|
|
69
|
+
# Require 50Gi of space per instance using ssd storage class
|
|
70
|
+
storage:
|
|
71
|
+
storageClass: premium-rwo
|
|
72
|
+
size: 50Gi
|
|
73
|
+
walStorage:
|
|
74
|
+
storageClass: premium-rwo
|
|
75
|
+
size: 1Gi
|
|
76
|
+
|
|
77
|
+
backup:
|
|
78
|
+
volumeSnapshot:
|
|
79
|
+
labels:
|
|
80
|
+
snapshotOf: db-timescale-plain
|
|
81
|
+
className: cnpg-snapshotclass
|
|
82
|
+
barmanObjectStore:
|
|
83
|
+
destinationPath: gs://OVH:<PROJECT_ID>-barman
|
|
84
|
+
googleCredentials:
|
|
85
|
+
gkeEnvironment: true
|
|
86
|
+
tags:
|
|
87
|
+
cnpgCluster: db-timescale-plain
|
|
88
|
+
wal:
|
|
89
|
+
compression: gzip
|
|
90
|
+
---
|
|
91
|
+
apiVersion: postgresql.cnpg.io/v1
|
|
92
|
+
kind: Pooler
|
|
93
|
+
metadata:
|
|
94
|
+
name: db-timescale-plain-pool-rw
|
|
95
|
+
namespace: cnpg-operands
|
|
96
|
+
spec:
|
|
97
|
+
cluster:
|
|
98
|
+
name: db-timescale-plain
|
|
99
|
+
|
|
100
|
+
instances: 1
|
|
101
|
+
type: rw
|
|
102
|
+
pgbouncer:
|
|
103
|
+
poolMode: session
|
|
104
|
+
parameters:
|
|
105
|
+
max_client_conn: "500"
|
|
106
|
+
default_pool_size: "10"
|
|
107
|
+
---
|
|
108
|
+
apiVersion: postgresql.cnpg.io/v1
|
|
109
|
+
kind: ScheduledBackup
|
|
110
|
+
metadata:
|
|
111
|
+
name: db-timescale-plain-backup
|
|
112
|
+
namespace: cnpg-operands
|
|
113
|
+
spec:
|
|
114
|
+
# https://pkg.go.dev/github.com/robfig/cron#hdr-CRON_Expression_Format
|
|
115
|
+
schedule: "0 0 * * * *"
|
|
116
|
+
cluster:
|
|
117
|
+
name: db-timescale-plain
|
|
118
|
+
method: volumeSnapshot
|
|
119
|
+
backupOwnerReference: self
|
|
120
|
+
immediate: true
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
db-timescale-plain.yaml
|
|
@@ -4,7 +4,7 @@ showInstalling "Redis"
|
|
|
4
4
|
|
|
5
5
|
OCI_CHART="oci://registry-1.docker.io/bitnamicharts/redis"
|
|
6
6
|
|
|
7
|
-
[ -z "$REDIS_CHART_VERSION" ] && REDIS_CHART_VERSION="18.
|
|
7
|
+
[ -z "$REDIS_CHART_VERSION" ] && REDIS_CHART_VERSION="18.12.1"
|
|
8
8
|
|
|
9
9
|
helm upgrade --install redis $OCI_CHART \
|
|
10
10
|
--values redis/redis-local.yaml \
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
postgresql:
|
|
2
2
|
postgresqlExtendedConf:
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
maxWorkerProcesses: 8
|
|
4
|
+
maxParallelWorkers: 8
|
|
5
|
+
maxConnections: 500
|
|
6
|
+
sharedBuffers: 2GB
|
|
7
|
+
effectiveCacheSize: 6GB
|
|
8
|
+
maintenanceWorkMem: 1GB
|
|
9
|
+
workMem: 20MB
|
|
10
|
+
idle_in_transaction_session_timeout: 30000 # 30ms timeout
|
|
11
|
+
maxWalSize: 2GB
|
|
12
|
+
walKeepSegments: 64
|
|
13
13
|
|
|
14
14
|
resources:
|
|
15
15
|
requests:
|
package/src/k8x.sh
CHANGED
|
@@ -1,21 +1,72 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
|
|
3
|
+
. `build-tools --bashfun`
|
|
4
|
+
|
|
5
|
+
if [ ! -x "$(command -v fzf)" ];
|
|
6
|
+
then
|
|
7
|
+
cat<<NO_FZF
|
|
8
|
+
|
|
9
|
+
`color r ***Error:` Missing fzf fuzzy matcher => `color g "brew install fzf"`
|
|
10
|
+
|
|
11
|
+
NO_FZF
|
|
12
|
+
exit 1
|
|
13
|
+
fi
|
|
14
|
+
|
|
3
15
|
cmd=${@:-"bash"}
|
|
4
16
|
ns="default"
|
|
5
17
|
|
|
6
|
-
|
|
18
|
+
case "$cmd" in
|
|
19
|
+
"bash")
|
|
20
|
+
# invoked simply as k8x
|
|
21
|
+
;;
|
|
22
|
+
|
|
23
|
+
"cnpg")
|
|
24
|
+
ns="cnpg-operands" && cmd="bash"
|
|
25
|
+
;;
|
|
26
|
+
|
|
27
|
+
"es8"|"elastic8")
|
|
28
|
+
ns="elastic" && cmd="bash"
|
|
29
|
+
;;
|
|
30
|
+
|
|
31
|
+
"psql"|"pgsql")
|
|
32
|
+
FZFQ="--query=postgresql" && cmd='psql -U postgres'
|
|
33
|
+
;;
|
|
34
|
+
|
|
35
|
+
"redis"|"redis-cli")
|
|
36
|
+
FZFQ="--query=redis" && cmd='redis-cli'
|
|
37
|
+
;;
|
|
38
|
+
|
|
39
|
+
"help"|*)
|
|
40
|
+
if [ "$cmd" != "help" ];
|
|
41
|
+
then
|
|
42
|
+
cat<<BAD_K8X
|
|
43
|
+
|
|
44
|
+
`color r ***Error:` unrecognized k8x target => `color y "$cmd"`
|
|
45
|
+
BAD_K8X
|
|
46
|
+
k8x.sh help
|
|
47
|
+
exit 1
|
|
48
|
+
fi
|
|
7
49
|
|
|
8
|
-
|
|
50
|
+
cat<<K8X_HELP
|
|
51
|
+
|
|
52
|
+
Usage: `color g 'k8x <target>'` where target can be:
|
|
9
53
|
|
|
10
|
-
|
|
54
|
+
`color g cnpg` - run bash on a cloudnative-pg cluster node
|
|
55
|
+
`color g es8` - run bash on an elasticsearch8 node
|
|
56
|
+
`color g psql` - run psql on a legacy database node
|
|
57
|
+
`color g redis` - run redis-cli on a redis master/replica
|
|
58
|
+
`color g help` - this right here
|
|
11
59
|
|
|
12
|
-
|
|
60
|
+
K8X_HELP
|
|
61
|
+
exit 0
|
|
62
|
+
;;
|
|
63
|
+
esac
|
|
13
64
|
|
|
14
|
-
[
|
|
65
|
+
[ -f overwhelm.yaml ] && [ -f package.json ] && overwhelm
|
|
15
66
|
|
|
16
67
|
pod=$(kubectl -n $ns get pods -owide | fzf $FZFQ | awk '{print $1}')
|
|
17
68
|
|
|
18
69
|
kubecmd="kubectl exec -n $ns -it $pod -- $cmd"
|
|
19
|
-
|
|
70
|
+
printf "\n`color y 'Running =>'` `color g \"${kubecmd}\"`\n\n"
|
|
20
71
|
|
|
21
72
|
eval ${kubecmd}
|
package/src/Docker.mjs
DELETED
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs'
|
|
2
|
-
|
|
3
|
-
import chalk from 'chalk'
|
|
4
|
-
import handlebars from 'handlebars'
|
|
5
|
-
|
|
6
|
-
import { errorExit, log, shellCmd, warning } from './Utils.mjs'
|
|
7
|
-
|
|
8
|
-
// The contents of these variables were initially located in files that live in
|
|
9
|
-
// the build-tools repository, but it just became simpler to pull the contents
|
|
10
|
-
// directly into these variables and forego the file loading.
|
|
11
|
-
//
|
|
12
|
-
const dockerfileTemplate = `
|
|
13
|
-
# Version {{regvers}} @ {{date}}
|
|
14
|
-
#
|
|
15
|
-
# The FROM directive sets the Base Image for subsequent instructions
|
|
16
|
-
FROM node:{{nodeimage}} as intermediate
|
|
17
|
-
ENV NODE_ENV production
|
|
18
|
-
|
|
19
|
-
RUN mkdir -p /usr/src/app
|
|
20
|
-
WORKDIR /usr/src/app
|
|
21
|
-
|
|
22
|
-
# Install app dependencies
|
|
23
|
-
COPY ./workspace/ /usr/src/app/
|
|
24
|
-
ENV GRPC_VERBOSITY ERROR
|
|
25
|
-
|
|
26
|
-
# --------------------------------------------------------------
|
|
27
|
-
# copy the ssh keys into place, npm install, and remove them
|
|
28
|
-
# --------------------------------------------------------------
|
|
29
|
-
|
|
30
|
-
# Install packages to install private repos with ssh keys
|
|
31
|
-
COPY ./.npmrc /usr/src/app/.npmrc
|
|
32
|
-
RUN apk --no-cache add openssh-client && \
|
|
33
|
-
apk --update add --no-cache --virtual build-dep g++ gcc libgcc \\
|
|
34
|
-
libstdc++ linux-headers make {{apkadds}} && \
|
|
35
|
-
npm install -g npm@10 && \
|
|
36
|
-
npm ci --only=production --ignore-scripts --no-optional {{npmlogging}} && \
|
|
37
|
-
rm -f /usr/src/app/.npmrc /root/.ssh/*
|
|
38
|
-
|
|
39
|
-
# --------------------------------------------------------------
|
|
40
|
-
# On to the real build now, the thing before was just an intermediate container
|
|
41
|
-
# --------------------------------------------------------------
|
|
42
|
-
|
|
43
|
-
FROM node:{{nodeimage}}
|
|
44
|
-
|
|
45
|
-
# Install tini for PID 1 and replace shell with bash so we can source files
|
|
46
|
-
RUN apk update && \
|
|
47
|
-
apk add --no-cache bash curl tini vim {{apkadds}} && \
|
|
48
|
-
npm install -g npm@10 && \
|
|
49
|
-
rm /bin/sh && ln -s /bin/bash /bin/sh && \
|
|
50
|
-
mkdir -p /usr/src/app /tmp/levlog && \
|
|
51
|
-
chown node:node /usr/src/app
|
|
52
|
-
|
|
53
|
-
{{pluginfile}}
|
|
54
|
-
|
|
55
|
-
ENTRYPOINT [ "/sbin/tini", "--" ]
|
|
56
|
-
WORKDIR /usr/src/app
|
|
57
|
-
|
|
58
|
-
COPY --chown=node:node --from=intermediate /usr/src/app /usr/src/app
|
|
59
|
-
|
|
60
|
-
USER {{runuser}}
|
|
61
|
-
COPY ./bashrc /home/node/.bashrc
|
|
62
|
-
CMD [ "/bin/bash", "-c", "node index.js" ]`
|
|
63
|
-
|
|
64
|
-
const pluginTemplate = `
|
|
65
|
-
# Dockerfile.plugin - optionally extend the service Docker image
|
|
66
|
-
#
|
|
67
|
-
# This file may be used to run additional docker commands during the image
|
|
68
|
-
# build process without needing to maintain a local custom Dockerfile. For
|
|
69
|
-
# example, uncommenting the following docker RUN command will cause the
|
|
70
|
-
# curl and vim packages to be added to the deployed image thus making them
|
|
71
|
-
# available from the pod's command line on k8s:
|
|
72
|
-
#
|
|
73
|
-
# RUN apk update && apk add --no-cache curl vim
|
|
74
|
-
#
|
|
75
|
-
# Keep in mind that the Alpine Linux base image is used to keep image
|
|
76
|
-
# footprints small, so adding packages "just because" is not considered
|
|
77
|
-
# a best practice.
|
|
78
|
-
`
|
|
79
|
-
|
|
80
|
-
const bashrcTemplate = `
|
|
81
|
-
#!/bin/bash
|
|
82
|
-
#
|
|
83
|
-
alias h=history
|
|
84
|
-
|
|
85
|
-
alias ls='ls -CF --color=auto'
|
|
86
|
-
alias ll='ls -lh'
|
|
87
|
-
alias lla='ls -lha'
|
|
88
|
-
alias glep='grep -l -s'
|
|
89
|
-
alias m=less
|
|
90
|
-
alias menv='env | sort | less'
|
|
91
|
-
|
|
92
|
-
alias whatsmyip='wget -qO- ifconfig.co'
|
|
93
|
-
|
|
94
|
-
alias err='wget -q -O- localhost:5111/logLevel/error'
|
|
95
|
-
alias wrn='wget -q -O- localhost:5111/logLevel/warn'
|
|
96
|
-
alias inf='wget -q -O- localhost:5111/logLevel/info'
|
|
97
|
-
alias dbg='wget -q -O- localhost:5111/logLevel/debug'
|
|
98
|
-
alias trc='wget -q -O- localhost:5111/logLevel/trace'
|
|
99
|
-
|
|
100
|
-
socks()
|
|
101
|
-
{
|
|
102
|
-
netstat -ant | awk '{print }' | sort | uniq -c | sort -n
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
cmetrics()
|
|
106
|
-
{
|
|
107
|
-
wget -qO- localhost:5111/metrics
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
cmstat()
|
|
111
|
-
{
|
|
112
|
-
wget -qO- localhost:5111${1}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
cmclear()
|
|
116
|
-
{
|
|
117
|
-
cmstat /status/clear
|
|
118
|
-
}
|
|
119
|
-
`
|
|
120
|
-
|
|
121
|
-
// Just uses the old dockreate of formatting the date.
|
|
122
|
-
const dateTimestamp = await shellCmd( 'date +%Y%m%d-%H%M' )
|
|
123
|
-
|
|
124
|
-
const defaultSettings = {
|
|
125
|
-
apkadds : '',
|
|
126
|
-
date : dateTimestamp,
|
|
127
|
-
nodeimage : 'iron-alpine',
|
|
128
|
-
npmlogging : '--silent',
|
|
129
|
-
pluginfile : '# NO PLUGIN',
|
|
130
|
-
regvers : 'package.version',
|
|
131
|
-
runuser : 'node',
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const previousFile = './docker/.previous'
|
|
135
|
-
|
|
136
|
-
const getPreviousBuild = () => {
|
|
137
|
-
return fs.existsSync( previousFile ) ? fs.readFileSync( previousFile ) : 'FIRST BUILD'
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const setPreviousBuild = ( version ) => {
|
|
141
|
-
fs.writeFileSync( previousFile, version )
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const generateDockerfile = ( settings = defaultSettings ) => {
|
|
145
|
-
|
|
146
|
-
log( chalk.green.bold( 'Validating the docker structure\n' ) )
|
|
147
|
-
|
|
148
|
-
// Ensure the presence of the docker dir with plugin and bashrc - this code
|
|
149
|
-
// could probably be tightened up a little.
|
|
150
|
-
try {
|
|
151
|
-
fs.readdirSync( './docker' )
|
|
152
|
-
} catch ( err ) {
|
|
153
|
-
warning( 'creating the missing ./docker directory' )
|
|
154
|
-
fs.mkdirSync( './docker' ) // TODO: blindly assumes the mkdir succeeds
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const bashrcFile = './docker/bashrc'
|
|
158
|
-
if ( !fs.existsSync( bashrcFile ) ) {
|
|
159
|
-
warning( `creating the missing ${bashrcFile} file in the docker directory` )
|
|
160
|
-
fs.writeFileSync( bashrcFile, bashrcTemplate )
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const dockerfilePlugin = './docker/Dockerfile.plugin'
|
|
164
|
-
if ( !fs.existsSync( dockerfilePlugin ) ) {
|
|
165
|
-
warning( `creating the missing ${dockerfilePlugin} file in the docker directory` )
|
|
166
|
-
fs.writeFileSync( dockerfilePlugin, pluginTemplate )
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
try {
|
|
170
|
-
const build = fs.readdirSync( './build' )
|
|
171
|
-
if ( build.length === 0 ) {
|
|
172
|
-
errorExit( `***ERROR: the build dir is empty - ${chalk.yellow( 'run npm build' )}` )
|
|
173
|
-
}
|
|
174
|
-
} catch ( err ) {
|
|
175
|
-
errorExit( `***ERROR: expected the ./build directory to exist - ${chalk.yellow( 'run npm build' )}` )
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// At this point the plugin template better exist.
|
|
179
|
-
if ( fs.existsSync( dockerfilePlugin ) ) {
|
|
180
|
-
defaultSettings.pluginfile = fs.readFileSync( dockerfilePlugin )
|
|
181
|
-
} else {
|
|
182
|
-
errorExit( `***ERROR: something went wrong with ${dockerfilePlugin} plugin creation` )
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const compiled = handlebars.compile( dockerfileTemplate )
|
|
186
|
-
const replaced = compiled( settings )
|
|
187
|
-
const dockerfile = './docker/Dockerfile'
|
|
188
|
-
try {
|
|
189
|
-
fs.writeFileSync( dockerfile, replaced )
|
|
190
|
-
} catch ( err ) {
|
|
191
|
-
errorExit( `***ERROR: failed to write ${dockerfile}\n${err}` )
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
const previousBuild = getPreviousBuild()
|
|
195
|
-
const dockerInfo = { dockerfile, previousBuild, ...defaultSettings }
|
|
196
|
-
delete dockerInfo.pluginfile
|
|
197
|
-
return dockerInfo
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
const formCloudBuildBucketName = ( artifactProject ) => {
|
|
201
|
-
return `gs://${artifactProject}_cloudbuild`
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const validateCloudBuildBucket = async ( artifactProject ) => {
|
|
205
|
-
const bucketName = formCloudBuildBucketName( artifactProject )
|
|
206
|
-
log( chalk.green.bold( `Verifying the build bucket exists => ${bucketName}\n` ) )
|
|
207
|
-
try {
|
|
208
|
-
await shellCmd( `gsutil ls -p ${artifactProject} -b ${bucketName}` )
|
|
209
|
-
} catch ( error ) {
|
|
210
|
-
errorExit( `***Error: from Docker.validateCloudBuildBucket\n\n${chalk.bold.yellow( error )}` )
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
const buildContainerImage = async ( { artifactProject, artifactRegistry, containerName, imageVersion } ) => {
|
|
215
|
-
const cloudBuildWorkspace = './docker/workspace'
|
|
216
|
-
|
|
217
|
-
if ( fs.existsSync( cloudBuildWorkspace ) ) {
|
|
218
|
-
fs.renameSync( cloudBuildWorkspace, `${cloudBuildWorkspace}-junk` )
|
|
219
|
-
fs.rm( `${cloudBuildWorkspace}-junk`, { recursive : true }, ( err ) => {} ) // fire and forget
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
fs.mkdirSync( cloudBuildWorkspace )
|
|
223
|
-
|
|
224
|
-
fs.cpSync( './build', './docker/workspace', { recursive : true } )
|
|
225
|
-
fs.cpSync( `${process.env.HOME}/.npmrc`, './docker/.npmrc' )
|
|
226
|
-
fs.cpSync( './package.json', './docker/workspace/package.json' )
|
|
227
|
-
fs.renameSync( './package-lock.json', './docker/workspace/package-lock.json' )
|
|
228
|
-
|
|
229
|
-
setPreviousBuild( imageVersion ) // update docker/.previous file
|
|
230
|
-
|
|
231
|
-
const gcloudBuild = `time gcloud builds submit --project ${artifactProject}`
|
|
232
|
-
const gcloudLogs = `--gcs-log-dir ${formCloudBuildBucketName( artifactProject )}/log`
|
|
233
|
-
const gcloudTags = `--tag ${artifactRegistry}/images/${containerName}:${imageVersion}`
|
|
234
|
-
|
|
235
|
-
log( chalk.green.bold( `
|
|
236
|
-
*** Submitting Build ***
|
|
237
|
-
${gcloudBuild} \\
|
|
238
|
-
${gcloudLogs} \\
|
|
239
|
-
${gcloudTags}
|
|
240
|
-
` ) )
|
|
241
|
-
|
|
242
|
-
await shellCmd( `${gcloudBuild} ${gcloudLogs} ${gcloudTags} ./docker`, { stdio : 'inherit' } )
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
export default {
|
|
246
|
-
getPreviousBuild,
|
|
247
|
-
setPreviousBuild,
|
|
248
|
-
generateDockerfile,
|
|
249
|
-
formCloudBuildBucketName,
|
|
250
|
-
validateCloudBuildBucket,
|
|
251
|
-
buildContainerImage,
|
|
252
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/*
|
|
3
|
-
* docker-to-registry will...
|
|
4
|
-
*/
|
|
5
|
-
import chalk from 'chalk'
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
debug, log,
|
|
9
|
-
errorExit,
|
|
10
|
-
describeRepository,
|
|
11
|
-
proceed,
|
|
12
|
-
shellCmd } from './Utils.mjs'
|
|
13
|
-
|
|
14
|
-
import docker from './Docker.mjs'
|
|
15
|
-
|
|
16
|
-
// refresh-npm-token does not throw so no need to try, but it emits in debug
|
|
17
|
-
const refreshErr = await shellCmd( 'refresh-npm-token' )
|
|
18
|
-
if ( refreshErr && !process.env.BUILD_TOOLS_DEBUG ) {
|
|
19
|
-
errorExit( `***Error: npm token refresh failed\n\n${refreshErr}` )
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Expected to be invoked like docker-to-registry v1.2.3
|
|
23
|
-
const imageVersion = process.argv[2]
|
|
24
|
-
const willGitTag = imageVersion.match( /^v\d+\.\d+\.\d+$/ )
|
|
25
|
-
const tagInfo = willGitTag ?
|
|
26
|
-
chalk.yellow.bold( 'will be git tagged' ) :
|
|
27
|
-
chalk.red( 'BETA RELEASE WILL NOT BE GIT TAGGED' )
|
|
28
|
-
|
|
29
|
-
const repoDescr = await describeRepository()
|
|
30
|
-
debug( { repoDescr }, '<==The Repo Description' )
|
|
31
|
-
|
|
32
|
-
const dockerInfo = await docker.generateDockerfile()
|
|
33
|
-
debug( { dockerInfo }, '<==The Docker Info' )
|
|
34
|
-
|
|
35
|
-
const { artifactProject, artifactRegistry, containerName } = repoDescr
|
|
36
|
-
|
|
37
|
-
await docker.validateCloudBuildBucket( artifactProject )
|
|
38
|
-
|
|
39
|
-
const registryFolder = `${artifactRegistry}/images/${containerName}`
|
|
40
|
-
|
|
41
|
-
// Update the dependencies...
|
|
42
|
-
log( chalk.green.bold( 'Updating dependencies and workspace...' ) )
|
|
43
|
-
await shellCmd( 'npm install', { stdio : 'inherit' } )
|
|
44
|
-
|
|
45
|
-
// Give the summary and the user a chance to proceed or not
|
|
46
|
-
log( `
|
|
47
|
-
${chalk.green.bold( 'Build Information:' )}
|
|
48
|
-
Container: ${chalk.green.bold( containerName )}
|
|
49
|
-
Version: ${chalk.green.bold( imageVersion )} ${tagInfo}
|
|
50
|
-
Registry: ${chalk.green.bold( artifactRegistry )}
|
|
51
|
-
Image Folder: ${chalk.yellow.bold( registryFolder )}
|
|
52
|
-
Monorepo: ${chalk.green.bold( repoDescr.isMonoRepo )}
|
|
53
|
-
NPM Workspace: ${chalk.green.bold( repoDescr.isNpmWorkspace )}
|
|
54
|
-
|
|
55
|
-
${chalk.green.bold( 'Docker Information:' )}
|
|
56
|
-
NodeImage: ${chalk.green.bold( dockerInfo.nodeimage )}
|
|
57
|
-
AddedPkgs: ${chalk.green.bold( dockerInfo.apkadds )}
|
|
58
|
-
Run User: ${chalk.green.bold( dockerInfo.runuser )}
|
|
59
|
-
Previous: ${chalk.yellow.bold( dockerInfo.previousBuild )}
|
|
60
|
-
DateStamp: ${chalk.green.bold( dockerInfo.date )}
|
|
61
|
-
NPM Logs: ${chalk.green.bold( dockerInfo.npmlogging )}
|
|
62
|
-
` )
|
|
63
|
-
|
|
64
|
-
await proceed()
|
|
65
|
-
|
|
66
|
-
if ( repoDescr.isNpmWorkspace ) {
|
|
67
|
-
log( chalk.yellow.bold( 'Generating an NPM workspace package-lock.json file' ) )
|
|
68
|
-
await shellCmd( 'npm install --package-lock-only --workspaces false', { stdio : 'inherit' } )
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
await docker.buildContainerImage( { artifactProject, artifactRegistry, containerName, imageVersion } )
|