@autofleet/cli 1.0.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/.eslintrc.json +54 -0
- package/.gitattributes +2 -0
- package/.nvmrc +1 -0
- package/README.md +2 -0
- package/bin/index.js +43 -0
- package/bin/utils/index.js +22 -0
- package/multi-services-e2e.sh +144 -0
- package/package.json +31 -0
package/.eslintrc.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"root": true,
|
|
3
|
+
"env": {
|
|
4
|
+
"node": true,
|
|
5
|
+
"jest": true
|
|
6
|
+
},
|
|
7
|
+
"extends": [
|
|
8
|
+
"airbnb-base"
|
|
9
|
+
],
|
|
10
|
+
"rules": {
|
|
11
|
+
"guard-for-in": 0,
|
|
12
|
+
"no-await-in-loop": 0,
|
|
13
|
+
"no-restricted-syntax" :0,
|
|
14
|
+
"no-return-assign": 0,
|
|
15
|
+
"no-dupe-class-members":0,
|
|
16
|
+
"import/prefer-default-export": 0,
|
|
17
|
+
"lines-between-class-members": [
|
|
18
|
+
"error",
|
|
19
|
+
"always",
|
|
20
|
+
{ "exceptAfterSingleLine": true }
|
|
21
|
+
],
|
|
22
|
+
"import/extensions": [
|
|
23
|
+
"error",
|
|
24
|
+
"ignorePackages",
|
|
25
|
+
{
|
|
26
|
+
"js": "never",
|
|
27
|
+
"jsx": "never",
|
|
28
|
+
"ts": "never",
|
|
29
|
+
"tsx": "never"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
"ignorePatterns": ["lib/*", "node_modules/", "jest.config.js"],
|
|
34
|
+
"settings": {
|
|
35
|
+
"import/extensions": [
|
|
36
|
+
"error",
|
|
37
|
+
"ignorePackages",
|
|
38
|
+
{
|
|
39
|
+
"js": "never",
|
|
40
|
+
"jsx": "never",
|
|
41
|
+
"ts": "never",
|
|
42
|
+
"tsx": "never"
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
"import/parsers": {
|
|
46
|
+
"@typescript-eslint/parser": [".ts",".tsx"]
|
|
47
|
+
},
|
|
48
|
+
"import/resolver": {
|
|
49
|
+
"node": {
|
|
50
|
+
"extensions": [".js",".jsx",".ts",".tsx"]
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
package/.gitattributes
ADDED
package/.nvmrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
17.9.0
|
package/README.md
ADDED
package/bin/index.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import yargs from 'yargs';
|
|
3
|
+
import { hideBin } from 'yargs/helpers';
|
|
4
|
+
import { connectAndGetPrefix, terminalCommand } from './utils/index.js';
|
|
5
|
+
|
|
6
|
+
yargs(hideBin(process.argv))
|
|
7
|
+
.command({
|
|
8
|
+
command: 'exposeService',
|
|
9
|
+
describe: '--service=driver-ms --variationId=${yourVariationUuid} --cluster=dev1/e2eManager',
|
|
10
|
+
async handler(argv) {
|
|
11
|
+
const { cluster, variationId, service } = argv;
|
|
12
|
+
const prefix = await connectAndGetPrefix({
|
|
13
|
+
clusterName: cluster,
|
|
14
|
+
variationId,
|
|
15
|
+
});
|
|
16
|
+
await terminalCommand(`kubectl patch svc ${prefix} ${service} -p '{"spec": {"ports": [{"port": 80,"targetPort": 80,"name": "http"}],"type": "LoadBalancer"}}' `);
|
|
17
|
+
await terminalCommand(`kubectl annotate ${prefix} service ${service} cloud.google.com/load-balancer-type-`);
|
|
18
|
+
},
|
|
19
|
+
})
|
|
20
|
+
.command({
|
|
21
|
+
command: 'getIps',
|
|
22
|
+
describe: '--service=driver-ms --variationId=${yourVariationUuid} --cluster=dev1/e2eManager',
|
|
23
|
+
async handler(argv) {
|
|
24
|
+
const { cluster, variationId, service } = argv;
|
|
25
|
+
const prefix = await connectAndGetPrefix({
|
|
26
|
+
clusterName: cluster,
|
|
27
|
+
variationId,
|
|
28
|
+
});
|
|
29
|
+
await terminalCommand(`kubectl ${prefix} get services > ips`);
|
|
30
|
+
const CAT_IPS = 'cat ips';
|
|
31
|
+
const getServicesCommand = service ? `${CAT_IPS} | grep ${service}` : CAT_IPS;
|
|
32
|
+
const serviceLine = await terminalCommand(getServicesCommand);
|
|
33
|
+
console.log(serviceLine);
|
|
34
|
+
},
|
|
35
|
+
})
|
|
36
|
+
.command({
|
|
37
|
+
command: 'diff',
|
|
38
|
+
describe: '--first=9 --second=5',
|
|
39
|
+
handler(argv) {
|
|
40
|
+
console.log(argv.first - argv.second);
|
|
41
|
+
},
|
|
42
|
+
})
|
|
43
|
+
.parse();
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
import { exec } from 'child_process';
|
|
4
|
+
|
|
5
|
+
const asyncExec = promisify(exec);
|
|
6
|
+
|
|
7
|
+
const CLUSTER_TO_CMD_MAP = {
|
|
8
|
+
dev1: 'gcloud container clusters get-credentials dev-cluster-2 --region europe-west1 --project dev1-experiment-manager',
|
|
9
|
+
e2eManager: 'gcloud container clusters get-credentials e2e-cluster-1 --region europe-west1 --project e2e-manager',
|
|
10
|
+
};
|
|
11
|
+
export const terminalCommand = async (command) => {
|
|
12
|
+
const output = await asyncExec(command);
|
|
13
|
+
const formattedOutput = output.stdout.trim();
|
|
14
|
+
return formattedOutput;
|
|
15
|
+
};
|
|
16
|
+
const connectToCluster = async (clusterName) => {
|
|
17
|
+
await terminalCommand(CLUSTER_TO_CMD_MAP[clusterName]);
|
|
18
|
+
};
|
|
19
|
+
export const connectAndGetPrefix = async ({ clusterName, variationId }) => {
|
|
20
|
+
await connectToCluster(clusterName);
|
|
21
|
+
return `--namespace=${variationId}`;
|
|
22
|
+
};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# standard bash error handling
|
|
4
|
+
set -o errexit;
|
|
5
|
+
set -o pipefail;
|
|
6
|
+
set -o nounset;
|
|
7
|
+
# debug commands
|
|
8
|
+
# set -x;
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# working dir to install binaries etc, cleaned up on exit
|
|
12
|
+
BIN_DIR="$(mktemp -d)"
|
|
13
|
+
# kind binary will be here
|
|
14
|
+
KIND="${BIN_DIR}/kind"
|
|
15
|
+
variation_id=''
|
|
16
|
+
CLUSTER_IP="http://34.79.247.124"
|
|
17
|
+
CLUSTER_NAME="e2e-cluster-1"
|
|
18
|
+
PROJECT_NAME="e2e-manager"
|
|
19
|
+
|
|
20
|
+
gcloud container clusters get-credentials e2e-cluster-1 --region europe-west1 --project e2e-manager
|
|
21
|
+
|
|
22
|
+
# cleanup on exit (useful for running locally)
|
|
23
|
+
cleanup() {
|
|
24
|
+
if [ -n "${variation_id// }" ]
|
|
25
|
+
then
|
|
26
|
+
curl -X DELETE \
|
|
27
|
+
${CLUSTER_IP}/api/v1/variations/${variation_id} \
|
|
28
|
+
-H 'Authorization: Bearer }n.>$X265*G>PK/Xj$%UY.7/7rMR)Nee*=V' 2>/dev/null | jq -r '.state'
|
|
29
|
+
fi
|
|
30
|
+
}
|
|
31
|
+
trap cleanup EXIT
|
|
32
|
+
main() {
|
|
33
|
+
dir=$(pwd)
|
|
34
|
+
dir="$(basename $dir)"
|
|
35
|
+
|
|
36
|
+
state=''
|
|
37
|
+
export variation_id=$(curl -X POST \
|
|
38
|
+
${CLUSTER_IP}/api/v1/variations \
|
|
39
|
+
-H 'Content-Type: application/json' \
|
|
40
|
+
-H 'authorization: Bearer }n.>$X265*G>PK/Xj$%UY.7/7rMR)Nee*=V' \
|
|
41
|
+
-H 'Postman-Token: 2b0e5ecf-bcc5-4cfe-9d57-332b92bf1ff9' \
|
|
42
|
+
-H 'cache-control: no-cache' \
|
|
43
|
+
-d '{
|
|
44
|
+
"variation": {
|
|
45
|
+
"name": "Multi branches E2E",
|
|
46
|
+
"description": "Multi branches E2E",
|
|
47
|
+
"withSimulator": false,
|
|
48
|
+
"criticalDeployment": true,
|
|
49
|
+
"withFleeter": false,
|
|
50
|
+
"numberOfVehicles": 0,
|
|
51
|
+
"branches" : {"ride-ms": "aut-7045" ,"vehicle-ms": "aut-7045", "vehicle-live-data-ms": "aut-7045"}
|
|
52
|
+
}
|
|
53
|
+
}' 2>/dev/null | jq -r '.variationId')
|
|
54
|
+
|
|
55
|
+
echo $variation_id
|
|
56
|
+
|
|
57
|
+
echo "Looking for variation state $variation_id"
|
|
58
|
+
until [ "$state" = "started" ]
|
|
59
|
+
do
|
|
60
|
+
state=$(curl -X GET \
|
|
61
|
+
${CLUSTER_IP}/api/v1/variations/${variation_id} \
|
|
62
|
+
-H 'Authorization: Bearer }n.>$X265*G>PK/Xj$%UY.7/7rMR)Nee*=V' 2>/dev/null | jq -r '.state')
|
|
63
|
+
|
|
64
|
+
echo "Looking for variation state $variation_id: $state"
|
|
65
|
+
sleep 10
|
|
66
|
+
done
|
|
67
|
+
|
|
68
|
+
kubectl get secret google-auth --namespace=default -o yaml | sed "s/namespace: .*/namespace: $variation_id/" | kubectl apply -f -
|
|
69
|
+
# https://stackoverflow.com/questions/54353129/kubectl-create-using-inline-options-in-bash-script-instead-of-yaml-file
|
|
70
|
+
cat <<EOF | kubectl --namespace=$variation_id apply -f -
|
|
71
|
+
apiVersion: batch/v1
|
|
72
|
+
kind: Job
|
|
73
|
+
metadata:
|
|
74
|
+
name: e2e-test
|
|
75
|
+
spec:
|
|
76
|
+
template:
|
|
77
|
+
spec:
|
|
78
|
+
containers:
|
|
79
|
+
- name: e2e-test
|
|
80
|
+
image: gcr.io/autofleetprod/e2e-tests:master-latest
|
|
81
|
+
imagePullPolicy: Always
|
|
82
|
+
command: ["npm", "run", "test"]
|
|
83
|
+
env:
|
|
84
|
+
- name: FIRE_BASE_URL
|
|
85
|
+
value: https://e2e-stats-default-rtdb.europe-west1.firebasedatabase.app
|
|
86
|
+
- name: E2E_RUN_NAME
|
|
87
|
+
value: custom_branches
|
|
88
|
+
- name: NAMESPACE
|
|
89
|
+
value: ${variation_id}
|
|
90
|
+
- name: CLIENT_EMAIL
|
|
91
|
+
valueFrom:
|
|
92
|
+
secretKeyRef:
|
|
93
|
+
name: google-auth
|
|
94
|
+
key: client_email
|
|
95
|
+
- name: CLIENT_PRIVATE_KEY
|
|
96
|
+
valueFrom:
|
|
97
|
+
secretKeyRef:
|
|
98
|
+
name: google-auth
|
|
99
|
+
key: private_key
|
|
100
|
+
- name: CONTROL_CENTER_USERNAME
|
|
101
|
+
valueFrom:
|
|
102
|
+
secretKeyRef:
|
|
103
|
+
name: google-auth
|
|
104
|
+
key: control_center_user
|
|
105
|
+
- name: CONTROL_CENTER_PASSWORD
|
|
106
|
+
valueFrom:
|
|
107
|
+
secretKeyRef:
|
|
108
|
+
name: google-auth
|
|
109
|
+
key: control_center_password
|
|
110
|
+
- name: NGROK_TOKEN
|
|
111
|
+
valueFrom:
|
|
112
|
+
secretKeyRef:
|
|
113
|
+
name: google-auth
|
|
114
|
+
key: ngrok_token
|
|
115
|
+
resources:
|
|
116
|
+
requests:
|
|
117
|
+
memory: "2Gi"
|
|
118
|
+
cpu: "2"
|
|
119
|
+
restartPolicy: Never
|
|
120
|
+
backoffLimit: 0
|
|
121
|
+
EOF
|
|
122
|
+
|
|
123
|
+
until [ "$(kubectl get pods --namespace=$variation_id | grep e2e-test | awk '{print $3}')" = "Running" ] || \
|
|
124
|
+
[ "$(kubectl get pods --namespace=$variation_id | grep e2e-test | awk '{print $3}')" = "Completed" ]
|
|
125
|
+
do
|
|
126
|
+
sleep 1
|
|
127
|
+
done
|
|
128
|
+
kubectl logs --namespace=$variation_id job/e2e-test -f
|
|
129
|
+
|
|
130
|
+
echo "gcp logs: https://console.cloud.google.com/logs/query;query=resource.type%3D%22k8s_container%22%0Aresource.labels.project_id%3D%22$PROJECT_NAME%22%0Aresource.labels.location%3D%22europe-west1%22%0Aresource.labels.cluster_name%3D%22$CLUSTER_NAME%22%0Aresource.labels.namespace_name%3D%22""$variation_id""%22%20labels.k8s-pod%2Flabels.k8s-pod%2Ftier%3D%22servers%22%20severity%3D%22ERROR%22;?organizationId=336109943451&project=$PROJECT_NAME"
|
|
131
|
+
|
|
132
|
+
echo $(kubectl get pods --namespace=$variation_id | grep e2e-test | awk '{print $3}')
|
|
133
|
+
sleep 5
|
|
134
|
+
echo $(kubectl get pods --namespace=$variation_id | grep e2e-test | awk '{print $3}')
|
|
135
|
+
if [ $(kubectl get pods --namespace=$variation_id | grep e2e-test | awk '{print $3}') = 'Completed' ]
|
|
136
|
+
then
|
|
137
|
+
echo "OK"
|
|
138
|
+
else
|
|
139
|
+
echo "Fail"
|
|
140
|
+
exit 1
|
|
141
|
+
fi
|
|
142
|
+
}
|
|
143
|
+
echo 'E2E logs will be visible in logs file :) '
|
|
144
|
+
main > logs
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@autofleet/cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI for common autofleet usage",
|
|
5
|
+
"main": "bin/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"linter": "./node_modules/.bin/eslint .",
|
|
8
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/Autofleet/scripts.git"
|
|
13
|
+
},
|
|
14
|
+
"author": "Omer Gery",
|
|
15
|
+
"license": "ISC",
|
|
16
|
+
"bin": {
|
|
17
|
+
"autofleet": "./bin/index.js"
|
|
18
|
+
},
|
|
19
|
+
"type": "module",
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/Autofleet/scripts/issues"
|
|
22
|
+
},
|
|
23
|
+
"homepage": "https://github.com/Autofleet/scripts#readme",
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"boxen": "^6.2.1",
|
|
26
|
+
"chalk": "^5.0.1",
|
|
27
|
+
"eslint": "^8.13.0",
|
|
28
|
+
"eslint-config-airbnb": "^19.0.4",
|
|
29
|
+
"yargs": "^17.4.1"
|
|
30
|
+
}
|
|
31
|
+
}
|