forked from cerc-io/stack-orchestrator
Compare commits
491 Commits
ng-deny-mu
...
main
Author | SHA1 | Date | |
---|---|---|---|
dceda936b7 | |||
bca332b598 | |||
f1fdc48aaa | |||
a54072de6c | |||
fa21ff2627 | |||
33d395e213 | |||
75ff60752a | |||
44b9709717 | |||
e56da7dcc1 | |||
60d34217f8 | |||
952389abb0 | |||
5c275aa622 | |||
8576137557 | |||
65c1cdf6b1 | |||
265699bc38 | |||
4a7670a5d6 | |||
6087e1cd31 | |||
1def279d26 | |||
64691bd206 | |||
aef5986135 | |||
6f8f0340d3 | |||
7590d6e237 | |||
573f99dbbe | |||
8052c1c25e | |||
a674d13493 | |||
0d4f4509c8 | |||
5af27b1b3a | |||
6c91b87348 | |||
7d18334953 | |||
79c1c5ed99 | |||
dfedd9e9ff | |||
f64683f03b | |||
913c3a8557 | |||
2f5b0cdd13 | |||
432bd4113d | |||
b26698b756 | |||
01deac78c4 | |||
40ccd47857 | |||
|
80cff73344 | ||
|
21b1270d27 | ||
|
008389dcd8 | ||
c81fb9581a | |||
83397bbae4 | |||
17c21464ab | |||
7fb9ccdfd8 | |||
2bad59dfcd | |||
13d04e9256 | |||
1f017c9066 | |||
3b9422095c | |||
36d4969b2d | |||
a2d6201be9 | |||
62f7825ec2 | |||
6d24d4a7e6 | |||
f06e5f9a2a | |||
c3a1402042 | |||
ca5fffaed5 | |||
df776c1b4c | |||
48a3e79e6a | |||
0eaa5b8f09 | |||
8980ac2581 | |||
fd15252c3f | |||
b4e82ebc19 | |||
2364924a59 | |||
a223797b4a | |||
b8004e9870 | |||
3fd99a1522 | |||
842d999792 | |||
d6a1fb3279 | |||
bf1eccd486 | |||
3fb025b5c9 | |||
4acb06325b | |||
b80b647fa4 | |||
9a1d3bb0f1 | |||
abc0c2423f | |||
a322d6eed4 | |||
ed8914b8d3 | |||
fef7649683 | |||
579b402f2f | |||
25d0bc8a98 | |||
855288368c | |||
8f2da38183 | |||
254f95e59f | |||
0acb6ea6bc | |||
b9369a13e6 | |||
0b1eb8eb0f | |||
78092f5793 | |||
247dbdd2f0 | |||
30db1f58d0 | |||
09a1cbb966 | |||
13ce521d84 | |||
6e4dae9777 | |||
9043a67c7c | |||
7f84a45cfd | |||
4126f2fc43 | |||
345d200873 | |||
87fffca358 | |||
66b92df498 | |||
108a5a3440 | |||
4b04a39faf | |||
40f362511b | |||
9cd34ffebb | |||
515f6d16f5 | |||
105805cb9b | |||
|
62f1962546 | ||
|
2a24e71c92 | ||
|
c789b82782 | ||
d2442bcc9b | |||
|
b3bc5a19ae | ||
44faf36837 | |||
18b006468d | |||
5308ab1e4e | |||
cd50832038 | |||
|
7f9e1da8ba | ||
|
0149346927 | ||
|
06de4fe485 | ||
aeddc82ebc | |||
|
821d401575 | ||
|
5123111db0 | ||
|
02c33cb229 | ||
17e860d6e4 | |||
|
b4eda902ea | ||
|
b4df8104c8 | ||
|
07282cdd6e | ||
|
e7c935fb78 | ||
523b5779be | |||
|
1a636799a6 | ||
|
0aa4b350bd | ||
62f7ce649d | |||
|
2252252072 | ||
|
c92f15f47c | ||
|
fee32ec703 | ||
fb55c1425e | |||
cc541ac20f | |||
10e2311a8b | |||
f32bbf9e48 | |||
0302153162 | |||
01e4437b62 | |||
64cec163b3 | |||
170ad71397 | |||
da1ff609fe | |||
21eb9f036f | |||
a0413659f7 | |||
a16fc657bf | |||
704c42c404 | |||
202f187172 | |||
aaed356d32 | |||
2af6ffce77 | |||
7bb86cf35e | |||
9e0892cb6b | |||
cf9cf6346f | |||
642c0ead0d | |||
6bd77c893a | |||
4a4d48ddb9 | |||
08438b1cd5 | |||
9f1dd284a5 | |||
5985242b8c | |||
d4152b7ce3 | |||
db4986dcc6 | |||
65f05ea80c | |||
01f9fe67ed | |||
049ffcff71 | |||
f5314a979b | |||
39f4fa4487 | |||
0b0394a940 | |||
37b9500483 | |||
3c3e582939 | |||
26d265360d | |||
f81b78cfbc | |||
d9bb6b3588 | |||
b59beb66eb | |||
65d67dba10 | |||
b22c72e715 | |||
c9444591f5 | |||
903f3b10e2 | |||
72ed2eb91a | |||
2104eb5f30 | |||
afd6be3b13 | |||
f914baa913 | |||
8be1e684e8 | |||
5d16251ce9 | |||
3309782439 | |||
4b3b3478e7 | |||
2a9955055c | |||
8964e1c0fe | |||
d2ebb81d77 | |||
4a981d8d2e | |||
88a0236ca9 | |||
937b983ec9 | |||
bfbcfb7904 | |||
3d5ececba5 | |||
6848fc33cf | |||
36bb068983 | |||
25a2b70f2c | |||
2fcd416e29 | |||
6629017d6a | |||
1c30441000 | |||
b398050787 | |||
12ec1bec43 | |||
62af03077f | |||
|
098567625a | ||
428b05158e | |||
a750b645b9 | |||
|
23ee3e19b7 | ||
|
2d764fc7d0 | ||
b7f215d9bf | |||
eca52b10b7 | |||
b9128841e4 | |||
0a302ea555 | |||
aa0f60baa1 | |||
cef73d8de2 | |||
7d0f2adb46 | |||
5fdee25dc1 | |||
554f05de87 | |||
b4fbee9b13 | |||
f826f50c4d | |||
b83465767d | |||
50509203d1 | |||
|
282e175566 | ||
635aa7037b | |||
9877cfaf85 | |||
c642e5d490 | |||
02c49d66f5 | |||
90cebdb7a6 | |||
1f9653e6f7 | |||
0587813dd0 | |||
4b3ea7c30f | |||
db8aec52aa | |||
b83030f63b | |||
|
a3eb3c0bb0 | ||
eae2af7ccc | |||
837e443800 | |||
|
a57b0cdd26 | ||
|
38622fb33c | ||
|
4a1a46facc | ||
|
42b92f7e23 | ||
def192edab | |||
d8357df345 | |||
997496b8a5 | |||
61f2884505 | |||
27a14737f8 | |||
|
b9b758bfdd | ||
|
9ba410b095 | ||
1f4eb57069 | |||
88f66a3626 | |||
|
1ef0b316c6 | ||
|
232d5618cb | ||
fa6b570f4a | |||
|
f9eb5a4ba8 | ||
077ea80c70 | |||
15faed00de | |||
|
6bef0c5b2f | ||
|
f27da19808 | ||
2dd54892a1 | |||
ab0e70ed83 | |||
c319e90ddd | |||
2173e7ce6a | |||
c19559967d | |||
d7093277b4 | |||
03a3645b3c | |||
113c0bfbf1 | |||
1a069a6816 | |||
a68cd5d65c | |||
1b94db27c1 | |||
|
9499941891 | ||
3fefc67e77 | |||
1a37255c18 | |||
87bedde5cb | |||
01029cf7aa | |||
0b87c12c13 | |||
f6624cb33a | |||
c9c6a0eee3 | |||
5c80887215 | |||
|
80c4b9214b | ||
70529c43e7 | |||
1e9d24a8ce | |||
9900565714 | |||
a13f841f34 | |||
d37f80553d | |||
2059d67dca | |||
638fa01649 | |||
4ae4d3b61d | |||
9687d84468 | |||
|
f088cbb3b0 | ||
f1f618c57a | |||
0aca087558 | |||
a04730e7ac | |||
|
95e881ba19 | ||
414b887036 | |||
|
3db443b2bb | ||
|
1072fc98c3 | ||
042b413598 | |||
8384e95049 | |||
a27cf86748 | |||
ce587457d7 | |||
5e91c2224e | |||
36e13f7199 | |||
d9bcc088a8 | |||
660326f713 | |||
4456e70c93 | |||
e989368793 | |||
0f93d30d54 | |||
fd5779f967 | |||
|
d854dd5c81 | ||
|
948f9f4287 | ||
b92d9cd7dd | |||
86076c7ed8 | |||
8cac598679 | |||
6130eab5cb | |||
|
f198f43b3a | ||
36d1e0eedd | |||
0f5b1a097b | |||
20d633f81c | |||
5e36e3e2ae | |||
f7eb8b9a38 | |||
5b9b12a223 | |||
|
567dadef7d | ||
052f0df4b0 | |||
c51671f786 | |||
573a19a3b7 | |||
|
fc051265d8 | ||
|
ddebb9c690 | ||
|
fe6c3f92ed | ||
|
c06be6da81 | ||
3291c16466 | |||
69b071ee7a | |||
4a90cedeb2 | |||
|
2402220273 | ||
|
771943864e | ||
|
dd4dd519dd | ||
|
3262ebe4ac | ||
8246e3551f | |||
e26a05f2c7 | |||
f9b102f5fa | |||
7ce40331d8 | |||
479a7772f3 | |||
|
4030c0a0d2 | ||
ba09043227 | |||
99f80ddc7c | |||
|
246d3d8732 | ||
a68abe5f5d | |||
c3d87692fa | |||
61579f0434 | |||
0bec51e96a | |||
f4216419c4 | |||
420b1c292b | |||
1446e54f31 | |||
2486003361 | |||
5ec98ee9a1 | |||
|
8c4ed24dfc | ||
|
9e56f6357d | ||
|
8770b1df86 | ||
889df76f4f | |||
5d19c56b0c | |||
|
d57efe87b8 | ||
80b0c07736 | |||
6fa3ca2b6d | |||
3c5489681f | |||
|
cf039d9562 | ||
|
b485a3b8d8 | ||
72dbee88d4 | |||
|
33e443f41f | ||
|
bc78c5e0d6 | ||
7fd2439aa9 | |||
eca5aae991 | |||
5beaf69a36 | |||
06c4a77afe | |||
aafadbbed6 | |||
be519e9ca0 | |||
|
e56a910260 | ||
|
e3dc75118b | ||
e0b5318ebe | |||
|
2425aa8556 | ||
|
3dc9cd584a | ||
ed9c253f61 | |||
bdf4f069b4 | |||
5f9c3c14b2 | |||
0b512db693 | |||
e0ecbc3ab3 | |||
626cc17373 | |||
c30c779535 | |||
|
3011a485ee | ||
d505664781 | |||
4197d39b0c | |||
8dcebe3737 | |||
50d17c3282 | |||
2c930bdbc3 | |||
f48f4978aa | |||
e89f7c9526 | |||
|
ae9dff553e | ||
bab3a8dba8 | |||
e0972033de | |||
b5988fba8f | |||
|
53ed18b3dc | ||
d3c26948fc | |||
7f9b556f9d | |||
|
125af19890 | ||
7797185d07 | |||
f55a14bd6c | |||
f411590452 | |||
97dc45549d | |||
|
8a7622ffa9 | ||
d35bbbab98 | |||
407571e18d | |||
d39e2e959e | |||
|
ddaddd2a8c | ||
|
59e0458c74 | ||
18e45af463 | |||
fd78935fe6 | |||
|
4c72acea96 | ||
|
bccf711206 | ||
|
333797b0c3 | ||
dc7bc6af31 | |||
d6bd99252d | |||
d30e746599 | |||
73e52c4eed | |||
e856616be8 | |||
2da03d7ed1 | |||
6a0a752e2e | |||
5afe7a29ae | |||
a8f4e4cee4 | |||
45ba1f337f | |||
0feeab6418 | |||
4ee745a4db | |||
8eed5a70a5 | |||
758ec168bd | |||
63a94bae0e | |||
29fc611885 | |||
1f9131ff5a | |||
950857fa84 | |||
54f50aa09e | |||
a5945c9e59 | |||
c8b4f89335 | |||
809889f9f0 | |||
6595659a7a | |||
|
9872ce33bb | ||
|
2ff490d121 | ||
c76195c491 | |||
831a8cd5f7 | |||
|
f0f40cad4a | ||
|
f473567bd7 | ||
|
3e7037e06f | ||
c465153cc7 | |||
|
b120682d8e | ||
|
c9bb0d0ccb | ||
c94fa3cccf | |||
|
55af33e0e8 | ||
|
c0f07c2d4f | ||
|
7ca7bcc952 | ||
|
ee8c8a0c13 | ||
|
30ce3deb31 | ||
|
a6cf131cd3 | ||
|
25b13d7822 | ||
|
01500e78b6 | ||
|
4ecc98dd46 | ||
32f8d65bb8 | |||
|
d19b9a65b9 | ||
98e1d120cc | |||
26ff7a969c | |||
a8e198ad55 | |||
f1a626ddf5 | |||
ff616db4ad | |||
9880b48b78 | |||
23a336020c | |||
|
605db8a4d2 | ||
6ec55ba460 | |||
938f51ef8c | |||
6d620ba9c2 | |||
|
0c4c128465 | ||
97c1ae1c43 | |||
ec6b5439f4 | |||
1d8f252a51 | |||
161665ef72 | |||
9c5f6469ff | |||
85225c72d7 | |||
223d1171e8 | |||
1e38e16550 | |||
dddae8cc7a | |||
aa702737ef | |||
|
c9155eafd2 | ||
1ffc6b1687 | |||
87c25dfb5e | |||
|
0691c22db4 | ||
|
5c7d445500 | ||
a93fa93d26 | |||
1852d7d4c1 | |||
|
fce41994a3 | ||
|
a5d3d6bae7 | ||
8add4671c0 | |||
|
b1b1464205 | ||
|
fbe901a0fb | ||
|
a9558aa874 |
66
.gitea/workflows/fixturenet-laconicd-test.yml
Normal file
66
.gitea/workflows/fixturenet-laconicd-test.yml
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
name: Fixturenet-Laconicd-Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: '*'
|
||||||
|
paths:
|
||||||
|
- '!**'
|
||||||
|
- '.gitea/workflows/triggers/fixturenet-laconicd-test'
|
||||||
|
schedule:
|
||||||
|
- cron: '1 13 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: "Run Laconicd fixturenet and Laconic CLI tests"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: 'Update'
|
||||||
|
run: apt-get update
|
||||||
|
- name: 'Setup jq'
|
||||||
|
run: apt-get install jq -y
|
||||||
|
- name: 'Check jq'
|
||||||
|
run: |
|
||||||
|
which jq
|
||||||
|
jq --version
|
||||||
|
- name: "Clone project repository"
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
# At present the stock setup-python action fails on Linux/aarch64
|
||||||
|
# Conditional steps below workaroud this by using deadsnakes for that case only
|
||||||
|
- name: "Install Python for ARM on Linux"
|
||||||
|
if: ${{ runner.arch == 'arm64' && runner.os == 'Linux' }}
|
||||||
|
uses: deadsnakes/action@v3.0.1
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Install Python cases other than ARM on Linux"
|
||||||
|
if: ${{ ! (runner.arch == 'arm64' && runner.os == 'Linux') }}
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Print Python version"
|
||||||
|
run: python3 --version
|
||||||
|
- name: "Install shiv"
|
||||||
|
run: pip install shiv
|
||||||
|
- name: "Generate build version file"
|
||||||
|
run: ./scripts/create_build_tag_file.sh
|
||||||
|
- name: "Build local shiv package"
|
||||||
|
run: ./scripts/build_shiv_package.sh
|
||||||
|
- name: "Run fixturenet-laconicd tests"
|
||||||
|
run: ./tests/fixturenet-laconicd/run-test.sh
|
||||||
|
- name: "Run laconic CLI tests"
|
||||||
|
run: ./tests/fixturenet-laconicd/run-cli-test.sh
|
||||||
|
- name: Notify Vulcanize Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.VULCANIZE_SLACK_CI_ALERTS }}
|
||||||
|
- name: Notify DeepStack Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.DEEPSTACK_SLACK_CI_ALERTS }}
|
37
.gitea/workflows/lint.yml
Normal file
37
.gitea/workflows/lint.yml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
name: Lint Checks
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: '*'
|
||||||
|
push:
|
||||||
|
branches: '*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: "Run linter"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: "Clone project repository"
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: "Install Python"
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name : "Run flake8"
|
||||||
|
uses: py-actions/flake8@v2
|
||||||
|
- name: Notify Vulcanize Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.VULCANIZE_SLACK_CI_ALERTS }}
|
||||||
|
- name: Notify DeepStack Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.DEEPSTACK_SLACK_CI_ALERTS }}
|
@ -5,6 +5,8 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- publish-test
|
- publish-test
|
||||||
|
paths-ignore:
|
||||||
|
- '.gitea/workflows/triggers/*'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish:
|
publish:
|
||||||
@ -18,8 +20,16 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
build_tag=$(./scripts/create_build_tag_file.sh)
|
build_tag=$(./scripts/create_build_tag_file.sh)
|
||||||
echo "build-tag=v${build_tag}" >> $GITHUB_OUTPUT
|
echo "build-tag=v${build_tag}" >> $GITHUB_OUTPUT
|
||||||
- name: "Install Python"
|
# At present the stock setup-python action fails on Linux/aarch64
|
||||||
uses: cerc-io/setup-python@v4
|
# Conditional steps below workaroud this by using deadsnakes for that case only
|
||||||
|
- name: "Install Python for ARM on Linux"
|
||||||
|
if: ${{ runner.arch == 'arm64' && runner.os == 'Linux' }}
|
||||||
|
uses: deadsnakes/action@v3.0.1
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Install Python cases other than ARM on Linux"
|
||||||
|
if: ${{ ! (runner.arch == 'arm64' && runner.os == 'Linux') }}
|
||||||
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: '3.8'
|
python-version: '3.8'
|
||||||
- name: "Print Python version"
|
- name: "Print Python version"
|
||||||
@ -37,10 +47,26 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cp ${{ steps.build.outputs.package-file }} ./laconic-so
|
cp ${{ steps.build.outputs.package-file }} ./laconic-so
|
||||||
- name: "Create release"
|
- name: "Create release"
|
||||||
uses: cerc-io/action-gh-release@gitea-v1
|
uses: https://gitea.com/cerc-io/action-gh-release@gitea-v2
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ steps.build-info.outputs.build-tag }}
|
tag_name: ${{ steps.build-info.outputs.build-tag }}
|
||||||
# On the publish test branch, mark our release as a draft
|
# On the publish test branch, mark our release as a draft
|
||||||
# Hack using endsWith to workaround Gitea sometimes sending "publish-test" vs "refs/heads/publish-test"
|
# Hack using endsWith to workaround Gitea sometimes sending "publish-test" vs "refs/heads/publish-test"
|
||||||
draft: ${{ endsWith('publish-test', github.ref ) }}
|
draft: ${{ endsWith('publish-test', github.ref ) }}
|
||||||
files: ./laconic-so
|
files: ./laconic-so
|
||||||
|
- name: Notify Vulcanize Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.VULCANIZE_SLACK_CI_ALERTS }}
|
||||||
|
- name: Notify DeepStack Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.DEEPSTACK_SLACK_CI_ALERTS }}
|
||||||
|
69
.gitea/workflows/test-container-registry.yml
Normal file
69
.gitea/workflows/test-container-registry.yml
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
name: Container Registry Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: '*'
|
||||||
|
paths:
|
||||||
|
- '!**'
|
||||||
|
- '.gitea/workflows/triggers/test-container-registry'
|
||||||
|
- '.gitea/workflows/test-container-registry.yml'
|
||||||
|
- 'tests/container-registry/run-test.sh'
|
||||||
|
schedule: # Note: coordinate with other tests to not overload runners at the same time of day
|
||||||
|
- cron: '6 19 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: "Run contaier registry hosting test on kind/k8s"
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- name: "Clone project repository"
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
# At present the stock setup-python action fails on Linux/aarch64
|
||||||
|
# Conditional steps below workaroud this by using deadsnakes for that case only
|
||||||
|
- name: "Install Python for ARM on Linux"
|
||||||
|
if: ${{ runner.arch == 'arm64' && runner.os == 'Linux' }}
|
||||||
|
uses: deadsnakes/action@v3.0.1
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Install Python cases other than ARM on Linux"
|
||||||
|
if: ${{ ! (runner.arch == 'arm64' && runner.os == 'Linux') }}
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Print Python version"
|
||||||
|
run: python3 --version
|
||||||
|
- name: "Install shiv"
|
||||||
|
run: pip install shiv
|
||||||
|
- name: "Generate build version file"
|
||||||
|
run: ./scripts/create_build_tag_file.sh
|
||||||
|
- name: "Build local shiv package"
|
||||||
|
run: ./scripts/build_shiv_package.sh
|
||||||
|
- name: "Check cgroups version"
|
||||||
|
run: mount | grep cgroup
|
||||||
|
- name: "Install kind"
|
||||||
|
run: ./tests/scripts/install-kind.sh
|
||||||
|
- name: "Install Kubectl"
|
||||||
|
run: ./tests/scripts/install-kubectl.sh
|
||||||
|
- name: "Install ed" # Only needed until we remove the need to edit the spec file
|
||||||
|
run: apt update && apt install -y ed
|
||||||
|
- name: "Run container registry deployment test"
|
||||||
|
run: |
|
||||||
|
source /opt/bash-utils/cgroup-helper.sh
|
||||||
|
join_cgroup
|
||||||
|
./tests/container-registry/run-test.sh
|
||||||
|
- name: Notify Vulcanize Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.VULCANIZE_SLACK_CI_ALERTS }}
|
||||||
|
- name: Notify DeepStack Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.DEEPSTACK_SLACK_CI_ALERTS }}
|
67
.gitea/workflows/test-database.yml
Normal file
67
.gitea/workflows/test-database.yml
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
name: Database Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: '*'
|
||||||
|
paths:
|
||||||
|
- '!**'
|
||||||
|
- '.gitea/workflows/triggers/test-database'
|
||||||
|
- '.gitea/workflows/test-database.yml'
|
||||||
|
- 'tests/database/run-test.sh'
|
||||||
|
schedule: # Note: coordinate with other tests to not overload runners at the same time of day
|
||||||
|
- cron: '5 18 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: "Run database hosting test on kind/k8s"
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- name: "Clone project repository"
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
# At present the stock setup-python action fails on Linux/aarch64
|
||||||
|
# Conditional steps below workaroud this by using deadsnakes for that case only
|
||||||
|
- name: "Install Python for ARM on Linux"
|
||||||
|
if: ${{ runner.arch == 'arm64' && runner.os == 'Linux' }}
|
||||||
|
uses: deadsnakes/action@v3.0.1
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Install Python cases other than ARM on Linux"
|
||||||
|
if: ${{ ! (runner.arch == 'arm64' && runner.os == 'Linux') }}
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Print Python version"
|
||||||
|
run: python3 --version
|
||||||
|
- name: "Install shiv"
|
||||||
|
run: pip install shiv
|
||||||
|
- name: "Generate build version file"
|
||||||
|
run: ./scripts/create_build_tag_file.sh
|
||||||
|
- name: "Build local shiv package"
|
||||||
|
run: ./scripts/build_shiv_package.sh
|
||||||
|
- name: "Check cgroups version"
|
||||||
|
run: mount | grep cgroup
|
||||||
|
- name: "Install kind"
|
||||||
|
run: ./tests/scripts/install-kind.sh
|
||||||
|
- name: "Install Kubectl"
|
||||||
|
run: ./tests/scripts/install-kubectl.sh
|
||||||
|
- name: "Run database deployment test"
|
||||||
|
run: |
|
||||||
|
source /opt/bash-utils/cgroup-helper.sh
|
||||||
|
join_cgroup
|
||||||
|
./tests/database/run-test.sh
|
||||||
|
- name: Notify Vulcanize Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.VULCANIZE_SLACK_CI_ALERTS }}
|
||||||
|
- name: Notify DeepStack Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.DEEPSTACK_SLACK_CI_ALERTS }}
|
58
.gitea/workflows/test-deploy.yml
Normal file
58
.gitea/workflows/test-deploy.yml
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
name: Deploy Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: '*'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- ci-test
|
||||||
|
paths-ignore:
|
||||||
|
- '.gitea/workflows/triggers/*'
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: "Run deploy test suite"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: "Clone project repository"
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
# At present the stock setup-python action fails on Linux/aarch64
|
||||||
|
# Conditional steps below workaroud this by using deadsnakes for that case only
|
||||||
|
- name: "Install Python for ARM on Linux"
|
||||||
|
if: ${{ runner.arch == 'arm64' && runner.os == 'Linux' }}
|
||||||
|
uses: deadsnakes/action@v3.0.1
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Install Python cases other than ARM on Linux"
|
||||||
|
if: ${{ ! (runner.arch == 'arm64' && runner.os == 'Linux') }}
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Print Python version"
|
||||||
|
run: python3 --version
|
||||||
|
- name: "Install shiv"
|
||||||
|
run: pip install shiv
|
||||||
|
- name: "Generate build version file"
|
||||||
|
run: ./scripts/create_build_tag_file.sh
|
||||||
|
- name: "Build local shiv package"
|
||||||
|
run: ./scripts/build_shiv_package.sh
|
||||||
|
- name: "Run deploy tests"
|
||||||
|
run: ./tests/deploy/run-deploy-test.sh
|
||||||
|
- name: Notify Vulcanize Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.VULCANIZE_SLACK_CI_ALERTS }}
|
||||||
|
- name: Notify DeepStack Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.DEEPSTACK_SLACK_CI_ALERTS }}
|
58
.gitea/workflows/test-external-stack.yml
Normal file
58
.gitea/workflows/test-external-stack.yml
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
name: External Stack Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: '*'
|
||||||
|
paths:
|
||||||
|
- '!**'
|
||||||
|
- '.gitea/workflows/triggers/test-external-stack'
|
||||||
|
- '.gitea/workflows/test-external-stack.yml'
|
||||||
|
- 'tests/external-stack/run-test.sh'
|
||||||
|
schedule: # Note: coordinate with other tests to not overload runners at the same time of day
|
||||||
|
- cron: '8 19 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: "Run external stack test suite"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: "Clone project repository"
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
# At present the stock setup-python action fails on Linux/aarch64
|
||||||
|
# Conditional steps below workaroud this by using deadsnakes for that case only
|
||||||
|
- name: "Install Python for ARM on Linux"
|
||||||
|
if: ${{ runner.arch == 'arm64' && runner.os == 'Linux' }}
|
||||||
|
uses: deadsnakes/action@v3.0.1
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Install Python cases other than ARM on Linux"
|
||||||
|
if: ${{ ! (runner.arch == 'arm64' && runner.os == 'Linux') }}
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Print Python version"
|
||||||
|
run: python3 --version
|
||||||
|
- name: "Install shiv"
|
||||||
|
run: pip install shiv
|
||||||
|
- name: "Generate build version file"
|
||||||
|
run: ./scripts/create_build_tag_file.sh
|
||||||
|
- name: "Build local shiv package"
|
||||||
|
run: ./scripts/build_shiv_package.sh
|
||||||
|
- name: "Run external stack tests"
|
||||||
|
run: ./tests/external-stack/run-test.sh
|
||||||
|
- name: Notify Vulcanize Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.VULCANIZE_SLACK_CI_ALERTS }}
|
||||||
|
- name: Notify DeepStack Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.DEEPSTACK_SLACK_CI_ALERTS }}
|
69
.gitea/workflows/test-k8s-deploy.yml
Normal file
69
.gitea/workflows/test-k8s-deploy.yml
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
name: K8s Deploy Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: '*'
|
||||||
|
push:
|
||||||
|
branches: '*'
|
||||||
|
paths:
|
||||||
|
- '!**'
|
||||||
|
- '.gitea/workflows/triggers/test-k8s-deploy'
|
||||||
|
- '.gitea/workflows/test-k8s-deploy.yml'
|
||||||
|
- 'tests/k8s-deploy/run-deploy-test.sh'
|
||||||
|
schedule: # Note: coordinate with other tests to not overload runners at the same time of day
|
||||||
|
- cron: '3 15 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: "Run deploy test suite on kind/k8s"
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- name: "Clone project repository"
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
# At present the stock setup-python action fails on Linux/aarch64
|
||||||
|
# Conditional steps below workaroud this by using deadsnakes for that case only
|
||||||
|
- name: "Install Python for ARM on Linux"
|
||||||
|
if: ${{ runner.arch == 'arm64' && runner.os == 'Linux' }}
|
||||||
|
uses: deadsnakes/action@v3.0.1
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Install Python cases other than ARM on Linux"
|
||||||
|
if: ${{ ! (runner.arch == 'arm64' && runner.os == 'Linux') }}
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Print Python version"
|
||||||
|
run: python3 --version
|
||||||
|
- name: "Install shiv"
|
||||||
|
run: pip install shiv
|
||||||
|
- name: "Generate build version file"
|
||||||
|
run: ./scripts/create_build_tag_file.sh
|
||||||
|
- name: "Build local shiv package"
|
||||||
|
run: ./scripts/build_shiv_package.sh
|
||||||
|
- name: "Check cgroups version"
|
||||||
|
run: mount | grep cgroup
|
||||||
|
- name: "Install kind"
|
||||||
|
run: ./tests/scripts/install-kind.sh
|
||||||
|
- name: "Install Kubectl"
|
||||||
|
run: ./tests/scripts/install-kubectl.sh
|
||||||
|
- name: "Run k8s deployment test"
|
||||||
|
run: |
|
||||||
|
source /opt/bash-utils/cgroup-helper.sh
|
||||||
|
join_cgroup
|
||||||
|
./tests/k8s-deploy/run-deploy-test.sh
|
||||||
|
- name: Notify Vulcanize Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.VULCANIZE_SLACK_CI_ALERTS }}
|
||||||
|
- name: Notify DeepStack Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.DEEPSTACK_SLACK_CI_ALERTS }}
|
69
.gitea/workflows/test-k8s-deployment-control.yml
Normal file
69
.gitea/workflows/test-k8s-deployment-control.yml
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
name: K8s Deployment Control Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: '*'
|
||||||
|
push:
|
||||||
|
branches: '*'
|
||||||
|
paths:
|
||||||
|
- '!**'
|
||||||
|
- '.gitea/workflows/triggers/test-k8s-deployment-control'
|
||||||
|
- '.gitea/workflows/test-k8s-deployment-control.yml'
|
||||||
|
- 'tests/k8s-deployment-control/run-test.sh'
|
||||||
|
schedule: # Note: coordinate with other tests to not overload runners at the same time of day
|
||||||
|
- cron: '3 30 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: "Run deployment control suite on kind/k8s"
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- name: "Clone project repository"
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
# At present the stock setup-python action fails on Linux/aarch64
|
||||||
|
# Conditional steps below workaroud this by using deadsnakes for that case only
|
||||||
|
- name: "Install Python for ARM on Linux"
|
||||||
|
if: ${{ runner.arch == 'arm64' && runner.os == 'Linux' }}
|
||||||
|
uses: deadsnakes/action@v3.0.1
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Install Python cases other than ARM on Linux"
|
||||||
|
if: ${{ ! (runner.arch == 'arm64' && runner.os == 'Linux') }}
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Print Python version"
|
||||||
|
run: python3 --version
|
||||||
|
- name: "Install shiv"
|
||||||
|
run: pip install shiv
|
||||||
|
- name: "Generate build version file"
|
||||||
|
run: ./scripts/create_build_tag_file.sh
|
||||||
|
- name: "Build local shiv package"
|
||||||
|
run: ./scripts/build_shiv_package.sh
|
||||||
|
- name: "Check cgroups version"
|
||||||
|
run: mount | grep cgroup
|
||||||
|
- name: "Install kind"
|
||||||
|
run: ./tests/scripts/install-kind.sh
|
||||||
|
- name: "Install Kubectl"
|
||||||
|
run: ./tests/scripts/install-kubectl.sh
|
||||||
|
- name: "Run k8s deployment control test"
|
||||||
|
run: |
|
||||||
|
source /opt/bash-utils/cgroup-helper.sh
|
||||||
|
join_cgroup
|
||||||
|
./tests/k8s-deployment-control/run-test.sh
|
||||||
|
- name: Notify Vulcanize Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.VULCANIZE_SLACK_CI_ALERTS }}
|
||||||
|
- name: Notify DeepStack Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.DEEPSTACK_SLACK_CI_ALERTS }}
|
59
.gitea/workflows/test-webapp.yml
Normal file
59
.gitea/workflows/test-webapp.yml
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
name: Webapp Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: '*'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- ci-test
|
||||||
|
paths-ignore:
|
||||||
|
- '.gitea/workflows/triggers/*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: "Run webapp test suite"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: "Clone project repository"
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
# At present the stock setup-python action fails on Linux/aarch64
|
||||||
|
# Conditional steps below workaroud this by using deadsnakes for that case only
|
||||||
|
- name: "Install Python for ARM on Linux"
|
||||||
|
if: ${{ runner.arch == 'arm64' && runner.os == 'Linux' }}
|
||||||
|
uses: deadsnakes/action@v3.0.1
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Install Python cases other than ARM on Linux"
|
||||||
|
if: ${{ ! (runner.arch == 'arm64' && runner.os == 'Linux') }}
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Print Python version"
|
||||||
|
run: python3 --version
|
||||||
|
- name: "Install shiv"
|
||||||
|
run: pip install shiv
|
||||||
|
- name: "Generate build version file"
|
||||||
|
run: ./scripts/create_build_tag_file.sh
|
||||||
|
- name: "Build local shiv package"
|
||||||
|
run: ./scripts/build_shiv_package.sh
|
||||||
|
- name: "Install wget" # 20240109 - Only needed until the executors are updated.
|
||||||
|
run: apt update && apt install -y wget
|
||||||
|
- name: "Run webapp tests"
|
||||||
|
run: ./tests/webapp-test/run-webapp-test.sh
|
||||||
|
- name: Notify Vulcanize Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.VULCANIZE_SLACK_CI_ALERTS }}
|
||||||
|
- name: Notify DeepStack Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.DEEPSTACK_SLACK_CI_ALERTS }}
|
@ -1,4 +1,4 @@
|
|||||||
name: Integration Test
|
name: Smoke Test
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
@ -7,10 +7,9 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- ci-test
|
- ci-test
|
||||||
|
paths-ignore:
|
||||||
|
- '.gitea/workflows/triggers/*'
|
||||||
|
|
||||||
# Needed until we can incorporate docker startup into the executor container
|
|
||||||
env:
|
|
||||||
DOCKER_HOST: unix:///var/run/dind.sock
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
@ -19,8 +18,16 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: "Clone project repository"
|
- name: "Clone project repository"
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: "Install Python"
|
# At present the stock setup-python action fails on Linux/aarch64
|
||||||
uses: cerc-io/setup-python@v4
|
# Conditional steps below workaroud this by using deadsnakes for that case only
|
||||||
|
- name: "Install Python for ARM on Linux"
|
||||||
|
if: ${{ runner.arch == 'arm64' && runner.os == 'Linux' }}
|
||||||
|
uses: deadsnakes/action@v3.0.1
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Install Python cases other than ARM on Linux"
|
||||||
|
if: ${{ ! (runner.arch == 'arm64' && runner.os == 'Linux') }}
|
||||||
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: '3.8'
|
python-version: '3.8'
|
||||||
- name: "Print Python version"
|
- name: "Print Python version"
|
||||||
@ -31,9 +38,21 @@ jobs:
|
|||||||
run: ./scripts/create_build_tag_file.sh
|
run: ./scripts/create_build_tag_file.sh
|
||||||
- name: "Build local shiv package"
|
- name: "Build local shiv package"
|
||||||
run: ./scripts/build_shiv_package.sh
|
run: ./scripts/build_shiv_package.sh
|
||||||
- name: Start dockerd # Also needed until we can incorporate into the executor
|
|
||||||
run: |
|
|
||||||
dockerd -H $DOCKER_HOST --userland-proxy=false &
|
|
||||||
sleep 5
|
|
||||||
- name: "Run smoke tests"
|
- name: "Run smoke tests"
|
||||||
run: ./tests/smoke-test/run-smoke-test.sh
|
run: ./tests/smoke-test/run-smoke-test.sh
|
||||||
|
- name: Notify Vulcanize Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.VULCANIZE_SLACK_CI_ALERTS }}
|
||||||
|
- name: Notify DeepStack Slack on CI failure
|
||||||
|
if: ${{ always() && github.ref_name == 'main' }}
|
||||||
|
uses: ravsamhq/notify-slack-action@v2
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
notify_when: 'failure'
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.DEEPSTACK_SLACK_CI_ALERTS }}
|
||||||
|
10
.gitea/workflows/triggers/fixturenet-laconicd-test
Normal file
10
.gitea/workflows/triggers/fixturenet-laconicd-test
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
Change this file to trigger running the fixturenet-laconicd-test CI job
|
||||||
|
Trigger
|
||||||
|
Trigger
|
||||||
|
Trigger
|
||||||
|
Trigger
|
||||||
|
Trigger
|
||||||
|
Trigger
|
||||||
|
Trigger
|
||||||
|
Trigger
|
||||||
|
Trigger
|
1
.gitea/workflows/triggers/test-container-registry
Normal file
1
.gitea/workflows/triggers/test-container-registry
Normal file
@ -0,0 +1 @@
|
|||||||
|
Change this file to trigger running the test-container-registry CI job
|
2
.gitea/workflows/triggers/test-database
Normal file
2
.gitea/workflows/triggers/test-database
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Change this file to trigger running the test-database CI job
|
||||||
|
Trigger test run
|
2
.gitea/workflows/triggers/test-external-stack
Normal file
2
.gitea/workflows/triggers/test-external-stack
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Change this file to trigger running the external-stack CI job
|
||||||
|
trigger
|
2
.gitea/workflows/triggers/test-k8s-deploy
Normal file
2
.gitea/workflows/triggers/test-k8s-deploy
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Change this file to trigger running the test-k8s-deploy CI job
|
||||||
|
Trigger test on PR branch
|
@ -1,18 +1,21 @@
|
|||||||
name: Fixturenet-Eth-Test
|
name: Fixturenet-Eth Test
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: 'ci-test'
|
branches: '*'
|
||||||
|
paths:
|
||||||
|
- '!**'
|
||||||
|
- '.github/workflows/triggers/fixturenet-eth-test'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
name: "Run an Ethereum fixturenet test"
|
name: "Run fixturenet-eth test suite"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: "Clone project repository"
|
- name: "Clone project repository"
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: "Install Python"
|
- name: "Install Python"
|
||||||
uses: cerc-io/setup-python@v4
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: '3.8'
|
python-version: '3.8'
|
||||||
- name: "Print Python version"
|
- name: "Print Python version"
|
30
.github/workflows/fixturenet-laconicd.yml
vendored
Normal file
30
.github/workflows/fixturenet-laconicd.yml
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
name: Fixturenet-Laconicd Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: '*'
|
||||||
|
paths:
|
||||||
|
- '!**'
|
||||||
|
- '.github/workflows/triggers/fixturenet-laconicd-test'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: "Run fixturenet-laconicd test suite"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: "Clone project repository"
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: "Install Python"
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Print Python version"
|
||||||
|
run: python3 --version
|
||||||
|
- name: "Install shiv"
|
||||||
|
run: pip install shiv
|
||||||
|
- name: "Generate build version file"
|
||||||
|
run: ./scripts/create_build_tag_file.sh
|
||||||
|
- name: "Build local shiv package"
|
||||||
|
run: ./scripts/build_shiv_package.sh
|
||||||
|
- name: "Run fixturenet-laconicd tests"
|
||||||
|
run: ./tests/fixturenet-laconicd/run-test.sh
|
21
.github/workflows/lint.yml
vendored
Normal file
21
.github/workflows/lint.yml
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
name: Lint Checks
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: '*'
|
||||||
|
push:
|
||||||
|
branches: '*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: "Run linter"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: "Clone project repository"
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: "Install Python"
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name : "Run flake8"
|
||||||
|
uses: py-actions/flake8@v2
|
29
.github/workflows/test-deploy.yml
vendored
Normal file
29
.github/workflows/test-deploy.yml
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
name: Deploy Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: '*'
|
||||||
|
push:
|
||||||
|
branches: '*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: "Run deploy test suite"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: "Clone project repository"
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: "Install Python"
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Print Python version"
|
||||||
|
run: python3 --version
|
||||||
|
- name: "Install shiv"
|
||||||
|
run: pip install shiv
|
||||||
|
- name: "Generate build version file"
|
||||||
|
run: ./scripts/create_build_tag_file.sh
|
||||||
|
- name: "Build local shiv package"
|
||||||
|
run: ./scripts/build_shiv_package.sh
|
||||||
|
- name: "Run deploy tests"
|
||||||
|
run: ./tests/deploy/run-deploy-test.sh
|
29
.github/workflows/test-webapp.yml
vendored
Normal file
29
.github/workflows/test-webapp.yml
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
name: Webapp Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: '*'
|
||||||
|
push:
|
||||||
|
branches: '*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: "Run webapp test suite"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: "Clone project repository"
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: "Install Python"
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Print Python version"
|
||||||
|
run: python3 --version
|
||||||
|
- name: "Install shiv"
|
||||||
|
run: pip install shiv
|
||||||
|
- name: "Generate build version file"
|
||||||
|
run: ./scripts/create_build_tag_file.sh
|
||||||
|
- name: "Build local shiv package"
|
||||||
|
run: ./scripts/build_shiv_package.sh
|
||||||
|
- name: "Run webapp tests"
|
||||||
|
run: ./tests/webapp-test/run-webapp-test.sh
|
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@ -1,4 +1,4 @@
|
|||||||
name: Test
|
name: Smoke Test
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
2
.github/workflows/triggers/fixturenet-eth-test
vendored
Normal file
2
.github/workflows/triggers/fixturenet-eth-test
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Change this file to trigger running the fixturenet-eth-test CI job
|
||||||
|
|
3
.github/workflows/triggers/fixturenet-laconicd-test
vendored
Normal file
3
.github/workflows/triggers/fixturenet-laconicd-test
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Change this file to trigger running the fixturenet-laconicd-test CI job
|
||||||
|
|
||||||
|
trigger
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -6,4 +6,5 @@ laconic_stack_orchestrator.egg-info
|
|||||||
__pycache__
|
__pycache__
|
||||||
*~
|
*~
|
||||||
package
|
package
|
||||||
app/data/build_tag.txt
|
stack_orchestrator/data/build_tag.txt
|
||||||
|
/build
|
||||||
|
29
README.md
29
README.md
@ -6,7 +6,7 @@ Stack Orchestrator allows building and deployment of a Laconic Stack on a single
|
|||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
**To get started quickly** on a fresh Ubuntu instance (e.g, Digital Ocean); [try this script](./scripts/quick-install-ubuntu.sh). **WARNING:** always review scripts prior to running them so that you know what is happening on your machine.
|
**To get started quickly** on a fresh Ubuntu instance (e.g, Digital Ocean); [try this script](./scripts/quick-install-linux.sh). **WARNING:** always review scripts prior to running them so that you know what is happening on your machine.
|
||||||
|
|
||||||
For any other installation, follow along below and **adapt these instructions based on the specifics of your system.**
|
For any other installation, follow along below and **adapt these instructions based on the specifics of your system.**
|
||||||
|
|
||||||
@ -16,6 +16,7 @@ Ensure that the following are already installed:
|
|||||||
- [Python3](https://wiki.python.org/moin/BeginnersGuide/Download): `python3 --version` >= `3.8.10` (the Python3 shipped in Ubuntu 20+ is good to go)
|
- [Python3](https://wiki.python.org/moin/BeginnersGuide/Download): `python3 --version` >= `3.8.10` (the Python3 shipped in Ubuntu 20+ is good to go)
|
||||||
- [Docker](https://docs.docker.com/get-docker/): `docker --version` >= `20.10.21`
|
- [Docker](https://docs.docker.com/get-docker/): `docker --version` >= `20.10.21`
|
||||||
- [jq](https://stedolan.github.io/jq/download/): `jq --version` >= `1.5`
|
- [jq](https://stedolan.github.io/jq/download/): `jq --version` >= `1.5`
|
||||||
|
- [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git): `git --version` >= `2.10.3`
|
||||||
|
|
||||||
Note: if installing docker-compose via package manager on Linux (as opposed to Docker Desktop), you must [install the plugin](https://docs.docker.com/compose/install/linux/#install-the-plugin-manually), e.g. :
|
Note: if installing docker-compose via package manager on Linux (as opposed to Docker Desktop), you must [install the plugin](https://docs.docker.com/compose/install/linux/#install-the-plugin-manually), e.g. :
|
||||||
|
|
||||||
@ -28,10 +29,10 @@ chmod +x ~/.docker/cli-plugins/docker-compose
|
|||||||
Next decide on a directory where you would like to put the stack-orchestrator program. Typically this would be
|
Next decide on a directory where you would like to put the stack-orchestrator program. Typically this would be
|
||||||
a "user" binary directory such as `~/bin` or perhaps `/usr/local/laconic` or possibly just the current working directory.
|
a "user" binary directory such as `~/bin` or perhaps `/usr/local/laconic` or possibly just the current working directory.
|
||||||
|
|
||||||
Now, having selected that directory, download the latest release from [this page](https://github.com/cerc-io/stack-orchestrator/tags) into it (we're using `~/bin` below for concreteness but edit to suit if you selected a different directory). Also be sure that the destination directory exists and is writable:
|
Now, having selected that directory, download the latest release from [this page](https://git.vdb.to/cerc-io/stack-orchestrator/tags) into it (we're using `~/bin` below for concreteness but edit to suit if you selected a different directory). Also be sure that the destination directory exists and is writable:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -L -o ~/bin/laconic-so https://github.com/cerc-io/stack-orchestrator/releases/latest/download/laconic-so
|
curl -L -o ~/bin/laconic-so https://git.vdb.to/cerc-io/stack-orchestrator/releases/download/latest/laconic-so
|
||||||
```
|
```
|
||||||
|
|
||||||
Give it execute permissions:
|
Give it execute permissions:
|
||||||
@ -48,15 +49,27 @@ Verify operation (your version will probably be different, just check here that
|
|||||||
laconic-so version
|
laconic-so version
|
||||||
Version: 1.1.0-7a607c2-202304260513
|
Version: 1.1.0-7a607c2-202304260513
|
||||||
```
|
```
|
||||||
|
Save the distribution url to `~/.laconic-so/config.yml`:
|
||||||
|
```bash
|
||||||
|
mkdir ~/.laconic-so
|
||||||
|
echo "distribution-url: https://git.vdb.to/cerc-io/stack-orchestrator/releases/download/latest/laconic-so" > ~/.laconic-so/config.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
### Update
|
||||||
|
If Stack Orchestrator was installed using the process described above, it is able to subsequently self-update to the current latest version by running:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
laconic-so update
|
||||||
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
The various [stacks](/app/data/stacks) each contain instructions for running different stacks based on your use case. For example:
|
The various [stacks](/stack_orchestrator/data/stacks) each contain instructions for running different stacks based on your use case. For example:
|
||||||
|
|
||||||
- [self-hosted Gitea](/app/data/stacks/build-support)
|
- [self-hosted Gitea](/stack_orchestrator/data/stacks/build-support)
|
||||||
- [an Optimism Fixturenet](/app/data/stacks/fixturenet-optimism)
|
- [an Optimism Fixturenet](/stack_orchestrator/data/stacks/fixturenet-optimism)
|
||||||
- [laconicd with console and CLI](app/data/stacks/fixturenet-laconic-loaded)
|
- [laconicd with console and CLI](stack_orchestrator/data/stacks/fixturenet-laconic-loaded)
|
||||||
- [kubo (IPFS)](app/data/stacks/kubo)
|
- [kubo (IPFS)](stack_orchestrator/data/stacks/kubo)
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
@ -1,141 +0,0 @@
|
|||||||
# Copyright © 2022, 2023 Cerc
|
|
||||||
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
# Builds or pulls containers for the system components
|
|
||||||
|
|
||||||
# env vars:
|
|
||||||
# CERC_REPO_BASE_DIR defaults to ~/cerc
|
|
||||||
|
|
||||||
# TODO: display the available list of containers; allow re-build of either all or specific containers
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from decouple import config
|
|
||||||
import subprocess
|
|
||||||
import click
|
|
||||||
import importlib.resources
|
|
||||||
from pathlib import Path
|
|
||||||
from .util import include_exclude_check, get_parsed_stack_config
|
|
||||||
|
|
||||||
# TODO: find a place for this
|
|
||||||
# epilog="Config provided either in .env or settings.ini or env vars: CERC_REPO_BASE_DIR (defaults to ~/cerc)"
|
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
|
||||||
@click.option('--include', help="only build these containers")
|
|
||||||
@click.option('--exclude', help="don\'t build these containers")
|
|
||||||
@click.option("--force-rebuild", is_flag=True, default=False, help="Override dependency checking -- always rebuild")
|
|
||||||
@click.option("--extra-build-args", help="Supply extra arguments to build")
|
|
||||||
@click.pass_context
|
|
||||||
def command(ctx, include, exclude, force_rebuild, extra_build_args):
|
|
||||||
'''build the set of containers required for a complete stack'''
|
|
||||||
|
|
||||||
quiet = ctx.obj.quiet
|
|
||||||
verbose = ctx.obj.verbose
|
|
||||||
dry_run = ctx.obj.dry_run
|
|
||||||
debug = ctx.obj.debug
|
|
||||||
local_stack = ctx.obj.local_stack
|
|
||||||
stack = ctx.obj.stack
|
|
||||||
continue_on_error = ctx.obj.continue_on_error
|
|
||||||
|
|
||||||
# See: https://stackoverflow.com/questions/25389095/python-get-path-of-root-project-structure
|
|
||||||
container_build_dir = Path(__file__).absolute().parent.joinpath("data", "container-build")
|
|
||||||
|
|
||||||
if local_stack:
|
|
||||||
dev_root_path = os.getcwd()[0:os.getcwd().rindex("stack-orchestrator")]
|
|
||||||
print(f'Local stack dev_root_path (CERC_REPO_BASE_DIR) overridden to: {dev_root_path}')
|
|
||||||
else:
|
|
||||||
dev_root_path = os.path.expanduser(config("CERC_REPO_BASE_DIR", default="~/cerc"))
|
|
||||||
|
|
||||||
if not quiet:
|
|
||||||
print(f'Dev Root is: {dev_root_path}')
|
|
||||||
|
|
||||||
if not os.path.isdir(dev_root_path):
|
|
||||||
print('Dev root directory doesn\'t exist, creating')
|
|
||||||
|
|
||||||
# See: https://stackoverflow.com/a/20885799/1701505
|
|
||||||
from . import data
|
|
||||||
with importlib.resources.open_text(data, "container-image-list.txt") as container_list_file:
|
|
||||||
all_containers = container_list_file.read().splitlines()
|
|
||||||
|
|
||||||
containers_in_scope = []
|
|
||||||
if stack:
|
|
||||||
stack_config = get_parsed_stack_config(stack)
|
|
||||||
containers_in_scope = stack_config['containers']
|
|
||||||
else:
|
|
||||||
containers_in_scope = all_containers
|
|
||||||
|
|
||||||
if verbose:
|
|
||||||
print(f'Containers: {containers_in_scope}')
|
|
||||||
if stack:
|
|
||||||
print(f"Stack: {stack}")
|
|
||||||
|
|
||||||
# TODO: make this configurable
|
|
||||||
container_build_env = {
|
|
||||||
"CERC_NPM_REGISTRY_URL": config("CERC_NPM_REGISTRY_URL", default="http://gitea.local:3000/api/packages/cerc-io/npm/"),
|
|
||||||
"CERC_NPM_AUTH_TOKEN": config("CERC_NPM_AUTH_TOKEN", default=""),
|
|
||||||
"CERC_REPO_BASE_DIR": dev_root_path,
|
|
||||||
"CERC_CONTAINER_BASE_DIR": container_build_dir,
|
|
||||||
"CERC_HOST_UID": f"{os.getuid()}",
|
|
||||||
"CERC_HOST_GID": f"{os.getgid()}",
|
|
||||||
"DOCKER_BUILDKIT": "0"
|
|
||||||
}
|
|
||||||
container_build_env.update({"CERC_SCRIPT_DEBUG": "true"} if debug else {})
|
|
||||||
container_build_env.update({"CERC_FORCE_REBUILD": "true"} if force_rebuild else {})
|
|
||||||
container_build_env.update({"CERC_CONTAINER_EXTRA_BUILD_ARGS": extra_build_args} if extra_build_args else {})
|
|
||||||
docker_host_env = os.getenv("DOCKER_HOST")
|
|
||||||
if docker_host_env:
|
|
||||||
container_build_env.update({"DOCKER_HOST": docker_host_env})
|
|
||||||
|
|
||||||
def process_container(container):
|
|
||||||
if not quiet:
|
|
||||||
print(f"Building: {container}")
|
|
||||||
build_dir = os.path.join(container_build_dir, container.replace("/", "-"))
|
|
||||||
build_script_filename = os.path.join(build_dir, "build.sh")
|
|
||||||
if verbose:
|
|
||||||
print(f"Build script filename: {build_script_filename}")
|
|
||||||
if os.path.exists(build_script_filename):
|
|
||||||
build_command = build_script_filename
|
|
||||||
else:
|
|
||||||
if verbose:
|
|
||||||
print(f"No script file found: {build_script_filename}, using default build script")
|
|
||||||
repo_dir = container.split('/')[1]
|
|
||||||
# TODO: make this less of a hack -- should be specified in some metadata somewhere
|
|
||||||
# Check if we have a repo for this container. If not, set the context dir to the container-build subdir
|
|
||||||
repo_full_path = os.path.join(dev_root_path, repo_dir)
|
|
||||||
repo_dir_or_build_dir = repo_dir if os.path.exists(repo_full_path) else build_dir
|
|
||||||
build_command = os.path.join(container_build_dir, "default-build.sh") + f" {container}:local {repo_dir_or_build_dir}"
|
|
||||||
if not dry_run:
|
|
||||||
if verbose:
|
|
||||||
print(f"Executing: {build_command} with environment: {container_build_env}")
|
|
||||||
build_result = subprocess.run(build_command, shell=True, env=container_build_env)
|
|
||||||
if verbose:
|
|
||||||
print(f"Return code is: {build_result.returncode}")
|
|
||||||
if build_result.returncode != 0:
|
|
||||||
print(f"Error running build for {container}")
|
|
||||||
if not continue_on_error:
|
|
||||||
print("FATAL Error: container build failed and --continue-on-error not set, exiting")
|
|
||||||
sys.exit(1)
|
|
||||||
else:
|
|
||||||
print("****** Container Build Error, continuing because --continue-on-error is set")
|
|
||||||
else:
|
|
||||||
print("Skipped")
|
|
||||||
|
|
||||||
for container in containers_in_scope:
|
|
||||||
if include_exclude_check(container, include, exclude):
|
|
||||||
process_container(container)
|
|
||||||
else:
|
|
||||||
if verbose:
|
|
||||||
print(f"Excluding: {container}")
|
|
@ -1,13 +0,0 @@
|
|||||||
version: "3.2"
|
|
||||||
# See: https://docs.ipfs.tech/install/run-ipfs-inside-docker/#set-up
|
|
||||||
services:
|
|
||||||
ipfs:
|
|
||||||
image: ipfs/kubo:master-2023-02-20-714a968
|
|
||||||
restart: always
|
|
||||||
volumes:
|
|
||||||
- ./ipfs/import:/import
|
|
||||||
- ./ipfs/data:/data/ipfs
|
|
||||||
ports:
|
|
||||||
- "0.0.0.0:8080:8080"
|
|
||||||
- "0.0.0.0:4001:4001"
|
|
||||||
- "0.0.0.0:5001:5001"
|
|
@ -1,7 +0,0 @@
|
|||||||
version: "3.2"
|
|
||||||
services:
|
|
||||||
test:
|
|
||||||
image: cerc/test-container:local
|
|
||||||
restart: always
|
|
||||||
ports:
|
|
||||||
- "80"
|
|
@ -1,304 +0,0 @@
|
|||||||
version: '3.2'
|
|
||||||
|
|
||||||
services:
|
|
||||||
# Starts the PostgreSQL database for watchers
|
|
||||||
watcher-db:
|
|
||||||
restart: unless-stopped
|
|
||||||
image: postgres:14-alpine
|
|
||||||
environment:
|
|
||||||
- POSTGRES_USER=vdbm
|
|
||||||
- POSTGRES_MULTIPLE_DATABASES=azimuth-watcher,azimuth-watcher-job-queue,censures-watcher,censures-watcher-job-queue,claims-watcher,claims-watcher-job-queue,conditional-star-release-watcher,conditional-star-release-watcher-job-queue,delegated-sending-watcher,delegated-sending-watcher-job-queue,ecliptic-watcher,ecliptic-watcher-job-queue,linear-star-release-watcher,linear-star-release-watcher-job-queue,polls-watcher,polls-watcher-job-queue
|
|
||||||
- POSTGRES_EXTENSION=azimuth-watcher-job-queue:pgcrypto,censures-watcher-job-queue:pgcrypto,claims-watcher-job-queue:pgcrypto,conditional-star-release-watcher-job-queue:pgcrypto,delegated-sending-watcher-job-queue:pgcrypto,ecliptic-watcher-job-queue:pgcrypto,linear-star-release-watcher-job-queue:pgcrypto,polls-watcher-job-queue:pgcrypto,
|
|
||||||
- POSTGRES_PASSWORD=password
|
|
||||||
volumes:
|
|
||||||
- ../config/postgresql/multiple-postgressql-databases.sh:/docker-entrypoint-initdb.d/multiple-postgressql-databases.sh
|
|
||||||
- watcher_db_data:/var/lib/postgresql/data
|
|
||||||
ports:
|
|
||||||
- "0.0.0.0:15432:5432"
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "nc", "-v", "localhost", "5432"]
|
|
||||||
interval: 20s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 15
|
|
||||||
start_period: 10s
|
|
||||||
|
|
||||||
# Starts the azimuth-watcher server
|
|
||||||
azimuth-watcher-server:
|
|
||||||
image: cerc/watcher-azimuth:local
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
watcher-db:
|
|
||||||
condition: service_healthy
|
|
||||||
env_file:
|
|
||||||
- ../config/watcher-azimuth/watcher-params.env
|
|
||||||
environment:
|
|
||||||
CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG}
|
|
||||||
CERC_IPLD_ETH_RPC: ${CERC_IPLD_ETH_RPC}
|
|
||||||
CERC_IPLD_ETH_GQL: ${CERC_IPLD_ETH_GQL}
|
|
||||||
working_dir: /app/packages/azimuth-watcher
|
|
||||||
command: "./start-server.sh"
|
|
||||||
volumes:
|
|
||||||
- ../config/watcher-azimuth/watcher-config-template.toml:/app/packages/azimuth-watcher/environments/watcher-config-template.toml
|
|
||||||
- ../config/watcher-azimuth/merge-toml.js:/app/packages/azimuth-watcher/merge-toml.js
|
|
||||||
- ../config/watcher-azimuth/start-server.sh:/app/packages/azimuth-watcher/start-server.sh
|
|
||||||
ports:
|
|
||||||
- "3001"
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "nc", "-vz", "localhost", "3001"]
|
|
||||||
interval: 20s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 15
|
|
||||||
start_period: 5s
|
|
||||||
extra_hosts:
|
|
||||||
- "host.docker.internal:host-gateway"
|
|
||||||
|
|
||||||
# Starts the censures-watcher server
|
|
||||||
censures-watcher-server:
|
|
||||||
image: cerc/watcher-azimuth:local
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
watcher-db:
|
|
||||||
condition: service_healthy
|
|
||||||
env_file:
|
|
||||||
- ../config/watcher-azimuth/watcher-params.env
|
|
||||||
environment:
|
|
||||||
CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG}
|
|
||||||
CERC_IPLD_ETH_RPC: ${CERC_IPLD_ETH_RPC}
|
|
||||||
CERC_IPLD_ETH_GQL: ${CERC_IPLD_ETH_GQL}
|
|
||||||
working_dir: /app/packages/censures-watcher
|
|
||||||
command: "./start-server.sh"
|
|
||||||
volumes:
|
|
||||||
- ../config/watcher-azimuth/watcher-config-template.toml:/app/packages/censures-watcher/environments/watcher-config-template.toml
|
|
||||||
- ../config/watcher-azimuth/merge-toml.js:/app/packages/censures-watcher/merge-toml.js
|
|
||||||
- ../config/watcher-azimuth/start-server.sh:/app/packages/censures-watcher/start-server.sh
|
|
||||||
ports:
|
|
||||||
- "3002"
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "nc", "-vz", "localhost", "3002"]
|
|
||||||
interval: 20s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 15
|
|
||||||
start_period: 5s
|
|
||||||
extra_hosts:
|
|
||||||
- "host.docker.internal:host-gateway"
|
|
||||||
|
|
||||||
# Starts the claims-watcher server
|
|
||||||
claims-watcher-server:
|
|
||||||
image: cerc/watcher-azimuth:local
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
watcher-db:
|
|
||||||
condition: service_healthy
|
|
||||||
env_file:
|
|
||||||
- ../config/watcher-azimuth/watcher-params.env
|
|
||||||
environment:
|
|
||||||
CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG}
|
|
||||||
CERC_IPLD_ETH_RPC: ${CERC_IPLD_ETH_RPC}
|
|
||||||
CERC_IPLD_ETH_GQL: ${CERC_IPLD_ETH_GQL}
|
|
||||||
working_dir: /app/packages/claims-watcher
|
|
||||||
command: "./start-server.sh"
|
|
||||||
volumes:
|
|
||||||
- ../config/watcher-azimuth/watcher-config-template.toml:/app/packages/claims-watcher/environments/watcher-config-template.toml
|
|
||||||
- ../config/watcher-azimuth/merge-toml.js:/app/packages/claims-watcher/merge-toml.js
|
|
||||||
- ../config/watcher-azimuth/start-server.sh:/app/packages/claims-watcher/start-server.sh
|
|
||||||
ports:
|
|
||||||
- "3003"
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "nc", "-vz", "localhost", "3003"]
|
|
||||||
interval: 20s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 15
|
|
||||||
start_period: 5s
|
|
||||||
extra_hosts:
|
|
||||||
- "host.docker.internal:host-gateway"
|
|
||||||
|
|
||||||
# Starts the conditional-star-release-watcher server
|
|
||||||
conditional-star-release-watcher-server:
|
|
||||||
image: cerc/watcher-azimuth:local
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
watcher-db:
|
|
||||||
condition: service_healthy
|
|
||||||
env_file:
|
|
||||||
- ../config/watcher-azimuth/watcher-params.env
|
|
||||||
environment:
|
|
||||||
CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG}
|
|
||||||
CERC_IPLD_ETH_RPC: ${CERC_IPLD_ETH_RPC}
|
|
||||||
CERC_IPLD_ETH_GQL: ${CERC_IPLD_ETH_GQL}
|
|
||||||
working_dir: /app/packages/conditional-star-release-watcher
|
|
||||||
command: "./start-server.sh"
|
|
||||||
volumes:
|
|
||||||
- ../config/watcher-azimuth/watcher-config-template.toml:/app/packages/conditional-star-release-watcher/environments/watcher-config-template.toml
|
|
||||||
- ../config/watcher-azimuth/merge-toml.js:/app/packages/conditional-star-release-watcher/merge-toml.js
|
|
||||||
- ../config/watcher-azimuth/start-server.sh:/app/packages/conditional-star-release-watcher/start-server.sh
|
|
||||||
ports:
|
|
||||||
- "3004"
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "nc", "-vz", "localhost", "3004"]
|
|
||||||
interval: 20s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 15
|
|
||||||
start_period: 5s
|
|
||||||
extra_hosts:
|
|
||||||
- "host.docker.internal:host-gateway"
|
|
||||||
|
|
||||||
# Starts the delegated-sending-watcher server
|
|
||||||
delegated-sending-watcher-server:
|
|
||||||
image: cerc/watcher-azimuth:local
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
watcher-db:
|
|
||||||
condition: service_healthy
|
|
||||||
env_file:
|
|
||||||
- ../config/watcher-azimuth/watcher-params.env
|
|
||||||
environment:
|
|
||||||
CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG}
|
|
||||||
CERC_IPLD_ETH_RPC: ${CERC_IPLD_ETH_RPC}
|
|
||||||
CERC_IPLD_ETH_GQL: ${CERC_IPLD_ETH_GQL}
|
|
||||||
working_dir: /app/packages/delegated-sending-watcher
|
|
||||||
command: "./start-server.sh"
|
|
||||||
volumes:
|
|
||||||
- ../config/watcher-azimuth/watcher-config-template.toml:/app/packages/delegated-sending-watcher/environments/watcher-config-template.toml
|
|
||||||
- ../config/watcher-azimuth/merge-toml.js:/app/packages/delegated-sending-watcher/merge-toml.js
|
|
||||||
- ../config/watcher-azimuth/start-server.sh:/app/packages/delegated-sending-watcher/start-server.sh
|
|
||||||
ports:
|
|
||||||
- "3005"
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "nc", "-vz", "localhost", "3005"]
|
|
||||||
interval: 20s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 15
|
|
||||||
start_period: 5s
|
|
||||||
extra_hosts:
|
|
||||||
- "host.docker.internal:host-gateway"
|
|
||||||
|
|
||||||
# Starts the ecliptic-watcher server
|
|
||||||
ecliptic-watcher-server:
|
|
||||||
image: cerc/watcher-azimuth:local
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
watcher-db:
|
|
||||||
condition: service_healthy
|
|
||||||
env_file:
|
|
||||||
- ../config/watcher-azimuth/watcher-params.env
|
|
||||||
environment:
|
|
||||||
CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG}
|
|
||||||
CERC_IPLD_ETH_RPC: ${CERC_IPLD_ETH_RPC}
|
|
||||||
CERC_IPLD_ETH_GQL: ${CERC_IPLD_ETH_GQL}
|
|
||||||
working_dir: /app/packages/ecliptic-watcher
|
|
||||||
command: "./start-server.sh"
|
|
||||||
volumes:
|
|
||||||
- ../config/watcher-azimuth/watcher-config-template.toml:/app/packages/ecliptic-watcher/environments/watcher-config-template.toml
|
|
||||||
- ../config/watcher-azimuth/merge-toml.js:/app/packages/ecliptic-watcher/merge-toml.js
|
|
||||||
- ../config/watcher-azimuth/start-server.sh:/app/packages/ecliptic-watcher/start-server.sh
|
|
||||||
ports:
|
|
||||||
- "3006"
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "nc", "-vz", "localhost", "3006"]
|
|
||||||
interval: 20s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 15
|
|
||||||
start_period: 5s
|
|
||||||
extra_hosts:
|
|
||||||
- "host.docker.internal:host-gateway"
|
|
||||||
|
|
||||||
# Starts the linear-star-release-watcher server
|
|
||||||
linear-star-release-watcher-server:
|
|
||||||
image: cerc/watcher-azimuth:local
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
watcher-db:
|
|
||||||
condition: service_healthy
|
|
||||||
env_file:
|
|
||||||
- ../config/watcher-azimuth/watcher-params.env
|
|
||||||
environment:
|
|
||||||
CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG}
|
|
||||||
CERC_IPLD_ETH_RPC: ${CERC_IPLD_ETH_RPC}
|
|
||||||
CERC_IPLD_ETH_GQL: ${CERC_IPLD_ETH_GQL}
|
|
||||||
working_dir: /app/packages/linear-star-release-watcher
|
|
||||||
command: "./start-server.sh"
|
|
||||||
volumes:
|
|
||||||
- ../config/watcher-azimuth/watcher-config-template.toml:/app/packages/linear-star-release-watcher/environments/watcher-config-template.toml
|
|
||||||
- ../config/watcher-azimuth/merge-toml.js:/app/packages/linear-star-release-watcher/merge-toml.js
|
|
||||||
- ../config/watcher-azimuth/start-server.sh:/app/packages/linear-star-release-watcher/start-server.sh
|
|
||||||
ports:
|
|
||||||
- "3007"
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "nc", "-vz", "localhost", "3007"]
|
|
||||||
interval: 20s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 15
|
|
||||||
start_period: 5s
|
|
||||||
extra_hosts:
|
|
||||||
- "host.docker.internal:host-gateway"
|
|
||||||
|
|
||||||
# Starts the polls-watcher server
|
|
||||||
polls-watcher-server:
|
|
||||||
image: cerc/watcher-azimuth:local
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
watcher-db:
|
|
||||||
condition: service_healthy
|
|
||||||
env_file:
|
|
||||||
- ../config/watcher-azimuth/watcher-params.env
|
|
||||||
environment:
|
|
||||||
CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG}
|
|
||||||
CERC_IPLD_ETH_RPC: ${CERC_IPLD_ETH_RPC}
|
|
||||||
CERC_IPLD_ETH_GQL: ${CERC_IPLD_ETH_GQL}
|
|
||||||
working_dir: /app/packages/polls-watcher
|
|
||||||
command: "./start-server.sh"
|
|
||||||
volumes:
|
|
||||||
- ../config/watcher-azimuth/watcher-config-template.toml:/app/packages/polls-watcher/environments/watcher-config-template.toml
|
|
||||||
- ../config/watcher-azimuth/merge-toml.js:/app/packages/polls-watcher/merge-toml.js
|
|
||||||
- ../config/watcher-azimuth/start-server.sh:/app/packages/polls-watcher/start-server.sh
|
|
||||||
ports:
|
|
||||||
- "3008"
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "nc", "-vz", "localhost", "3008"]
|
|
||||||
interval: 20s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 15
|
|
||||||
start_period: 5s
|
|
||||||
extra_hosts:
|
|
||||||
- "host.docker.internal:host-gateway"
|
|
||||||
|
|
||||||
# Starts the gateway-server for proxying queries
|
|
||||||
gateway-server:
|
|
||||||
image: cerc/watcher-azimuth:local
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
azimuth-watcher-server:
|
|
||||||
condition: service_healthy
|
|
||||||
censures-watcher-server:
|
|
||||||
condition: service_healthy
|
|
||||||
claims-watcher-server:
|
|
||||||
condition: service_healthy
|
|
||||||
conditional-star-release-watcher-server:
|
|
||||||
condition: service_healthy
|
|
||||||
delegated-sending-watcher-server:
|
|
||||||
condition: service_healthy
|
|
||||||
ecliptic-watcher-server:
|
|
||||||
condition: service_healthy
|
|
||||||
linear-star-release-watcher-server:
|
|
||||||
condition: service_healthy
|
|
||||||
polls-watcher-server:
|
|
||||||
condition: service_healthy
|
|
||||||
environment:
|
|
||||||
CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG}
|
|
||||||
working_dir: /app/packages/gateway-server
|
|
||||||
command: "yarn server"
|
|
||||||
volumes:
|
|
||||||
- ../config/watcher-azimuth/gateway-watchers.json:/app/packages/gateway-server/dist/watchers.json
|
|
||||||
ports:
|
|
||||||
- "0.0.0.0:4000:4000"
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "nc", "-vz", "localhost", "4000"]
|
|
||||||
interval: 20s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 15
|
|
||||||
start_period: 5s
|
|
||||||
extra_hosts:
|
|
||||||
- "host.docker.internal:host-gateway"
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
watcher_db_data:
|
|
@ -1,118 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# TODO: this file is now an unmodified copy of cerc-io/laconicd/init.sh
|
|
||||||
# so we should have a mechanism to bundle it inside the container rather than link from here
|
|
||||||
# at deploy time.
|
|
||||||
|
|
||||||
KEY="mykey"
|
|
||||||
CHAINID="laconic_9000-1"
|
|
||||||
MONIKER="localtestnet"
|
|
||||||
KEYRING="test"
|
|
||||||
KEYALGO="eth_secp256k1"
|
|
||||||
LOGLEVEL="info"
|
|
||||||
# trace evm
|
|
||||||
TRACE="--trace"
|
|
||||||
# TRACE=""
|
|
||||||
|
|
||||||
# validate dependencies are installed
|
|
||||||
command -v jq > /dev/null 2>&1 || { echo >&2 "jq not installed. More info: https://stedolan.github.io/jq/download/"; exit 1; }
|
|
||||||
|
|
||||||
# remove existing daemon and client
|
|
||||||
rm -rf ~/.laconic*
|
|
||||||
|
|
||||||
make install
|
|
||||||
|
|
||||||
laconicd config keyring-backend $KEYRING
|
|
||||||
laconicd config chain-id $CHAINID
|
|
||||||
|
|
||||||
# if $KEY exists it should be deleted
|
|
||||||
laconicd keys add $KEY --keyring-backend $KEYRING --algo $KEYALGO
|
|
||||||
|
|
||||||
# Set moniker and chain-id for Ethermint (Moniker can be anything, chain-id must be an integer)
|
|
||||||
laconicd init $MONIKER --chain-id $CHAINID
|
|
||||||
|
|
||||||
# Change parameter token denominations to aphoton
|
|
||||||
cat $HOME/.laconicd/config/genesis.json | jq '.app_state["staking"]["params"]["bond_denom"]="aphoton"' > $HOME/.laconicd/config/tmp_genesis.json && mv $HOME/.laconicd/config/tmp_genesis.json $HOME/.laconicd/config/genesis.json
|
|
||||||
cat $HOME/.laconicd/config/genesis.json | jq '.app_state["crisis"]["constant_fee"]["denom"]="aphoton"' > $HOME/.laconicd/config/tmp_genesis.json && mv $HOME/.laconicd/config/tmp_genesis.json $HOME/.laconicd/config/genesis.json
|
|
||||||
cat $HOME/.laconicd/config/genesis.json | jq '.app_state["gov"]["deposit_params"]["min_deposit"][0]["denom"]="aphoton"' > $HOME/.laconicd/config/tmp_genesis.json && mv $HOME/.laconicd/config/tmp_genesis.json $HOME/.laconicd/config/genesis.json
|
|
||||||
cat $HOME/.laconicd/config/genesis.json | jq '.app_state["mint"]["params"]["mint_denom"]="aphoton"' > $HOME/.laconicd/config/tmp_genesis.json && mv $HOME/.laconicd/config/tmp_genesis.json $HOME/.laconicd/config/genesis.json
|
|
||||||
# Custom modules
|
|
||||||
cat $HOME/.laconicd/config/genesis.json | jq '.app_state["registry"]["params"]["record_rent"]["denom"]="aphoton"' > $HOME/.laconicd/config/tmp_genesis.json && mv $HOME/.laconicd/config/tmp_genesis.json $HOME/.laconicd/config/genesis.json
|
|
||||||
cat $HOME/.laconicd/config/genesis.json | jq '.app_state["registry"]["params"]["authority_rent"]["denom"]="aphoton"' > $HOME/.laconicd/config/tmp_genesis.json && mv $HOME/.laconicd/config/tmp_genesis.json $HOME/.laconicd/config/genesis.json
|
|
||||||
cat $HOME/.laconicd/config/genesis.json | jq '.app_state["registry"]["params"]["authority_auction_commit_fee"]["denom"]="aphoton"' > $HOME/.laconicd/config/tmp_genesis.json && mv $HOME/.laconicd/config/tmp_genesis.json $HOME/.laconicd/config/genesis.json
|
|
||||||
cat $HOME/.laconicd/config/genesis.json | jq '.app_state["registry"]["params"]["authority_auction_reveal_fee"]["denom"]="aphoton"' > $HOME/.laconicd/config/tmp_genesis.json && mv $HOME/.laconicd/config/tmp_genesis.json $HOME/.laconicd/config/genesis.json
|
|
||||||
cat $HOME/.laconicd/config/genesis.json | jq '.app_state["registry"]["params"]["authority_auction_minimum_bid"]["denom"]="aphoton"' > $HOME/.laconicd/config/tmp_genesis.json && mv $HOME/.laconicd/config/tmp_genesis.json $HOME/.laconicd/config/genesis.json
|
|
||||||
|
|
||||||
if [[ "$TEST_REGISTRY_EXPIRY" == "true" ]]; then
|
|
||||||
echo "Setting timers for expiry tests."
|
|
||||||
|
|
||||||
cat $HOME/.laconicd/config/genesis.json | jq '.app_state["registry"]["params"]["record_rent_duration"]="60s"' > $HOME/.laconicd/config/tmp_genesis.json && mv $HOME/.laconicd/config/tmp_genesis.json $HOME/.laconicd/config/genesis.json
|
|
||||||
cat $HOME/.laconicd/config/genesis.json | jq '.app_state["registry"]["params"]["authority_grace_period"]="60s"' > $HOME/.laconicd/config/tmp_genesis.json && mv $HOME/.laconicd/config/tmp_genesis.json $HOME/.laconicd/config/genesis.json
|
|
||||||
cat $HOME/.laconicd/config/genesis.json | jq '.app_state["registry"]["params"]["authority_rent_duration"]="60s"' > $HOME/.laconicd/config/tmp_genesis.json && mv $HOME/.laconicd/config/tmp_genesis.json $HOME/.laconicd/config/genesis.json
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$TEST_AUCTION_ENABLED" == "true" ]]; then
|
|
||||||
echo "Enabling auction and setting timers."
|
|
||||||
|
|
||||||
cat $HOME/.laconicd/config/genesis.json | jq '.app_state["registry"]["params"]["authority_auction_enabled"]=true' > $HOME/.laconicd/config/tmp_genesis.json && mv $HOME/.laconicd/config/tmp_genesis.json $HOME/.laconicd/config/genesis.json
|
|
||||||
cat $HOME/.laconicd/config/genesis.json | jq '.app_state["registry"]["params"]["authority_rent_duration"]="60s"' > $HOME/.laconicd/config/tmp_genesis.json && mv $HOME/.laconicd/config/tmp_genesis.json $HOME/.laconicd/config/genesis.json
|
|
||||||
cat $HOME/.laconicd/config/genesis.json | jq '.app_state["registry"]["params"]["authority_grace_period"]="300s"' > $HOME/.laconicd/config/tmp_genesis.json && mv $HOME/.laconicd/config/tmp_genesis.json $HOME/.laconicd/config/genesis.json
|
|
||||||
cat $HOME/.laconicd/config/genesis.json | jq '.app_state["registry"]["params"]["authority_auction_commits_duration"]="60s"' > $HOME/.laconicd/config/tmp_genesis.json && mv $HOME/.laconicd/config/tmp_genesis.json $HOME/.laconicd/config/genesis.json
|
|
||||||
cat $HOME/.laconicd/config/genesis.json | jq '.app_state["registry"]["params"]["authority_auction_reveals_duration"]="60s"' > $HOME/.laconicd/config/tmp_genesis.json && mv $HOME/.laconicd/config/tmp_genesis.json $HOME/.laconicd/config/genesis.json
|
|
||||||
fi
|
|
||||||
|
|
||||||
# increase block time (?)
|
|
||||||
cat $HOME/.laconicd/config/genesis.json | jq '.consensus_params["block"]["time_iota_ms"]="1000"' > $HOME/.laconicd/config/tmp_genesis.json && mv $HOME/.laconicd/config/tmp_genesis.json $HOME/.laconicd/config/genesis.json
|
|
||||||
|
|
||||||
# Set gas limit in genesis
|
|
||||||
cat $HOME/.laconicd/config/genesis.json | jq '.consensus_params["block"]["max_gas"]="10000000"' > $HOME/.laconicd/config/tmp_genesis.json && mv $HOME/.laconicd/config/tmp_genesis.json $HOME/.laconicd/config/genesis.json
|
|
||||||
|
|
||||||
# disable produce empty block
|
|
||||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
||||||
sed -i '' 's/create_empty_blocks = true/create_empty_blocks = false/g' $HOME/.laconicd/config/config.toml
|
|
||||||
else
|
|
||||||
sed -i 's/create_empty_blocks = true/create_empty_blocks = false/g' $HOME/.laconicd/config/config.toml
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $1 == "pending" ]]; then
|
|
||||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
||||||
sed -i '' 's/create_empty_blocks_interval = "0s"/create_empty_blocks_interval = "30s"/g' $HOME/.laconicd/config/config.toml
|
|
||||||
sed -i '' 's/timeout_propose = "3s"/timeout_propose = "30s"/g' $HOME/.laconicd/config/config.toml
|
|
||||||
sed -i '' 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "5s"/g' $HOME/.laconicd/config/config.toml
|
|
||||||
sed -i '' 's/timeout_prevote = "1s"/timeout_prevote = "10s"/g' $HOME/.laconicd/config/config.toml
|
|
||||||
sed -i '' 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "5s"/g' $HOME/.laconicd/config/config.toml
|
|
||||||
sed -i '' 's/timeout_precommit = "1s"/timeout_precommit = "10s"/g' $HOME/.laconicd/config/config.toml
|
|
||||||
sed -i '' 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "5s"/g' $HOME/.laconicd/config/config.toml
|
|
||||||
sed -i '' 's/timeout_commit = "5s"/timeout_commit = "150s"/g' $HOME/.laconicd/config/config.toml
|
|
||||||
sed -i '' 's/timeout_broadcast_tx_commit = "10s"/timeout_broadcast_tx_commit = "150s"/g' $HOME/.laconicd/config/config.toml
|
|
||||||
else
|
|
||||||
sed -i 's/create_empty_blocks_interval = "0s"/create_empty_blocks_interval = "30s"/g' $HOME/.laconicd/config/config.toml
|
|
||||||
sed -i 's/timeout_propose = "3s"/timeout_propose = "30s"/g' $HOME/.laconicd/config/config.toml
|
|
||||||
sed -i 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "5s"/g' $HOME/.laconicd/config/config.toml
|
|
||||||
sed -i 's/timeout_prevote = "1s"/timeout_prevote = "10s"/g' $HOME/.laconicd/config/config.toml
|
|
||||||
sed -i 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "5s"/g' $HOME/.laconicd/config/config.toml
|
|
||||||
sed -i 's/timeout_precommit = "1s"/timeout_precommit = "10s"/g' $HOME/.laconicd/config/config.toml
|
|
||||||
sed -i 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "5s"/g' $HOME/.laconicd/config/config.toml
|
|
||||||
sed -i 's/timeout_commit = "5s"/timeout_commit = "150s"/g' $HOME/.laconicd/config/config.toml
|
|
||||||
sed -i 's/timeout_broadcast_tx_commit = "10s"/timeout_broadcast_tx_commit = "150s"/g' $HOME/.laconicd/config/config.toml
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Allocate genesis accounts (cosmos formatted addresses)
|
|
||||||
laconicd add-genesis-account $KEY 100000000000000000000000000aphoton --keyring-backend $KEYRING
|
|
||||||
|
|
||||||
# Sign genesis transaction
|
|
||||||
laconicd gentx $KEY 1000000000000000000000aphoton --keyring-backend $KEYRING --chain-id $CHAINID
|
|
||||||
|
|
||||||
# Collect genesis tx
|
|
||||||
laconicd collect-gentxs
|
|
||||||
|
|
||||||
# Run this to ensure everything worked and that the genesis file is setup correctly
|
|
||||||
laconicd validate-genesis
|
|
||||||
|
|
||||||
if [[ $1 == "pending" ]]; then
|
|
||||||
echo "pending mode is on, please wait for the first block committed."
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Start the node (remove the --pruning=nothing flag if historical queries are not needed)
|
|
||||||
laconicd start --pruning=nothing --evm.tracer=json $TRACE --log_level $LOGLEVEL --minimum-gas-prices=0.0001aphoton --json-rpc.api eth,txpool,personal,net,debug,web3,miner --api.enable --gql-server --gql-playground
|
|
@ -1,37 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
|
||||||
set -x
|
|
||||||
fi
|
|
||||||
|
|
||||||
CERC_L1_RPC="${CERC_L1_RPC:-${DEFAULT_CERC_L1_RPC}}"
|
|
||||||
|
|
||||||
# Check existing config if it exists
|
|
||||||
if [ -f /app/jwt.txt ] && [ -f /app/rollup.json ]; then
|
|
||||||
echo "Found existing L2 config, cross-checking with L1 deployment config"
|
|
||||||
|
|
||||||
SOURCE_L1_CONF=$(cat /contracts-bedrock/deploy-config/getting-started.json)
|
|
||||||
EXP_L1_BLOCKHASH=$(echo "$SOURCE_L1_CONF" | jq -r '.l1StartingBlockTag')
|
|
||||||
EXP_BATCHER=$(echo "$SOURCE_L1_CONF" | jq -r '.batchSenderAddress')
|
|
||||||
|
|
||||||
GEN_L2_CONF=$(cat /app/rollup.json)
|
|
||||||
GEN_L1_BLOCKHASH=$(echo "$GEN_L2_CONF" | jq -r '.genesis.l1.hash')
|
|
||||||
GEN_BATCHER=$(echo "$GEN_L2_CONF" | jq -r '.genesis.system_config.batcherAddr')
|
|
||||||
|
|
||||||
if [ "$EXP_L1_BLOCKHASH" = "$GEN_L1_BLOCKHASH" ] && [ "$EXP_BATCHER" = "$GEN_BATCHER" ]; then
|
|
||||||
echo "Config cross-checked, exiting"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Existing L2 config doesn't match the L1 deployment config, please clear L2 config volume before starting"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
op-node genesis l2 \
|
|
||||||
--deploy-config /contracts-bedrock/deploy-config/getting-started.json \
|
|
||||||
--deployment-dir /contracts-bedrock/deployments/getting-started/ \
|
|
||||||
--outfile.l2 /app/genesis.json \
|
|
||||||
--outfile.rollup /app/rollup.json \
|
|
||||||
--l1-rpc $CERC_L1_RPC
|
|
||||||
|
|
||||||
openssl rand -hex 32 > /app/jwt.txt
|
|
@ -1,131 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
|
||||||
set -x
|
|
||||||
fi
|
|
||||||
|
|
||||||
CERC_L1_CHAIN_ID="${CERC_L1_CHAIN_ID:-${DEFAULT_CERC_L1_CHAIN_ID}}"
|
|
||||||
CERC_L1_RPC="${CERC_L1_RPC:-${DEFAULT_CERC_L1_RPC}}"
|
|
||||||
|
|
||||||
CERC_L1_ACCOUNTS_CSV_URL="${CERC_L1_ACCOUNTS_CSV_URL:-${DEFAULT_CERC_L1_ACCOUNTS_CSV_URL}}"
|
|
||||||
|
|
||||||
echo "Using L1 RPC endpoint ${CERC_L1_RPC}"
|
|
||||||
|
|
||||||
IMPORT_1="import './verify-contract-deployment'"
|
|
||||||
IMPORT_2="import './rekey-json'"
|
|
||||||
IMPORT_3="import './send-balance'"
|
|
||||||
|
|
||||||
# Append mounted tasks to tasks/index.ts file if not present
|
|
||||||
if ! grep -Fxq "$IMPORT_1" tasks/index.ts; then
|
|
||||||
echo "$IMPORT_1" >> tasks/index.ts
|
|
||||||
echo "$IMPORT_2" >> tasks/index.ts
|
|
||||||
echo "$IMPORT_3" >> tasks/index.ts
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Update the chainId in the hardhat config
|
|
||||||
sed -i "/getting-started/ {n; s/.*chainId.*/ chainId: $CERC_L1_CHAIN_ID,/}" hardhat.config.ts
|
|
||||||
|
|
||||||
# Exit if a deployment already exists (on restarts)
|
|
||||||
# Note: fixturenet-eth-geth currently starts fresh on a restart
|
|
||||||
if [ -d "deployments/getting-started" ]; then
|
|
||||||
echo "Deployment directory deployments/getting-started found, checking SystemDictator deployment"
|
|
||||||
|
|
||||||
# Read JSON file into variable
|
|
||||||
SYSTEM_DICTATOR_DETAILS=$(cat deployments/getting-started/SystemDictator.json)
|
|
||||||
|
|
||||||
# Parse JSON into variables
|
|
||||||
SYSTEM_DICTATOR_ADDRESS=$(echo "$SYSTEM_DICTATOR_DETAILS" | jq -r '.address')
|
|
||||||
SYSTEM_DICTATOR_TXHASH=$(echo "$SYSTEM_DICTATOR_DETAILS" | jq -r '.transactionHash')
|
|
||||||
|
|
||||||
if yarn hardhat verify-contract-deployment --contract "${SYSTEM_DICTATOR_ADDRESS}" --transaction-hash "${SYSTEM_DICTATOR_TXHASH}"; then
|
|
||||||
echo "Deployment verfication successful, exiting"
|
|
||||||
exit 0
|
|
||||||
else
|
|
||||||
echo "Deployment verfication failed, please clear L1 deployment volume before starting"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Generate the L2 account addresses
|
|
||||||
yarn hardhat rekey-json --output /l2-accounts/keys.json
|
|
||||||
|
|
||||||
# Read JSON file into variable
|
|
||||||
KEYS_JSON=$(cat /l2-accounts/keys.json)
|
|
||||||
|
|
||||||
# Parse JSON into variables
|
|
||||||
ADMIN_ADDRESS=$(echo "$KEYS_JSON" | jq -r '.Admin.address')
|
|
||||||
ADMIN_PRIV_KEY=$(echo "$KEYS_JSON" | jq -r '.Admin.privateKey')
|
|
||||||
PROPOSER_ADDRESS=$(echo "$KEYS_JSON" | jq -r '.Proposer.address')
|
|
||||||
BATCHER_ADDRESS=$(echo "$KEYS_JSON" | jq -r '.Batcher.address')
|
|
||||||
SEQUENCER_ADDRESS=$(echo "$KEYS_JSON" | jq -r '.Sequencer.address')
|
|
||||||
|
|
||||||
# Get the private keys of L1 accounts
|
|
||||||
if [ -n "$CERC_L1_ACCOUNTS_CSV_URL" ] && \
|
|
||||||
l1_accounts_response=$(curl -L --write-out '%{http_code}' --silent --output /dev/null "$CERC_L1_ACCOUNTS_CSV_URL") && \
|
|
||||||
[ "$l1_accounts_response" -eq 200 ];
|
|
||||||
then
|
|
||||||
echo "Fetching L1 account credentials using provided URL"
|
|
||||||
mkdir -p /geth-accounts
|
|
||||||
wget -O /geth-accounts/accounts.csv "$CERC_L1_ACCOUNTS_CSV_URL"
|
|
||||||
|
|
||||||
CERC_L1_ADDRESS=$(head -n 1 /geth-accounts/accounts.csv | cut -d ',' -f 2)
|
|
||||||
CERC_L1_PRIV_KEY=$(head -n 1 /geth-accounts/accounts.csv | cut -d ',' -f 3)
|
|
||||||
CERC_L1_ADDRESS_2=$(awk -F, 'NR==2{print $(NF-1)}' /geth-accounts/accounts.csv)
|
|
||||||
CERC_L1_PRIV_KEY_2=$(awk -F, 'NR==2{print $NF}' /geth-accounts/accounts.csv)
|
|
||||||
else
|
|
||||||
echo "Couldn't fetch L1 account credentials, using them from env"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Send balances to the above L2 addresses
|
|
||||||
yarn hardhat send-balance --to "${ADMIN_ADDRESS}" --amount 2 --private-key "${CERC_L1_PRIV_KEY}" --network getting-started
|
|
||||||
yarn hardhat send-balance --to "${PROPOSER_ADDRESS}" --amount 5 --private-key "${CERC_L1_PRIV_KEY}" --network getting-started
|
|
||||||
yarn hardhat send-balance --to "${BATCHER_ADDRESS}" --amount 1000 --private-key "${CERC_L1_PRIV_KEY}" --network getting-started
|
|
||||||
|
|
||||||
echo "Balances sent to L2 accounts"
|
|
||||||
|
|
||||||
# Select a finalized L1 block as the starting point for roll ups
|
|
||||||
until FINALIZED_BLOCK=$(cast block finalized --rpc-url "$CERC_L1_RPC"); do
|
|
||||||
echo "Waiting for a finalized L1 block to exist, retrying after 10s"
|
|
||||||
sleep 10
|
|
||||||
done
|
|
||||||
|
|
||||||
L1_BLOCKNUMBER=$(echo "$FINALIZED_BLOCK" | awk '/number/{print $2}')
|
|
||||||
L1_BLOCKHASH=$(echo "$FINALIZED_BLOCK" | awk '/hash/{print $2}')
|
|
||||||
L1_BLOCKTIMESTAMP=$(echo "$FINALIZED_BLOCK" | awk '/timestamp/{print $2}')
|
|
||||||
|
|
||||||
echo "Selected L1 block ${L1_BLOCKNUMBER} as the starting block for roll ups"
|
|
||||||
|
|
||||||
# Update the deployment config
|
|
||||||
sed -i 's/"l2OutputOracleStartingTimestamp": TIMESTAMP/"l2OutputOracleStartingTimestamp": '"$L1_BLOCKTIMESTAMP"'/g' deploy-config/getting-started.json
|
|
||||||
jq --arg chainid "$CERC_L1_CHAIN_ID" '.l1ChainID = ($chainid | tonumber)' deploy-config/getting-started.json > tmp.json && mv tmp.json deploy-config/getting-started.json
|
|
||||||
|
|
||||||
node update-config.js deploy-config/getting-started.json "$ADMIN_ADDRESS" "$PROPOSER_ADDRESS" "$BATCHER_ADDRESS" "$SEQUENCER_ADDRESS" "$L1_BLOCKHASH"
|
|
||||||
|
|
||||||
echo "Updated the deployment config"
|
|
||||||
|
|
||||||
# Create a .env file
|
|
||||||
echo "L1_RPC=$CERC_L1_RPC" > .env
|
|
||||||
echo "PRIVATE_KEY_DEPLOYER=$ADMIN_PRIV_KEY" >> .env
|
|
||||||
|
|
||||||
echo "Deploying the L1 smart contracts, this will take a while..."
|
|
||||||
|
|
||||||
# Deploy the L1 smart contracts
|
|
||||||
yarn hardhat deploy --network getting-started --tags l1
|
|
||||||
|
|
||||||
echo "Deployed the L1 smart contracts"
|
|
||||||
|
|
||||||
# Read Proxy contract's JSON and get the address
|
|
||||||
PROXY_JSON=$(cat deployments/getting-started/Proxy__OVM_L1StandardBridge.json)
|
|
||||||
PROXY_ADDRESS=$(echo "$PROXY_JSON" | jq -r '.address')
|
|
||||||
|
|
||||||
# Send balance to the above Proxy contract in L1 for reflecting balance in L2
|
|
||||||
# First account
|
|
||||||
yarn hardhat send-balance --to "${PROXY_ADDRESS}" --amount 1 --private-key "${CERC_L1_PRIV_KEY}" --network getting-started
|
|
||||||
# Second account
|
|
||||||
yarn hardhat send-balance --to "${PROXY_ADDRESS}" --amount 1 --private-key "${CERC_L1_PRIV_KEY_2}" --network getting-started
|
|
||||||
|
|
||||||
echo "Balance sent to Proxy L2 contract"
|
|
||||||
echo "Use following accounts for transactions in L2:"
|
|
||||||
echo "${CERC_L1_ADDRESS}"
|
|
||||||
echo "${CERC_L1_ADDRESS_2}"
|
|
||||||
echo "Done"
|
|
@ -1,36 +0,0 @@
|
|||||||
const fs = require('fs')
|
|
||||||
|
|
||||||
// Get the command-line argument
|
|
||||||
const configFile = process.argv[2]
|
|
||||||
const adminAddress = process.argv[3]
|
|
||||||
const proposerAddress = process.argv[4]
|
|
||||||
const batcherAddress = process.argv[5]
|
|
||||||
const sequencerAddress = process.argv[6]
|
|
||||||
const blockHash = process.argv[7]
|
|
||||||
|
|
||||||
// Read the JSON file
|
|
||||||
const configData = fs.readFileSync(configFile)
|
|
||||||
const configObj = JSON.parse(configData)
|
|
||||||
|
|
||||||
// Update the finalSystemOwner property with the ADMIN_ADDRESS value
|
|
||||||
configObj.finalSystemOwner =
|
|
||||||
configObj.portalGuardian =
|
|
||||||
configObj.controller =
|
|
||||||
configObj.l2OutputOracleChallenger =
|
|
||||||
configObj.proxyAdminOwner =
|
|
||||||
configObj.baseFeeVaultRecipient =
|
|
||||||
configObj.l1FeeVaultRecipient =
|
|
||||||
configObj.sequencerFeeVaultRecipient =
|
|
||||||
configObj.governanceTokenOwner =
|
|
||||||
adminAddress
|
|
||||||
|
|
||||||
configObj.l2OutputOracleProposer = proposerAddress
|
|
||||||
|
|
||||||
configObj.batchSenderAddress = batcherAddress
|
|
||||||
|
|
||||||
configObj.p2pSequencerAddress = sequencerAddress
|
|
||||||
|
|
||||||
configObj.l1StartingBlockTag = blockHash
|
|
||||||
|
|
||||||
// Write the updated JSON object back to the file
|
|
||||||
fs.writeFileSync(configFile, JSON.stringify(configObj, null, 2))
|
|
@ -1,90 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
|
||||||
set -x
|
|
||||||
fi
|
|
||||||
|
|
||||||
# TODO: Add in container build or use other tool
|
|
||||||
echo "Installing jq"
|
|
||||||
apk update && apk add jq
|
|
||||||
|
|
||||||
# Get Sequencer key from keys.json
|
|
||||||
SEQUENCER_KEY=$(jq -r '.Sequencer.privateKey' /l2-accounts/keys.json | tr -d '"')
|
|
||||||
|
|
||||||
# Initialize op-geth if datadir/geth not found
|
|
||||||
if [ -f /op-node/jwt.txt ] && [ -d datadir/geth ]; then
|
|
||||||
echo "Found existing datadir, checking block signer key"
|
|
||||||
|
|
||||||
BLOCK_SIGNER_KEY=$(cat datadir/block-signer-key)
|
|
||||||
|
|
||||||
if [ "$SEQUENCER_KEY" = "$BLOCK_SIGNER_KEY" ]; then
|
|
||||||
echo "Sequencer and block signer keys match, skipping initialization"
|
|
||||||
else
|
|
||||||
echo "Sequencer and block signer keys don't match, please clear L2 geth data volume before starting"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "Initializing op-geth"
|
|
||||||
|
|
||||||
mkdir -p datadir
|
|
||||||
echo "pwd" > datadir/password
|
|
||||||
echo $SEQUENCER_KEY > datadir/block-signer-key
|
|
||||||
|
|
||||||
geth account import --datadir=datadir --password=datadir/password datadir/block-signer-key
|
|
||||||
|
|
||||||
while [ ! -f "/op-node/jwt.txt" ]
|
|
||||||
do
|
|
||||||
echo "Config files not created. Checking after 5 seconds."
|
|
||||||
sleep 5
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Config files created by op-node, proceeding with the initialization..."
|
|
||||||
|
|
||||||
geth init --datadir=datadir /op-node/genesis.json
|
|
||||||
echo "Node Initialized"
|
|
||||||
fi
|
|
||||||
|
|
||||||
SEQUENCER_ADDRESS=$(jq -r '.Sequencer.address' /l2-accounts/keys.json | tr -d '"')
|
|
||||||
echo "SEQUENCER_ADDRESS: ${SEQUENCER_ADDRESS}"
|
|
||||||
|
|
||||||
cleanup() {
|
|
||||||
echo "Signal received, cleaning up..."
|
|
||||||
kill ${geth_pid}
|
|
||||||
|
|
||||||
wait
|
|
||||||
echo "Done"
|
|
||||||
}
|
|
||||||
trap 'cleanup' INT TERM
|
|
||||||
|
|
||||||
# Run op-geth
|
|
||||||
geth \
|
|
||||||
--datadir ./datadir \
|
|
||||||
--http \
|
|
||||||
--http.corsdomain="*" \
|
|
||||||
--http.vhosts="*" \
|
|
||||||
--http.addr=0.0.0.0 \
|
|
||||||
--http.api=web3,debug,eth,txpool,net,engine \
|
|
||||||
--ws \
|
|
||||||
--ws.addr=0.0.0.0 \
|
|
||||||
--ws.port=8546 \
|
|
||||||
--ws.origins="*" \
|
|
||||||
--ws.api=debug,eth,txpool,net,engine \
|
|
||||||
--syncmode=full \
|
|
||||||
--gcmode=archive \
|
|
||||||
--nodiscover \
|
|
||||||
--maxpeers=0 \
|
|
||||||
--networkid=42069 \
|
|
||||||
--authrpc.vhosts="*" \
|
|
||||||
--authrpc.addr=0.0.0.0 \
|
|
||||||
--authrpc.port=8551 \
|
|
||||||
--authrpc.jwtsecret=/op-node/jwt.txt \
|
|
||||||
--rollup.disabletxpoolgossip=true \
|
|
||||||
--password=./datadir/password \
|
|
||||||
--allow-insecure-unlock \
|
|
||||||
--mine \
|
|
||||||
--miner.etherbase=$SEQUENCER_ADDRESS \
|
|
||||||
--unlock=$SEQUENCER_ADDRESS \
|
|
||||||
&
|
|
||||||
|
|
||||||
geth_pid=$!
|
|
||||||
wait $geth_pid
|
|
@ -1,26 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
|
||||||
set -x
|
|
||||||
fi
|
|
||||||
|
|
||||||
CERC_L1_RPC="${CERC_L1_RPC:-${DEFAULT_CERC_L1_RPC}}"
|
|
||||||
|
|
||||||
# Get Sequencer key from keys.json
|
|
||||||
SEQUENCER_KEY=$(jq -r '.Sequencer.privateKey' /l2-accounts/keys.json | tr -d '"')
|
|
||||||
|
|
||||||
# Run op-node
|
|
||||||
op-node \
|
|
||||||
--l2=http://op-geth:8551 \
|
|
||||||
--l2.jwt-secret=/op-node-data/jwt.txt \
|
|
||||||
--sequencer.enabled \
|
|
||||||
--sequencer.l1-confs=3 \
|
|
||||||
--verifier.l1-confs=3 \
|
|
||||||
--rollup.config=/op-node-data/rollup.json \
|
|
||||||
--rpc.addr=0.0.0.0 \
|
|
||||||
--rpc.port=8547 \
|
|
||||||
--p2p.disable \
|
|
||||||
--rpc.enable-admin \
|
|
||||||
--p2p.sequencer.key=$SEQUENCER_KEY \
|
|
||||||
--l1=$CERC_L1_RPC \
|
|
||||||
--l1.rpckind=any
|
|
@ -1,36 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
|
||||||
set -x
|
|
||||||
fi
|
|
||||||
|
|
||||||
CERC_L1_RPC="${CERC_L1_RPC:-${DEFAULT_CERC_L1_RPC}}"
|
|
||||||
|
|
||||||
# Read the L2OutputOracle contract address from the deployment
|
|
||||||
L2OO_DEPLOYMENT=$(cat /contracts-bedrock/deployments/getting-started/L2OutputOracle.json)
|
|
||||||
L2OO_ADDR=$(echo "$L2OO_DEPLOYMENT" | jq -r '.address')
|
|
||||||
|
|
||||||
# Get Proposer key from keys.json
|
|
||||||
PROPOSER_KEY=$(jq -r '.Proposer.privateKey' /l2-accounts/keys.json | tr -d '"')
|
|
||||||
|
|
||||||
cleanup() {
|
|
||||||
echo "Signal received, cleaning up..."
|
|
||||||
kill ${proposer_pid}
|
|
||||||
|
|
||||||
wait
|
|
||||||
echo "Done"
|
|
||||||
}
|
|
||||||
trap 'cleanup' INT TERM
|
|
||||||
|
|
||||||
# Run op-proposer
|
|
||||||
op-proposer \
|
|
||||||
--poll-interval 12s \
|
|
||||||
--rpc.port 8560 \
|
|
||||||
--rollup-rpc http://op-node:8547 \
|
|
||||||
--l2oo-address $L2OO_ADDR \
|
|
||||||
--private-key $PROPOSER_KEY \
|
|
||||||
--l1-eth-rpc $CERC_L1_RPC \
|
|
||||||
&
|
|
||||||
|
|
||||||
proposer_pid=$!
|
|
||||||
wait $proposer_pid
|
|
@ -1,27 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
|
||||||
set -x
|
|
||||||
fi
|
|
||||||
|
|
||||||
CERC_IPLD_ETH_RPC="${CERC_IPLD_ETH_RPC:-${DEFAULT_CERC_IPLD_ETH_RPC}}"
|
|
||||||
CERC_IPLD_ETH_GQL="${CERC_IPLD_ETH_GQL:-${DEFAULT_CERC_IPLD_ETH_GQL}}"
|
|
||||||
|
|
||||||
echo "Using IPLD ETH RPC endpoint ${CERC_IPLD_ETH_RPC}"
|
|
||||||
echo "Using IPLD GQL endpoint ${CERC_IPLD_ETH_GQL}"
|
|
||||||
|
|
||||||
# Replace env variables in template TOML file
|
|
||||||
# Read in the config template TOML file and modify it
|
|
||||||
WATCHER_CONFIG_TEMPLATE=$(cat environments/watcher-config-template.toml)
|
|
||||||
WATCHER_CONFIG=$(echo "$WATCHER_CONFIG_TEMPLATE" | \
|
|
||||||
sed -E "s|REPLACE_WITH_CERC_IPLD_ETH_RPC|${CERC_IPLD_ETH_RPC}|g; \
|
|
||||||
s|REPLACE_WITH_CERC_IPLD_ETH_GQL|${CERC_IPLD_ETH_GQL}| ")
|
|
||||||
|
|
||||||
# Write the modified content to a new file
|
|
||||||
echo "$WATCHER_CONFIG" > environments/watcher-config.toml
|
|
||||||
|
|
||||||
# Merge SO watcher config with existing config file
|
|
||||||
node merge-toml.js
|
|
||||||
|
|
||||||
echo 'yarn server'
|
|
||||||
yarn server
|
|
@ -1,14 +0,0 @@
|
|||||||
[server]
|
|
||||||
host = "0.0.0.0"
|
|
||||||
maxSimultaneousRequests = -1
|
|
||||||
|
|
||||||
[database]
|
|
||||||
host = "watcher-db"
|
|
||||||
port = 5432
|
|
||||||
username = "vdbm"
|
|
||||||
password = "password"
|
|
||||||
|
|
||||||
[upstream]
|
|
||||||
[upstream.ethServer]
|
|
||||||
gqlApiEndpoint = "REPLACE_WITH_CERC_IPLD_ETH_GQL"
|
|
||||||
rpcProviderEndpoint = "REPLACE_WITH_CERC_IPLD_ETH_RPC"
|
|
@ -1,5 +0,0 @@
|
|||||||
# Defaults
|
|
||||||
|
|
||||||
# ipld-eth-server endpoints
|
|
||||||
DEFAULT_CERC_IPLD_ETH_RPC=
|
|
||||||
DEFAULT_CERC_IPLD_ETH_GQL=
|
|
File diff suppressed because it is too large
Load Diff
@ -1,27 +0,0 @@
|
|||||||
FROM skylenet/ethereum-genesis-generator@sha256:210353ce7c898686bc5092f16c61220a76d357f51eff9c451e9ad1b9ad03d4d3 AS ethgen
|
|
||||||
|
|
||||||
# Using the same golang image as used to build geth: https://github.com/cerc-io/go-ethereum/blob/HEAD/Dockerfile
|
|
||||||
FROM golang:1.18-alpine as delve
|
|
||||||
RUN go install github.com/go-delve/delve/cmd/dlv@latest
|
|
||||||
|
|
||||||
FROM cerc/go-ethereum:local as geth
|
|
||||||
|
|
||||||
FROM alpine:latest
|
|
||||||
RUN apk add --no-cache python3 python3-dev py3-pip curl wget jq build-base gettext libintl openssl bash bind-tools postgresql-client
|
|
||||||
|
|
||||||
COPY --from=delve /go/bin/dlv /usr/local/bin/
|
|
||||||
COPY --from=ethgen /usr/local/bin/eth2-testnet-genesis /usr/local/bin/
|
|
||||||
COPY --from=ethgen /usr/local/bin/eth2-val-tools /usr/local/bin/
|
|
||||||
COPY --from=ethgen /apps /apps
|
|
||||||
|
|
||||||
RUN cd /apps/el-gen && pip3 install -r requirements.txt
|
|
||||||
|
|
||||||
COPY genesis /opt/testnet
|
|
||||||
COPY run-el.sh /opt/testnet/run.sh
|
|
||||||
|
|
||||||
RUN cd /opt/testnet && make genesis-el
|
|
||||||
|
|
||||||
COPY --from=geth /usr/local/bin/geth /usr/local/bin/
|
|
||||||
RUN geth --datadir ~/ethdata init /opt/testnet/build/el/geth.json && rm -f ~/ethdata/geth/nodekey
|
|
||||||
|
|
||||||
ENTRYPOINT ["/opt/testnet/run.sh"]
|
|
@ -1,38 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# See: https://github.com/skylenet/ethereum-genesis-generator/blob/master/entrypoint.sh
|
|
||||||
|
|
||||||
rm -rf ../build/el
|
|
||||||
mkdir -p ../build/el
|
|
||||||
|
|
||||||
tmp_dir=$(mktemp -d -t ci-XXXXXXXXXX)
|
|
||||||
envsubst < el-config.yaml > $tmp_dir/genesis-config.yaml
|
|
||||||
|
|
||||||
ttd=`cat $tmp_dir/genesis-config.yaml | grep terminal_total_difficulty | awk '{ print $2 }'`
|
|
||||||
homestead_block=`cat $tmp_dir/genesis-config.yaml | grep homestead_block | awk '{ print $2 }'`
|
|
||||||
eip150_block=`cat $tmp_dir/genesis-config.yaml | grep eip150_block | awk '{ print $2 }'`
|
|
||||||
eip155_block=`cat $tmp_dir/genesis-config.yaml | grep eip155_block | awk '{ print $2 }'`
|
|
||||||
eip158_block=`cat $tmp_dir/genesis-config.yaml | grep eip158_block | awk '{ print $2 }'`
|
|
||||||
byzantium_block=`cat $tmp_dir/genesis-config.yaml | grep byzantium_block | awk '{ print $2 }'`
|
|
||||||
constantinople_block=`cat $tmp_dir/genesis-config.yaml | grep constantinople_block | awk '{ print $2 }'`
|
|
||||||
petersburg_block=`cat $tmp_dir/genesis-config.yaml | grep petersburg_block | awk '{ print $2 }'`
|
|
||||||
istanbul_block=`cat $tmp_dir/genesis-config.yaml | grep istanbul_block | awk '{ print $2 }'`
|
|
||||||
berlin_block=`cat $tmp_dir/genesis-config.yaml | grep berlin_block | awk '{ print $2 }'`
|
|
||||||
london_block=`cat $tmp_dir/genesis-config.yaml | grep london_block | awk '{ print $2 }'`
|
|
||||||
merge_fork_block=`cat $tmp_dir/genesis-config.yaml | grep merge_fork_block | awk '{ print $2 }'`
|
|
||||||
|
|
||||||
python3 /apps/el-gen/genesis_geth.py $tmp_dir/genesis-config.yaml | \
|
|
||||||
jq ".config.terminalTotalDifficulty=$ttd" | \
|
|
||||||
jq ".config.homesteadBlock=$homestead_block" | \
|
|
||||||
jq ".config.eip150Block=$eip150_block" | \
|
|
||||||
jq ".config.eip155Block=$eip155_block" | \
|
|
||||||
jq ".config.eip158Block=$eip158_block" | \
|
|
||||||
jq ".config.byzantiumBlock=$byzantium_block" | \
|
|
||||||
jq ".config.constantinopleBlock=$constantinople_block" | \
|
|
||||||
jq ".config.petersburgBlock=$petersburg_block" | \
|
|
||||||
jq ".config.istanbulBlock=$istanbul_block" | \
|
|
||||||
jq ".config.berlinBlock=$berlin_block" | \
|
|
||||||
jq ".config.londonBlock=$london_block" | \
|
|
||||||
jq ".config.mergeForkBlock=$merge_fork_block" > ../build/el/geth.json
|
|
||||||
python3 ../accounts/mnemonic_to_csv.py $tmp_dir/genesis-config.yaml > ../build/el/accounts.csv
|
|
@ -1,37 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# See: https://github.com/sigp/lighthouse/blob/stable/scripts/local_testnet/bootnode.sh
|
|
||||||
#
|
|
||||||
# Starts a bootnode from the generated enr.
|
|
||||||
#
|
|
||||||
|
|
||||||
set -Eeuo pipefail
|
|
||||||
|
|
||||||
source ./vars.env
|
|
||||||
|
|
||||||
DEBUG_LEVEL=${1:-info}
|
|
||||||
|
|
||||||
echo "Starting bootnode"
|
|
||||||
|
|
||||||
if [ ! -f "$DATADIR/bootnode/enr.dat" ]; then
|
|
||||||
echo "Generating bootnode enr"
|
|
||||||
lcli \
|
|
||||||
generate-bootnode-enr \
|
|
||||||
--ip $ENR_IP \
|
|
||||||
--udp-port $BOOTNODE_PORT \
|
|
||||||
--tcp-port $BOOTNODE_PORT \
|
|
||||||
--genesis-fork-version $GENESIS_FORK_VERSION \
|
|
||||||
--output-dir $DATADIR/bootnode
|
|
||||||
|
|
||||||
bootnode_enr=`cat $DATADIR/bootnode/enr.dat`
|
|
||||||
echo "- $bootnode_enr" > $TESTNET_DIR/boot_enr.yaml
|
|
||||||
|
|
||||||
echo "Generated bootnode enr and written to $TESTNET_DIR/boot_enr.yaml"
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec lighthouse boot_node \
|
|
||||||
--testnet-dir $TESTNET_DIR \
|
|
||||||
--port $BOOTNODE_PORT \
|
|
||||||
--listen-address 0.0.0.0 \
|
|
||||||
--disable-packet-filter \
|
|
||||||
--network-dir $DATADIR/bootnode \
|
|
@ -1,6 +0,0 @@
|
|||||||
# Config for laconic-console running in a fixturenet with laconicd
|
|
||||||
|
|
||||||
services:
|
|
||||||
wns:
|
|
||||||
server: 'LACONIC_HOSTED_ENDPOINT:9473/api'
|
|
||||||
webui: 'LACONIC_HOSTED_ENDPOINT:9473/console'
|
|
@ -1,8 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
|
||||||
set -x
|
|
||||||
fi
|
|
||||||
# TODO: Don't hard wire this:
|
|
||||||
webapp_files_dir=/usr/local/share/.config/yarn/global/node_modules/@cerc-io/console-app/dist/production
|
|
||||||
/scripts/apply-webapp-config.sh /config/config.yml ${webapp_files_dir}
|
|
||||||
http-server -p 80 ${webapp_files_dir}
|
|
@ -1,29 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Create some demo/test records in the registry
|
|
||||||
set -e
|
|
||||||
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
|
||||||
set -x
|
|
||||||
fi
|
|
||||||
registry_command="laconic cns"
|
|
||||||
record_1_filename=demo-record-1.yml
|
|
||||||
cat <<EOF > ${record_1_filename}
|
|
||||||
record:
|
|
||||||
type: WebsiteRegistrationRecord
|
|
||||||
url: 'https://cerc.io'
|
|
||||||
repo_registration_record_cid: QmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D
|
|
||||||
build_artifact_cid: QmP8jTG1m9GSDJLCbeWhVSVgEzCPPwXRdCRuJtQ5Tz9Kc9
|
|
||||||
tls_cert_cid: QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR
|
|
||||||
version: 1.0.23
|
|
||||||
EOF
|
|
||||||
# Check we have funds
|
|
||||||
funds_response=$(${registry_command} account get --address $(cat my-address.txt))
|
|
||||||
funds_balance=$(echo ${funds_response} | jq -r .[0].balance[0].quantity)
|
|
||||||
echo "Balance is: ${funds_balance}"
|
|
||||||
# Create a bond
|
|
||||||
bond_create_result=$(${registry_command} bond create --type aphoton --quantity 1000000000)
|
|
||||||
bond_id=$(echo ${bond_create_result} | jq -r .bondId)
|
|
||||||
echo "Created bond with id: ${bond_id}"
|
|
||||||
# Publish a demo record
|
|
||||||
publish_response=$(${registry_command} record publish --filename ${record_1_filename} --bond-id ${bond_id})
|
|
||||||
published_record_id=$(echo ${publish_response} | jq -r .id)
|
|
||||||
echo "Published ${record_1_filename} with id: ${published_record_id}"
|
|
@ -1,8 +0,0 @@
|
|||||||
FROM sigp/lighthouse:v4.1.0-modern
|
|
||||||
|
|
||||||
RUN apt-get update; apt-get install bash netcat curl less jq -y;
|
|
||||||
|
|
||||||
WORKDIR /root/
|
|
||||||
ADD start-lighthouse.sh .
|
|
||||||
|
|
||||||
ENTRYPOINT [ "./start-lighthouse.sh" ]
|
|
@ -1,42 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
|
||||||
set -x
|
|
||||||
fi
|
|
||||||
if [[ $# -ne 3 ]]; then
|
|
||||||
echo "Illegal number of parameters" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
config_file_name=$1
|
|
||||||
webapp_files_dir=$2
|
|
||||||
config_prefix=$3
|
|
||||||
if ! [[ -f ${config_file_name} ]]; then
|
|
||||||
echo "Config file ${config_file_name} does not exist" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if ! [[ -d ${webapp_files_dir} ]]; then
|
|
||||||
echo "Webapp directory ${webapp_files_dir} does not exist" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
# First some magic using sed to translate our yaml config file into an array of key value pairs like:
|
|
||||||
# ${config_prefix}<path-through-objects>=<value>
|
|
||||||
# sed "s/'//g" is used to remove single quote for relayNodes value
|
|
||||||
readarray -t config_kv_pair_array < <( sed -E 's/([^:]+):\s*(.*)/\1=\2/g' ${config_file_name} | sed "s/'//g" | sed "s/^/${config_prefix}_/" )
|
|
||||||
declare -p config_kv_pair_array
|
|
||||||
# Then iterate over that kv array making the template substitution in our web app files
|
|
||||||
for kv_pair_string in "${config_kv_pair_array[@]}"
|
|
||||||
do
|
|
||||||
kv_pair=(${kv_pair_string//=/ })
|
|
||||||
template_string_to_replace=${kv_pair[0]}
|
|
||||||
template_value_to_substitute=${kv_pair[1]}
|
|
||||||
# Run find and sed to do the substitution of one variable over all files
|
|
||||||
# See: https://stackoverflow.com/a/21479607/1701505
|
|
||||||
echo "Substituting: ${template_string_to_replace} = ${template_value_to_substitute}"
|
|
||||||
|
|
||||||
# TODO: Pass keys to be replaced without double quotes
|
|
||||||
if [[ "$template_string_to_replace" =~ ^${config_prefix}_(relayNodes|chainId|denyMultiaddrs)$ ]]; then
|
|
||||||
find ${webapp_files_dir} -type f -exec sed -i 's#"'"${template_string_to_replace}"'"#'"${template_value_to_substitute}"'#g' {} +
|
|
||||||
else
|
|
||||||
# Note: we do not escape our strings, on the expectation they do not container the '#' char.
|
|
||||||
find ${webapp_files_dir} -type f -exec sed -i 's#'${template_string_to_replace}'#'${template_value_to_substitute}'#g' {} +
|
|
||||||
fi
|
|
||||||
done
|
|
@ -1,9 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
|
||||||
set -x
|
|
||||||
fi
|
|
||||||
|
|
||||||
# TODO: Don't hard wire this:
|
|
||||||
webapp_files_dir="/usr/local/share/.config/yarn/global/node_modules/${CERC_BUILD_DIR}"
|
|
||||||
/scripts/apply-webapp-config.sh /config/config.yml ${webapp_files_dir} MOBYMASK_HOSTED_CONFIG
|
|
||||||
http-server -p 80 ${webapp_files_dir}
|
|
@ -1,16 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Test if the container's filesystem is old (run previously) or new
|
|
||||||
EXISTSFILENAME=/var/exists
|
|
||||||
echo "Test container starting"
|
|
||||||
if [[ -f "$EXISTSFILENAME" ]];
|
|
||||||
then
|
|
||||||
TIMESTAMP = `cat $EXISTSFILENAME`
|
|
||||||
echo "Filesystem is old, created: $TIMESTAMP"
|
|
||||||
else
|
|
||||||
echo "Filesystem is fresh"
|
|
||||||
echo `date` > $EXISTSFILENAME
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Run nginx which will block here forever
|
|
||||||
/usr/sbin/nginx -g "daemon off;"
|
|
@ -1,13 +0,0 @@
|
|||||||
FROM node:18.16.0-alpine3.16
|
|
||||||
|
|
||||||
RUN apk --update --no-cache add git python3 alpine-sdk
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
RUN echo "Building azimuth-watcher-ts" && \
|
|
||||||
yarn && yarn build
|
|
||||||
|
|
||||||
RUN echo "Install toml-js to update watcher config files" && \
|
|
||||||
yarn add --dev --ignore-workspace-root-check toml-js
|
|
@ -1,13 +0,0 @@
|
|||||||
FROM node:16.17.1-alpine3.16
|
|
||||||
|
|
||||||
RUN apk --update --no-cache add git python3 alpine-sdk
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
RUN echo "Building watcher-ts" && \
|
|
||||||
git checkout v0.2.19 && \
|
|
||||||
yarn && yarn build
|
|
||||||
|
|
||||||
WORKDIR /app/packages/erc20-watcher
|
|
@ -1,32 +0,0 @@
|
|||||||
cerc-io/ipld-eth-db
|
|
||||||
cerc-io/go-ethereum
|
|
||||||
cerc-io/ipld-eth-server
|
|
||||||
cerc-io/eth-statediff-service
|
|
||||||
cerc-io/eth-statediff-fill-service
|
|
||||||
cerc-io/ipld-eth-db-validator
|
|
||||||
cerc-io/ipld-eth-beacon-indexer
|
|
||||||
cerc-io/ipld-eth-beacon-db
|
|
||||||
cerc-io/laconicd
|
|
||||||
cerc-io/laconic-sdk
|
|
||||||
cerc-io/laconic-registry-cli
|
|
||||||
cerc-io/laconic-console
|
|
||||||
cerc-io/mobymask-watcher
|
|
||||||
cerc-io/watcher-ts
|
|
||||||
cerc-io/mobymask-v2-watcher-ts
|
|
||||||
cerc-io/MobyMask
|
|
||||||
vulcanize/uniswap-watcher-ts
|
|
||||||
vulcanize/uniswap-v3-info
|
|
||||||
vulcanize/assemblyscript
|
|
||||||
cerc-io/eth-probe
|
|
||||||
cerc-io/tx-spammer
|
|
||||||
dboreham/foundry
|
|
||||||
lirewine/gem
|
|
||||||
lirewine/debug
|
|
||||||
lirewine/crypto
|
|
||||||
lirewine/sdk
|
|
||||||
telackey/act_runner
|
|
||||||
ethereum-optimism/op-geth
|
|
||||||
ethereum-optimism/optimism
|
|
||||||
pokt-network/pocket-core
|
|
||||||
pokt-network/pocket-core-deployments
|
|
||||||
cerc-io/azimuth-watcher-ts
|
|
@ -1,72 +0,0 @@
|
|||||||
# Azimuth Watcher
|
|
||||||
|
|
||||||
Instructions to setup and deploy Azimuth Watcher stack
|
|
||||||
|
|
||||||
## Setup
|
|
||||||
|
|
||||||
Prerequisite: ipld-eth-server RPC and GQL endpoints
|
|
||||||
|
|
||||||
Clone required repositories:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
laconic-so --stack azimuth setup-repositories
|
|
||||||
```
|
|
||||||
|
|
||||||
NOTE: If the repository already exists and checked out to a different version, `setup-repositories` command will throw an error.
|
|
||||||
For getting around this, the `azimuth-watcher-ts` repository can be removed and then run the command.
|
|
||||||
|
|
||||||
Checkout to the required versions and branches in repos
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# azimuth-watcher-ts
|
|
||||||
cd ~/cerc/azimuth-watcher-ts
|
|
||||||
git checkout v0.1.0
|
|
||||||
```
|
|
||||||
|
|
||||||
Build the container images:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
laconic-so --stack azimuth build-containers
|
|
||||||
```
|
|
||||||
|
|
||||||
This should create the required docker images in the local image registry.
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
|
|
||||||
* Create and update an env file to be used in the next step:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# External ipld-eth-server endpoints
|
|
||||||
CERC_IPLD_ETH_RPC=
|
|
||||||
CERC_IPLD_ETH_GQL=
|
|
||||||
```
|
|
||||||
|
|
||||||
* NOTE: If ipld-eth-server is running on the host machine, use `host.docker.internal` as the hostname to access host ports
|
|
||||||
|
|
||||||
### Deploy the stack
|
|
||||||
|
|
||||||
* Deploy the containers:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
laconic-so --stack azimuth deploy-system --env-file <PATH_TO_ENV_FILE> up
|
|
||||||
```
|
|
||||||
|
|
||||||
* List and check the health status of all the containers using `docker ps` and wait for them to be `healthy`
|
|
||||||
|
|
||||||
## Clean up
|
|
||||||
|
|
||||||
Stop all the services running in background run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
laconic-so --stack azimuth deploy-system down
|
|
||||||
```
|
|
||||||
|
|
||||||
Clear volumes created by this stack:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# List all relevant volumes
|
|
||||||
docker volume ls -q --filter "name=.*watcher_db_data"
|
|
||||||
|
|
||||||
# Remove all the listed volumes
|
|
||||||
docker volume rm $(docker volume ls -q --filter "name=.*watcher_db_data")
|
|
||||||
```
|
|
@ -1,18 +0,0 @@
|
|||||||
version: "1.2"
|
|
||||||
name: fixturenet-eth-tx
|
|
||||||
decription: "Ethereum Fixturenet w/ tx-spammer"
|
|
||||||
repos:
|
|
||||||
- cerc-io/go-ethereum
|
|
||||||
- cerc-io/tx-spammer
|
|
||||||
- dboreham/foundry
|
|
||||||
containers:
|
|
||||||
- cerc/go-ethereum
|
|
||||||
- cerc/lighthouse
|
|
||||||
- cerc/fixturenet-eth-geth
|
|
||||||
- cerc/fixturenet-eth-lighthouse
|
|
||||||
- cerc/tx-spammer
|
|
||||||
- cerc/foundry
|
|
||||||
pods:
|
|
||||||
- fixturenet-eth
|
|
||||||
- foundry
|
|
||||||
- tx-spammer
|
|
@ -1,128 +0,0 @@
|
|||||||
# fixturenet-optimism
|
|
||||||
|
|
||||||
Instructions to setup and deploy an end-to-end L1+L2 stack with [fixturenet-eth](../fixturenet-eth/) (L1) and [Optimism](https://stack.optimism.io) (L2)
|
|
||||||
|
|
||||||
We support running just the L2 part of stack, given an external L1 endpoint. Follow the [L2 only doc](./l2-only.md) for the same.
|
|
||||||
|
|
||||||
## Setup
|
|
||||||
|
|
||||||
Clone required repositories:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
laconic-so --stack fixturenet-optimism setup-repositories
|
|
||||||
|
|
||||||
# If this throws an error as a result of being already checked out to a branch/tag in a repo, remove the repositories mentioned below and re-run the command
|
|
||||||
```
|
|
||||||
|
|
||||||
Checkout to the required versions and branches in repos:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Optimism
|
|
||||||
cd ~/cerc/optimism
|
|
||||||
git checkout v1.0.4
|
|
||||||
```
|
|
||||||
|
|
||||||
Build the container images:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
laconic-so --stack fixturenet-optimism build-containers
|
|
||||||
```
|
|
||||||
|
|
||||||
Note: this will take >10 mins depending on the specs of your machine, and **requires** 16GB of memory or greater.
|
|
||||||
|
|
||||||
This should create the required docker images in the local image registry:
|
|
||||||
* `cerc/go-ethereum`
|
|
||||||
* `cerc/lighthouse`
|
|
||||||
* `cerc/fixturenet-eth-geth`
|
|
||||||
* `cerc/fixturenet-eth-lighthouse`
|
|
||||||
* `cerc/foundry`
|
|
||||||
* `cerc/optimism-contracts`
|
|
||||||
* `cerc/optimism-l2geth`
|
|
||||||
* `cerc/optimism-op-node`
|
|
||||||
* `cerc/optimism-op-batcher`
|
|
||||||
* `cerc/optimism-op-proposer`
|
|
||||||
|
|
||||||
## Deploy
|
|
||||||
|
|
||||||
Deploy the stack:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
laconic-so --stack fixturenet-optimism deploy up
|
|
||||||
```
|
|
||||||
|
|
||||||
If you get the error `service "fixturenet-optimism-contracts" didn't complete successfully: exit 1` with ~25 lines of Traceback, wait 15-20 mins then re-run the command.
|
|
||||||
|
|
||||||
The `fixturenet-optimism-contracts` service takes a while to complete running as it:
|
|
||||||
1. waits for the 'Merge' to happen on L1
|
|
||||||
2. waits for a finalized block to exist on L1 (so that it can be taken as a starting block for roll ups)
|
|
||||||
3. deploys the L1 contracts
|
|
||||||
|
|
||||||
To list and monitor the running containers:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
laconic-so --stack fixturenet-optimism deploy ps
|
|
||||||
|
|
||||||
# With status
|
|
||||||
docker ps
|
|
||||||
|
|
||||||
# Check logs for a container
|
|
||||||
docker logs -f <CONTAINER_ID>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Clean up
|
|
||||||
|
|
||||||
Stop all services running in the background:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
laconic-so --stack fixturenet-optimism deploy down 30
|
|
||||||
```
|
|
||||||
|
|
||||||
Clear volumes created by this stack:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# List all relevant volumes
|
|
||||||
docker volume ls -q --filter "name=.*l1_deployment|.*l2_accounts|.*l2_config|.*l2_geth_data"
|
|
||||||
|
|
||||||
# Remove all the listed volumes
|
|
||||||
docker volume rm $(docker volume ls -q --filter "name=.*l1_deployment|.*l2_accounts|.*l2_config|.*l2_geth_data")
|
|
||||||
```
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
* If `op-geth` service aborts or is restarted, the following error might occur in the `op-node` service:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
WARN [02-16|21:22:02.868] Derivation process temporary error attempts=14 err="stage 0 failed resetting: temp: failed to find the L2 Heads to start from: failed to fetch L2 block by hash 0x0000000000000000000000000000000000000000000000000000000000000000: failed to determine block-hash of hash 0x0000000000000000000000000000000000000000000000000000000000000000, could not get payload: not found"
|
|
||||||
```
|
|
||||||
|
|
||||||
* This means that the data directory that `op-geth` is using is corrupted and needs to be reinitialized; the containers `op-geth`, `op-node` and `op-batcher` need to be started afresh:
|
|
||||||
|
|
||||||
WARNING: This will reset the L2 chain; consequently, all the data on it will be lost
|
|
||||||
|
|
||||||
* Stop and remove the concerned containers:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# List the containers
|
|
||||||
docker ps -f "name=op-geth|op-node|op-batcher"
|
|
||||||
|
|
||||||
# Force stop and remove the listed containers
|
|
||||||
docker rm -f $(docker ps -qf "name=op-geth|op-node|op-batcher")
|
|
||||||
```
|
|
||||||
|
|
||||||
* Remove the concerned volume:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# List the volume
|
|
||||||
docker volume ls -q --filter name=l2_geth_data
|
|
||||||
|
|
||||||
# Remove the listed volume
|
|
||||||
docker volume rm $(docker volume ls -q --filter name=l2_geth_data)
|
|
||||||
```
|
|
||||||
|
|
||||||
* Re-run the deployment command used in [Deploy](#deploy) to restart the stopped containers
|
|
||||||
|
|
||||||
## Known Issues
|
|
||||||
|
|
||||||
* `fixturenet-eth` currently starts fresh on a restart
|
|
||||||
* Resource requirements (memory + time) for building the `cerc/foundry` image are on the higher side
|
|
||||||
* `cerc/optimism-contracts` image is currently based on `cerc/foundry` (Optimism requires foundry installation)
|
|
@ -1,108 +0,0 @@
|
|||||||
# fixturenet-optimism
|
|
||||||
|
|
||||||
Instructions to setup and deploy L2 fixturenet using [Optimism](https://stack.optimism.io)
|
|
||||||
|
|
||||||
## Setup
|
|
||||||
|
|
||||||
Prerequisite: An L1 Ethereum RPC endpoint
|
|
||||||
|
|
||||||
Clone required repositories:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
laconic-so --stack fixturenet-optimism setup-repositories --exclude cerc-io/go-ethereum
|
|
||||||
|
|
||||||
# If this throws an error as a result of being already checked out to a branch/tag in a repo, remove the repositories mentioned below and re-run the command
|
|
||||||
```
|
|
||||||
|
|
||||||
Checkout to the required versions and branches in repos:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Optimism
|
|
||||||
cd ~/cerc/optimism
|
|
||||||
git checkout v1.0.4
|
|
||||||
```
|
|
||||||
|
|
||||||
Build the container images:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
laconic-so --stack fixturenet-optimism build-containers --include cerc/foundry,cerc/optimism-contracts,cerc/optimism-op-node,cerc/optimism-l2geth,cerc/optimism-op-batcher,cerc/optimism-op-proposer
|
|
||||||
```
|
|
||||||
|
|
||||||
This should create the required docker images in the local image registry:
|
|
||||||
* `cerc/foundry`
|
|
||||||
* `cerc/optimism-contracts`
|
|
||||||
* `cerc/optimism-l2geth`
|
|
||||||
* `cerc/optimism-op-node`
|
|
||||||
* `cerc/optimism-op-batcher`
|
|
||||||
* `cerc/optimism-op-proposer`
|
|
||||||
|
|
||||||
## Deploy
|
|
||||||
|
|
||||||
Create and update an env file to be used in the next step ([defaults](../../config/fixturenet-optimism/l1-params.env)):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# External L1 endpoint
|
|
||||||
CERC_L1_CHAIN_ID=
|
|
||||||
CERC_L1_RPC=
|
|
||||||
CERC_L1_HOST=
|
|
||||||
CERC_L1_PORT=
|
|
||||||
|
|
||||||
# URL to get CSV with credentials for accounts on L1
|
|
||||||
# that are used to send balance to Optimism Proxy contract
|
|
||||||
# (enables them to do transactions on L2)
|
|
||||||
CERC_L1_ACCOUNTS_CSV_URL=
|
|
||||||
|
|
||||||
# OR
|
|
||||||
# Specify the required account credentials
|
|
||||||
CERC_L1_ADDRESS=
|
|
||||||
CERC_L1_PRIV_KEY=
|
|
||||||
CERC_L1_ADDRESS_2=
|
|
||||||
CERC_L1_PRIV_KEY_2=
|
|
||||||
```
|
|
||||||
|
|
||||||
* NOTE: If L1 is running on the host machine, use `host.docker.internal` as the hostname to access the host port
|
|
||||||
|
|
||||||
Deploy the stack:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
laconic-so --stack fixturenet-optimism deploy --include fixturenet-optimism --env-file <PATH_TO_ENV_FILE> up
|
|
||||||
```
|
|
||||||
|
|
||||||
The `fixturenet-optimism-contracts` service may take a while (`~15 mins`) to complete running as it:
|
|
||||||
1. waits for the 'Merge' to happen on L1
|
|
||||||
2. waits for a finalized block to exist on L1 (so that it can be taken as a starting block for roll ups)
|
|
||||||
3. deploys the L1 contracts
|
|
||||||
|
|
||||||
To list down and monitor the running containers:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
laconic-so --stack fixturenet-optimism deploy --include fixturenet-optimism ps
|
|
||||||
|
|
||||||
# With status
|
|
||||||
docker ps
|
|
||||||
|
|
||||||
# Check logs for a container
|
|
||||||
docker logs -f <CONTAINER_ID>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Clean up
|
|
||||||
|
|
||||||
Stop all services running in the background:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
laconic-so --stack fixturenet-optimism deploy --include fixturenet-optimism down 30
|
|
||||||
```
|
|
||||||
|
|
||||||
Clear volumes created by this stack:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# List all relevant volumes
|
|
||||||
docker volume ls -q --filter "name=.*l1_deployment|.*l2_accounts|.*l2_config|.*l2_geth_data"
|
|
||||||
|
|
||||||
# Remove all the listed volumes
|
|
||||||
docker volume rm $(docker volume ls -q --filter "name=.*l1_deployment|.*l2_accounts|.*l2_config|.*l2_geth_data")
|
|
||||||
```
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
See [Troubleshooting](./README.md#troubleshooting)
|
|
@ -1,53 +0,0 @@
|
|||||||
# MobyMask
|
|
||||||
|
|
||||||
The MobyMask watcher is a Laconic Network component that provides efficient access to MobyMask contract data from Ethereum, along with evidence allowing users to verify the correctness of that data. The watcher source code is available in [this repository](https://github.com/cerc-io/watcher-ts/tree/main/packages/mobymask-watcher) and a developer-oriented Docker Compose setup for the watcher can be found [here](https://github.com/cerc-io/mobymask-watcher). The watcher can be deployed automatically using the Laconic Stack Orchestrator tool as detailed below:
|
|
||||||
|
|
||||||
## Deploy the MobyMask Watcher
|
|
||||||
|
|
||||||
The instructions below show how to deploy a MobyMask watcher using laconic-stack-orchestrator (the installation of which is covered [here](https://github.com/cerc-io/stack-orchestrator#user-mode)).
|
|
||||||
|
|
||||||
This deployment expects that ipld-eth-server's endpoints are available on the local machine at http://ipld-eth-server.example.com:8083/graphql and http://ipld-eth-server.example.com:8082. More advanced configurations are supported by modifying the watcher's [config file](../../config/watcher-mobymask/mobymask-watcher.toml).
|
|
||||||
|
|
||||||
## Clone required repositories
|
|
||||||
|
|
||||||
```
|
|
||||||
$ laconic-so setup-repositories --include cerc-io/watcher-ts
|
|
||||||
```
|
|
||||||
|
|
||||||
## Build the watcher container
|
|
||||||
|
|
||||||
```
|
|
||||||
$ laconic-so build-containers --include cerc/watcher-mobymask
|
|
||||||
```
|
|
||||||
|
|
||||||
This should create a container with tag `cerc/watcher-mobymask` in the local image registry.
|
|
||||||
|
|
||||||
## Deploy the stack
|
|
||||||
|
|
||||||
First the watcher database has to be initialized. Start only the mobymask-watcher-db service:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ laconic-so deploy-system --include watcher-mobymask up mobymask-watcher-db
|
|
||||||
```
|
|
||||||
|
|
||||||
Next find the container's id using `docker ps` then run the following command to initialize the database:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ docker exec -i <mobymask-watcher-db-container> psql -U vdbm mobymask-watcher < config/watcher-mobymask/mobymask-watcher-db.sql
|
|
||||||
```
|
|
||||||
|
|
||||||
Finally start the remaining containers:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ laconic-so deploy-system --include watcher-mobymask up
|
|
||||||
```
|
|
||||||
|
|
||||||
Correct operation should be verified by following the instructions [here](https://github.com/cerc-io/mobymask-watcher/tree/main/mainnet-watcher-only#run), checking GraphQL queries return valid results in the watcher's [playground](http://127.0.0.1:3001/graphql).
|
|
||||||
|
|
||||||
## Clean up
|
|
||||||
|
|
||||||
Stop all the services running in background:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ laconic-so deploy-system --include watcher-mobymask down
|
|
||||||
```
|
|
@ -1,5 +0,0 @@
|
|||||||
# Package Registry Stack
|
|
||||||
|
|
||||||
The Package Registry Stack supports a build environment that requires a package registry (initially for NPM packages only).
|
|
||||||
|
|
||||||
Setup instructions can be found [here](../build-support/README.md).
|
|
@ -1,15 +0,0 @@
|
|||||||
version: "1.1"
|
|
||||||
name: package-registry
|
|
||||||
decription: "Local Package Registry"
|
|
||||||
repos:
|
|
||||||
- cerc-io/hosting
|
|
||||||
- telackey/act_runner
|
|
||||||
containers:
|
|
||||||
- cerc/act-runner
|
|
||||||
- cerc/act-runner-task-executor
|
|
||||||
pods:
|
|
||||||
- name: gitea
|
|
||||||
repository: cerc-io/hosting
|
|
||||||
path: gitea
|
|
||||||
pre_start_command: "run-this-first.sh"
|
|
||||||
post_start_command: "initialize-gitea.sh"
|
|
@ -1,339 +0,0 @@
|
|||||||
# Copyright © 2022, 2023 Cerc
|
|
||||||
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
# Deploys the system components using docker-compose
|
|
||||||
|
|
||||||
import hashlib
|
|
||||||
import copy
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from dataclasses import dataclass
|
|
||||||
from decouple import config
|
|
||||||
import subprocess
|
|
||||||
from python_on_whales import DockerClient, DockerException
|
|
||||||
import click
|
|
||||||
import importlib.resources
|
|
||||||
from pathlib import Path
|
|
||||||
from .util import include_exclude_check, get_parsed_stack_config
|
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
|
||||||
@click.option("--include", help="only start these components")
|
|
||||||
@click.option("--exclude", help="don\'t start these components")
|
|
||||||
@click.option("--env-file", help="env file to be used")
|
|
||||||
@click.option("--cluster", help="specify a non-default cluster name")
|
|
||||||
@click.argument('command', required=True) # help: command: up|down|ps
|
|
||||||
@click.argument('extra_args', nargs=-1) # help: command: up|down|ps <service1> <service2>
|
|
||||||
@click.pass_context
|
|
||||||
def command(ctx, include, exclude, env_file, cluster, command, extra_args):
|
|
||||||
'''deploy a stack'''
|
|
||||||
|
|
||||||
# TODO: implement option exclusion and command value constraint lost with the move from argparse to click
|
|
||||||
|
|
||||||
debug = ctx.obj.debug
|
|
||||||
quiet = ctx.obj.quiet
|
|
||||||
verbose = ctx.obj.verbose
|
|
||||||
local_stack = ctx.obj.local_stack
|
|
||||||
dry_run = ctx.obj.dry_run
|
|
||||||
stack = ctx.obj.stack
|
|
||||||
|
|
||||||
cluster_context = _make_cluster_context(ctx.obj, include, exclude, cluster)
|
|
||||||
|
|
||||||
# See: https://gabrieldemarmiesse.github.io/python-on-whales/sub-commands/compose/
|
|
||||||
docker = DockerClient(compose_files=cluster_context.compose_files, compose_project_name=cluster_context.cluster, compose_env_file=env_file)
|
|
||||||
|
|
||||||
extra_args_list = list(extra_args) or None
|
|
||||||
|
|
||||||
if not dry_run:
|
|
||||||
if command == "up":
|
|
||||||
container_exec_env = _make_runtime_env(ctx.obj)
|
|
||||||
for attr, value in container_exec_env.items():
|
|
||||||
os.environ[attr] = value
|
|
||||||
if verbose:
|
|
||||||
print(f"Running compose up with container_exec_env: {container_exec_env}, extra_args: {extra_args_list}")
|
|
||||||
for pre_start_command in cluster_context.pre_start_commands:
|
|
||||||
_run_command(ctx.obj, cluster_context.cluster, pre_start_command)
|
|
||||||
docker.compose.up(detach=True, services=extra_args_list)
|
|
||||||
for post_start_command in cluster_context.post_start_commands:
|
|
||||||
_run_command(ctx.obj, cluster_context.cluster, post_start_command)
|
|
||||||
|
|
||||||
_orchestrate_cluster_config(ctx.obj, cluster_context.config, docker, container_exec_env)
|
|
||||||
|
|
||||||
elif command == "down":
|
|
||||||
if verbose:
|
|
||||||
print("Running compose down")
|
|
||||||
|
|
||||||
timeout_arg = None
|
|
||||||
if extra_args_list:
|
|
||||||
timeout_arg=extra_args_list[0]
|
|
||||||
|
|
||||||
# Specify shutdown timeout (default 10s) to give services enough time to shutdown gracefully
|
|
||||||
docker.compose.down(timeout=timeout_arg)
|
|
||||||
elif command == "exec":
|
|
||||||
if extra_args_list is None or len(extra_args_list) < 2:
|
|
||||||
print("Usage: exec <service> <cmd>")
|
|
||||||
sys.exit(1)
|
|
||||||
service_name = extra_args_list[0]
|
|
||||||
command_to_exec = ["sh", "-c"] + extra_args_list[1:]
|
|
||||||
container_exec_env = _make_runtime_env(ctx.obj)
|
|
||||||
if verbose:
|
|
||||||
print(f"Running compose exec {service_name} {command_to_exec}")
|
|
||||||
try:
|
|
||||||
docker.compose.execute(service_name, command_to_exec, envs=container_exec_env)
|
|
||||||
except DockerException as error:
|
|
||||||
print(f"container command returned error exit status")
|
|
||||||
elif command == "port":
|
|
||||||
if extra_args_list is None or len(extra_args_list) < 2:
|
|
||||||
print("Usage: port <service> <exposed-port>")
|
|
||||||
sys.exit(1)
|
|
||||||
service_name = extra_args_list[0]
|
|
||||||
exposed_port = extra_args_list[1]
|
|
||||||
if verbose:
|
|
||||||
print(f"Running compose port {service_name} {exposed_port}")
|
|
||||||
mapped_port_data = docker.compose.port(service_name, exposed_port)
|
|
||||||
print(f"{mapped_port_data[0]}:{mapped_port_data[1]}")
|
|
||||||
elif command == "ps":
|
|
||||||
if verbose:
|
|
||||||
print("Running compose ps")
|
|
||||||
container_list = docker.compose.ps()
|
|
||||||
if len(container_list) > 0:
|
|
||||||
print("Running containers:")
|
|
||||||
for container in container_list:
|
|
||||||
print(f"id: {container.id}, name: {container.name}, ports: ", end="")
|
|
||||||
ports = container.network_settings.ports
|
|
||||||
comma = ""
|
|
||||||
for port_mapping in ports.keys():
|
|
||||||
mapping = ports[port_mapping]
|
|
||||||
print(comma, end="")
|
|
||||||
if mapping is None:
|
|
||||||
print(f"{port_mapping}", end="")
|
|
||||||
else:
|
|
||||||
print(f"{mapping[0]['HostIp']}:{mapping[0]['HostPort']}->{port_mapping}", end="")
|
|
||||||
comma = ", "
|
|
||||||
print()
|
|
||||||
else:
|
|
||||||
print("No containers running")
|
|
||||||
elif command == "logs":
|
|
||||||
if verbose:
|
|
||||||
print("Running compose logs")
|
|
||||||
logs_output = docker.compose.logs(services=extra_args_list if extra_args_list is not None else [])
|
|
||||||
print(logs_output)
|
|
||||||
|
|
||||||
|
|
||||||
def get_stack_status(ctx, stack):
|
|
||||||
|
|
||||||
ctx_copy = copy.copy(ctx)
|
|
||||||
ctx_copy.stack = stack
|
|
||||||
|
|
||||||
cluster_context = _make_cluster_context(ctx_copy, None, None, None)
|
|
||||||
docker = DockerClient(compose_files=cluster_context.compose_files, compose_project_name=cluster_context.cluster)
|
|
||||||
# TODO: refactor to avoid duplicating this code above
|
|
||||||
if ctx.verbose:
|
|
||||||
print("Running compose ps")
|
|
||||||
container_list = docker.compose.ps()
|
|
||||||
if len(container_list) > 0:
|
|
||||||
if ctx.debug:
|
|
||||||
print(f"Container list from compose ps: {container_list}")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
if ctx.debug:
|
|
||||||
print("No containers found from compose ps")
|
|
||||||
False
|
|
||||||
|
|
||||||
|
|
||||||
def _make_runtime_env(ctx):
|
|
||||||
container_exec_env = {
|
|
||||||
"CERC_HOST_UID": f"{os.getuid()}",
|
|
||||||
"CERC_HOST_GID": f"{os.getgid()}"
|
|
||||||
}
|
|
||||||
container_exec_env.update({"CERC_SCRIPT_DEBUG": "true"} if ctx.debug else {})
|
|
||||||
return container_exec_env
|
|
||||||
|
|
||||||
|
|
||||||
def _make_cluster_context(ctx, include, exclude, cluster):
|
|
||||||
|
|
||||||
if ctx.local_stack:
|
|
||||||
dev_root_path = os.getcwd()[0:os.getcwd().rindex("stack-orchestrator")]
|
|
||||||
print(f'Local stack dev_root_path (CERC_REPO_BASE_DIR) overridden to: {dev_root_path}')
|
|
||||||
else:
|
|
||||||
dev_root_path = os.path.expanduser(config("CERC_REPO_BASE_DIR", default="~/cerc"))
|
|
||||||
|
|
||||||
# See: https://stackoverflow.com/questions/25389095/python-get-path-of-root-project-structure
|
|
||||||
compose_dir = Path(__file__).absolute().parent.joinpath("data", "compose")
|
|
||||||
|
|
||||||
if cluster is None:
|
|
||||||
# Create default unique, stable cluster name from confile file path and stack name if provided
|
|
||||||
# TODO: change this to the config file path
|
|
||||||
path = os.path.realpath(sys.argv[0])
|
|
||||||
unique_cluster_descriptor = f"{path},{ctx.stack},{include},{exclude}"
|
|
||||||
if ctx.debug:
|
|
||||||
print(f"pre-hash descriptor: {unique_cluster_descriptor}")
|
|
||||||
hash = hashlib.md5(unique_cluster_descriptor.encode()).hexdigest()
|
|
||||||
cluster = f"laconic-{hash}"
|
|
||||||
if ctx.verbose:
|
|
||||||
print(f"Using cluster name: {cluster}")
|
|
||||||
|
|
||||||
# See: https://stackoverflow.com/a/20885799/1701505
|
|
||||||
from . import data
|
|
||||||
with importlib.resources.open_text(data, "pod-list.txt") as pod_list_file:
|
|
||||||
all_pods = pod_list_file.read().splitlines()
|
|
||||||
|
|
||||||
pods_in_scope = []
|
|
||||||
if ctx.stack:
|
|
||||||
stack_config = get_parsed_stack_config(ctx.stack)
|
|
||||||
# TODO: syntax check the input here
|
|
||||||
pods_in_scope = stack_config['pods']
|
|
||||||
cluster_config = stack_config['config'] if 'config' in stack_config else None
|
|
||||||
else:
|
|
||||||
pods_in_scope = all_pods
|
|
||||||
cluster_config = None
|
|
||||||
|
|
||||||
# Convert all pod definitions to v1.1 format
|
|
||||||
pods_in_scope = _convert_to_new_format(pods_in_scope)
|
|
||||||
|
|
||||||
if ctx.verbose:
|
|
||||||
print(f"Pods: {pods_in_scope}")
|
|
||||||
|
|
||||||
# Construct a docker compose command suitable for our purpose
|
|
||||||
|
|
||||||
compose_files = []
|
|
||||||
pre_start_commands = []
|
|
||||||
post_start_commands = []
|
|
||||||
for pod in pods_in_scope:
|
|
||||||
pod_name = pod["name"]
|
|
||||||
pod_repository = pod["repository"]
|
|
||||||
pod_path = pod["path"]
|
|
||||||
if include_exclude_check(pod_name, include, exclude):
|
|
||||||
if pod_repository is None or pod_repository == "internal":
|
|
||||||
compose_file_name = os.path.join(compose_dir, f"docker-compose-{pod_path}.yml")
|
|
||||||
else:
|
|
||||||
pod_root_dir = os.path.join(dev_root_path, pod_repository.split("/")[-1], pod["path"])
|
|
||||||
compose_file_name = os.path.join(pod_root_dir, "docker-compose.yml")
|
|
||||||
pod_pre_start_command = pod["pre_start_command"]
|
|
||||||
pod_post_start_command = pod["post_start_command"]
|
|
||||||
if pod_pre_start_command is not None:
|
|
||||||
pre_start_commands.append(os.path.join(pod_root_dir, pod_pre_start_command))
|
|
||||||
if pod_post_start_command is not None:
|
|
||||||
post_start_commands.append(os.path.join(pod_root_dir, pod_post_start_command))
|
|
||||||
compose_files.append(compose_file_name)
|
|
||||||
else:
|
|
||||||
if ctx.verbose:
|
|
||||||
print(f"Excluding: {pod_name}")
|
|
||||||
|
|
||||||
if ctx.verbose:
|
|
||||||
print(f"files: {compose_files}")
|
|
||||||
|
|
||||||
return cluster_context(cluster, compose_files, pre_start_commands, post_start_commands, cluster_config)
|
|
||||||
|
|
||||||
|
|
||||||
class cluster_context:
|
|
||||||
def __init__(self, cluster, compose_files, pre_start_commands, post_start_commands, config) -> None:
|
|
||||||
self.cluster = cluster
|
|
||||||
self.compose_files = compose_files
|
|
||||||
self.pre_start_commands = pre_start_commands
|
|
||||||
self.post_start_commands = post_start_commands
|
|
||||||
self.config = config
|
|
||||||
|
|
||||||
|
|
||||||
def _convert_to_new_format(old_pod_array):
|
|
||||||
new_pod_array = []
|
|
||||||
for old_pod in old_pod_array:
|
|
||||||
if isinstance(old_pod, dict):
|
|
||||||
new_pod_array.append(old_pod)
|
|
||||||
else:
|
|
||||||
new_pod = {
|
|
||||||
"name": old_pod,
|
|
||||||
"repository": "internal",
|
|
||||||
"path": old_pod
|
|
||||||
}
|
|
||||||
new_pod_array.append(new_pod)
|
|
||||||
return new_pod_array
|
|
||||||
|
|
||||||
|
|
||||||
def _run_command(ctx, cluster_name, command):
|
|
||||||
if ctx.verbose:
|
|
||||||
print(f"Running command: {command}")
|
|
||||||
command_dir = os.path.dirname(command)
|
|
||||||
command_file = os.path.join(".", os.path.basename(command))
|
|
||||||
command_env = os.environ.copy()
|
|
||||||
command_env["CERC_SO_COMPOSE_PROJECT"] = cluster_name
|
|
||||||
if ctx.debug:
|
|
||||||
command_env["CERC_SCRIPT_DEBUG"] = "true"
|
|
||||||
command_result = subprocess.run(command_file, shell=True, env=command_env, cwd=command_dir)
|
|
||||||
if command_result.returncode != 0:
|
|
||||||
print(f"FATAL Error running command: {command}")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
def _orchestrate_cluster_config(ctx, cluster_config, docker, container_exec_env):
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class ConfigDirective:
|
|
||||||
source_container: str
|
|
||||||
source_variable: str
|
|
||||||
destination_container: str
|
|
||||||
destination_variable: str
|
|
||||||
|
|
||||||
if cluster_config is not None:
|
|
||||||
for container in cluster_config:
|
|
||||||
container_config = cluster_config[container]
|
|
||||||
if ctx.verbose:
|
|
||||||
print(f"{container} config: {container_config}")
|
|
||||||
for directive in container_config:
|
|
||||||
pd = ConfigDirective(
|
|
||||||
container_config[directive].split(".")[0],
|
|
||||||
container_config[directive].split(".")[1],
|
|
||||||
container,
|
|
||||||
directive
|
|
||||||
)
|
|
||||||
if ctx.verbose:
|
|
||||||
print(f"Setting {pd.destination_container}.{pd.destination_variable}"
|
|
||||||
f" = {pd.source_container}.{pd.source_variable}")
|
|
||||||
# TODO: add a timeout
|
|
||||||
waiting_for_data = True
|
|
||||||
while waiting_for_data:
|
|
||||||
# TODO: fix the script paths so they're consistent between containers
|
|
||||||
source_value = None
|
|
||||||
try:
|
|
||||||
source_value = docker.compose.execute(pd.source_container,
|
|
||||||
["sh", "-c",
|
|
||||||
"sh /docker-entrypoint-scripts.d/export-"
|
|
||||||
f"{pd.source_variable}.sh"],
|
|
||||||
tty=False,
|
|
||||||
envs=container_exec_env)
|
|
||||||
except DockerException as error:
|
|
||||||
if ctx.debug:
|
|
||||||
print(f"Docker exception reading config source: {error}")
|
|
||||||
# If the script executed failed for some reason, we get:
|
|
||||||
# "It returned with code 1"
|
|
||||||
if "It returned with code 1" in str(error):
|
|
||||||
if ctx.verbose:
|
|
||||||
print("Config export script returned an error, re-trying")
|
|
||||||
# If the script failed to execute (e.g. the file is not there) then we get:
|
|
||||||
# "It returned with code 2"
|
|
||||||
if "It returned with code 2" in str(error):
|
|
||||||
print(f"Fatal error reading config source: {error}")
|
|
||||||
if source_value:
|
|
||||||
if ctx.debug:
|
|
||||||
print(f"fetched source value: {source_value}")
|
|
||||||
destination_output = docker.compose.execute(pd.destination_container,
|
|
||||||
["sh", "-c",
|
|
||||||
f"sh /scripts/import-{pd.destination_variable}.sh"
|
|
||||||
f" {source_value}"],
|
|
||||||
tty=False,
|
|
||||||
envs=container_exec_env)
|
|
||||||
waiting_for_data = False
|
|
||||||
if ctx.debug:
|
|
||||||
print(f"destination output: {destination_output}")
|
|
@ -1,182 +0,0 @@
|
|||||||
# Copyright © 2022 Cerc
|
|
||||||
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
# env vars:
|
|
||||||
# CERC_REPO_BASE_DIR defaults to ~/cerc
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from decouple import config
|
|
||||||
import git
|
|
||||||
from tqdm import tqdm
|
|
||||||
import click
|
|
||||||
import importlib.resources
|
|
||||||
from pathlib import Path
|
|
||||||
import yaml
|
|
||||||
from .util import include_exclude_check
|
|
||||||
|
|
||||||
|
|
||||||
class GitProgress(git.RemoteProgress):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__()
|
|
||||||
self.pbar = tqdm(unit='B', ascii=True, unit_scale=True)
|
|
||||||
|
|
||||||
def update(self, op_code, cur_count, max_count=None, message=''):
|
|
||||||
self.pbar.total = max_count
|
|
||||||
self.pbar.n = cur_count
|
|
||||||
self.pbar.refresh()
|
|
||||||
|
|
||||||
|
|
||||||
def is_git_repo(path):
|
|
||||||
try:
|
|
||||||
_ = git.Repo(path).git_dir
|
|
||||||
return True
|
|
||||||
except git.exc.InvalidGitRepositoryError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
# TODO: find a place for this in the context of click
|
|
||||||
# parser = argparse.ArgumentParser(
|
|
||||||
# epilog="Config provided either in .env or settings.ini or env vars: CERC_REPO_BASE_DIR (defaults to ~/cerc)"
|
|
||||||
# )
|
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
|
||||||
@click.option("--include", help="only clone these repositories")
|
|
||||||
@click.option("--exclude", help="don\'t clone these repositories")
|
|
||||||
@click.option('--git-ssh', is_flag=True, default=False)
|
|
||||||
@click.option('--check-only', is_flag=True, default=False)
|
|
||||||
@click.option('--pull', is_flag=True, default=False)
|
|
||||||
@click.option('--branches-file', help="checkout branches specified in this file")
|
|
||||||
@click.pass_context
|
|
||||||
def command(ctx, include, exclude, git_ssh, check_only, pull, branches_file):
|
|
||||||
'''git clone the set of repositories required to build the complete system from source'''
|
|
||||||
|
|
||||||
quiet = ctx.obj.quiet
|
|
||||||
verbose = ctx.obj.verbose
|
|
||||||
dry_run = ctx.obj.dry_run
|
|
||||||
stack = ctx.obj.stack
|
|
||||||
|
|
||||||
branches = []
|
|
||||||
|
|
||||||
# TODO: branches file needs to be re-worked in the context of stacks
|
|
||||||
if branches_file:
|
|
||||||
if verbose:
|
|
||||||
print(f"loading branches from: {branches_file}")
|
|
||||||
with open(branches_file) as branches_file_open:
|
|
||||||
branches = branches_file_open.read().splitlines()
|
|
||||||
if verbose:
|
|
||||||
print(f"Branches are: {branches}")
|
|
||||||
|
|
||||||
local_stack = ctx.obj.local_stack
|
|
||||||
|
|
||||||
if local_stack:
|
|
||||||
dev_root_path = os.getcwd()[0:os.getcwd().rindex("stack-orchestrator")]
|
|
||||||
print(f"Local stack dev_root_path (CERC_REPO_BASE_DIR) overridden to: {dev_root_path}")
|
|
||||||
else:
|
|
||||||
dev_root_path = os.path.expanduser(config("CERC_REPO_BASE_DIR", default="~/cerc"))
|
|
||||||
|
|
||||||
if not quiet:
|
|
||||||
print(f"Dev Root is: {dev_root_path}")
|
|
||||||
|
|
||||||
if not os.path.isdir(dev_root_path):
|
|
||||||
if not quiet:
|
|
||||||
print('Dev root directory doesn\'t exist, creating')
|
|
||||||
os.makedirs(dev_root_path)
|
|
||||||
|
|
||||||
# See: https://stackoverflow.com/a/20885799/1701505
|
|
||||||
from . import data
|
|
||||||
with importlib.resources.open_text(data, "repository-list.txt") as repository_list_file:
|
|
||||||
all_repos = repository_list_file.read().splitlines()
|
|
||||||
|
|
||||||
repos_in_scope = []
|
|
||||||
if stack:
|
|
||||||
# In order to be compatible with Python 3.8 we need to use this hack to get the path:
|
|
||||||
# See: https://stackoverflow.com/questions/25389095/python-get-path-of-root-project-structure
|
|
||||||
stack_file_path = Path(__file__).absolute().parent.joinpath("data", "stacks", stack, "stack.yml")
|
|
||||||
with stack_file_path:
|
|
||||||
stack_config = yaml.safe_load(open(stack_file_path, "r"))
|
|
||||||
# TODO: syntax check the input here
|
|
||||||
repos_in_scope = stack_config['repos']
|
|
||||||
else:
|
|
||||||
repos_in_scope = all_repos
|
|
||||||
|
|
||||||
if verbose:
|
|
||||||
print(f"Repos: {repos_in_scope}")
|
|
||||||
if stack:
|
|
||||||
print(f"Stack: {stack}")
|
|
||||||
|
|
||||||
repos = []
|
|
||||||
for repo in repos_in_scope:
|
|
||||||
if include_exclude_check(repo, include, exclude):
|
|
||||||
repos.append(repo)
|
|
||||||
else:
|
|
||||||
if verbose:
|
|
||||||
print(f"Excluding: {repo}")
|
|
||||||
|
|
||||||
def process_repo(repo):
|
|
||||||
git_ssh_prefix = "git@github.com:"
|
|
||||||
git_http_prefix = "https://github.com/"
|
|
||||||
full_github_repo_path = f"{git_ssh_prefix if git_ssh else git_http_prefix}{repo}"
|
|
||||||
repoName = repo.split("/")[-1]
|
|
||||||
full_filesystem_repo_path = os.path.join(dev_root_path, repoName)
|
|
||||||
is_present = os.path.isdir(full_filesystem_repo_path)
|
|
||||||
if not quiet:
|
|
||||||
present_text = f"already exists active branch: {git.Repo(full_filesystem_repo_path).active_branch}" if is_present \
|
|
||||||
else 'Needs to be fetched'
|
|
||||||
print(f"Checking: {full_filesystem_repo_path}: {present_text}")
|
|
||||||
# Quick check that it's actually a repo
|
|
||||||
if is_present:
|
|
||||||
if not is_git_repo(full_filesystem_repo_path):
|
|
||||||
print(f"Error: {full_filesystem_repo_path} does not contain a valid git repository")
|
|
||||||
sys.exit(1)
|
|
||||||
else:
|
|
||||||
if pull:
|
|
||||||
if verbose:
|
|
||||||
print(f"Running git pull for {full_filesystem_repo_path}")
|
|
||||||
if not check_only:
|
|
||||||
git_repo = git.Repo(full_filesystem_repo_path)
|
|
||||||
origin = git_repo.remotes.origin
|
|
||||||
origin.pull(progress=None if quiet else GitProgress())
|
|
||||||
else:
|
|
||||||
print("(git pull skipped)")
|
|
||||||
if not is_present:
|
|
||||||
# Clone
|
|
||||||
if verbose:
|
|
||||||
print(f'Running git clone for {full_github_repo_path} into {full_filesystem_repo_path}')
|
|
||||||
if not dry_run:
|
|
||||||
git.Repo.clone_from(full_github_repo_path,
|
|
||||||
full_filesystem_repo_path,
|
|
||||||
progress=None if quiet else GitProgress())
|
|
||||||
else:
|
|
||||||
print("(git clone skipped)")
|
|
||||||
# Checkout the requested branch, if one was specified
|
|
||||||
if branches:
|
|
||||||
# Find the current repo in the branches list
|
|
||||||
for repo_branch in branches:
|
|
||||||
repo_branch_tuple = repo_branch.split(" ")
|
|
||||||
if repo_branch_tuple[0] == repo:
|
|
||||||
# checkout specified branch
|
|
||||||
branch_to_checkout = repo_branch_tuple[1]
|
|
||||||
if verbose:
|
|
||||||
print(f"checking out branch {branch_to_checkout} in repo {repo}")
|
|
||||||
git_repo = git.Repo(full_filesystem_repo_path)
|
|
||||||
git_repo.git.checkout(branch_to_checkout)
|
|
||||||
|
|
||||||
for repo in repos:
|
|
||||||
try:
|
|
||||||
process_repo(repo)
|
|
||||||
except git.exc.GitCommandError as error:
|
|
||||||
print(f"\n******* git command returned error exit status:\n{error}")
|
|
||||||
sys.exit(1)
|
|
50
app/util.py
50
app/util.py
@ -1,50 +0,0 @@
|
|||||||
# Copyright © 2022, 2023 Cerc
|
|
||||||
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
import os.path
|
|
||||||
import sys
|
|
||||||
import yaml
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
|
|
||||||
def include_exclude_check(s, include, exclude):
|
|
||||||
if include is None and exclude is None:
|
|
||||||
return True
|
|
||||||
if include is not None:
|
|
||||||
include_list = include.split(",")
|
|
||||||
return s in include_list
|
|
||||||
if exclude is not None:
|
|
||||||
exclude_list = exclude.split(",")
|
|
||||||
return s not in exclude_list
|
|
||||||
|
|
||||||
|
|
||||||
def get_parsed_stack_config(stack):
|
|
||||||
# In order to be compatible with Python 3.8 we need to use this hack to get the path:
|
|
||||||
# See: https://stackoverflow.com/questions/25389095/python-get-path-of-root-project-structure
|
|
||||||
stack_file_path = Path(__file__).absolute().parent.joinpath("data", "stacks", stack, "stack.yml")
|
|
||||||
try:
|
|
||||||
with stack_file_path:
|
|
||||||
stack_config = yaml.safe_load(open(stack_file_path, "r"))
|
|
||||||
return stack_config
|
|
||||||
except FileNotFoundError as error:
|
|
||||||
# We try here to generate a useful diagnostic error
|
|
||||||
# First check if the stack directory is present
|
|
||||||
stack_directory = stack_file_path.parent
|
|
||||||
if os.path.exists(stack_directory):
|
|
||||||
print(f"Error: stack.yml file is missing from stack: {stack}")
|
|
||||||
else:
|
|
||||||
print(f"Error: stack: {stack} does not exist")
|
|
||||||
print(f"Exiting, error: {error}")
|
|
||||||
sys.exit(1)
|
|
60
cli.py
60
cli.py
@ -1,60 +0,0 @@
|
|||||||
# Copyright © 2022 Cerc
|
|
||||||
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
import click
|
|
||||||
|
|
||||||
from app import setup_repositories
|
|
||||||
from app import build_containers
|
|
||||||
from app import build_npms
|
|
||||||
from app import deploy_system
|
|
||||||
from app import version
|
|
||||||
|
|
||||||
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: this seems kind of weird and heavy on boilerplate -- check it is
|
|
||||||
# the best Python can do for us.
|
|
||||||
class Options(object):
|
|
||||||
def __init__(self, stack, quiet, verbose, dry_run, local_stack, debug, continue_on_error):
|
|
||||||
self.stack = stack
|
|
||||||
self.quiet = quiet
|
|
||||||
self.verbose = verbose
|
|
||||||
self.dry_run = dry_run
|
|
||||||
self.local_stack = local_stack
|
|
||||||
self.debug = debug
|
|
||||||
self.continue_on_error = continue_on_error
|
|
||||||
|
|
||||||
|
|
||||||
@click.group(context_settings=CONTEXT_SETTINGS)
|
|
||||||
@click.option('--stack', help="specify a stack to build/deploy")
|
|
||||||
@click.option('--quiet', is_flag=True, default=False)
|
|
||||||
@click.option('--verbose', is_flag=True, default=False)
|
|
||||||
@click.option('--dry-run', is_flag=True, default=False)
|
|
||||||
@click.option('--local-stack', is_flag=True, default=False)
|
|
||||||
@click.option('--debug', is_flag=True, default=False)
|
|
||||||
@click.option('--continue-on-error', is_flag=True, default=False)
|
|
||||||
# See: https://click.palletsprojects.com/en/8.1.x/complex/#building-a-git-clone
|
|
||||||
@click.pass_context
|
|
||||||
def cli(ctx, stack, quiet, verbose, dry_run, local_stack, debug, continue_on_error):
|
|
||||||
"""Laconic Stack Orchestrator"""
|
|
||||||
ctx.obj = Options(stack, quiet, verbose, dry_run, local_stack, debug, continue_on_error)
|
|
||||||
|
|
||||||
|
|
||||||
cli.add_command(setup_repositories.command, "setup-repositories")
|
|
||||||
cli.add_command(build_containers.command, "build-containers")
|
|
||||||
cli.add_command(build_npms.command, "build-npms")
|
|
||||||
cli.add_command(deploy_system.command, "deploy") # deploy is an alias for deploy-system
|
|
||||||
cli.add_command(deploy_system.command, "deploy-system")
|
|
||||||
cli.add_command(version.command, "version")
|
|
@ -26,7 +26,7 @@ In addition to the pre-requisites listed in the [README](/README.md), the follow
|
|||||||
|
|
||||||
1. Clone this repository:
|
1. Clone this repository:
|
||||||
```
|
```
|
||||||
$ git clone (https://github.com/cerc-io/stack-orchestrator.git
|
$ git clone https://git.vdb.to/cerc-io/stack-orchestrator.git
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Enter the project directory:
|
2. Enter the project directory:
|
||||||
@ -87,20 +87,27 @@ Use shiv to build a single file Python executable zip archive of laconic-so:
|
|||||||
```
|
```
|
||||||
$ cp stack-orchetrator/laconic-so ~/bin
|
$ cp stack-orchetrator/laconic-so ~/bin
|
||||||
$ laconic-so
|
$ laconic-so
|
||||||
Usage: python -m laconic-so [OPTIONS] COMMAND [ARGS]...
|
Usage: laconic-so [OPTIONS] COMMAND [ARGS]...
|
||||||
|
|
||||||
Laconic Stack Orchestrator
|
Laconic Stack Orchestrator
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
|
--stack TEXT specify a stack to build/deploy
|
||||||
--quiet
|
--quiet
|
||||||
--verbose
|
--verbose
|
||||||
--dry-run
|
--dry-run
|
||||||
|
--local-stack
|
||||||
|
--debug
|
||||||
|
--continue-on-error
|
||||||
-h, --help Show this message and exit.
|
-h, --help Show this message and exit.
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
build-containers build the set of containers required for a complete...
|
build-containers build the set of containers required for a complete...
|
||||||
|
build-npms build the set of npm packages required for a...
|
||||||
|
deploy deploy a stack
|
||||||
deploy-system deploy a stack
|
deploy-system deploy a stack
|
||||||
setup-repositories git clone the set of repositories required to build...
|
setup-repositories git clone the set of repositories required to build...
|
||||||
|
version print tool version
|
||||||
```
|
```
|
||||||
|
|
||||||
For cutting releases, use the [shiv build script](/scripts/build_shiv_package.sh).
|
For cutting releases, use the [shiv build script](/scripts/build_shiv_package.sh).
|
||||||
|
8
docs/README.md
Normal file
8
docs/README.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Stack Orchestrator
|
||||||
|
|
||||||
|
Here you will find information about the design of stack orchestrator, contributing to it, and deploying services/applications that combine two or more "stacks".
|
||||||
|
|
||||||
|
Most "stacks" contain their own README which has plenty of information on deploying, but stacks can be combined in a variety of ways which are document here, for example:
|
||||||
|
|
||||||
|
- [Gitea with Laconicd Fixturenet](./gitea-with-laconicd-fixturenet.md)
|
||||||
|
- [Laconicd Registry with Console](./laconicd-with-console.md)
|
71
docs/adding-a-new-stack.md
Normal file
71
docs/adding-a-new-stack.md
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
# Adding a new stack
|
||||||
|
|
||||||
|
See [this PR](https://git.vdb.to/cerc-io/stack-orchestrator/pull/434) for an example of how to currently add a minimal stack to stack orchestrator. The [reth stack](https://git.vdb.to/cerc-io/stack-orchestrator/pull/435) is another good example.
|
||||||
|
|
||||||
|
For external developers, we recommend forking this repo and adding your stack directly to your fork. This initially requires running in "developer mode" as described [here](/docs/CONTRIBUTING.md). Check out the [Namada stack](https://github.com/vknowable/stack-orchestrator/blob/main/app/data/stacks/public-namada/digitalocean_quickstart.md) from Knowable to see how that is done.
|
||||||
|
|
||||||
|
Core to the feature completeness of stack orchestrator is to [decouple the tool functionality from payload](https://git.vdb.to/cerc-io/stack-orchestrator/issues/315) which will no longer require forking to add a stack.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
- in `stack_orchestrator/data/stacks/my-new-stack/stack.yml` add:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: "0.1"
|
||||||
|
name: my-new-stack
|
||||||
|
repos:
|
||||||
|
- github.com/my-org/my-new-stack
|
||||||
|
containers:
|
||||||
|
- cerc/my-new-stack
|
||||||
|
pods:
|
||||||
|
- my-new-stack
|
||||||
|
```
|
||||||
|
|
||||||
|
- in `stack_orchestrator/data/container-build/cerc-my-new-stack/build.sh` add:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Build the my-new-stack image
|
||||||
|
source ${CERC_CONTAINER_BASE_DIR}/build-base.sh
|
||||||
|
docker build -t cerc/my-new-stack:local -f ${CERC_REPO_BASE_DIR}/my-new-stack/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/my-new-stack
|
||||||
|
```
|
||||||
|
|
||||||
|
- in `stack_orchestrator/data/compose/docker-compose-my-new-stack.yml` add:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: "3.2"
|
||||||
|
|
||||||
|
services:
|
||||||
|
my-new-stack:
|
||||||
|
image: cerc/my-new-stack:local
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "0.0.0.0:3000:3000"
|
||||||
|
```
|
||||||
|
|
||||||
|
- in `stack_orchestrator/data/repository-list.txt` add:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
github.com/my-org/my-new-stack
|
||||||
|
```
|
||||||
|
whereby that repository contains your source code and a `Dockerfile`, and matches the `repos:` field in the `stack.yml`.
|
||||||
|
|
||||||
|
- in `stack_orchestrator/data/container-image-list.txt` add:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cerc/my-new-stack
|
||||||
|
```
|
||||||
|
|
||||||
|
- in `stack_orchestrator/data/pod-list.txt` add:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
my-new-stack
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, the following commands will fetch, build, and deploy you app:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
laconic-so --stack my-new-stack setup-repositories
|
||||||
|
laconic-so --stack my-new-stack build-containers
|
||||||
|
laconic-so --stack my-new-stack deploy-system up
|
||||||
|
```
|
@ -6,7 +6,7 @@ Sub-commands and flags
|
|||||||
|
|
||||||
Clone a single repository:
|
Clone a single repository:
|
||||||
```
|
```
|
||||||
$ laconic-so setup-repositories --include cerc-io/go-ethereum
|
$ laconic-so setup-repositories --include github.com/cerc-io/go-ethereum
|
||||||
```
|
```
|
||||||
Clone the repositories for a stack:
|
Clone the repositories for a stack:
|
||||||
```
|
```
|
||||||
@ -51,7 +51,7 @@ $ laconic-so build-npms --include <package-name>
|
|||||||
```
|
```
|
||||||
e.g.
|
e.g.
|
||||||
```
|
```
|
||||||
$ laconic-so build-npms --include laconic-sdk
|
$ laconic-so build-npms --include registry-sdk
|
||||||
```
|
```
|
||||||
Build the packages for a stack:
|
Build the packages for a stack:
|
||||||
```
|
```
|
||||||
|
9
docs/fetching-containers.md
Normal file
9
docs/fetching-containers.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Fetching pre-built container images
|
||||||
|
When Stack Orchestrator deploys a stack containing a suite of one or more containers it expects images for those containers to be on the local machine with a tag of the form `<image-name>:local` Images for these containers can be built from source (and optionally base container images from public registries) with the `build-containers` subcommand.
|
||||||
|
|
||||||
|
However, the task of building a large number of containers from source may consume considerable time and machine resources. This is where the `fetch-containers` subcommand steps in. It is designed to work exactly like `build-containers` but instead the images, pre-built, are fetched from an image registry then re-tagged for deployment. It can be used in place of `build-containers` for any stack provided the necessary containers, built for the local machine architecture (e.g. arm64 or x86-64) have already been published in an image registry.
|
||||||
|
## Usage
|
||||||
|
To use `fetch-containers`, provide an image registry path, a username and token/password with read access to the registry, and optionally specify `--force-local-overwrite`. If this argument is not specified, if there is already a locally built or previously fetched image for a stack container on the machine, it will not be overwritten and a warning issued.
|
||||||
|
```
|
||||||
|
$ laconic-so --stack mobymask-v3-demo fetch-containers --image-registry git.vdb.to/cerc-io --registry-username <registry-user> --registry-token <registry-token> --force-local-overwrite
|
||||||
|
```
|
80
docs/gitea-with-laconicd-fixturenet.md
Normal file
80
docs/gitea-with-laconicd-fixturenet.md
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
# Gitea x NPMs X Laconicd
|
||||||
|
|
||||||
|
Deploy a local Gitea server, publish NPM packages to it, then use those packages to build a Laconicd fixturenet. Demonstrates several components of the Laconic stack
|
||||||
|
|
||||||
|
### Build and Deploy Gitea
|
||||||
|
|
||||||
|
```bash
|
||||||
|
laconic-so --stack build-support build-containers
|
||||||
|
laconic-so --stack package-registry setup-repositories
|
||||||
|
laconic-so --stack package-registry build-containers
|
||||||
|
laconic-so --stack package-registry deploy up
|
||||||
|
```
|
||||||
|
|
||||||
|
These commands can take awhile. Eventually, some instructions and a token will output. Set `CERC_NPM_AUTH_TOKEN`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export CERC_NPM_AUTH_TOKEN=<your-token>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configure the hostname gitea.local
|
||||||
|
|
||||||
|
How to do this depends on your operating system but usually involves editing a `hosts` file. For example, on Linux add this line to the file `/etc/hosts` (needs sudo):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
127.0.0.1 gitea.local
|
||||||
|
```
|
||||||
|
|
||||||
|
Test with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ping gitea.local
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
PING gitea.local (127.0.0.1) 56(84) bytes of data.
|
||||||
|
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.147 ms
|
||||||
|
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.033 ms
|
||||||
|
```
|
||||||
|
|
||||||
|
Although not necessary in order to build and publish packages, you can now access the Gitea web interface at: [http://gitea.local:3000](http://gitea.local:3000) using these credentials: `gitea_admin/admin1234` (Note: please properly secure Gitea if public internet access is allowed).
|
||||||
|
|
||||||
|
### Build npm Packages
|
||||||
|
|
||||||
|
Clone the required repositories:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
laconic-so --stack fixturenet-laconicd setup-repositories
|
||||||
|
```
|
||||||
|
|
||||||
|
Build and publish the npm packages:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
laconic-so --stack fixturenet-laconicd build-npms
|
||||||
|
```
|
||||||
|
|
||||||
|
Navigate to the Gitea console and switch to the `cerc-io` user then find the `Packages` tab to confirm that these two npm packages have been published:
|
||||||
|
|
||||||
|
- `@cerc-io/laconic-registry-cli`
|
||||||
|
- `@cerc-io/registry-sdk`
|
||||||
|
|
||||||
|
### Build and deploy fixturenet containers
|
||||||
|
|
||||||
|
```bash
|
||||||
|
laconic-so --stack fixturenet-laconicd build-containers
|
||||||
|
laconic-so --stack fixturenet-laconicd deploy up
|
||||||
|
```
|
||||||
|
|
||||||
|
Check the logs:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
laconic-so --stack fixturenet-laconicd deploy logs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test with the registry CLI
|
||||||
|
|
||||||
|
```bash
|
||||||
|
laconic-so --stack fixturenet-laconicd deploy exec cli "laconic registry status"
|
||||||
|
```
|
||||||
|
|
||||||
|
Try additional CLI commands, documented [here](https://github.com/cerc-io/laconic-registry-cli#operations).
|
27
docs/k8s-deployment-enhancements.md
Normal file
27
docs/k8s-deployment-enhancements.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# K8S Deployment Enhancements
|
||||||
|
## Controlling pod placement
|
||||||
|
The placement of pods created as part of a stack deployment can be controlled to either avoid certain nodes, or require certain nodes.
|
||||||
|
### Pod/Node Affinity
|
||||||
|
Node affinity rules applied to pods target node labels. The effect is that a pod can only be placed on a node having the specified label value. Note that other pods that do not have any node affinity rules can also be placed on those same nodes. Thus node affinity for a pod controls where that pod can be placed, but does not control where other pods are placed.
|
||||||
|
|
||||||
|
Node affinity for stack pods is specified in the deployment's `spec.yml` file as follows:
|
||||||
|
```
|
||||||
|
node-affinities:
|
||||||
|
- label: nodetype
|
||||||
|
value: typeb
|
||||||
|
```
|
||||||
|
This example denotes that the stack's pods should only be placed on nodes that have the label `nodetype` with value `typeb`.
|
||||||
|
### Node Taint Toleration
|
||||||
|
K8s nodes can be given one or more "taints". These are special fields (distinct from labels) with a name (key) and optional value.
|
||||||
|
When placing pods, the k8s scheduler will only assign a pod to a tainted node if the pod posesses a corresponding "toleration".
|
||||||
|
This is metadata associated with the pod that specifies that the pod "tolerates" a given taint.
|
||||||
|
Therefore taint toleration provides a mechanism by which only certain pods can be placed on specific nodes, and provides a complementary mechanism to node affinity.
|
||||||
|
|
||||||
|
Taint toleration for stack pods is specified in the deployment's `spec.yml` file as follows:
|
||||||
|
```
|
||||||
|
node-tolerations:
|
||||||
|
- key: nodetype
|
||||||
|
value: typeb
|
||||||
|
```
|
||||||
|
This example denotes that the stack's pods will tolerate a taint: `nodetype=typeb`
|
||||||
|
|
@ -1,183 +0,0 @@
|
|||||||
# Running a laconicd fixturenet with console
|
|
||||||
|
|
||||||
The following tutorial explains the steps to run a laconicd fixturenet with CLI and web console that displays records in the registry. It is designed as an introduction to Stack Orchestrator and to showcase one component of the Laconic Stack. Prior to Stack Orchestrator, the following 4 repositories had to be cloned and setup manually:
|
|
||||||
|
|
||||||
- https://github.com/cerc-io/laconicd
|
|
||||||
- https://github.com/cerc-io/laconic-sdk
|
|
||||||
- https://github.com/cerc-io/laconic-registry-cli
|
|
||||||
- https://github.com/cerc-io/laconic-console
|
|
||||||
|
|
||||||
Now, with Stack Orchestrator, it is a few quick commands. Additionally, the `docker` and `docker compose` integration on the back-end allows the stack to easily persist, facilitating workflows.
|
|
||||||
|
|
||||||
## Setup laconic-so
|
|
||||||
|
|
||||||
To avoid hiccups on Mac M1/M2 and any local machine nuances that may affect the user experience, this tutorial is focused on using a fresh Digital Ocean (DO) droplet with similar specs:
|
|
||||||
16 GB Memory / 8 Intel vCPUs / 160 GB Disk.
|
|
||||||
|
|
||||||
1. Login to the droplet as root (either by SSH key or password set in the DO console)
|
|
||||||
|
|
||||||
```
|
|
||||||
ssh root@IP
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Get the install script, give it executable permissions, and run it:
|
|
||||||
|
|
||||||
```
|
|
||||||
curl -o install.sh https://raw.githubusercontent.com/cerc-io/stack-orchestrator/main/scripts/quick-install-ubuntu.sh
|
|
||||||
```
|
|
||||||
```
|
|
||||||
chmod +x install.sh
|
|
||||||
```
|
|
||||||
```
|
|
||||||
bash install.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Confirm docker was installed and activate the changes in `~/.profile`:
|
|
||||||
|
|
||||||
```
|
|
||||||
docker run hello-world
|
|
||||||
```
|
|
||||||
```
|
|
||||||
source ~/.profile
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Verify installation:
|
|
||||||
|
|
||||||
```
|
|
||||||
laconic-so version
|
|
||||||
```
|
|
||||||
|
|
||||||
## Setup the laconic fixturenet stack
|
|
||||||
|
|
||||||
1. Get the repositories
|
|
||||||
|
|
||||||
```
|
|
||||||
laconic-so --stack fixturenet-laconic-loaded setup-repositories --include cerc-io/laconicd,cerc-io/laconic-sdk,cerc-io/laconic-registry-cli,cerc-io/laconic-console
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Set this environment variable to the Laconic self-hosted Gitea instance:
|
|
||||||
|
|
||||||
```
|
|
||||||
export CERC_NPM_REGISTRY_URL=https://git.vdb.to/api/packages/cerc-io/npm/
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Build the containers:
|
|
||||||
|
|
||||||
```
|
|
||||||
laconic-so --stack fixturenet-laconic-loaded build-containers
|
|
||||||
```
|
|
||||||
|
|
||||||
It's possible to run into an `ESOCKETTIMEDOUT` error, e.g., `error An unexpected error occurred: "https://registry.yarnpkg.com/@material-ui/icons/-/icons-4.11.3.tgz: ESOCKETTIMEDOUT"`. This may happen even if you have a great internet connection. In that case, re-run the `build-containers` command.
|
|
||||||
|
|
||||||
4. Set this environment variable to your droplet's IP address:
|
|
||||||
|
|
||||||
```
|
|
||||||
export LACONIC_HOSTED_ENDPOINT=http://<your-IP>
|
|
||||||
```
|
|
||||||
|
|
||||||
5. Deploy the stack:
|
|
||||||
|
|
||||||
```
|
|
||||||
laconic-so --stack fixturenet-laconic-loaded deploy up
|
|
||||||
```
|
|
||||||
|
|
||||||
6. Check the logs:
|
|
||||||
|
|
||||||
```
|
|
||||||
laconic-so --stack fixturenet-laconic-loaded deploy logs
|
|
||||||
```
|
|
||||||
|
|
||||||
You'll see output from `laconicd` and the block height should be >1 to confirm it is running:
|
|
||||||
|
|
||||||
```
|
|
||||||
laconic-5cd0a80c1442c3044c8b295d26426bae-laconicd-1 | 9:29PM INF indexed block exents height=12 module=txindex server=node
|
|
||||||
laconic-5cd0a80c1442c3044c8b295d26426bae-laconicd-1 | 9:30PM INF Timed out dur=4976.960115 height=13 module=consensus round=0 server=node step=1
|
|
||||||
laconic-5cd0a80c1442c3044c8b295d26426bae-laconicd-1 | 9:30PM INF received proposal module=consensus proposal={"Type":32,"block_id":{"hash":"D26C088A711F912ADB97888C269F628DA33153795621967BE44DCB43C3D03CA4","parts":{"hash":"22411A20B7F14CDA33244420FBDDAF24450C0628C7A06034FF22DAC3699DDCC8","total":1}},"height":13,"pol_round":-1,"round":0,"signature":"DEuqnaQmvyYbUwckttJmgKdpRu6eVm9i+9rQ1pIrV2PidkMNdWRZBLdmNghkIrUzGbW8Xd7UVJxtLRmwRASgBg==","timestamp":"2023-04-18T21:30:01.49450663Z"} server=node
|
|
||||||
laconic-5cd0a80c1442c3044c8b295d26426bae-laconicd-1 | 9:30PM INF received complete proposal block hash=D26C088A711F912ADB97888C269F628DA33153795621967BE44DCB43C3D03CA4 height=13 module=consensus server=node
|
|
||||||
laconic-5cd0a80c1442c3044c8b295d26426bae-laconicd-1 | 9:30PM INF finalizing commit of block hash={} height=13 module=consensus num_txs=0 root=1A8CA1AF139CCC80EC007C6321D8A63A46A793386EE2EDF9A5CA0AB2C90728B7 server=node
|
|
||||||
laconic-5cd0a80c1442c3044c8b295d26426bae-laconicd-1 | 9:30PM INF minted coins from module account amount=2059730459416582643aphoton from=mint module=x/bank
|
|
||||||
laconic-5cd0a80c1442c3044c8b295d26426bae-laconicd-1 | 9:30PM INF executed block height=13 module=state num_invalid_txs=0 num_valid_txs=0 server=node
|
|
||||||
laconic-5cd0a80c1442c3044c8b295d26426bae-laconicd-1 | 9:30PM INF commit synced commit=436F6D6D697449447B5B363520313037203630203232372039352038352032303820313334203231392032303520313433203130372031343920313431203139203139322038362031323720362031383520323533203137362031333820313735203135392031383620323334203135382031323120313431203230342037335D3A447D
|
|
||||||
laconic-5cd0a80c1442c3044c8b295d26426bae-laconicd-1 | 9:30PM INF committed state app_hash=416B3CE35F55D086DBCD8F6B958D13C0567F06B9FDB08AAF9FBAEA9E798DCC49 height=13 module=state num_txs=0 server=node
|
|
||||||
laconic-5cd0a80c1442c3044c8b295d26426bae-laconicd-1 | 9:30PM INF indexed block exents height=13 module=txindex server=node
|
|
||||||
```
|
|
||||||
|
|
||||||
7. Confirm operation of the registry CLI:
|
|
||||||
|
|
||||||
```
|
|
||||||
laconic-so --stack fixturenet-laconic-loaded deploy exec cli "laconic cns status"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Configure Digital Ocean firewall
|
|
||||||
|
|
||||||
Let's open some ports.
|
|
||||||
|
|
||||||
1. In the Digital Ocean web console, navigate to your droplet's main page. Select the "Networking" tab and scroll down to "Firewall".
|
|
||||||
|
|
||||||
2. Get the port for the running console:
|
|
||||||
|
|
||||||
```
|
|
||||||
echo http://IP:$(laconic-so --stack fixturenet-laconic-loaded deploy port laconic-console 80 | cut -d ':' -f 2)
|
|
||||||
```
|
|
||||||
```
|
|
||||||
http://IP:32778
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Go back to the Digital Ocean web console and set an Inbound Rule for Custom TCP of the above port:
|
|
||||||
|
|
||||||
- `32778` in this example, but yours will be different.
|
|
||||||
- do the same for port `9473`
|
|
||||||
|
|
||||||
Additional ports will need to be opened depending on your application. Ensure you add your droplet to this new Firewall and wait a minute or so for the update to propagate.
|
|
||||||
|
|
||||||
4. Navigate to http://IP:port and ensure laconic-console is functioning as expected:
|
|
||||||
|
|
||||||
- ensure you are connected to `laconicd`; no error message should pop up;
|
|
||||||
- the wifi symbol in the bottom right should have a green check mark beside it
|
|
||||||
- navigate to the status tab; it should display similar/identical information
|
|
||||||
- navigate to the config tab, you'll see something like (with your IP):
|
|
||||||
|
|
||||||
```
|
|
||||||
wns
|
|
||||||
webui http://68.183.195.210:9473/console
|
|
||||||
server http://68.183.195.210:9473/api
|
|
||||||
```
|
|
||||||
|
|
||||||
## Publish and query a sample record to the registry
|
|
||||||
|
|
||||||
1. The following command will create a bond and publish a record:
|
|
||||||
|
|
||||||
```
|
|
||||||
laconic-so --stack fixturenet-laconic-loaded deploy exec cli ./scripts/create-demo-records.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
You'll get an output like:
|
|
||||||
|
|
||||||
```
|
|
||||||
Balance is: 99998999999999998999600000
|
|
||||||
Created bond with id: dd88e8d6f9567b32b28e70552aea4419c5dd3307ebae85a284d1fe38904e301a
|
|
||||||
Published demo-record-1.yml with id: bafyreierh3xnfivexlscdwubvczmddsnf46uytyfvrbdhkjzztvsz6ruly
|
|
||||||
```
|
|
||||||
|
|
||||||
The sample record we deployed looks like:
|
|
||||||
|
|
||||||
```
|
|
||||||
TODO
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Return to the laconic-console
|
|
||||||
|
|
||||||
- the published record should now be viewable
|
|
||||||
- explore it for more information
|
|
||||||
- click on the link that opens the GraphQL console
|
|
||||||
- the query is pre-loaded, click the button to run it
|
|
||||||
- inspect the output
|
|
||||||
|
|
||||||
3. Try out additional CLI commands
|
|
||||||
|
|
||||||
- these are documented [here](https://github.com/cerc-io/laconic-registry-cli#readme) and updates are forthcoming
|
|
||||||
- e.g,:
|
|
||||||
|
|
||||||
```
|
|
||||||
laconic-so --stack fixturenet-laconic-loaded deploy exec cli "laconic cns record list"
|
|
||||||
```
|
|
227
docs/laconicd-with-console.md
Normal file
227
docs/laconicd-with-console.md
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
# Running a laconicd fixturenet with console
|
||||||
|
|
||||||
|
The following tutorial explains the steps to run a laconicd fixturenet with CLI and web console that displays records in the registry. It is designed as an introduction to Stack Orchestrator and to showcase one component of the Laconic Stack. Prior to Stack Orchestrator, the following repositories had to be cloned and setup manually:
|
||||||
|
|
||||||
|
- https://git.vdb.to/cerc-io/laconicd
|
||||||
|
- https://git.vdb.to/cerc-io/laconic-registry-cli
|
||||||
|
- https://git.vdb.to/cerc-io/laconic-console
|
||||||
|
|
||||||
|
Now, with Stack Orchestrator, it is a few quick commands. Additionally, the `docker` and `docker compose` integration on the back-end allows the stack to easily persist, facilitating workflows.
|
||||||
|
|
||||||
|
## Setup laconic-so
|
||||||
|
|
||||||
|
To avoid hiccups on Mac M1/M2 and any local machine nuances that may affect the user experience, this tutorial is focused on using a fresh Digital Ocean (DO) droplet with similar specs:
|
||||||
|
16 GB Memory / 8 Intel vCPUs / 160 GB Disk.
|
||||||
|
|
||||||
|
1. Login to the droplet as root (either by SSH key or password set in the DO console)
|
||||||
|
```
|
||||||
|
ssh root@IP
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Get the install script, give it executable permissions, and run it:
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -o install.sh https://raw.githubusercontent.com/cerc-io/stack-orchestrator/main/scripts/quick-install-linux.sh
|
||||||
|
```
|
||||||
|
```
|
||||||
|
chmod +x install.sh
|
||||||
|
```
|
||||||
|
```
|
||||||
|
bash install.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Confirm docker was installed and activate the changes in `~/.profile`:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run hello-world
|
||||||
|
```
|
||||||
|
```
|
||||||
|
source ~/.profile
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Verify installation:
|
||||||
|
|
||||||
|
```
|
||||||
|
laconic-so version
|
||||||
|
```
|
||||||
|
|
||||||
|
## Setup the laconic fixturenet stack
|
||||||
|
|
||||||
|
1. Get the repositories
|
||||||
|
|
||||||
|
```
|
||||||
|
laconic-so --stack fixturenet-laconic-loaded setup-repositories --include git.vdb.to/cerc-io/laconicd
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Build the containers:
|
||||||
|
|
||||||
|
```
|
||||||
|
laconic-so --stack fixturenet-laconic-loaded build-containers
|
||||||
|
```
|
||||||
|
|
||||||
|
It's possible to run into an `ESOCKETTIMEDOUT` error, e.g., `error An unexpected error occurred: "https://registry.yarnpkg.com/@material-ui/icons/-/icons-4.11.3.tgz: ESOCKETTIMEDOUT"`. This may happen even if you have a great internet connection. In that case, re-run the `build-containers` command.
|
||||||
|
|
||||||
|
|
||||||
|
1. Set this environment variable to your droplet's IP address or fully qualified DNS host name if it has one:
|
||||||
|
|
||||||
|
```
|
||||||
|
export BACKEND_ENDPOINT=http://<your-IP-or-hostname>:9473
|
||||||
|
```
|
||||||
|
e.g.
|
||||||
|
```
|
||||||
|
export BACKEND_ENDPOINT=http://my-test-server.example.com:9473
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Create a deployment directory for the stack:
|
||||||
|
```
|
||||||
|
laconic-so --stack fixturenet-laconic-loaded deploy init --output laconic-loaded.spec --map-ports-to-host any-same --config LACONIC_HOSTED_ENDPOINT=$BACKEND_ENDPOINT
|
||||||
|
|
||||||
|
# Update port mapping in the laconic-loaded.spec file to resolve port conflicts on host if any
|
||||||
|
```
|
||||||
|
```
|
||||||
|
laconic-so --stack fixturenet-laconic-loaded deploy create --deployment-dir laconic-loaded-deployment --spec-file laconic-loaded.spec
|
||||||
|
```
|
||||||
|
2. Start the stack:
|
||||||
|
|
||||||
|
```
|
||||||
|
laconic-so deployment --dir laconic-loaded-deployment start
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Check the logs:
|
||||||
|
|
||||||
|
```
|
||||||
|
laconic-so deployment --dir laconic-loaded-deployment logs
|
||||||
|
```
|
||||||
|
|
||||||
|
You'll see output from `laconicd` and the block height should be >1 to confirm it is running:
|
||||||
|
|
||||||
|
```
|
||||||
|
laconicd-1 | 6:12AM INF indexed block events height=16 module=txindex
|
||||||
|
laconicd-1 | 6:12AM INF Timed out dur=2993.893332 height=17 module=consensus round=0 step=RoundStepNewHeight
|
||||||
|
laconicd-1 | 6:12AM INF received proposal module=consensus proposal="Proposal{17/0 (E15D03C180CE607AE8340A1325A0C134DFB4E1ADD992E173C701EBD362523267:1:DF138772FEF0, -1) 6A6F3B0A42B3 @ 2024-07-25T06:12:31.952967053Z}" proposer=86970D950BC9C16F3991A52D9C6DC55BA478A7C6
|
||||||
|
laconicd-1 | 6:12AM INF received complete proposal block hash=E15D03C180CE607AE8340A1325A0C134DFB4E1ADD992E173C701EBD362523267 height=17 module=consensus
|
||||||
|
laconicd-1 | 6:12AM INF finalizing commit of block hash=E15D03C180CE607AE8340A1325A0C134DFB4E1ADD992E173C701EBD362523267 height=17 module=consensus num_txs=0 root=AF4941107DC718ED1425E77A3DC7F1154FB780B7A7DE20288DC43442203527E3
|
||||||
|
laconicd-1 | 6:12AM INF finalized block block_app_hash=26A665360BB1EE64E54F97F2A5AB7F621B33A86D9896574000C05DE63F43F788 height=17 module=state num_txs_res=0 num_val_updates=0
|
||||||
|
laconicd-1 | 6:12AM INF executed block app_hash=26A665360BB1EE64E54F97F2A5AB7F621B33A86D9896574000C05DE63F43F788 height=17 module=state
|
||||||
|
laconicd-1 | 6:12AM INF committed state block_app_hash=AF4941107DC718ED1425E77A3DC7F1154FB780B7A7DE20288DC43442203527E3 height=17 module=state
|
||||||
|
laconicd-1 | 6:12AM INF indexed block events height=17 module=txindex
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Confirm operation of the registry CLI:
|
||||||
|
|
||||||
|
```
|
||||||
|
laconic-so deployment --dir laconic-loaded-deployment exec cli "laconic registry status"
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"version": "0.3.0",
|
||||||
|
"node": {
|
||||||
|
"id": "6e072894aa1f5d9535a1127a0d7a7f8e65100a2c",
|
||||||
|
"network": "laconic_9000-1",
|
||||||
|
"moniker": "localtestnet"
|
||||||
|
},
|
||||||
|
"sync": {
|
||||||
|
"latestBlockHash": "260102C283D0411CFBA0270F7DC182650FFCA737A2F6F652A985F6065696F590",
|
||||||
|
"latestBlockHeight": "49",
|
||||||
|
"latestBlockTime": "2024-07-25 06:14:05.626744215 +0000 UTC",
|
||||||
|
"catchingUp": false
|
||||||
|
},
|
||||||
|
"validator": {
|
||||||
|
"address": "86970D950BC9C16F3991A52D9C6DC55BA478A7C6",
|
||||||
|
"votingPower": "1000000000000000"
|
||||||
|
},
|
||||||
|
"validators": [
|
||||||
|
{
|
||||||
|
"address": "86970D950BC9C16F3991A52D9C6DC55BA478A7C6",
|
||||||
|
"votingPower": "1000000000000000",
|
||||||
|
"proposerPriority": "0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"numPeers": "0",
|
||||||
|
"peers": [],
|
||||||
|
"diskUsage": "688K"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configure Digital Ocean firewall
|
||||||
|
|
||||||
|
(Note this step may not be necessary depending on the droplet image used)
|
||||||
|
|
||||||
|
Let's open some ports.
|
||||||
|
|
||||||
|
1. In the Digital Ocean web console, navigate to your droplet's main page. Select the "Networking" tab and scroll down to "Firewall".
|
||||||
|
|
||||||
|
2. Get the port for the running console:
|
||||||
|
|
||||||
|
```
|
||||||
|
echo http://IP:$(laconic-so --stack fixturenet-laconic-loaded deploy port laconic-console 80 | cut -d ':' -f 2)
|
||||||
|
```
|
||||||
|
```
|
||||||
|
http://IP:32778
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Go back to the Digital Ocean web console and set an Inbound Rule for Custom TCP of the above port:
|
||||||
|
|
||||||
|
- `32778` in this example, but yours will be different.
|
||||||
|
- do the same for port `9473`
|
||||||
|
|
||||||
|
Additional ports will need to be opened depending on your application. Ensure you add your droplet to this new Firewall and wait a minute or so for the update to propagate.
|
||||||
|
|
||||||
|
4. Navigate to http://IP:port and ensure laconic-console is functioning as expected:
|
||||||
|
|
||||||
|
- ensure you are connected to `laconicd`; no error message should pop up;
|
||||||
|
- the wifi symbol in the bottom right should have a green check mark beside it
|
||||||
|
- navigate to the status tab; it should display similar/identical information
|
||||||
|
- navigate to the config tab, you'll see something like (with your IP):
|
||||||
|
|
||||||
|
```
|
||||||
|
wns
|
||||||
|
webui http://68.183.195.210:9473/console
|
||||||
|
server http://68.183.195.210:9473/api
|
||||||
|
```
|
||||||
|
|
||||||
|
## Publish and query a sample record to the registry
|
||||||
|
|
||||||
|
1. The following command will create a bond and publish a record:
|
||||||
|
|
||||||
|
```
|
||||||
|
laconic-so deployment --dir laconic-loaded-deployment exec cli ./scripts/create-demo-records.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
You'll get an output like:
|
||||||
|
|
||||||
|
```
|
||||||
|
Balance is: 9.9999e+25
|
||||||
|
Created bond with id: dd88e8d6f9567b32b28e70552aea4419c5dd3307ebae85a284d1fe38904e301a
|
||||||
|
Published demo-record-1.yml with id: bafyreierh3xnfivexlscdwubvczmddsnf46uytyfvrbdhkjzztvsz6ruly
|
||||||
|
```
|
||||||
|
|
||||||
|
The sample record we deployed looks like:
|
||||||
|
|
||||||
|
```
|
||||||
|
record:
|
||||||
|
type: WebsiteRegistrationRecord
|
||||||
|
url: 'https://cerc.io'
|
||||||
|
repo_registration_record_cid: QmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D
|
||||||
|
build_artifact_cid: QmP8jTG1m9GSDJLCbeWhVSVgEzCPPwXRdCRuJtQ5Tz9Kc9
|
||||||
|
tls_cert_cid: QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR
|
||||||
|
version: 1.0.23
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Return to the laconic-console
|
||||||
|
|
||||||
|
- the published record should now be viewable
|
||||||
|
- explore it for more information
|
||||||
|
- click on the link that opens the GraphQL console
|
||||||
|
- the query is pre-loaded, click the button to run it
|
||||||
|
- inspect the output
|
||||||
|
|
||||||
|
3. Try out additional CLI commands
|
||||||
|
|
||||||
|
- these are documented [here](https://git.vdb.to/cerc-io/laconic-registry-cli#readme) and updates are forthcoming
|
||||||
|
- e.g,:
|
||||||
|
|
||||||
|
```
|
||||||
|
laconic-so deployment --dir laconic-loaded-deployment exec cli "laconic registry record list"
|
||||||
|
```
|
@ -1,7 +1,6 @@
|
|||||||
# Specification
|
# Specification
|
||||||
|
|
||||||
(note this page is out of date)
|
Note: this page is out of date (but still useful) - it will no longer be useful once stacks are [decoupled from the tool functionality](https://git.vdb.to/cerc-io/stack-orchestrator/issues/315).
|
||||||
|
|
||||||
|
|
||||||
## Implementation
|
## Implementation
|
||||||
|
|
||||||
|
64
docs/webapp.md
Normal file
64
docs/webapp.md
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
### Building and Running Webapps
|
||||||
|
|
||||||
|
It is possible to build and run Next.js webapps using the `build-webapp` and `run-webapp` subcommands.
|
||||||
|
|
||||||
|
To make it easier to build once and deploy into different environments and with different configuration,
|
||||||
|
compilation and static page generation are separated in the `build-webapp` and `run-webapp` steps.
|
||||||
|
|
||||||
|
This offers much more flexibilty than standard Next.js build methods, since any environment variables accessed
|
||||||
|
via `process.env`, whether for pages or for API, will have values drawn from their runtime deployment environment,
|
||||||
|
not their build environment.
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
Building usually requires no additional configuration. By default, the Next.js version specified in `package.json`
|
||||||
|
is used, and either `yarn` or `npm` will be used automatically depending on which lock files are present. These
|
||||||
|
can be overidden with the build arguments `CERC_NEXT_VERSION` and `CERC_BUILD_TOOL` respectively. For example: `--extra-build-args "--build-arg CERC_NEXT_VERSION=13.4.12"`
|
||||||
|
|
||||||
|
**Example**:
|
||||||
|
```
|
||||||
|
$ cd ~/cerc
|
||||||
|
$ git clone git@git.vdb.to:cerc-io/test-progressive-web-app.git
|
||||||
|
$ laconic-so build-webapp --source-repo ~/cerc/test-progressive-web-app
|
||||||
|
...
|
||||||
|
|
||||||
|
Built host container for ~/cerc/test-progressive-web-app with tag:
|
||||||
|
|
||||||
|
cerc/test-progressive-web-app:local
|
||||||
|
|
||||||
|
To test locally run:
|
||||||
|
|
||||||
|
laconic-so run-webapp --image cerc/test-progressive-web-app:local --env-file /path/to/environment.env
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running
|
||||||
|
|
||||||
|
With `run-webapp` a new container will be launched on the local machine, with runtime configuration provided by `--env-file` (if specified) and published on an available port. Multiple instances can be launched with different configuration.
|
||||||
|
|
||||||
|
**Example**:
|
||||||
|
```
|
||||||
|
# Production env
|
||||||
|
$ laconic-so run-webapp --image cerc/test-progressive-web-app:local --env-file /path/to/environment/production.env
|
||||||
|
|
||||||
|
Image: cerc/test-progressive-web-app:local
|
||||||
|
ID: 4c6e893bf436b3e91a2b92ce37e30e499685131705700bd92a90d2eb14eefd05
|
||||||
|
URL: http://localhost:32768
|
||||||
|
|
||||||
|
# Dev env
|
||||||
|
$ laconic-so run-webapp --image cerc/test-progressive-web-app:local --env-file /path/to/environment/dev.env
|
||||||
|
|
||||||
|
Image: cerc/test-progressive-web-app:local
|
||||||
|
ID: 9ab96494f563aafb6c057d88df58f9eca81b90f8721a4e068493a289a976051c
|
||||||
|
URL: http://localhost:32769
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deploying
|
||||||
|
|
||||||
|
Use the subcommand `deploy-webapp create` to make a deployment directory that can be subsequently deployed to a Kubernetes cluster.
|
||||||
|
Example commands are shown below, assuming that the webapp container image `cerc/test-progressive-web-app:local` has already been built:
|
||||||
|
```
|
||||||
|
$ laconic-so deploy-webapp create --kube-config ~/kubectl/k8s-kubeconfig.yaml --image-registry registry.digitalocean.com/laconic-registry --deployment-dir webapp-k8s-deployment --image cerc/test-progressive-web-app:local --url https://test-pwa-app.hosting.laconic.com/ --env-file test-webapp.env
|
||||||
|
$ laconic-so deployment --dir webapp-k8s-deployment push-images
|
||||||
|
$ laconic-so deployment --dir webapp-k8s-deployment start
|
||||||
|
```
|
@ -1,6 +1,15 @@
|
|||||||
python-decouple>=3.6
|
python-decouple>=3.8
|
||||||
GitPython>=3.1.27
|
python-dotenv==1.0.0
|
||||||
tqdm>=4.64.0
|
GitPython>=3.1.32
|
||||||
python-on-whales>=0.58.0
|
tqdm>=4.65.0
|
||||||
click>=8.1.3
|
python-on-whales>=0.64.0
|
||||||
pyyaml>=6.0
|
click>=8.1.6
|
||||||
|
PyYAML>=6.0.1
|
||||||
|
ruamel.yaml>=0.17.32
|
||||||
|
pydantic==1.10.9
|
||||||
|
tomli==2.0.1
|
||||||
|
validators==0.22.0
|
||||||
|
kubernetes>=28.1.0
|
||||||
|
humanfriendly>=10.0
|
||||||
|
python-gnupg>=0.5.2
|
||||||
|
requests>=2.3.2
|
||||||
|
44
scripts/cloud-init-dev-mode-install.yaml
Normal file
44
scripts/cloud-init-dev-mode-install.yaml
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#cloud-config
|
||||||
|
|
||||||
|
# Used for easily testing stacks-in-development on cloud platforms
|
||||||
|
# Assumes Ubuntu, edit the last line if targeting a different OS
|
||||||
|
|
||||||
|
# Once SSH'd into the server, run:
|
||||||
|
# `$ cd stack-orchestrator`
|
||||||
|
# `$ git checkout <branch>
|
||||||
|
# `$ ./scripts/developer-mode-setup.sh`
|
||||||
|
# `$ source ./venv/bin/activate`
|
||||||
|
|
||||||
|
# Followed by the stack instructions.
|
||||||
|
|
||||||
|
package_update: true
|
||||||
|
package_upgrade: true
|
||||||
|
|
||||||
|
groups:
|
||||||
|
- docker
|
||||||
|
|
||||||
|
system_info:
|
||||||
|
default_user:
|
||||||
|
groups: [ docker ]
|
||||||
|
|
||||||
|
packages:
|
||||||
|
- apt-transport-https
|
||||||
|
- ca-certificates
|
||||||
|
- curl
|
||||||
|
- jq
|
||||||
|
- git
|
||||||
|
- gnupg
|
||||||
|
- lsb-release
|
||||||
|
- unattended-upgrades
|
||||||
|
- python3.10-venv
|
||||||
|
- pip
|
||||||
|
|
||||||
|
runcmd:
|
||||||
|
- mkdir -p /etc/apt/keyrings
|
||||||
|
- curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||||
|
- echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||||
|
- apt-get update
|
||||||
|
- apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||||
|
- systemctl enable docker
|
||||||
|
- systemctl start docker
|
||||||
|
- git clone https://git.vdb.to/cerc-io/stack-orchestrator.git /home/ubuntu/stack-orchestrator
|
35
scripts/cloud-init-user-mode-install.yaml
Normal file
35
scripts/cloud-init-user-mode-install.yaml
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#cloud-config
|
||||||
|
|
||||||
|
# Used for installing Stack Orchestrator on platforms that support `cloud-init`
|
||||||
|
# Tested on Ubuntu
|
||||||
|
|
||||||
|
package_update: true
|
||||||
|
package_upgrade: true
|
||||||
|
|
||||||
|
groups:
|
||||||
|
- docker
|
||||||
|
|
||||||
|
system_info:
|
||||||
|
default_user:
|
||||||
|
groups: [ docker ]
|
||||||
|
|
||||||
|
packages:
|
||||||
|
- apt-transport-https
|
||||||
|
- ca-certificates
|
||||||
|
- curl
|
||||||
|
- jq
|
||||||
|
- git
|
||||||
|
- gnupg
|
||||||
|
- lsb-release
|
||||||
|
- unattended-upgrades
|
||||||
|
|
||||||
|
runcmd:
|
||||||
|
- mkdir -p /etc/apt/keyrings
|
||||||
|
- curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||||
|
- echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||||
|
- apt-get update
|
||||||
|
- apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||||
|
- systemctl enable docker
|
||||||
|
- systemctl start docker
|
||||||
|
- curl -L -o /usr/local/bin/laconic-so https://git.vdb.to/cerc-io/stack-orchestrator/releases/download/latest/laconic-so
|
||||||
|
- chmod +x /usr/local/bin/laconic-so
|
@ -1,6 +1,6 @@
|
|||||||
build_tag_file_name=./app/data/build_tag.txt
|
build_tag_file_name=./stack_orchestrator/data/build_tag.txt
|
||||||
echo "# This file should be re-generated running: scripts/create_build_tag_file.sh script" > $build_tag_file_name
|
echo "# This file should be re-generated running: scripts/create_build_tag_file.sh script" > $build_tag_file_name
|
||||||
product_version_string=$( tail -1 ./app/data/version.txt )
|
product_version_string=$( tail -1 ./stack_orchestrator/data/version.txt )
|
||||||
commit_string=$( git rev-parse --short HEAD )
|
commit_string=$( git rev-parse --short HEAD )
|
||||||
timestamp_string=$(date +'%Y%m%d%H%M')
|
timestamp_string=$(date +'%Y%m%d%H%M')
|
||||||
build_tag_string=${product_version_string}-${commit_string}-${timestamp_string}
|
build_tag_string=${product_version_string}-${commit_string}-${timestamp_string}
|
||||||
|
19
scripts/quick-deploy-test.sh
Executable file
19
scripts/quick-deploy-test.sh
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Beginnings of a script to quickly spin up and test a deployment
|
||||||
|
if [[ -n "$CERC_SCRIPT_DEBUG" ]]; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
if [[ -n "$1" ]]; then
|
||||||
|
stack_name=$1
|
||||||
|
else
|
||||||
|
stack_name="test"
|
||||||
|
fi
|
||||||
|
spec_file_name="${stack_name}-spec.yml"
|
||||||
|
deployment_dir_name="${stack_name}-deployment"
|
||||||
|
rm -f ${spec_file_name}
|
||||||
|
rm -rf ${deployment_dir_name}
|
||||||
|
laconic-so --stack ${stack_name} deploy --deploy-to compose init --output ${spec_file_name}
|
||||||
|
laconic-so --stack ${stack_name} deploy --deploy-to compose create --deployment-dir ${deployment_dir_name} --spec-file ${spec_file_name}
|
||||||
|
#laconic-so deployment --dir ${deployment_dir_name} start
|
||||||
|
#laconic-so deployment --dir ${deployment_dir_name} ps
|
||||||
|
#laconic-so deployment --dir ${deployment_dir_name} stop
|
@ -5,6 +5,9 @@ fi
|
|||||||
|
|
||||||
install_dir=~/bin
|
install_dir=~/bin
|
||||||
|
|
||||||
|
# Skip the package install stuff if so directed
|
||||||
|
if ! [[ -n "$CERC_SO_INSTALL_SKIP_PACKAGES" ]]; then
|
||||||
|
|
||||||
# First display a reasonable warning to the user unless run with -y
|
# First display a reasonable warning to the user unless run with -y
|
||||||
if ! [[ $# -eq 1 && $1 == "-y" ]]; then
|
if ! [[ $# -eq 1 && $1 == "-y" ]]; then
|
||||||
echo "**************************************************************************************"
|
echo "**************************************************************************************"
|
||||||
@ -28,12 +31,43 @@ fi
|
|||||||
# Check python3 is available
|
# Check python3 is available
|
||||||
# Check machine resources are sufficient
|
# Check machine resources are sufficient
|
||||||
|
|
||||||
|
# Determine if we are on Debian or Ubuntu
|
||||||
|
linux_distro=$(lsb_release -a 2>/dev/null | grep "^Distributor ID:" | cut -f 2)
|
||||||
|
# Some systems don't have lsb_release installed (e.g. ChromeOS) and so we try to
|
||||||
|
# use /etc/os-release instead
|
||||||
|
if [[ -z "$linux_distro" ]]; then
|
||||||
|
if [[ -f "/etc/os-release" ]]; then
|
||||||
|
distro_name_string=$(grep "^NAME=" /etc/os-release | cut -d '=' -f 2)
|
||||||
|
if [[ $distro_name_string =~ Debian ]]; then
|
||||||
|
linux_distro="Debian"
|
||||||
|
elif [[ $distro_name_string =~ Ubuntu ]]; then
|
||||||
|
linux_distro="Ubuntu"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Failed to identify distro: /etc/os-release doesn't exist"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
case $linux_distro in
|
||||||
|
Debian)
|
||||||
|
echo "Installing docker for Debian"
|
||||||
|
;;
|
||||||
|
Ubuntu)
|
||||||
|
echo "Installing docker for Ubuntu"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "ERROR: Detected unknown distribution $linux_distro, can't install docker"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
# dismiss the popups
|
# dismiss the popups
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
## https://docs.docker.com/engine/install/ubuntu/
|
## https://docs.docker.com/engine/install/ubuntu/
|
||||||
|
## https://docs.docker.com/engine/install/debian/
|
||||||
## https://superuser.com/questions/518859/ignore-packages-that-are-not-currently-installed-when-using-apt-get-remove1
|
## https://superuser.com/questions/518859/ignore-packages-that-are-not-currently-installed-when-using-apt-get-remove1
|
||||||
packages_to_remove="docker docker-engine docker.io containerd runc"
|
packages_to_remove="docker docker-engine docker.io containerd runc docker-compose docker-doc podman-docker"
|
||||||
installed_packages_to_remove=""
|
installed_packages_to_remove=""
|
||||||
for package_to_remove in $(echo $packages_to_remove); do
|
for package_to_remove in $(echo $packages_to_remove); do
|
||||||
$(dpkg --info $package_to_remove &> /dev/null)
|
$(dpkg --info $package_to_remove &> /dev/null)
|
||||||
@ -65,10 +99,25 @@ sudo apt -y install curl
|
|||||||
sudo apt -y install ca-certificates gnupg
|
sudo apt -y install ca-certificates gnupg
|
||||||
|
|
||||||
# Add dockerco package repository
|
# Add dockerco package repository
|
||||||
|
# For reasons not obvious, the dockerco instructions for installation on
|
||||||
|
# Debian and Ubuntu are slightly different here
|
||||||
|
case $linux_distro in
|
||||||
|
Debian)
|
||||||
|
sudo install -m 0755 -d /etc/apt/keyrings
|
||||||
|
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||||
|
sudo chmod a+r /etc/apt/keyrings/docker.gpg
|
||||||
|
;;
|
||||||
|
Ubuntu)
|
||||||
sudo mkdir -m 0755 -p /etc/apt/keyrings
|
sudo mkdir -m 0755 -p /etc/apt/keyrings
|
||||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "ERROR: Detected unknown distribution $linux_distro, can't install docker"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
echo \
|
echo \
|
||||||
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
|
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/${linux_distro,,} \
|
||||||
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
|
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
|
||||||
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||||
|
|
||||||
@ -82,13 +131,20 @@ sudo apt -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin d
|
|||||||
# Allow the current user to use Docker
|
# Allow the current user to use Docker
|
||||||
sudo usermod -aG docker $USER
|
sudo usermod -aG docker $USER
|
||||||
|
|
||||||
|
# End of long if block: Skip the package install stuff if so directed
|
||||||
|
fi
|
||||||
|
|
||||||
echo "**************************************************************************************"
|
echo "**************************************************************************************"
|
||||||
echo "Installing laconic-so"
|
echo "Installing laconic-so"
|
||||||
# install latest `laconic-so`
|
# install latest `laconic-so`
|
||||||
|
distribution_url=https://git.vdb.to/cerc-io/stack-orchestrator/releases/download/latest/laconic-so
|
||||||
install_filename=${install_dir}/laconic-so
|
install_filename=${install_dir}/laconic-so
|
||||||
mkdir -p ${install_dir}
|
mkdir -p ${install_dir}
|
||||||
curl -L -o ${install_filename} https://github.com/cerc-io/stack-orchestrator/releases/latest/download/laconic-so
|
curl -L -o ${install_filename} ${distribution_url}
|
||||||
chmod +x ${install_filename}
|
chmod +x ${install_filename}
|
||||||
|
# Set up config file for self-update feature
|
||||||
|
mkdir ~/.laconic-so
|
||||||
|
echo "distribution-url: ${distribution_url}" > ~/.laconic-so/config.yml
|
||||||
|
|
||||||
echo "**************************************************************************************"
|
echo "**************************************************************************************"
|
||||||
# Check if our PATH line is already there
|
# Check if our PATH line is already there
|
13
setup.py
13
setup.py
@ -4,28 +4,29 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|||||||
long_description = fh.read()
|
long_description = fh.read()
|
||||||
with open("requirements.txt", "r", encoding="utf-8") as fh:
|
with open("requirements.txt", "r", encoding="utf-8") as fh:
|
||||||
requirements = fh.read()
|
requirements = fh.read()
|
||||||
|
with open("stack_orchestrator/data/version.txt", "r", encoding="utf-8") as fh:
|
||||||
|
version = fh.readlines()[-1].strip(" \n")
|
||||||
setup(
|
setup(
|
||||||
name='laconic-stack-orchestrator',
|
name='laconic-stack-orchestrator',
|
||||||
version='1.0.12',
|
version=version,
|
||||||
author='Cerc',
|
author='Cerc',
|
||||||
author_email='info@cerc.io',
|
author_email='info@cerc.io',
|
||||||
license='GNU Affero General Public License',
|
license='GNU Affero General Public License',
|
||||||
description='Orchestrates deployment of the Laconic stack',
|
description='Orchestrates deployment of the Laconic stack',
|
||||||
long_description=long_description,
|
long_description=long_description,
|
||||||
long_description_content_type="text/markdown",
|
long_description_content_type="text/markdown",
|
||||||
url='https://github.com/cerc-io/stack-orchestrator',
|
url='https://git.vdb.to/cerc-io/stack-orchestrator',
|
||||||
py_modules=['cli', 'app'],
|
py_modules=['stack_orchestrator'],
|
||||||
packages=find_packages(),
|
packages=find_packages(),
|
||||||
install_requires=[requirements],
|
install_requires=[requirements],
|
||||||
python_requires='>=3.7',
|
python_requires='>=3.7',
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
# See: https://github.com/pypa/setuptools/issues/1806
|
package_data={'': ['data/**']},
|
||||||
package_data={'': ['data/*', 'data/*/*', 'data/*/*/*', 'data/*/*/*/*', 'data/*/*/*/*/*']},
|
|
||||||
classifiers=[
|
classifiers=[
|
||||||
"Programming Language :: Python :: 3.8",
|
"Programming Language :: Python :: 3.8",
|
||||||
"Operating System :: OS Independent",
|
"Operating System :: OS Independent",
|
||||||
],
|
],
|
||||||
entry_points={
|
entry_points={
|
||||||
'console_scripts': ['laconic-so=cli:cli'],
|
'console_scripts': ['laconic-so=stack_orchestrator.main:cli'],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright © 2022, 2023 Cerc
|
# Copyright © 2022, 2023 Vulcanize
|
||||||
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU Affero General Public License as published by
|
# it under the terms of the GNU Affero General Public License as published by
|
||||||
@ -15,7 +15,8 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from .deploy_system import get_stack_status
|
from stack_orchestrator.deploy.deploy import get_stack_status
|
||||||
|
from decouple import config
|
||||||
|
|
||||||
|
|
||||||
def get_stack(config, stack):
|
def get_stack(config, stack):
|
||||||
@ -62,10 +63,20 @@ class package_registry_stack(base_stack):
|
|||||||
self.url = "http://gitea.local:3000/api/packages/cerc-io/npm/"
|
self.url = "http://gitea.local:3000/api/packages/cerc-io/npm/"
|
||||||
else:
|
else:
|
||||||
# If not, print a message about how to start it and return fail to the caller
|
# If not, print a message about how to start it and return fail to the caller
|
||||||
print("ERROR: The package-registry stack is not running, and no external registry specified with CERC_NPM_REGISTRY_URL")
|
print("ERROR: The package-registry stack is not running, and no external registry "
|
||||||
|
"specified with CERC_NPM_REGISTRY_URL")
|
||||||
print("ERROR: Start the local package registry with: laconic-so --stack package-registry deploy-system up")
|
print("ERROR: Start the local package registry with: laconic-so --stack package-registry deploy-system up")
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_url(self):
|
def get_url(self):
|
||||||
return self.url
|
return self.url
|
||||||
|
|
||||||
|
|
||||||
|
def get_npm_registry_url():
|
||||||
|
# If an auth token is not defined, we assume the default should be the cerc registry
|
||||||
|
# If an auth token is defined, we assume the local gitea should be used.
|
||||||
|
default_npm_registry_url = "http://gitea.local:3000/api/packages/cerc-io/npm/" if config(
|
||||||
|
"CERC_NPM_AUTH_TOKEN", default=None
|
||||||
|
) else "https://git.vdb.to/api/packages/cerc-io/npm/"
|
||||||
|
return config("CERC_NPM_REGISTRY_URL", default=default_npm_registry_url)
|
0
stack_orchestrator/build/__init__.py
Normal file
0
stack_orchestrator/build/__init__.py
Normal file
183
stack_orchestrator/build/build_containers.py
Normal file
183
stack_orchestrator/build/build_containers.py
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
# Copyright © 2022, 2023 Vulcanize
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Builds or pulls containers for the system components
|
||||||
|
|
||||||
|
# env vars:
|
||||||
|
# CERC_REPO_BASE_DIR defaults to ~/cerc
|
||||||
|
|
||||||
|
# TODO: display the available list of containers; allow re-build of either all or specific containers
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from decouple import config
|
||||||
|
import subprocess
|
||||||
|
import click
|
||||||
|
from pathlib import Path
|
||||||
|
from stack_orchestrator.opts import opts
|
||||||
|
from stack_orchestrator.util import include_exclude_check, stack_is_external, error_exit
|
||||||
|
from stack_orchestrator.base import get_npm_registry_url
|
||||||
|
from stack_orchestrator.build.build_types import BuildContext
|
||||||
|
from stack_orchestrator.build.publish import publish_image
|
||||||
|
from stack_orchestrator.build.build_util import get_containers_in_scope
|
||||||
|
|
||||||
|
# TODO: find a place for this
|
||||||
|
# epilog="Config provided either in .env or settings.ini or env vars: CERC_REPO_BASE_DIR (defaults to ~/cerc)"
|
||||||
|
|
||||||
|
|
||||||
|
def make_container_build_env(dev_root_path: str,
|
||||||
|
container_build_dir: str,
|
||||||
|
debug: bool,
|
||||||
|
force_rebuild: bool,
|
||||||
|
extra_build_args: str):
|
||||||
|
container_build_env = {
|
||||||
|
"CERC_NPM_REGISTRY_URL": get_npm_registry_url(),
|
||||||
|
"CERC_GO_AUTH_TOKEN": config("CERC_GO_AUTH_TOKEN", default=""),
|
||||||
|
"CERC_NPM_AUTH_TOKEN": config("CERC_NPM_AUTH_TOKEN", default=""),
|
||||||
|
"CERC_REPO_BASE_DIR": dev_root_path,
|
||||||
|
"CERC_CONTAINER_BASE_DIR": container_build_dir,
|
||||||
|
"CERC_HOST_UID": f"{os.getuid()}",
|
||||||
|
"CERC_HOST_GID": f"{os.getgid()}",
|
||||||
|
"DOCKER_BUILDKIT": config("DOCKER_BUILDKIT", default="0")
|
||||||
|
}
|
||||||
|
container_build_env.update({"CERC_SCRIPT_DEBUG": "true"} if debug else {})
|
||||||
|
container_build_env.update({"CERC_FORCE_REBUILD": "true"} if force_rebuild else {})
|
||||||
|
container_build_env.update({"CERC_CONTAINER_EXTRA_BUILD_ARGS": extra_build_args} if extra_build_args else {})
|
||||||
|
docker_host_env = os.getenv("DOCKER_HOST")
|
||||||
|
if docker_host_env:
|
||||||
|
container_build_env.update({"DOCKER_HOST": docker_host_env})
|
||||||
|
|
||||||
|
return container_build_env
|
||||||
|
|
||||||
|
|
||||||
|
def process_container(build_context: BuildContext) -> bool:
|
||||||
|
if not opts.o.quiet:
|
||||||
|
print(f"Building: {build_context.container}")
|
||||||
|
|
||||||
|
default_container_tag = f"{build_context.container}:local"
|
||||||
|
build_context.container_build_env.update({"CERC_DEFAULT_CONTAINER_IMAGE_TAG": default_container_tag})
|
||||||
|
|
||||||
|
# Check if this is in an external stack
|
||||||
|
if stack_is_external(build_context.stack):
|
||||||
|
container_parent_dir = Path(build_context.stack).parent.parent.joinpath("container-build")
|
||||||
|
temp_build_dir = container_parent_dir.joinpath(build_context.container.replace("/", "-"))
|
||||||
|
temp_build_script_filename = temp_build_dir.joinpath("build.sh")
|
||||||
|
# Now check if the container exists in the external stack.
|
||||||
|
if not temp_build_script_filename.exists():
|
||||||
|
# If not, revert to building an internal container
|
||||||
|
container_parent_dir = build_context.container_build_dir
|
||||||
|
else:
|
||||||
|
container_parent_dir = build_context.container_build_dir
|
||||||
|
|
||||||
|
build_dir = container_parent_dir.joinpath(build_context.container.replace("/", "-"))
|
||||||
|
build_script_filename = build_dir.joinpath("build.sh")
|
||||||
|
|
||||||
|
if opts.o.verbose:
|
||||||
|
print(f"Build script filename: {build_script_filename}")
|
||||||
|
if os.path.exists(build_script_filename):
|
||||||
|
build_command = build_script_filename.as_posix()
|
||||||
|
else:
|
||||||
|
if opts.o.verbose:
|
||||||
|
print(f"No script file found: {build_script_filename}, using default build script")
|
||||||
|
repo_dir = build_context.container.split('/')[1]
|
||||||
|
# TODO: make this less of a hack -- should be specified in some metadata somewhere
|
||||||
|
# Check if we have a repo for this container. If not, set the context dir to the container-build subdir
|
||||||
|
repo_full_path = os.path.join(build_context.dev_root_path, repo_dir)
|
||||||
|
repo_dir_or_build_dir = repo_full_path if os.path.exists(repo_full_path) else build_dir
|
||||||
|
build_command = os.path.join(build_context.container_build_dir,
|
||||||
|
"default-build.sh") + f" {default_container_tag} {repo_dir_or_build_dir}"
|
||||||
|
if not opts.o.dry_run:
|
||||||
|
# No PATH at all causes failures with podman.
|
||||||
|
if "PATH" not in build_context.container_build_env:
|
||||||
|
build_context.container_build_env["PATH"] = os.environ["PATH"]
|
||||||
|
if opts.o.verbose:
|
||||||
|
print(f"Executing: {build_command} with environment: {build_context.container_build_env}")
|
||||||
|
build_result = subprocess.run(build_command, shell=True, env=build_context.container_build_env)
|
||||||
|
if opts.o.verbose:
|
||||||
|
print(f"Return code is: {build_result.returncode}")
|
||||||
|
if build_result.returncode != 0:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print("Skipped")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@click.command()
|
||||||
|
@click.option('--include', help="only build these containers")
|
||||||
|
@click.option('--exclude', help="don\'t build these containers")
|
||||||
|
@click.option("--force-rebuild", is_flag=True, default=False, help="Override dependency checking -- always rebuild")
|
||||||
|
@click.option("--extra-build-args", help="Supply extra arguments to build")
|
||||||
|
@click.option("--publish-images", is_flag=True, default=False, help="Publish the built images in the specified image registry")
|
||||||
|
@click.option("--image-registry", help="Specify the image registry for --publish-images")
|
||||||
|
@click.pass_context
|
||||||
|
def command(ctx, include, exclude, force_rebuild, extra_build_args, publish_images, image_registry):
|
||||||
|
'''build the set of containers required for a complete stack'''
|
||||||
|
|
||||||
|
local_stack = ctx.obj.local_stack
|
||||||
|
stack = ctx.obj.stack
|
||||||
|
|
||||||
|
# See: https://stackoverflow.com/questions/25389095/python-get-path-of-root-project-structure
|
||||||
|
container_build_dir = Path(__file__).absolute().parent.parent.joinpath("data", "container-build")
|
||||||
|
|
||||||
|
if local_stack:
|
||||||
|
dev_root_path = os.getcwd()[0:os.getcwd().rindex("stack-orchestrator")]
|
||||||
|
print(f'Local stack dev_root_path (CERC_REPO_BASE_DIR) overridden to: {dev_root_path}')
|
||||||
|
else:
|
||||||
|
dev_root_path = os.path.expanduser(config("CERC_REPO_BASE_DIR", default="~/cerc"))
|
||||||
|
|
||||||
|
if not opts.o.quiet:
|
||||||
|
print(f'Dev Root is: {dev_root_path}')
|
||||||
|
|
||||||
|
if not os.path.isdir(dev_root_path):
|
||||||
|
print('Dev root directory doesn\'t exist, creating')
|
||||||
|
|
||||||
|
if publish_images:
|
||||||
|
if not image_registry:
|
||||||
|
error_exit("--image-registry must be supplied with --publish-images")
|
||||||
|
|
||||||
|
containers_in_scope = get_containers_in_scope(stack)
|
||||||
|
|
||||||
|
container_build_env = make_container_build_env(dev_root_path,
|
||||||
|
container_build_dir,
|
||||||
|
opts.o.debug,
|
||||||
|
force_rebuild,
|
||||||
|
extra_build_args)
|
||||||
|
|
||||||
|
for container in containers_in_scope:
|
||||||
|
if include_exclude_check(container, include, exclude):
|
||||||
|
|
||||||
|
build_context = BuildContext(
|
||||||
|
stack,
|
||||||
|
container,
|
||||||
|
container_build_dir,
|
||||||
|
container_build_env,
|
||||||
|
dev_root_path
|
||||||
|
)
|
||||||
|
result = process_container(build_context)
|
||||||
|
if result:
|
||||||
|
if publish_images:
|
||||||
|
publish_image(f"{container}:local", image_registry)
|
||||||
|
else:
|
||||||
|
print(f"Error running build for {build_context.container}")
|
||||||
|
if not opts.o.continue_on_error:
|
||||||
|
error_exit("container build failed and --continue-on-error not set, exiting")
|
||||||
|
sys.exit(1)
|
||||||
|
else:
|
||||||
|
print("****** Container Build Error, continuing because --continue-on-error is set")
|
||||||
|
else:
|
||||||
|
if opts.o.verbose:
|
||||||
|
print(f"Excluding: {container}")
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright © 2022, 2023 Cerc
|
# Copyright © 2022, 2023 Vulcanize
|
||||||
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU Affero General Public License as published by
|
# it under the terms of the GNU Affero General Public License as published by
|
||||||
@ -25,15 +25,17 @@ from decouple import config
|
|||||||
import click
|
import click
|
||||||
import importlib.resources
|
import importlib.resources
|
||||||
from python_on_whales import docker, DockerException
|
from python_on_whales import docker, DockerException
|
||||||
from .base import get_stack
|
from stack_orchestrator.base import get_stack
|
||||||
from .util import include_exclude_check, get_parsed_stack_config
|
from stack_orchestrator.util import include_exclude_check, get_parsed_stack_config
|
||||||
|
|
||||||
builder_js_image_name = "cerc/builder-js:local"
|
builder_js_image_name = "cerc/builder-js:local"
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
@click.option('--include', help="only build these packages")
|
@click.option('--include', help="only build these packages")
|
||||||
@click.option('--exclude', help="don\'t build these packages")
|
@click.option('--exclude', help="don\'t build these packages")
|
||||||
@click.option("--force-rebuild", is_flag=True, default=False, help="Override existing target package version check -- force rebuild")
|
@click.option("--force-rebuild", is_flag=True, default=False,
|
||||||
|
help="Override existing target package version check -- force rebuild")
|
||||||
@click.option("--extra-build-args", help="Supply extra arguments to build")
|
@click.option("--extra-build-args", help="Supply extra arguments to build")
|
||||||
@click.pass_context
|
@click.pass_context
|
||||||
def command(ctx, include, exclude, force_rebuild, extra_build_args):
|
def command(ctx, include, exclude, force_rebuild, extra_build_args):
|
||||||
@ -81,7 +83,7 @@ def command(ctx, include, exclude, force_rebuild, extra_build_args):
|
|||||||
os.makedirs(build_root_path)
|
os.makedirs(build_root_path)
|
||||||
|
|
||||||
# See: https://stackoverflow.com/a/20885799/1701505
|
# See: https://stackoverflow.com/a/20885799/1701505
|
||||||
from . import data
|
from stack_orchestrator import data
|
||||||
with importlib.resources.open_text(data, "npm-package-list.txt") as package_list_file:
|
with importlib.resources.open_text(data, "npm-package-list.txt") as package_list_file:
|
||||||
all_packages = package_list_file.read().splitlines()
|
all_packages = package_list_file.read().splitlines()
|
||||||
|
|
29
stack_orchestrator/build/build_types.py
Normal file
29
stack_orchestrator/build/build_types.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# Copyright © 2024 Vulcanize
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Mapping
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class BuildContext:
|
||||||
|
stack: str
|
||||||
|
container: str
|
||||||
|
container_build_dir: Path
|
||||||
|
container_build_env: Mapping[str,str]
|
||||||
|
dev_root_path: str
|
||||||
|
|
41
stack_orchestrator/build/build_util.py
Normal file
41
stack_orchestrator/build/build_util.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# Copyright © 2024 Vulcanize
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import importlib.resources
|
||||||
|
|
||||||
|
from stack_orchestrator.opts import opts
|
||||||
|
from stack_orchestrator.util import get_parsed_stack_config, warn_exit
|
||||||
|
|
||||||
|
|
||||||
|
def get_containers_in_scope(stack: str):
|
||||||
|
|
||||||
|
containers_in_scope = []
|
||||||
|
if stack:
|
||||||
|
stack_config = get_parsed_stack_config(stack)
|
||||||
|
if "containers" not in stack_config or stack_config["containers"] is None:
|
||||||
|
warn_exit(f"stack {stack} does not define any containers")
|
||||||
|
containers_in_scope = stack_config['containers']
|
||||||
|
else:
|
||||||
|
# See: https://stackoverflow.com/a/20885799/1701505
|
||||||
|
from stack_orchestrator import data
|
||||||
|
with importlib.resources.open_text(data, "container-image-list.txt") as container_list_file:
|
||||||
|
containers_in_scope = container_list_file.read().splitlines()
|
||||||
|
|
||||||
|
if opts.o.verbose:
|
||||||
|
print(f'Containers: {containers_in_scope}')
|
||||||
|
if stack:
|
||||||
|
print(f"Stack: {stack}")
|
||||||
|
|
||||||
|
return containers_in_scope
|
143
stack_orchestrator/build/build_webapp.py
Normal file
143
stack_orchestrator/build/build_webapp.py
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
# Copyright © 2022, 2023 Vulcanize
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Builds webapp containers
|
||||||
|
|
||||||
|
# env vars:
|
||||||
|
# CERC_REPO_BASE_DIR defaults to ~/cerc
|
||||||
|
|
||||||
|
# TODO: display the available list of containers; allow re-build of either all or specific containers
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from decouple import config
|
||||||
|
import click
|
||||||
|
from pathlib import Path
|
||||||
|
from stack_orchestrator.build import build_containers
|
||||||
|
from stack_orchestrator.deploy.webapp.util import determine_base_container, TimedLogger
|
||||||
|
from stack_orchestrator.build.build_types import BuildContext
|
||||||
|
|
||||||
|
def create_env_file(env_vars, repo_root):
|
||||||
|
env_file_path = os.path.join(repo_root, '.env')
|
||||||
|
with open(env_file_path, 'w') as env_file:
|
||||||
|
for key, value in env_vars.items():
|
||||||
|
env_file.write(f"{key}={value}\n")
|
||||||
|
return env_file_path
|
||||||
|
|
||||||
|
@click.command()
|
||||||
|
@click.option('--base-container')
|
||||||
|
@click.option('--source-repo', help="directory containing the webapp to build", required=True)
|
||||||
|
@click.option("--force-rebuild", is_flag=True, default=False, help="Override dependency checking -- always rebuild")
|
||||||
|
@click.option("--extra-build-args", help="Supply extra arguments to build")
|
||||||
|
@click.option("--tag", help="Container tag (default: cerc/<app_name>:local)")
|
||||||
|
@click.option("--env", help="Environment variables for webapp (format: KEY1=VALUE1,KEY2=VALUE2)", default="")
|
||||||
|
@click.pass_context
|
||||||
|
def command(ctx, base_container, source_repo, force_rebuild, extra_build_args, tag, env):
|
||||||
|
'''build the specified webapp container'''
|
||||||
|
logger = TimedLogger()
|
||||||
|
|
||||||
|
quiet = ctx.obj.quiet
|
||||||
|
debug = ctx.obj.debug
|
||||||
|
verbose = ctx.obj.verbose
|
||||||
|
local_stack = ctx.obj.local_stack
|
||||||
|
stack = ctx.obj.stack
|
||||||
|
|
||||||
|
# See: https://stackoverflow.com/questions/25389095/python-get-path-of-root-project-structure
|
||||||
|
container_build_dir = Path(__file__).absolute().parent.parent.joinpath("data", "container-build")
|
||||||
|
|
||||||
|
if local_stack:
|
||||||
|
dev_root_path = os.getcwd()[0:os.getcwd().rindex("stack-orchestrator")]
|
||||||
|
logger.log(f'Local stack dev_root_path (CERC_REPO_BASE_DIR) overridden to: {dev_root_path}')
|
||||||
|
else:
|
||||||
|
dev_root_path = os.path.expanduser(config("CERC_REPO_BASE_DIR", default="~/cerc"))
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
logger.log(f'Dev Root is: {dev_root_path}')
|
||||||
|
|
||||||
|
if not base_container:
|
||||||
|
base_container = determine_base_container(source_repo)
|
||||||
|
|
||||||
|
# First build the base container.
|
||||||
|
container_build_env = build_containers.make_container_build_env(dev_root_path, container_build_dir, debug,
|
||||||
|
force_rebuild, extra_build_args)
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
logger.log(f"Building base container: {base_container}")
|
||||||
|
|
||||||
|
build_context_1 = BuildContext(
|
||||||
|
stack,
|
||||||
|
base_container,
|
||||||
|
container_build_dir,
|
||||||
|
container_build_env,
|
||||||
|
dev_root_path,
|
||||||
|
)
|
||||||
|
ok = build_containers.process_container(build_context_1)
|
||||||
|
if not ok:
|
||||||
|
logger.log("ERROR: Build failed.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
logger.log(f"Base container {base_container} build finished.")
|
||||||
|
|
||||||
|
# Now build the target webapp. We use the same build script, but with a different Dockerfile and work dir.
|
||||||
|
container_build_env["CERC_WEBAPP_BUILD_RUNNING"] = "true"
|
||||||
|
container_build_env["CERC_CONTAINER_BUILD_WORK_DIR"] = os.path.abspath(source_repo)
|
||||||
|
|
||||||
|
# Check if Dockerfile exists in the repository
|
||||||
|
repo_dockerfile = os.path.join(container_build_env["CERC_CONTAINER_BUILD_WORK_DIR"], "Dockerfile")
|
||||||
|
default_dockerfile = os.path.join(container_build_dir,
|
||||||
|
base_container.replace("/", "-"),
|
||||||
|
"Dockerfile.webapp")
|
||||||
|
|
||||||
|
if os.path.isfile(repo_dockerfile):
|
||||||
|
env_vars = {}
|
||||||
|
if env:
|
||||||
|
for pair in env.split(','):
|
||||||
|
key, value = pair.split('=')
|
||||||
|
env_vars[key.strip()] = value.strip()
|
||||||
|
|
||||||
|
container_build_env["CERC_CONTAINER_BUILD_DOCKERFILE"] = repo_dockerfile
|
||||||
|
|
||||||
|
# Create .env file with environment variables
|
||||||
|
env_file_path = create_env_file(env_vars, container_build_env["CERC_CONTAINER_BUILD_WORK_DIR"])
|
||||||
|
container_build_env["CERC_CONTAINER_BUILD_ENV_FILE"] = env_file_path
|
||||||
|
else:
|
||||||
|
container_build_env["CERC_CONTAINER_BUILD_DOCKERFILE"] = default_dockerfile
|
||||||
|
|
||||||
|
if not tag:
|
||||||
|
webapp_name = os.path.abspath(source_repo).split(os.path.sep)[-1]
|
||||||
|
tag = f"cerc/{webapp_name}:local"
|
||||||
|
|
||||||
|
container_build_env["CERC_CONTAINER_BUILD_TAG"] = tag
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
logger.log(f"Building app container: {tag}")
|
||||||
|
|
||||||
|
build_context_2 = BuildContext(
|
||||||
|
stack,
|
||||||
|
base_container,
|
||||||
|
container_build_dir,
|
||||||
|
container_build_env,
|
||||||
|
dev_root_path,
|
||||||
|
)
|
||||||
|
ok = build_containers.process_container(build_context_2)
|
||||||
|
if not ok:
|
||||||
|
logger.log("ERROR: Build failed.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
logger.log(f"App container {base_container} build finished.")
|
||||||
|
logger.log("build-webapp complete", show_step_time=False, show_total_time=True)
|
195
stack_orchestrator/build/fetch_containers.py
Normal file
195
stack_orchestrator/build/fetch_containers.py
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
# Copyright © 2024 Vulcanize
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import click
|
||||||
|
from dataclasses import dataclass
|
||||||
|
import json
|
||||||
|
import platform
|
||||||
|
from python_on_whales import DockerClient
|
||||||
|
from python_on_whales.components.manifest.cli_wrapper import ManifestCLI, ManifestList
|
||||||
|
from python_on_whales.utils import run
|
||||||
|
import requests
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from stack_orchestrator.opts import opts
|
||||||
|
from stack_orchestrator.util import include_exclude_check, error_exit
|
||||||
|
from stack_orchestrator.build.build_util import get_containers_in_scope
|
||||||
|
|
||||||
|
# Experimental fetch-container command
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class RegistryInfo:
|
||||||
|
registry: str
|
||||||
|
registry_username: str
|
||||||
|
registry_token: str
|
||||||
|
|
||||||
|
|
||||||
|
# Extending this code to support the --verbose option, cnosider contributing upstream
|
||||||
|
# https://github.com/gabrieldemarmiesse/python-on-whales/blob/master/python_on_whales/components/manifest/cli_wrapper.py#L129
|
||||||
|
class ExtendedManifestCLI(ManifestCLI):
|
||||||
|
def inspect_verbose(self, x: str) -> ManifestList:
|
||||||
|
"""Returns a Docker manifest list object."""
|
||||||
|
json_str = run(self.docker_cmd + ["manifest", "inspect", "--verbose", x])
|
||||||
|
return json.loads(json_str)
|
||||||
|
|
||||||
|
|
||||||
|
def _local_tag_for(container: str):
|
||||||
|
return f"{container}:local"
|
||||||
|
|
||||||
|
|
||||||
|
# See: https://docker-docs.uclv.cu/registry/spec/api/
|
||||||
|
# Emulate this:
|
||||||
|
# $ curl -u "my-username:my-token" -X GET "https://<container-registry-hostname>/v2/cerc-io/cerc/test-container/tags/list"
|
||||||
|
# {"name":"cerc-io/cerc/test-container","tags":["202402232130","202402232208"]}
|
||||||
|
def _get_tags_for_container(container: str, registry_info: RegistryInfo) -> List[str]:
|
||||||
|
# registry looks like: git.vdb.to/cerc-io
|
||||||
|
registry_parts = registry_info.registry.split("/")
|
||||||
|
url = f"https://{registry_parts[0]}/v2/{registry_parts[1]}/{container}/tags/list"
|
||||||
|
if opts.o.debug:
|
||||||
|
print(f"Fetching tags from: {url}")
|
||||||
|
response = requests.get(url, auth=(registry_info.registry_username, registry_info.registry_token))
|
||||||
|
if response.status_code == 200:
|
||||||
|
tag_info = response.json()
|
||||||
|
if opts.o.debug:
|
||||||
|
print(f"container tags list: {tag_info}")
|
||||||
|
tags_array = tag_info["tags"]
|
||||||
|
return tags_array
|
||||||
|
else:
|
||||||
|
error_exit(f"failed to fetch tags from image registry, status code: {response.status_code}")
|
||||||
|
|
||||||
|
|
||||||
|
def _find_latest(candidate_tags: List[str]):
|
||||||
|
# Lex sort should give us the latest first
|
||||||
|
sorted_candidates = sorted(candidate_tags)
|
||||||
|
if opts.o.debug:
|
||||||
|
print(f"sorted candidates: {sorted_candidates}")
|
||||||
|
return sorted_candidates[-1]
|
||||||
|
|
||||||
|
|
||||||
|
def _filter_for_platform(container: str,
|
||||||
|
registry_info: RegistryInfo,
|
||||||
|
tag_list: List[str]) -> List[str] :
|
||||||
|
filtered_tags = []
|
||||||
|
this_machine = platform.machine()
|
||||||
|
# Translate between Python and docker platform names
|
||||||
|
if this_machine == "x86_64":
|
||||||
|
this_machine = "amd64"
|
||||||
|
if this_machine == "aarch64":
|
||||||
|
this_machine = "arm64"
|
||||||
|
if opts.o.debug:
|
||||||
|
print(f"Python says the architecture is: {this_machine}")
|
||||||
|
docker = DockerClient()
|
||||||
|
for tag in tag_list:
|
||||||
|
remote_tag = f"{registry_info.registry}/{container}:{tag}"
|
||||||
|
manifest_cmd = ExtendedManifestCLI(docker.client_config)
|
||||||
|
manifest = manifest_cmd.inspect_verbose(remote_tag)
|
||||||
|
if opts.o.debug:
|
||||||
|
print(f"manifest: {manifest}")
|
||||||
|
image_architecture = manifest["Descriptor"]["platform"]["architecture"]
|
||||||
|
if opts.o.debug:
|
||||||
|
print(f"image_architecture: {image_architecture}")
|
||||||
|
if this_machine == image_architecture:
|
||||||
|
filtered_tags.append(tag)
|
||||||
|
if opts.o.debug:
|
||||||
|
print(f"Tags filtered for platform: {filtered_tags}")
|
||||||
|
return filtered_tags
|
||||||
|
|
||||||
|
|
||||||
|
def _get_latest_image(container: str, registry_info: RegistryInfo):
|
||||||
|
all_tags = _get_tags_for_container(container, registry_info)
|
||||||
|
tags_for_platform = _filter_for_platform(container, registry_info, all_tags)
|
||||||
|
if len(tags_for_platform) > 0:
|
||||||
|
latest_tag = _find_latest(tags_for_platform)
|
||||||
|
return f"{container}:{latest_tag}"
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _fetch_image(tag: str, registry_info: RegistryInfo):
|
||||||
|
docker = DockerClient()
|
||||||
|
remote_tag = f"{registry_info.registry}/{tag}"
|
||||||
|
if opts.o.debug:
|
||||||
|
print(f"Attempting to pull this image: {remote_tag}")
|
||||||
|
docker.image.pull(remote_tag)
|
||||||
|
|
||||||
|
|
||||||
|
def _exists_locally(container: str):
|
||||||
|
docker = DockerClient()
|
||||||
|
return docker.image.exists(_local_tag_for(container))
|
||||||
|
|
||||||
|
|
||||||
|
def _add_local_tag(remote_tag: str, registry: str, local_tag: str):
|
||||||
|
docker = DockerClient()
|
||||||
|
docker.image.tag(f"{registry}/{remote_tag}", local_tag)
|
||||||
|
|
||||||
|
|
||||||
|
@click.command()
|
||||||
|
@click.option('--include', help="only fetch these containers")
|
||||||
|
@click.option('--exclude', help="don\'t fetch these containers")
|
||||||
|
@click.option("--force-local-overwrite", is_flag=True, default=False, help="Overwrite a locally built image, if present")
|
||||||
|
@click.option("--image-registry", required=True, help="Specify the image registry to fetch from")
|
||||||
|
@click.option("--registry-username", required=True, help="Specify the image registry username")
|
||||||
|
@click.option("--registry-token", required=True, help="Specify the image registry access token")
|
||||||
|
@click.pass_context
|
||||||
|
def command(ctx, include, exclude, force_local_overwrite, image_registry, registry_username, registry_token):
|
||||||
|
'''EXPERIMENTAL: fetch the images for a stack from remote registry'''
|
||||||
|
|
||||||
|
registry_info = RegistryInfo(image_registry, registry_username, registry_token)
|
||||||
|
docker = DockerClient()
|
||||||
|
if not opts.o.quiet:
|
||||||
|
print("Logging into container registry:")
|
||||||
|
docker.login(registry_info.registry, registry_info.registry_username, registry_info.registry_token)
|
||||||
|
# Generate list of target containers
|
||||||
|
stack = ctx.obj.stack
|
||||||
|
containers_in_scope = get_containers_in_scope(stack)
|
||||||
|
all_containers_found = True
|
||||||
|
for container in containers_in_scope:
|
||||||
|
local_tag = _local_tag_for(container)
|
||||||
|
if include_exclude_check(container, include, exclude):
|
||||||
|
if opts.o.debug:
|
||||||
|
print(f"Processing: {container}")
|
||||||
|
# For each container, attempt to find the latest of a set of
|
||||||
|
# images with the correct name and platform in the specified registry
|
||||||
|
image_to_fetch = _get_latest_image(container, registry_info)
|
||||||
|
if not image_to_fetch:
|
||||||
|
print(f"Warning: no image found to fetch for container: {container}")
|
||||||
|
all_containers_found = False
|
||||||
|
continue
|
||||||
|
if opts.o.debug:
|
||||||
|
print(f"Fetching: {image_to_fetch}")
|
||||||
|
_fetch_image(image_to_fetch, registry_info)
|
||||||
|
# Now check if the target container already exists exists locally already
|
||||||
|
if (_exists_locally(container)):
|
||||||
|
if not opts.o.quiet:
|
||||||
|
print(f"Container image {container} already exists locally")
|
||||||
|
# if so, fail unless the user specified force-local-overwrite
|
||||||
|
if (force_local_overwrite):
|
||||||
|
# In that case remove the existing :local tag
|
||||||
|
if not opts.o.quiet:
|
||||||
|
print(f"Warning: overwriting local tag from this image: {container} because "
|
||||||
|
"--force-local-overwrite was specified")
|
||||||
|
else:
|
||||||
|
if not opts.o.quiet:
|
||||||
|
print(f"Skipping local tagging for this image: {container} because that would "
|
||||||
|
"overwrite an existing :local tagged image, use --force-local-overwrite to do so.")
|
||||||
|
continue
|
||||||
|
# Tag the fetched image with the :local tag
|
||||||
|
_add_local_tag(image_to_fetch, image_registry, local_tag)
|
||||||
|
else:
|
||||||
|
if opts.o.verbose:
|
||||||
|
print(f"Excluding: {container}")
|
||||||
|
if not all_containers_found:
|
||||||
|
print("Warning: couldn't find usable images for one or more containers, this stack will not deploy")
|
48
stack_orchestrator/build/publish.py
Normal file
48
stack_orchestrator/build/publish.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# Copyright © 2024 Vulcanize
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
from python_on_whales import DockerClient
|
||||||
|
|
||||||
|
from stack_orchestrator.opts import opts
|
||||||
|
from stack_orchestrator.util import error_exit
|
||||||
|
|
||||||
|
|
||||||
|
def _publish_tag_for_image(local_image_tag: str, remote_repo: str, version: str):
|
||||||
|
# Turns image tags of the form: foo/bar:local into remote.repo/org/bar:deploy
|
||||||
|
(image_name, image_version) = local_image_tag.split(":")
|
||||||
|
if image_version == "local":
|
||||||
|
return f"{remote_repo}/{image_name}:{version}"
|
||||||
|
else:
|
||||||
|
error_exit("Asked to publish a non-locally built image")
|
||||||
|
|
||||||
|
|
||||||
|
def publish_image(local_tag, registry):
|
||||||
|
if opts.o.verbose:
|
||||||
|
print(f"Publishing this image: {local_tag} to this registry: {registry}")
|
||||||
|
docker = DockerClient()
|
||||||
|
# Figure out the target image tag
|
||||||
|
# Eventually this version will be generated from the source repo state
|
||||||
|
# Using a timestemp is an intermediate step
|
||||||
|
version = datetime.now().strftime("%Y%m%d%H%M")
|
||||||
|
remote_tag = _publish_tag_for_image(local_tag, registry, version)
|
||||||
|
# Tag the image thus
|
||||||
|
if opts.o.debug:
|
||||||
|
print(f"Tagging {local_tag} to {remote_tag}")
|
||||||
|
docker.image.tag(local_tag, remote_tag)
|
||||||
|
# Push it to the desired registry
|
||||||
|
if opts.o.verbose:
|
||||||
|
print(f"Pushing image {remote_tag}")
|
||||||
|
docker.image.push(remote_tag)
|
27
stack_orchestrator/command_types.py
Normal file
27
stack_orchestrator/command_types.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# Copyright © 2023 Vulcanize
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class CommandOptions:
|
||||||
|
stack: str
|
||||||
|
quiet: bool = False
|
||||||
|
verbose: bool = False
|
||||||
|
dry_run: bool = False
|
||||||
|
local_stack: bool = False
|
||||||
|
debug: bool = False
|
||||||
|
continue_on_error: bool = False
|
41
stack_orchestrator/constants.py
Normal file
41
stack_orchestrator/constants.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# Copyright © 2023 Vulcanize
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
cluster_name_prefix = "laconic-"
|
||||||
|
stack_file_name = "stack.yml"
|
||||||
|
spec_file_name = "spec.yml"
|
||||||
|
config_file_name = "config.env"
|
||||||
|
deployment_file_name = "deployment.yml"
|
||||||
|
compose_dir_name = "compose"
|
||||||
|
compose_deploy_type = "compose"
|
||||||
|
k8s_kind_deploy_type = "k8s-kind"
|
||||||
|
k8s_deploy_type = "k8s"
|
||||||
|
cluster_id_key = "cluster-id"
|
||||||
|
kube_config_key = "kube-config"
|
||||||
|
deploy_to_key = "deploy-to"
|
||||||
|
network_key = "network"
|
||||||
|
http_proxy_key = "http-proxy"
|
||||||
|
image_registry_key = "image-registry"
|
||||||
|
configmaps_key = "configmaps"
|
||||||
|
resources_key = "resources"
|
||||||
|
volumes_key = "volumes"
|
||||||
|
security_key = "security"
|
||||||
|
annotations_key = "annotations"
|
||||||
|
labels_key = "labels"
|
||||||
|
replicas_key = "replicas"
|
||||||
|
node_affinities_key = "node-affinities"
|
||||||
|
node_tolerations_key = "node-tolerations"
|
||||||
|
kind_config_filename = "kind-config.yml"
|
||||||
|
kube_config_filename = "kubeconfig.yml"
|
0
stack_orchestrator/data/__init__.py
Normal file
0
stack_orchestrator/data/__init__.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
services:
|
||||||
|
registry:
|
||||||
|
image: registry:2.8
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
REGISTRY_LOG_LEVEL: ${REGISTRY_LOG_LEVEL}
|
||||||
|
volumes:
|
||||||
|
- config:/config:ro
|
||||||
|
- registry-data:/var/lib/registry
|
||||||
|
ports:
|
||||||
|
- "5000"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
config:
|
||||||
|
registry-data:
|
@ -0,0 +1,49 @@
|
|||||||
|
version: '3.2'
|
||||||
|
|
||||||
|
services:
|
||||||
|
# Deploys the core (UniswapV3Factory) contract
|
||||||
|
sushiswap-v3-core:
|
||||||
|
image: cerc/sushiswap-v3-core:local
|
||||||
|
restart: on-failure
|
||||||
|
env_file:
|
||||||
|
# Defaults
|
||||||
|
- ../config/contract-sushiswap/deployment-params.env
|
||||||
|
environment:
|
||||||
|
# Overrides
|
||||||
|
CERC_ETH_RPC_ENDPOINT: ${ETH_RPC_ENDPOINT}
|
||||||
|
CERC_CHAIN_ID: ${CHAIN_ID}
|
||||||
|
CERC_ACCOUNT_PRIVATE_KEY: ${ACCOUNT_PRIVATE_KEY}
|
||||||
|
CERC_DEPLOY: ${DEPLOY}
|
||||||
|
volumes:
|
||||||
|
- ../config/network/wait-for-it.sh:/app/wait-for-it.sh
|
||||||
|
- ../config/contract-sushiswap/deploy-core-contracts.sh:/app/deploy-core-contracts.sh
|
||||||
|
- sushiswap_core_deployment:/app/deployments/docker
|
||||||
|
command: ["bash", "-c", "/app/deploy-core-contracts.sh && tail -f"]
|
||||||
|
extra_hosts:
|
||||||
|
- "host.docker.internal:host-gateway"
|
||||||
|
|
||||||
|
# Deploys the periphery (NFPM, token, etc.) contracts
|
||||||
|
sushiswap-v3-periphery:
|
||||||
|
image: cerc/sushiswap-v3-periphery:local
|
||||||
|
restart: on-failure
|
||||||
|
env_file:
|
||||||
|
# Defaults
|
||||||
|
- ../config/contract-sushiswap/deployment-params.env
|
||||||
|
environment:
|
||||||
|
# Overrides
|
||||||
|
CERC_ETH_RPC_ENDPOINT: ${ETH_RPC_ENDPOINT}
|
||||||
|
CERC_CHAIN_ID: ${CHAIN_ID}
|
||||||
|
CERC_ACCOUNT_PRIVATE_KEY: ${ACCOUNT_PRIVATE_KEY}
|
||||||
|
CERC_DEPLOY: ${DEPLOY}
|
||||||
|
volumes:
|
||||||
|
- ../config/network/wait-for-it.sh:/app/wait-for-it.sh
|
||||||
|
- ../config/contract-sushiswap/deploy-periphery-contracts.sh:/app/deploy-periphery-contracts.sh
|
||||||
|
- sushiswap_core_deployment:/app/core-deployments/docker
|
||||||
|
- sushiswap_periphery_deployment:/app/deployments/docker
|
||||||
|
command: ["bash", "-c", "/app/deploy-periphery-contracts.sh && tail -f"]
|
||||||
|
extra_hosts:
|
||||||
|
- "host.docker.internal:host-gateway"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
sushiswap_core_deployment:
|
||||||
|
sushiswap_periphery_deployment:
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user