From 3de20175cd0776c46d7d1296b65f323b9a3c02f2 Mon Sep 17 00:00:00 2001 From: Paal Kvamme Date: Thu, 5 Aug 2021 07:06:17 +0000 Subject: [PATCH] Major overhaul of build pipelines. --- .dockerignore | 28 +- .gitignore | 1 + Makefile | 4 +- README.md | 50 ++- azure/ozcloud-bionic-osdu.yml | 37 ++ azure/ozcloud-bionic.yml | 37 ++ azure/ozcloud-buster-osdu.yml | 37 ++ azure/ozcloud-buster.yml | 37 ++ azure/ozcloud-centos7-osdu.yml | 37 ++ azure/ozcloud-centos7.yml | 37 ++ azure/ozcloud-centos8-coverage.yml | 31 ++ azure/ozcloud-centos8-osdu.yml | 37 ++ azure/ozcloud-centos8-vg.yml | 31 ++ azure/ozcloud-centos8.yml | 39 ++ azure/ozcloud-focal-osdu.yml | 37 ++ azure/ozcloud-focal.yml | 37 ++ azure/ozcloud-omega-osdu.yml | 37 ++ azure/ozcloud-omega.yml | 37 ++ azure/templates/build-steps.yml | 4 +- azure/templates/combo-build-steps.yml | 139 +++++++ azure/templates/combo-coverage-steps.yml | 120 ++++++ azure/templates/combo-valgrind-steps.yml | 134 +++++++ azure/templates/coverage-build-steps.yml | 18 +- azure/templates/valgrind-build-steps.yml | 17 +- doc/dockerstages.md | 84 +++++ doc/images/dockerstages-fig1.dot | 39 ++ doc/images/dockerstages-fig1.png | Bin 0 -> 112944 bytes native/sdglue/runtests.sh | 8 +- native/sdglue/setup.py | 2 +- native/src/Makefile | 10 +- native/src/test/test_api.cpp | 3 +- python/setup.py | 2 +- scripts/Dockerfile-bionic | 21 +- scripts/Dockerfile-buster | 16 +- scripts/Dockerfile-centos7 | 27 +- scripts/Dockerfile-centos8 | 63 +--- scripts/Dockerfile-focal | 26 +- scripts/gethead.sh | 22 ++ sd-env/Dockerfile | 89 ----- sd-env/Dockerfile-bionic | 246 ++++++++---- sd-env/Dockerfile-buster | 246 ++++++++---- sd-env/Dockerfile-centos7 | 238 ++++++++++++ sd-env/Dockerfile-centos8 | 265 ++++++++++--- sd-env/Dockerfile-fedora | 152 ++++---- sd-env/Dockerfile-focal | 233 ++++++++---- sd-env/Dockerfile-omega | 277 ++++++++++---- sd-env/Dockerfile-omega-dynamic | 154 -------- sd-env/Dockerfile-omega-static | 458 ----------------------- sd-env/Dockerfile-stretch | 130 +++---- sd-env/Dockerfile-xenial | 132 ++++--- sd-env/Makefile | 248 ++++++------ sd-env/README-details.md | 137 +++++++ sd-env/README.md | 91 ++--- sd-env/build-template.sh | 53 +-- sd-env/cmakelists1.patch | 23 ++ sd-env/cmakelists2.patch | 38 ++ sd-env/cmakelists3.patch | 25 ++ sd-env/switchuser.sh | 47 --- wrapper/setup.py | 2 +- 59 files changed, 3003 insertions(+), 1627 deletions(-) create mode 100644 azure/ozcloud-bionic-osdu.yml create mode 100644 azure/ozcloud-bionic.yml create mode 100644 azure/ozcloud-buster-osdu.yml create mode 100644 azure/ozcloud-buster.yml create mode 100644 azure/ozcloud-centos7-osdu.yml create mode 100644 azure/ozcloud-centos7.yml create mode 100644 azure/ozcloud-centos8-coverage.yml create mode 100644 azure/ozcloud-centos8-osdu.yml create mode 100644 azure/ozcloud-centos8-vg.yml create mode 100644 azure/ozcloud-centos8.yml create mode 100644 azure/ozcloud-focal-osdu.yml create mode 100644 azure/ozcloud-focal.yml create mode 100644 azure/ozcloud-omega-osdu.yml create mode 100644 azure/ozcloud-omega.yml create mode 100644 azure/templates/combo-build-steps.yml create mode 100644 azure/templates/combo-coverage-steps.yml create mode 100644 azure/templates/combo-valgrind-steps.yml create mode 100644 doc/dockerstages.md create mode 100644 doc/images/dockerstages-fig1.dot create mode 100644 doc/images/dockerstages-fig1.png create mode 100755 scripts/gethead.sh delete mode 100644 sd-env/Dockerfile create mode 100644 sd-env/Dockerfile-centos7 delete mode 100644 sd-env/Dockerfile-omega-dynamic delete mode 100644 sd-env/Dockerfile-omega-static create mode 100644 sd-env/README-details.md create mode 100644 sd-env/cmakelists1.patch create mode 100644 sd-env/cmakelists2.patch create mode 100644 sd-env/cmakelists3.patch delete mode 100755 sd-env/switchuser.sh diff --git a/.dockerignore b/.dockerignore index ef017d3..d0ba13d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,18 +1,20 @@ -.git -build/deploy -build/testdata -build/temp - -# Test files created in the source tree. Should be fixed. +**/.dockerignore +**/.git* +/.git* +!/.git/HEAD +!/.git/refs/heads +!/seismic-store-cpp-lib/.git/HEAD +!/seismic-store-cpp-lib/.git/refs/heads +**/build **/tmp-*.zgy **/test-venv **/__pycache__ **/*.egg-info -python/build -python/test-venv -wrapper/build -wrapper/test-venv -native/sdglue/build -native/sdglue/test-venv +**/.eggs +**/typescript* +**/*~ +**/*# misc/** -.eggs +azure/** +**/Dockerfile* +/sd-env/Makefile diff --git a/.gitignore b/.gitignore index ae4bb70..9e0d68b 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ test-venv *.egg-info .eggs .coverage +typescript # These really shouldn't be in the source area. /python/build diff --git a/Makefile b/Makefile index e9c4bf0..b17a4dc 100644 --- a/Makefile +++ b/Makefile @@ -137,8 +137,8 @@ docker-build: rmdir --ignore-fail-on-non-empty seismic-service-bin private docker rmi -f $(TAG):old $(TAG):test || true $(RM) cid.txt - docker run --cidfile cid.txt $(TAG) make SDAPI_INTERNAL=$(SDAPI_INTERNAL) $(DOCKERTARGET) - docker cp $$(cat cid.txt):/home/build/oz/build/deploy - | gzip -9 > deploy.tgz + docker run --cidfile cid.txt $(TAG) make -j 8 SDAPI_INTERNAL=$(SDAPI_INTERNAL) $(DOCKERTARGET) + docker cp $$(cat cid.txt):/home/me/oz/build/deploy - | gzip -9 > deploy.tgz docker rm $$(cat cid.txt) $(RM) cid.txt docker build -t $(TAG):test -f $(DOCKERFILE)-test . diff --git a/README.md b/README.md index daf7ccb..71b93b3 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,41 @@ All writes and updates have the following *recommendations*: ## Building and testing the core parts -### Building Linux core +### Building on Linux using docker + +This is the simplest approach. + +```sh +git clone https://community.opengroup.org/osdu/platform/domain-data-mgmt-services/seismic/open-zgy.git open-zgy +git clone --recursive https://community.opengroup.org/osdu/platform/domain-data-mgmt-services/seismic/seismic-dms-suite/seismic-store-cpp-lib.git open-zgy/seismic-store-cpp-lib +make -C sd-env final-${distro} +make -C sd-env testonly-${distro} +``` + +This will build SDAPI, build OpenZGY, and run the OpenZGY unit tests. +Currently supported in the distro parameter is +- stretch +- xenial +- bionic +- focal +- buster +- omega +- fedora +- centos8 + +The resulting docker image can be used to experiment with both the +pure and the wrapped C++ Python versions. The image also contains a +tar file that can be copied out of the image for deploying OpenZGY. + +You might want to use ```make -C sd-env PULL="" final-${distro}``` +if you don't want to trigger a full rebuild, which can easily take +30 minutes, every time the base image is updated with some minor fix. +There can be such a thing as too much continous integration. + +For an explanation of the more obscure targets you might want to build, +see the [detailed readme file](sd-env/README-details.md). + +### Building Linux core locally The code should build pretty much out of the box as long as Seismic Store access is not enabled. On Linux there is a top level Makefile. @@ -130,7 +164,11 @@ In both cases both C++ and Python versions are built / packaged. See [Output folders](#output-folders) for where to find the output. -### Building Windows core +If you want support for Seismic Store then using the docker build is +recommended. Otherwise you need to build SDAPI first and then copy the +binaries by hand into the OpenZGY source tree. + +### Building Windows core locally Prerequisites are Visual Studio 2019 with Platform Toolset v142. If building with cloud support you might also need NuGet, @@ -195,10 +233,12 @@ The repository that is publicly accessible but may lag behind the internal versi So when the instructions below mention downloading the cloud library you may download SDAPI from [Azure](https://dev.azure.com/slb-des-ext-collaboration/open-data-ecosystem/_git/os-seismic-store-cpp-lib) or [OSDU](https://community.opengroup.org/osdu/platform/domain-data-mgmt-services/seismic/seismic-dms-suite/seismic-store-cpp-lib.git). -### Building Linux cloud +### Building Linux cloud locally + +This is somewhat tricky. Consider using the +[docker build](#Building-on Linux-using-docker) instead. -If you want to use Seismic Store to access the cloud then there are -some additional steps needed. You will need to download and build the +You will need to download and build the Seismic Store SDK a.k.a. SDAPI. And then package the binaries so they can be picked up by OpenZGY. The Linux build expects it to be available as a tarball in the source tree. So if you want cloud diff --git a/azure/ozcloud-bionic-osdu.yml b/azure/ozcloud-bionic-osdu.yml new file mode 100644 index 0000000..163a9b5 --- /dev/null +++ b/azure/ozcloud-bionic-osdu.yml @@ -0,0 +1,37 @@ +# name: 'OpenZGY Linux Ubuntu Bionic py36' +name: $(Build.BuildID)-bionic + +trigger: none +schedules: +- cron: "0 3 * * 1" + displayName: Nightly build + branches: + include: + - master + +pool: + name: Paal-Kvamme-Test + +workspace: + clean: all + +variables: + - group: 'Salmon Variables' + +steps: +- template: templates/combo-build-steps.yml + parameters: + linuxdistro: 'bionic' + tagtail: 'osdu' + deployed: > + deploy.tgz + deploy/pure/OpenZGY-*-py3-none-any.whl + deploy/pure/OpenZGY-*.tar.gz + deploy/native/bionic-gcc75/libopenzgy.so.*.* + deploy/native/bionic-gcc75/libsdapi.so.*.*.* + deploy/native/include/openzgy/api.h + deploy/native/include/openzgy/exception.h + deploy/native/include/openzgy/iocontext.h + deploy/sdglue/bionic-gcc75/SdGlue-*-cp36-cp36m-linux_x86_64.whl + deploy/wrapper/bionic-gcc75/OpenZgyBindings-*-cp36-cp36m-linux_x86_64.whl + deploy/sdapi/Lin64_gcc750/sdapi_linux64.tar.gz diff --git a/azure/ozcloud-bionic.yml b/azure/ozcloud-bionic.yml new file mode 100644 index 0000000..5ba2997 --- /dev/null +++ b/azure/ozcloud-bionic.yml @@ -0,0 +1,37 @@ +# name: 'OpenZGY Linux Ubuntu Bionic py36' +name: $(Build.BuildID)-bionic + +trigger: none +schedules: +- cron: "0 4 * * 1" + displayName: Nightly build + branches: + include: + - master + +pool: + name: Paal-Kvamme-Test + +workspace: + clean: all + +variables: + - group: 'Salmon Variables' + +steps: +- template: templates/combo-build-steps.yml + parameters: + linuxdistro: 'bionic' + tagtail: 'default' + deployed: > + deploy.tgz + deploy/pure/OpenZGY-*-py3-none-any.whl + deploy/pure/OpenZGY-*.tar.gz + deploy/native/bionic-gcc75/libopenzgy.so.*.* + deploy/native/bionic-gcc75/libsdapi.so.*.*.* + deploy/native/include/openzgy/api.h + deploy/native/include/openzgy/exception.h + deploy/native/include/openzgy/iocontext.h + deploy/sdglue/bionic-gcc75/SdGlue-*-cp36-cp36m-linux_x86_64.whl + deploy/wrapper/bionic-gcc75/OpenZgyBindings-*-cp36-cp36m-linux_x86_64.whl + deploy/sdapi/Lin64_gcc750/sdapi_linux64.tar.gz diff --git a/azure/ozcloud-buster-osdu.yml b/azure/ozcloud-buster-osdu.yml new file mode 100644 index 0000000..e7b495b --- /dev/null +++ b/azure/ozcloud-buster-osdu.yml @@ -0,0 +1,37 @@ +# name: 'OpenZGY Linux Debian Buster py37' +name: $(Build.BuildID)-buster + +trigger: none +schedules: +- cron: "0 3 * * 2" + displayName: Nightly build + branches: + include: + - master + +pool: + name: Paal-Kvamme-Test + +workspace: + clean: all + +variables: + - group: 'Salmon Variables' + +steps: +- template: templates/combo-build-steps.yml + parameters: + linuxdistro: 'buster' + tagtail: 'osdu' + deployed: > + deploy.tgz + deploy/pure/OpenZGY-*-py3-none-any.whl + deploy/pure/OpenZGY-*.tar.gz + deploy/native/buster-gcc83/libopenzgy.so.*.* + deploy/native/buster-gcc83/libsdapi.so.*.*.* + deploy/native/include/openzgy/api.h + deploy/native/include/openzgy/exception.h + deploy/native/include/openzgy/iocontext.h + deploy/sdglue/buster-gcc83/SdGlue-*-cp37-cp37m-linux_x86_64.whl + deploy/wrapper/buster-gcc83/OpenZgyBindings-*-cp37-cp37m-linux_x86_64.whl + deploy/sdapi/Lin64_gcc830/sdapi_linux64.tar.gz diff --git a/azure/ozcloud-buster.yml b/azure/ozcloud-buster.yml new file mode 100644 index 0000000..7615cc7 --- /dev/null +++ b/azure/ozcloud-buster.yml @@ -0,0 +1,37 @@ +# name: 'OpenZGY Linux Debian Buster py37' +name: $(Build.BuildID)-buster + +trigger: none +schedules: +- cron: "0 4 * * 2" + displayName: Nightly build + branches: + include: + - master + +pool: + name: Paal-Kvamme-Test + +workspace: + clean: all + +variables: + - group: 'Salmon Variables' + +steps: +- template: templates/combo-build-steps.yml + parameters: + linuxdistro: 'buster' + tagtail: 'default' + deployed: > + deploy.tgz + deploy/pure/OpenZGY-*-py3-none-any.whl + deploy/pure/OpenZGY-*.tar.gz + deploy/native/buster-gcc83/libopenzgy.so.*.* + deploy/native/buster-gcc83/libsdapi.so.*.*.* + deploy/native/include/openzgy/api.h + deploy/native/include/openzgy/exception.h + deploy/native/include/openzgy/iocontext.h + deploy/sdglue/buster-gcc83/SdGlue-*-cp37-cp37m-linux_x86_64.whl + deploy/wrapper/buster-gcc83/OpenZgyBindings-*-cp37-cp37m-linux_x86_64.whl + deploy/sdapi/Lin64_gcc830/sdapi_linux64.tar.gz diff --git a/azure/ozcloud-centos7-osdu.yml b/azure/ozcloud-centos7-osdu.yml new file mode 100644 index 0000000..ebc700c --- /dev/null +++ b/azure/ozcloud-centos7-osdu.yml @@ -0,0 +1,37 @@ +# name: 'OpenZGY Linux CentOS 7 py36' +name: $(Build.BuildID)-centos7 + +trigger: none +schedules: +- cron: "0 3 * * 3" + displayName: Nightly build + branches: + include: + - master + +pool: + name: Paal-Kvamme-Test + +workspace: + clean: all + +variables: + - group: 'Salmon Variables' + +steps: +- template: templates/combo-build-steps.yml + parameters: + linuxdistro: 'centos7' + tagtail: 'osdu' + deployed: > + deploy.tgz + deploy/pure/OpenZGY-*-py3-none-any.whl + deploy/pure/OpenZGY-*.tar.gz + deploy/native/centos7-gcc48/libopenzgy.so.*.* + deploy/native/centos7-gcc48/libsdapi.so.*.*.* + deploy/native/include/openzgy/api.h + deploy/native/include/openzgy/exception.h + deploy/native/include/openzgy/iocontext.h + deploy/sdglue/centos7-gcc48/SdGlue-*-cp36-cp36m-linux_x86_64.whl + deploy/wrapper/centos7-gcc48/OpenZgyBindings-*-cp36-cp36m-linux_x86_64.whl + deploy/sdapi/Lin64_gcc485/sdapi_linux64.tar.gz diff --git a/azure/ozcloud-centos7.yml b/azure/ozcloud-centos7.yml new file mode 100644 index 0000000..b8020be --- /dev/null +++ b/azure/ozcloud-centos7.yml @@ -0,0 +1,37 @@ +# name: 'OpenZGY Linux CentOS 7 py36' +name: $(Build.BuildID)-centos7 + +trigger: none +schedules: +- cron: "0 4 * * 3" + displayName: Nightly build + branches: + include: + - master + +pool: + name: Paal-Kvamme-Test + +workspace: + clean: all + +variables: + - group: 'Salmon Variables' + +steps: +- template: templates/combo-build-steps.yml + parameters: + linuxdistro: 'centos7' + tagtail: 'default' + deployed: > + deploy.tgz + deploy/pure/OpenZGY-*-py3-none-any.whl + deploy/pure/OpenZGY-*.tar.gz + deploy/native/centos7-gcc48/libopenzgy.so.*.* + deploy/native/centos7-gcc48/libsdapi.so.*.*.* + deploy/native/include/openzgy/api.h + deploy/native/include/openzgy/exception.h + deploy/native/include/openzgy/iocontext.h + deploy/sdglue/centos7-gcc48/SdGlue-*-cp36-cp36m-linux_x86_64.whl + deploy/wrapper/centos7-gcc48/OpenZgyBindings-*-cp36-cp36m-linux_x86_64.whl + deploy/sdapi/Lin64_gcc485/sdapi_linux64.tar.gz diff --git a/azure/ozcloud-centos8-coverage.yml b/azure/ozcloud-centos8-coverage.yml new file mode 100644 index 0000000..2c83b6f --- /dev/null +++ b/azure/ozcloud-centos8-coverage.yml @@ -0,0 +1,31 @@ +# name: 'OpenZGY Linux CentOS 8 py36' +name: $(Build.BuildID)-centos8-coverage + +trigger: none +schedules: +- cron: "0 3 * * 0" + displayName: Nightly build + branches: + include: + - master + +pool: + name: Paal-Kvamme-Test + +variables: + - group: 'Salmon Variables' + +jobs: +- job: + timeoutInMinutes: 60 + workspace: + clean: all + steps: + - template: templates/combo-coverage-steps.yml + parameters: + linuxdistro: 'centos8' + tagtail: coverage + deployed: > + coverage.tgz + summary.txt + final.info diff --git a/azure/ozcloud-centos8-osdu.yml b/azure/ozcloud-centos8-osdu.yml new file mode 100644 index 0000000..ea1cc63 --- /dev/null +++ b/azure/ozcloud-centos8-osdu.yml @@ -0,0 +1,37 @@ +# name: 'OpenZGY Linux CentOS 8 py36' +name: $(Build.BuildID)-centos8 + +trigger: none +schedules: +- cron: "0 3 * * 4" + displayName: Nightly build + branches: + include: + - master + +pool: + name: Paal-Kvamme-Test + +workspace: + clean: all + +variables: + - group: 'Salmon Variables' + +steps: +- template: templates/combo-build-steps.yml + parameters: + linuxdistro: 'centos8' + tagtail: 'osdu' + deployed: > + deploy.tgz + deploy/pure/OpenZGY-*-py3-none-any.whl + deploy/pure/OpenZGY-*.tar.gz + deploy/native/centos8-gcc84/libopenzgy.so.*.* + deploy/native/centos8-gcc84/libsdapi.so.*.*.* + deploy/native/include/openzgy/api.h + deploy/native/include/openzgy/exception.h + deploy/native/include/openzgy/iocontext.h + deploy/sdglue/centos8-gcc84/SdGlue-*-cp36-cp36m-linux_x86_64.whl + deploy/wrapper/centos8-gcc84/OpenZgyBindings-*-cp36-cp36m-linux_x86_64.whl + deploy/sdapi/Lin64_gcc841/sdapi_linux64.tar.gz diff --git a/azure/ozcloud-centos8-vg.yml b/azure/ozcloud-centos8-vg.yml new file mode 100644 index 0000000..108e75e --- /dev/null +++ b/azure/ozcloud-centos8-vg.yml @@ -0,0 +1,31 @@ +# name: 'OpenZGY Linux CentOS 8 py36' +name: $(Build.BuildID)-centos8-vg + +trigger: none +schedules: +- cron: "0 4 * * 0" + displayName: Nightly build + branches: + include: + - master + +pool: + name: Paal-Kvamme-Test + +variables: + - group: 'Salmon Variables' + +jobs: +- job: + timeoutInMinutes: 120 + workspace: + clean: all + steps: + - template: templates/combo-valgrind-steps.yml + parameters: + linuxdistro: 'centos8' + tagtail: valgrind + deployed: > + valgrind.txt + valgrind-1.txt + valgrind-2.txt diff --git a/azure/ozcloud-centos8.yml b/azure/ozcloud-centos8.yml new file mode 100644 index 0000000..3ecd870 --- /dev/null +++ b/azure/ozcloud-centos8.yml @@ -0,0 +1,39 @@ +# name: 'OpenZGY Linux CentOS 8 py36' +name: $(Build.BuildID)-centos8 + +trigger: +- master + +schedules: +- cron: "0 4 * * 4" + displayName: Nightly build + branches: + include: + - master + +pool: + name: Paal-Kvamme-Test + +workspace: + clean: all + +variables: + - group: 'Salmon Variables' + +steps: +- template: templates/combo-build-steps.yml + parameters: + linuxdistro: 'centos8' + tagtail: 'default' + deployed: > + deploy.tgz + deploy/pure/OpenZGY-*-py3-none-any.whl + deploy/pure/OpenZGY-*.tar.gz + deploy/native/centos8-gcc84/libopenzgy.so.*.* + deploy/native/centos8-gcc84/libsdapi.so.*.*.* + deploy/native/include/openzgy/api.h + deploy/native/include/openzgy/exception.h + deploy/native/include/openzgy/iocontext.h + deploy/sdglue/centos8-gcc84/SdGlue-*-cp36-cp36m-linux_x86_64.whl + deploy/wrapper/centos8-gcc84/OpenZgyBindings-*-cp36-cp36m-linux_x86_64.whl + deploy/sdapi/Lin64_gcc841/sdapi_linux64.tar.gz diff --git a/azure/ozcloud-focal-osdu.yml b/azure/ozcloud-focal-osdu.yml new file mode 100644 index 0000000..73f16dd --- /dev/null +++ b/azure/ozcloud-focal-osdu.yml @@ -0,0 +1,37 @@ +# name: 'OpenZGY Linux Ubuntu Focal py38' +name: $(Build.BuildID)-focal + +trigger: none +schedules: +- cron: "0 3 * * 5" + displayName: Nightly build + branches: + include: + - master + +pool: + name: Paal-Kvamme-Test + +workspace: + clean: all + +variables: + - group: 'Salmon Variables' + +steps: +- template: templates/combo-build-steps.yml + parameters: + linuxdistro: 'focal' + tagtail: 'osdu' + deployed: > + deploy.tgz + deploy/pure/OpenZGY-*-py3-none-any.whl + deploy/pure/OpenZGY-*.tar.gz + deploy/native/focal-gcc93/libopenzgy.so.*.* + deploy/native/focal-gcc93/libsdapi.so.*.*.* + deploy/native/include/openzgy/api.h + deploy/native/include/openzgy/exception.h + deploy/native/include/openzgy/iocontext.h + deploy/sdglue/focal-gcc93/SdGlue-*-cp38-cp38-linux_x86_64.whl + deploy/wrapper/focal-gcc93/OpenZgyBindings-*-cp38-cp38-linux_x86_64.whl + deploy/sdapi/Lin64_gcc930/sdapi_linux64.tar.gz diff --git a/azure/ozcloud-focal.yml b/azure/ozcloud-focal.yml new file mode 100644 index 0000000..2e83df2 --- /dev/null +++ b/azure/ozcloud-focal.yml @@ -0,0 +1,37 @@ +# name: 'OpenZGY Linux Ubuntu Focal py38' +name: $(Build.BuildID)-focal + +trigger: none +schedules: +- cron: "0 4 * * 5" + displayName: Nightly build + branches: + include: + - master + +pool: + name: Paal-Kvamme-Test + +workspace: + clean: all + +variables: + - group: 'Salmon Variables' + +steps: +- template: templates/combo-build-steps.yml + parameters: + linuxdistro: 'focal' + tagtail: 'default' + deployed: > + deploy.tgz + deploy/pure/OpenZGY-*-py3-none-any.whl + deploy/pure/OpenZGY-*.tar.gz + deploy/native/focal-gcc93/libopenzgy.so.*.* + deploy/native/focal-gcc93/libsdapi.so.*.*.* + deploy/native/include/openzgy/api.h + deploy/native/include/openzgy/exception.h + deploy/native/include/openzgy/iocontext.h + deploy/sdglue/focal-gcc93/SdGlue-*-cp38-cp38-linux_x86_64.whl + deploy/wrapper/focal-gcc93/OpenZgyBindings-*-cp38-cp38-linux_x86_64.whl + deploy/sdapi/Lin64_gcc930/sdapi_linux64.tar.gz diff --git a/azure/ozcloud-omega-osdu.yml b/azure/ozcloud-omega-osdu.yml new file mode 100644 index 0000000..72d96d9 --- /dev/null +++ b/azure/ozcloud-omega-osdu.yml @@ -0,0 +1,37 @@ +# name: 'OpenZGY Linux omega py36' +name: $(Build.BuildID)-omega + +trigger: none +schedules: +- cron: "0 3 * * 6" + displayName: Nightly build + branches: + include: + - master + +pool: + name: Paal-Kvamme-Test + +workspace: + clean: all + +variables: + - group: 'Salmon Variables' + +steps: +- template: templates/combo-build-steps.yml + parameters: + linuxdistro: 'omega' + tagtail: 'osdu' + deployed: > + deploy.tgz + deploy/pure/OpenZGY-*-py3-none-any.whl + deploy/pure/OpenZGY-*.tar.gz + deploy/native/omega-gcc73/libopenzgy.so.*.* + deploy/native/omega-gcc73/libsdapi.so.*.*.* + deploy/native/include/openzgy/api.h + deploy/native/include/openzgy/exception.h + deploy/native/include/openzgy/iocontext.h + deploy/sdglue/omega-gcc73/SdGlue-*-cp36-cp36m-linux_x86_64.whl + deploy/wrapper/omega-gcc73/OpenZgyBindings-*-cp36-cp36m-linux_x86_64.whl + deploy/sdapi/Lin64_gcc731/sdapi_linux64.tar.gz diff --git a/azure/ozcloud-omega.yml b/azure/ozcloud-omega.yml new file mode 100644 index 0000000..e33aa29 --- /dev/null +++ b/azure/ozcloud-omega.yml @@ -0,0 +1,37 @@ +# name: 'OpenZGY Linux omega py36' +name: $(Build.BuildID)-omega + +trigger: none +schedules: +- cron: "0 4 * * 6" + displayName: Nightly build + branches: + include: + - master + +pool: + name: Paal-Kvamme-Test + +workspace: + clean: all + +variables: + - group: 'Salmon Variables' + +steps: +- template: templates/combo-build-steps.yml + parameters: + linuxdistro: 'omega' + tagtail: 'default' + deployed: > + deploy.tgz + deploy/pure/OpenZGY-*-py3-none-any.whl + deploy/pure/OpenZGY-*.tar.gz + deploy/native/omega-gcc73/libopenzgy.so.*.* + deploy/native/omega-gcc73/libsdapi.so.*.*.* + deploy/native/include/openzgy/api.h + deploy/native/include/openzgy/exception.h + deploy/native/include/openzgy/iocontext.h + deploy/sdglue/omega-gcc73/SdGlue-*-cp36-cp36m-linux_x86_64.whl + deploy/wrapper/omega-gcc73/OpenZgyBindings-*-cp36-cp36m-linux_x86_64.whl + deploy/sdapi/Lin64_gcc731/sdapi_linux64.tar.gz diff --git a/azure/templates/build-steps.yml b/azure/templates/build-steps.yml index 64b6735..543fd95 100644 --- a/azure/templates/build-steps.yml +++ b/azure/templates/build-steps.yml @@ -43,9 +43,9 @@ steps: # Note, keep the CopyFiles task below in sync with this choice. # deploy.tgz needs download to check the contents # deploy/** breaks symbolic links. - docker cp $(cat cid.txt):/home/build/oz/build/deploy - | gzip -9 > deploy.tgz + docker cp $(cat cid.txt):/home/me/oz/build/deploy - | gzip -9 > deploy.tgz rm -rf deploy; mkdir deploy - docker cp $(cat cid.txt):/home/build/oz/build/deploy - | tar -C . -xf - --exclude '*.timestamp' + docker cp $(cat cid.txt):/home/me/oz/build/deploy - | tar -C . -xf - --exclude '*.timestamp' docker rm $(cat cid.txt) /bin/rm -f cid.txt docker build -t ${TAG}:test -f ${DOCKERFILE}-test . diff --git a/azure/templates/combo-build-steps.yml b/azure/templates/combo-build-steps.yml new file mode 100644 index 0000000..75ee99d --- /dev/null +++ b/azure/templates/combo-build-steps.yml @@ -0,0 +1,139 @@ +parameters: + linuxdistro: 'centos8' + deployed: . + tagtail: 'default' + +steps: +- checkout: self + clean: true + +- bash: | + rm -rf seismic-dms-sdapi + redacted=$(echo -n "${SLB_DIGITAL_US_PAT}" | cut -c1-8) + echo "SLB_DIGITAL_US_PAT=${redacted}..." + echo "current version of git is $(git --version)" + git -c http.extraheader="Authorization: Basic ${SLB_DIGITAL_US_PAT}" clone https://slb-digital-us@dev.azure.com/slb-digital-us/osdu/_git/seismic-dms-sdapi + env: + SLB_DIGITAL_US_PAT: $(SLB_DIGITAL_US_PAT) + condition: + and(succeeded(), ne('${{parameters.tagtail}}', 'osdu')) + displayName: 'Download slb extensions' + +- bash: | + # Note: here the sdapi is inside the openzgy folder, + # inside the docker builder it is one level up. + rm -rf seismic-store-cpp-lib seismic-dms-sdapi sdutil sdutil-slb + git clone --recursive https://community.opengroup.org/osdu/platform/domain-data-mgmt-services/seismic/seismic-dms-suite/seismic-store-cpp-lib.git seismic-store-cpp-lib + echo "All files in $(pwd)"; ls -FC .. . * || true + displayName: 'Download more sources' + +- bash: | + eval $(test ! -x private/grabtoken.sh || private/grabtoken.sh -vv) + env: + OPENZGY_SDURL: $(SEISMIC_STORE_URL) + OPENZGY_SDAPIKEY: $(SEISMIC_STORE_KEY) + CLIENT_ID: $(OPENZGY_TEST_CLIENT_ID) + CLIENT_SECRET: $(OPENZGY_TEST_CLIENT_SECRET) + displayName: 'Show SAuth token' + +- bash: | + set -e -x + export LINUXDISTRO=${{parameters.linuxdistro}} + DOCKERFILE=sd-env/Dockerfile-${LINUXDISTRO} + TAG=az-build-openzgy-${LINUXDISTRO}-${{parameters.tagtail}} + docker --version + docker system info | grep -i version + docker system df + rm -f oztests.iid + mkdir -p seismic-store-cpp-lib seismic-dms-sdapi private + docker build --pull -f ${DOCKERFILE} --target sdapi-manual --build-arg AZURE_BUILDID=$(Build.BuildId) -t ${TAG}:manual . + docker build -f ${DOCKERFILE} --target sdapi-build --build-arg AZURE_BUILDID=$(Build.BuildId) -t ${TAG}:sdbuild . + docker build -f ${DOCKERFILE} --target openzgy-build --build-arg AZURE_BUILDID=$(Build.BuildId) -t ${TAG}:ozbuild . + docker build -f ${DOCKERFILE} --target openzgy-testenv --build-arg AZURE_BUILDID=$(Build.BuildId) -t ${TAG}:oztests --iidfile oztests.iid . + docker rmi ${TAG}:{manual,sdbuild,ozbuild,oztests}-old || true + docker tag ${TAG}:manual ${TAG}:manual-old || true + docker tag ${TAG}:sdbuild ${TAG}:sdbuild-old || true + docker tag ${TAG}:ozbuild ${TAG}:ozbuild-old || true + docker tag ${TAG}:oztests ${TAG}:oztests-old || true + rmdir --ignore-fail-on-non-empty seismic-store-cpp-lib seismic-dms-sdapi private || true + id=$(docker create $(cat oztests.iid)) + docker cp ${id}:/home/me/oz/build/deploy - | gzip -9 > deploy.tgz + rm -rf deploy; mkdir deploy + docker cp ${id}:/home/me/oz/build/deploy - | tar -C . -xf - --exclude '*.timestamp' + docker rm ${id} + displayName: 'Build SD+OpenZGY' + +- bash: | + docker run --rm -e CLIENT_ID -e CLIENT_SECRET -e OPENZGY_SDURL -e OPENZGY_SDAPIKEY -e LINUXDISTRO=${{parameters.linuxdistro}} $(cat oztests.iid) native/src/runtests.sh + env: + OPENZGY_SDURL: $(SEISMIC_STORE_URL) + OPENZGY_SDAPIKEY: $(SEISMIC_STORE_KEY) + CLIENT_ID: $(OPENZGY_TEST_CLIENT_ID) + CLIENT_SECRET: $(OPENZGY_TEST_CLIENT_SECRET) + displayName: 'Test native' + +- bash: | + docker run --rm -e CLIENT_ID -e CLIENT_SECRET -e OPENZGY_SDURL -e OPENZGY_SDAPIKEY -e LINUXDISTRO=${{parameters.linuxdistro}} $(cat oztests.iid) native/sdglue/runtests.sh + env: + OPENZGY_SDURL: $(SEISMIC_STORE_URL) + OPENZGY_SDAPIKEY: $(SEISMIC_STORE_KEY) + CLIENT_ID: $(OPENZGY_TEST_CLIENT_ID) + CLIENT_SECRET: $(OPENZGY_TEST_CLIENT_SECRET) + displayName: 'Test sdglue' + +- bash: | + docker run --rm -e CLIENT_ID -e CLIENT_SECRET -e OPENZGY_SDURL -e OPENZGY_SDAPIKEY -e LINUXDISTRO=${{parameters.linuxdistro}} $(cat oztests.iid) wrapper/runtests.sh + env: + OPENZGY_SDURL: $(SEISMIC_STORE_URL) + OPENZGY_SDAPIKEY: $(SEISMIC_STORE_KEY) + CLIENT_ID: $(OPENZGY_TEST_CLIENT_ID) + CLIENT_SECRET: $(OPENZGY_TEST_CLIENT_SECRET) + displayName: 'Test wrapper' + +- bash: | + docker run --rm -e CLIENT_ID -e CLIENT_SECRET -e OPENZGY_SDURL -e OPENZGY_SDAPIKEY -e LINUXDISTRO=${{parameters.linuxdistro}} $(cat oztests.iid) python/runtests.sh + env: + OPENZGY_SDURL: $(SEISMIC_STORE_URL) + OPENZGY_SDAPIKEY: $(SEISMIC_STORE_KEY) + CLIENT_ID: $(OPENZGY_TEST_CLIENT_ID) + CLIENT_SECRET: $(OPENZGY_TEST_CLIENT_SECRET) + displayName: 'Test pure' + +- task: CopyFiles@2 + inputs: + contents: | + deploy/** + deploy.tgz + targetFolder: $(Build.ArtifactStagingDirectory) + flattenFolders: false + +- bash: | + echo === Contents of $(Build.ArtifactStagingDirectory) + find $(Build.ArtifactStagingDirectory) -print + set -e -f + echo === + ( + cd "$(Build.ArtifactStagingDirectory)" + for i in ${{parameters.deployed}} + do + echo "Check that $i exists" + file=$(set +f; set -- $i; echo $1) + test -d "$file" -o -s "$file" || (echo "$file is missing"; exit 42) + done + ) + displayName: 'Check that artifacts exist' + +- task: PublishBuildArtifacts@1 + inputs: + pathToPublish: $(Build.ArtifactStagingDirectory) + artifactName: OpenZGY-${{parameters.linuxdistro}} + +- task: UniversalPackages@0 + inputs: + command: 'publish' + publishDirectory: $(Build.ArtifactStagingDirectory) + feedsToUsePublish: 'internal' + vstsFeedPublish: 'openzgy' + vstsFeedPackagePublish: openzgy-${{parameters.linuxdistro}} + versionOption: 'patch' + packagePublishDescription: 'OpenZGY build for ${{parameters.linuxdistro}}' diff --git a/azure/templates/combo-coverage-steps.yml b/azure/templates/combo-coverage-steps.yml new file mode 100644 index 0000000..253f8cc --- /dev/null +++ b/azure/templates/combo-coverage-steps.yml @@ -0,0 +1,120 @@ +# Based on build-steps.yml but used to make a coverage report. +# The following explanation might help to keep the two in sync. +# Remove the separate test steps; tests now run as part of the build. +# instead of make, run "/bin/bash scripts/build-coverage.sh" +# Instead of copy-out deploy/..., need the following handled +# in both "docker cp" and CopyFiles@2: +# build/deploy/native/coverage.tgz +# native/src/summary.txt +# native/src/final.info +# The build step needs secrets etc. since it now also runs tests +# Remove the "universal publish" step. +# +# In the "combo" Seismic Store + OpenZGY setup, run the coverage +# script in the openzgy-build image instead of the openzgy-testenv +# image. The coverage script needs to rebuild with instrumentation, +# and the tests must then run with access to the intermediate files +# from that compilation. Technically the compilation done when +# building the image is then wasted. But please don't make me +# complicated the build rules even more. + +parameters: + linuxdistro: 'centos8' + deployed: . + tagtail: 'default' + +steps: +- checkout: self + clean: true + +- bash: | + rm -rf seismic-dms-sdapi + redacted=$(echo -n "${SLB_DIGITAL_US_PAT}" | cut -c1-8) + echo "SLB_DIGITAL_US_PAT=${redacted}..." + echo "current version of git is $(git --version)" + git -c http.extraheader="Authorization: Basic ${SLB_DIGITAL_US_PAT}" clone https://slb-digital-us@dev.azure.com/slb-digital-us/osdu/_git/seismic-dms-sdapi + env: + SLB_DIGITAL_US_PAT: $(SLB_DIGITAL_US_PAT) + condition: + and(succeeded(), ne('${{parameters.tagtail}}', 'osdu')) + displayName: 'Download slb extensions' + +- bash: | + # Note: here the sdapi is inside the openzgy folder, + # inside the docker builder it is one level up. + rm -rf seismic-store-cpp-lib seismic-dms-sdapi sdutil sdutil-slb + git clone --recursive https://community.opengroup.org/osdu/platform/domain-data-mgmt-services/seismic/seismic-dms-suite/seismic-store-cpp-lib.git seismic-store-cpp-lib + echo "All files in $(pwd)"; ls -FC .. . * || true + displayName: 'Download more sources' + +- bash: | + eval $(test ! -x private/grabtoken.sh || private/grabtoken.sh -vv) + env: + OPENZGY_SDURL: $(SEISMIC_STORE_URL) + OPENZGY_SDAPIKEY: $(SEISMIC_STORE_KEY) + CLIENT_ID: $(OPENZGY_TEST_CLIENT_ID) + CLIENT_SECRET: $(OPENZGY_TEST_CLIENT_SECRET) + displayName: 'Show SAuth token' + +- bash: | + set -e -x + export LINUXDISTRO=${{parameters.linuxdistro}} + DOCKERFILE=sd-env/Dockerfile-${LINUXDISTRO} + TAG=az-build-openzgy-${LINUXDISTRO}-${{parameters.tagtail}} + docker --version + docker system info | grep -i version + docker system df + rm -f ozbuild.iid + mkdir -p seismic-store-cpp-lib seismic-dms-sdapi private + docker build --pull -f ${DOCKERFILE} --target sdapi-manual --build-arg AZURE_BUILDID=$(Build.BuildId) -t ${TAG}:manual . + docker build -f ${DOCKERFILE} --target sdapi-build --build-arg AZURE_BUILDID=$(Build.BuildId) -t ${TAG}:sdbuild . + docker build -f ${DOCKERFILE} --target openzgy-build --build-arg AZURE_BUILDID=$(Build.BuildId) -t ${TAG}:ozbuild --iidfile ozbuild.iid . + # Stop after the openzgy-build stage, see top of this file. + docker rmi ${TAG}:{manual,sdbuild,ozbuild}-old || true + docker tag ${TAG}:manual ${TAG}:manual-old || true + docker tag ${TAG}:sdbuild ${TAG}:sdbuild-old || true + docker tag ${TAG}:ozbuild ${TAG}:ozbuild-old || true + rmdir --ignore-fail-on-non-empty seismic-store-cpp-lib seismic-dms-sdapi private || true + rm -f cidfile.txt + docker run --cidfile cid.txt -e CLIENT_ID -e CLIENT_SECRET -e OPENZGY_SDURL -e OPENZGY_SDAPIKEY -e LINUXDISTRO -e AZURE_BUILDID=$(Build.BuildId) $(cat ozbuild.iid) /bin/bash scripts/build-coverage.sh + docker cp $(cat cid.txt):/home/me/oz/build/deploy/native/coverage.tgz coverage.tgz + docker cp $(cat cid.txt):/home/me/oz/native/src/summary.txt summary.txt + docker cp $(cat cid.txt):/home/me/oz/native/src/final.info final.info + docker rm $(cat cid.txt) + /bin/rm -f cid.txt + env: + OPENZGY_SDURL: $(SEISMIC_STORE_URL) + OPENZGY_SDAPIKEY: $(SEISMIC_STORE_KEY) + CLIENT_ID: $(OPENZGY_TEST_CLIENT_ID) + CLIENT_SECRET: $(OPENZGY_TEST_CLIENT_SECRET) + displayName: 'Build and run' + +- task: CopyFiles@2 + inputs: + contents: | + coverage.tgz + summary.txt + final.info + targetFolder: $(Build.ArtifactStagingDirectory) + flattenFolders: false + +- bash: | + echo === Contents of $(Build.ArtifactStagingDirectory) + find $(Build.ArtifactStagingDirectory) -print + set -e -f + echo === + ( + cd "$(Build.ArtifactStagingDirectory)" + for i in ${{parameters.deployed}} + do + echo "Check that $i exists" + file=$(set +f; set -- $i; echo $1) + test -d "$file" -o -s "$file" || (echo "$file is missing"; exit 42) + done + ) + displayName: 'Check that artifacts exist' + +- task: PublishBuildArtifacts@1 + inputs: + pathToPublish: $(Build.ArtifactStagingDirectory) + artifactName: OpenZGY-${{parameters.linuxdistro}} diff --git a/azure/templates/combo-valgrind-steps.yml b/azure/templates/combo-valgrind-steps.yml new file mode 100644 index 0000000..4fec633 --- /dev/null +++ b/azure/templates/combo-valgrind-steps.yml @@ -0,0 +1,134 @@ +# Based on build-steps.yml but used to make a valgrind report. +# The following explanation might help to keep the two in sync. +# Disable optimizer when building. +# Remove "Test sdglue" and "Test pure" steps. +# Change "runtests.sh" to "runtests.sh valgrind" two places +# Both the remaining tests need to copy out some files, +# which means the cid needs to be captured. The files are: +# build/deploy/native/valgrind.txt +# build/deploy/wrapper/valgrind-1.txt +# build/deploy/wrapper/valgrind-2.txt +# This is also reflected in CopyFiles@2, only export valgrind*.txt. +# Remove the "universal publish" step. + +parameters: + linuxdistro: 'centos8' + deployed: . + tagtail: 'default' + +steps: +- checkout: self + clean: true + +- bash: | + rm -rf seismic-dms-sdapi + redacted=$(echo -n "${SLB_DIGITAL_US_PAT}" | cut -c1-8) + echo "SLB_DIGITAL_US_PAT=${redacted}..." + echo "current version of git is $(git --version)" + git -c http.extraheader="Authorization: Basic ${SLB_DIGITAL_US_PAT}" clone https://slb-digital-us@dev.azure.com/slb-digital-us/osdu/_git/seismic-dms-sdapi + env: + SLB_DIGITAL_US_PAT: $(SLB_DIGITAL_US_PAT) + condition: + and(succeeded(), ne('${{parameters.tagtail}}', 'osdu')) + displayName: 'Download slb extensions' + +- bash: | + # Note: here the sdapi is inside the openzgy folder, + # inside the docker builder it is one level up. + rm -rf seismic-store-cpp-lib seismic-dms-sdapi sdutil sdutil-slb + git clone --recursive https://community.opengroup.org/osdu/platform/domain-data-mgmt-services/seismic/seismic-dms-suite/seismic-store-cpp-lib.git seismic-store-cpp-lib + echo "All files in $(pwd)"; ls -FC .. . * || true + displayName: 'Download more sources' + +- bash: | + eval $(test ! -x private/grabtoken.sh || private/grabtoken.sh -vv) + env: + OPENZGY_SDURL: $(SEISMIC_STORE_URL) + OPENZGY_SDAPIKEY: $(SEISMIC_STORE_KEY) + CLIENT_ID: $(OPENZGY_TEST_CLIENT_ID) + CLIENT_SECRET: $(OPENZGY_TEST_CLIENT_SECRET) + displayName: 'Show SAuth token' + +- bash: | + set -e -x + export LINUXDISTRO=${{parameters.linuxdistro}} + DOCKERFILE=sd-env/Dockerfile-${LINUXDISTRO} + TAG=az-build-openzgy-${LINUXDISTRO}-${{parameters.tagtail}} + docker --version + docker system info | grep -i version + docker system df + rm -f oztests.iid + mkdir -p seismic-store-cpp-lib seismic-dms-sdapi private + docker build --pull -f ${DOCKERFILE} --target sdapi-manual --build-arg AZURE_BUILDID=$(Build.BuildId) -t ${TAG}:manual . + docker build -f ${DOCKERFILE} --target sdapi-build --build-arg AZURE_BUILDID=$(Build.BuildId) -t ${TAG}:sdbuild . + docker build -f ${DOCKERFILE} --target openzgy-build --build-arg AZURE_BUILDID=$(Build.BuildId) -t ${TAG}:ozbuild . + docker build -f ${DOCKERFILE} --target openzgy-testenv --build-arg AZURE_BUILDID=$(Build.BuildId) -t ${TAG}:oztests --iidfile oztests.iid . + docker rmi ${TAG}:{manual,sdbuild,ozbuild,oztests}-old || true + docker tag ${TAG}:manual ${TAG}:manual-old || true + docker tag ${TAG}:sdbuild ${TAG}:sdbuild-old || true + docker tag ${TAG}:ozbuild ${TAG}:ozbuild-old || true + docker tag ${TAG}:oztests ${TAG}:oztests-old || true + rmdir --ignore-fail-on-non-empty seismic-store-cpp-lib seismic-dms-sdapi private || true + id=$(docker create $(cat oztests.iid)) + docker cp ${id}:/home/me/oz/build/deploy - | gzip -9 > deploy.tgz + rm -rf deploy; mkdir deploy + docker cp ${id}:/home/me/oz/build/deploy - | tar -C . -xf - --exclude '*.timestamp' + docker rm ${id} + displayName: 'Build SD+OpenZGY' + +- bash: | + /bin/rm -f cid.txt + docker run --cidfile cid.txt -e CLIENT_ID -e CLIENT_SECRET -e OPENZGY_SDURL -e OPENZGY_SDAPIKEY -e LINUXDISTRO=${{parameters.linuxdistro}} $(cat oztests.iid) native/src/runtests.sh valgrind + docker cp $(cat cid.txt):/home/me/oz/build/deploy/native/valgrind.txt . + docker rm $(cat cid.txt) + /bin/rm -f cid.txt + + env: + OPENZGY_SDURL: $(SEISMIC_STORE_URL) + OPENZGY_SDAPIKEY: $(SEISMIC_STORE_KEY) + CLIENT_ID: $(OPENZGY_TEST_CLIENT_ID) + CLIENT_SECRET: $(OPENZGY_TEST_CLIENT_SECRET) + displayName: 'Test native' + +- bash: | + /bin/rm -f cid.txt + docker run --cidfile cid.txt -e CLIENT_ID -e CLIENT_SECRET -e OPENZGY_SDURL -e OPENZGY_SDAPIKEY -e LINUXDISTRO=${{parameters.linuxdistro}} $(cat oztests.iid) wrapper/runtests.sh valgrind + docker cp $(cat cid.txt):/home/me/oz/build/deploy/wrapper/valgrind-1.txt . + docker cp $(cat cid.txt):/home/me/oz/build/deploy/wrapper/valgrind-2.txt . + docker rm $(cat cid.txt) + /bin/rm -f cid.txt + + env: + OPENZGY_SDURL: $(SEISMIC_STORE_URL) + OPENZGY_SDAPIKEY: $(SEISMIC_STORE_KEY) + CLIENT_ID: $(OPENZGY_TEST_CLIENT_ID) + CLIENT_SECRET: $(OPENZGY_TEST_CLIENT_SECRET) + displayName: 'Test wrapper' + +- task: CopyFiles@2 + inputs: + contents: | + valgrind*.txt + targetFolder: $(Build.ArtifactStagingDirectory) + flattenFolders: false + +- bash: | + echo === Contents of $(Build.ArtifactStagingDirectory) + find $(Build.ArtifactStagingDirectory) -print + set -e -f + echo === + ( + cd "$(Build.ArtifactStagingDirectory)" + for i in ${{parameters.deployed}} + do + echo "Check that $i exists" + file=$(set +f; set -- $i; echo $1) + test -d "$file" -o -s "$file" || (echo "$file is missing"; exit 42) + done + ) + displayName: 'Check that artifacts exist' + +- task: PublishBuildArtifacts@1 + inputs: + pathToPublish: $(Build.ArtifactStagingDirectory) + artifactName: OpenZGY-${{parameters.linuxdistro}} diff --git a/azure/templates/coverage-build-steps.yml b/azure/templates/coverage-build-steps.yml index 469435f..7c79de8 100644 --- a/azure/templates/coverage-build-steps.yml +++ b/azure/templates/coverage-build-steps.yml @@ -1,3 +1,15 @@ +# Based on build-steps.yml but used to make a coverage report. +# The following explanation might help to keep the two in sync. +# Remove the separate test steps; tests now run as part of the build. +# instead of make, run "/bin/bash scripts/build-coverage.sh" +# Instead of copy-out deploy/..., need the following handled +# in both "docker cp" and CopyFiles@2: +# build/deploy/native/coverage.tgz +# native/src/summary.txt +# native/src/final.info +# The build step needs secrets etc. since it now also runs tests +# Remove the "universal publish" step. + parameters: linuxdistro: 'centos8' deployed: . @@ -39,9 +51,9 @@ steps: docker rmi -f ${TAG}:old ${TAG}:test || true /bin/rm -f cid.txt docker run --cidfile cid.txt -e CLIENT_ID -e CLIENT_SECRET -e OPENZGY_SDURL -e OPENZGY_SDAPIKEY -e LINUXDISTRO -e AZURE_BUILDID=$(Build.BuildId) ${TAG} /bin/bash scripts/build-coverage.sh - docker cp $(cat cid.txt):/home/build/oz/build/deploy/native/coverage.tgz coverage.tgz - docker cp $(cat cid.txt):/home/build/oz/native/src/summary.txt summary.txt - docker cp $(cat cid.txt):/home/build/oz/native/src/final.info final.info + docker cp $(cat cid.txt):/home/me/oz/build/deploy/native/coverage.tgz coverage.tgz + docker cp $(cat cid.txt):/home/me/oz/native/src/summary.txt summary.txt + docker cp $(cat cid.txt):/home/me/oz/native/src/final.info final.info docker rm $(cat cid.txt) /bin/rm -f cid.txt env: diff --git a/azure/templates/valgrind-build-steps.yml b/azure/templates/valgrind-build-steps.yml index 9c5b4fe..179cc35 100644 --- a/azure/templates/valgrind-build-steps.yml +++ b/azure/templates/valgrind-build-steps.yml @@ -1,3 +1,16 @@ +# Based on build-steps.yml but used to make a valgrind report. +# The following explanation might help to keep the two in sync. +# Disable optimizer when building. +# Remove "Test sdglue" and "Test pure" steps. +# Change "runtests.sh" to "runtests.sh valgrind" two places +# Both the remaining tests need to copy out some files, +# which means the cid needs to be captured. The files are: +# build/deploy/native/valgrind.txt +# build/deploy/wrapper/valgrind-1.txt +# build/deploy/wrapper/valgrind-2.txt +# This is also reflected in CopyFiles@2, only export valgrind*.txt. +# Remove the "universal publish" step. + parameters: linuxdistro: 'centos8' deployed: . @@ -43,9 +56,9 @@ steps: # Note, keep the CopyFiles task below in sync with this choice. # deploy.tgz needs download to check the contents # deploy/** breaks symbolic links. - docker cp $(cat cid.txt):/home/build/oz/build/deploy - | gzip -9 > deploy.tgz + docker cp $(cat cid.txt):/home/me/oz/build/deploy - | gzip -9 > deploy.tgz rm -rf deploy; mkdir deploy - docker cp $(cat cid.txt):/home/build/oz/build/deploy - | tar -C . -xf - --exclude '*.timestamp' + docker cp $(cat cid.txt):/home/me/oz/build/deploy - | tar -C . -xf - --exclude '*.timestamp' docker rm $(cat cid.txt) /bin/rm -f cid.txt docker build -t ${TAG}:test -f ${DOCKERFILE}-test . diff --git a/doc/dockerstages.md b/doc/dockerstages.md new file mode 100644 index 0000000..ae3ad9f --- /dev/null +++ b/doc/dockerstages.md @@ -0,0 +1,84 @@ +## Dockerfiles + +See also sd-env/README-details.md. + +There are now two sets of docker files to build OpenZGY, +in addition to the option of just using "make" without docker. +Which to choose depends on what you want to achieve. + +### To build locally on developer machine + +Use the top level Makefile. + +#### Drawbacks: + +- Difficult to have reproducible builds. + +- Difficult to integrate with Seismic Store, see next item. + +### To build OpenZGY only + +In ```scripts/Dockerfile-{distro}``` there is a setup to build OpenZGY only. +In the same folder there is also ```scripts/Dockerfile-{distro}-test``` +showing the minimal environment needed to install OpenZGY. The latter +is also used for running unit tests. + +It is also possible to use the dockerfiles in sd-env for OpenZGY-only +builds, see [README-details.md](../sd-env/README-details.md) in sd-env +for details. Due to limitations in the current version of docker this +is not recommended. Stages that don't affect the final result may still +get built. + +#### Drawbacks: + +- It is possible to integrate Seismic Store with this build but this + requires some manual steps. The seismic store SDK must be built and + placed in + ```seismic-service-bin/Lin64_gcc{version}/sdapi_linux64_osdu.tar.gz.``` + If you don't need Seismic Store integration this issue is moot. + +- Maintaining two sets of dockerfiles (three if you count the -test + file) is tedious and error prone. + +### To build both Seismic Store and OpenZGY + +This is intended to be a single-click build if the complete system. In +```sd-env/Dockerfile-{distro}``` there is a setup to build Seismic +Store prerequisites, seismic store itself, and OpenZGY. + +#### Drawbacks: + +- Both Seismic Store and OpenZGY will be rebuilt each time. This in + itself is not a big issue since building Seismic Store is fairly + quick. + +- Due to how Docker works, the system will occasionally also rebuild + the Seismic Store prerequisites such as Azure Storage, even when not + needed. This can easily take several times longer than just Seismic + Store and OpenZGY. Irritating but harmless. A partial mitigation is + to tag some of the intermediate builds. + See + [build-steps-osdu.yml](../azure/templates/build-steps-osdu.yml) + in azure/templates and the + [Makefile](../sd-env/Makefile) in sd-env. + +- The pipelines in Azure Devops don't handle pulling from multiple + repositories very well. Internally in SLB this becomes somewhat + awkward. For public builds where all inputs are public it probably + works better. + +- The pipelines in Azure Devops have problems detecting when third + party libraries need to be rebuilt. Especially those managed by + vcpkg. They do get built from scratch if the base image (e.g. + centos:centos8) is updated but that means the time for rebuild will + appear to be random. One partial mitigation is to clone vcpkg using + a hard coded hash. That approach comes with its own problems. + Somebody must remember to manually upgrade the vcpkg version ever so + often. + +- The all in one dockerfiles are complex and difficult to maintain. + See below for a diagram. + +#### Dockerfile layout for Seismic Store plus OpenZGY + +![Visualize Dockerfile layout](images/dockerstages-fig1.png) diff --git a/doc/images/dockerstages-fig1.dot b/doc/images/dockerstages-fig1.dot new file mode 100644 index 0000000..4d4a7c1 --- /dev/null +++ b/doc/images/dockerstages-fig1.dot @@ -0,0 +1,39 @@ +digraph "Docker stages for OpenZGY builds" { +graph [overlap=false rankdir="TB"]; +edge [minlen=1] +node [shape=box] +intro [label="Dockerfile stages\lAll distros mostly look like this,\lbut there are some variations.\l", color="invis"] +"devtoolset" [shape=record label="{Devtoolset|Compiler upgrade\l(if required)\l}"] +"sdapi-base" [shape=record label="{sdapi-base|Install some\limportant packages\l}"] +"sdapi-vcpkg" [shape=record label="{sdapi-vcpkg|Add Azure Sorage\land other vcpkg\ldependencies\lMay take a long time!\l}"] +"sdapi-manual" [shape=record label="{sdapi-manual|Add more dependencies.\lIf none, do vcpkg\lhere instead\l|TAG: \{distro\}:manual}"] +"sdapi-build" [shape=record label="{sdapi-build|Copies source from\lhost, builds SDAPI\l|TAG: \{distro\}:sdbuild}"] +"openzgy-source-vanilla" [shape=record label="{openzgy-source-vanilla|Install prerequisites\lCopies OpenZGY\lsources from host\l}"] +"openzgy-source-cloud" [shape=record label="{openzgy-source-cloud|Add SDAPI binaries\lfrom earlier stage\l}"] +"openzgy-build" [shape=record label="{openzgy-build|Builds OpenZGY\l|TAG: \{distro\}:ozbuild}"] +"openzgy-minimal" [label="openzgy-minimal\nExample of how\lto consume OpenZGY\l"] +"openzgy-testenv" [shape=record label="{openzgy-testenv|Add unit tests to\lthe minimal image\lAlso as a convenience\lexport SDAPI SDK\lfrom here\l|TAG: \{distro\}:oztests\l}"] +"openzgy-test" [shape=record label="{openzgy-test|Run unit tests\lNote, might be\lbetter to do this\lin a 'docker run'\l}"] +"deliverables" [label="Both OpenZGY\ldeliverables and\lSDAPI (for use\lin ZGY-Cloud)\lcan be extracted\lfrom this image.\l", color=invis] + +"Linux distro" -> "devtoolset" +"devtoolset" -> "sdapi-base" +"sdapi-base" -> "sdapi-vcpkg" +"sdapi-vcpkg" -> "sdapi-manual" +"sdapi-manual" -> "sdapi-build" + +"devtoolset" -> "openzgy-source-vanilla"; + +"openzgy-source-vanilla" -> "openzgy-source-cloud" +"openzgy-source-vanilla" -> "openzgy-build" [label="disable\lseismic\lstore\l"] + +"openzgy-source-cloud" -> "openzgy-build"; +"devtoolset" -> "openzgy-minimal"; +"openzgy-minimal" -> "openzgy-testenv"; +"openzgy-testenv" -> "openzgy-test"; + +"sdapi-build" -> "openzgy-source-cloud" [style=dashed, constraint=false]; +"openzgy-build" -> "openzgy-minimal" [style=dashed, constraint=false]; +"sdapi-build" -> "openzgy-testenv" [style=dashed, constraint=false, label="convenience\lonly\l"]; +"openzgy-testenv" -> "deliverables" [style=dashed] +} diff --git a/doc/images/dockerstages-fig1.png b/doc/images/dockerstages-fig1.png new file mode 100644 index 0000000000000000000000000000000000000000..c3ff3cf7775037ff6ba8d9462774dee5d38cd95b GIT binary patch literal 112944 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

?T1cZ~Td0^$Xq*U;=TfeI%;+ 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 literal 0 HcmV?d00001 diff --git a/native/sdglue/runtests.sh b/native/sdglue/runtests.sh index eb78735..d5dbb8a 100755 --- a/native/sdglue/runtests.sh +++ b/native/sdglue/runtests.sh @@ -42,12 +42,18 @@ else # present but not for this platform. This is assumed to be a # real problem. It will cause failures below, so I don't # need an explicit test here. - echo "OpenZGY was built with Seismic Store. Testing sdglue." + echo "OpenZGY was built with Seismic Store. Prepare to test sdglue." fi # Local tricks in my environment to get a valid SAuth token. eval $(test ! -x private/grabtoken.sh || private/grabtoken.sh -v) +if [ x"$OPENZGY_TOKEN" = x ] +then + echo >&2 "Skipping sdglue tests because no credentials given." + exit 0 +fi + # I'd rather not depend on scripts/getdistro and g++ -dumpfullversion here, # because the tests ought to be runnable even without the compiler present. # So, just look at the deploy folder and use whatever architecture is there. diff --git a/native/sdglue/setup.py b/native/sdglue/setup.py index b662ffc..f33c77c 100755 --- a/native/sdglue/setup.py +++ b/native/sdglue/setup.py @@ -26,7 +26,7 @@ are not supported and might not work correctly. from setuptools import setup, Extension import os -version = "0.2." + os.getenv("AZURE_BUILDID", "unknown") +version = "0.2." + (os.getenv("AZURE_BUILDID", "dev0") or "dev0") module1 = Extension('sdglue', libraries = ['sdapi' ], diff --git a/native/src/Makefile b/native/src/Makefile index 4aa2d8f..b3c1562 100644 --- a/native/src/Makefile +++ b/native/src/Makefile @@ -46,7 +46,6 @@ TESTDATARW = $(BUILDROOT)/build/testdata LIB = LIB += $(ORIGIN) -LIB += -lpthread -lcurl -lssl -lcrypto -ldl CXXFLAGS += $(SD_CXXFLAGS) $(ZFP_CXXFLAGS) @@ -191,10 +190,17 @@ $(LIBDSO): $(MAIN_OBJ) $(SD_SENTINEL) $(ZFP_SENTINEL) | $(BIN_DIR) $(RM) $(BIN_DIR)/libsdapi.so* $(BIN_DIR)/libzfp.so* ifneq ($(strip $(SD_LIBRARY)),) /bin/cp -a -t $(BIN_DIR) $(strip $(SD_LIBRARY))* + /bin/mkdir -p $(BUILDROOT)/build/deploy/sdapi/$(PLATFORM) + test ! -r $(SD_ZIPFILE) || /bin/cp -p -t $(BUILDROOT)/build/deploy/sdapi/$(PLATFORM) $(SD_ZIPFILE) endif ifneq ($(strip $(ZFP_LIBRARY)),) /bin/cp -a -t $(BIN_DIR) $(strip $(ZFP_LIBRARY))* endif + echo "OPENZGY:" $$($(BUILDROOT)/scripts/gethead.sh $(BUILDROOT)) > $(BIN_DIR)/../../version.txt + test ! -r $(SD_BUILDDIR)/version.txt || cat $(SD_BUILDDIR)/version.txt >> $(BIN_DIR)/../../version.txt + echo >> $(BIN_DIR)/../../version.txt + echo "DYNAMIC $@" >> $(BIN_DIR)/../../version.txt + ldd $@ >> $(BIN_DIR)/../../version.txt # SD_LIBRARY is only needed because of test/sdutils.cpp doing direct access # to SDAPI and bypassing OpenZGY entirely. @@ -241,6 +247,8 @@ clean: packages-clean clobber: clean $(RM) -rf $(BUILDROOT)/build/deploy/native + $(RM) -rf $(BUILDROOT)/build/deploy/sdapi + $(RM) -rf $(BUILDROOT)/build/deploy/version.txt # The automatic dependency generator doesn't catch SDAPI / ZFP header files. $(OBJ_DIR)/impl/file_sd.o: $(SD_SENTINEL) diff --git a/native/src/test/test_api.cpp b/native/src/test/test_api.cpp index fbd71d0..61162e4 100644 --- a/native/src/test/test_api.cpp +++ b/native/src/test/test_api.cpp @@ -2823,8 +2823,7 @@ public: #ifdef HAVE_SD register_sd_test("api.write_cloud", test_write_cloud); register_sd_test("api.write_cloud_mt", test_write_cloud_mt); - // FAILS: Need to make the dataset read-only. - //register_sd_test("api.alturl", test_alturl); + register_sd_test("api.alturl", test_alturl); #endif register_test("api.historange", test_historange); register_test("api.lod_lowpass", test_lod_lowpass); diff --git a/python/setup.py b/python/setup.py index 133fe69..7504d5f 100755 --- a/python/setup.py +++ b/python/setup.py @@ -19,7 +19,7 @@ import setuptools, os with open("README.md", "r") as fh: long_description = fh.read() -version = "0.2." + os.getenv("AZURE_BUILDID", "unknown") +version = "0.2." + (os.getenv("AZURE_BUILDID", "dev0") or "dev0") setuptools.setup( name="OpenZGY", diff --git a/scripts/Dockerfile-bionic b/scripts/Dockerfile-bionic index 749116a..54da00e 100644 --- a/scripts/Dockerfile-bionic +++ b/scripts/Dockerfile-bionic @@ -13,25 +13,24 @@ # limitations under the License. FROM ubuntu:bionic +ENV LINUXDISTRO=bionic -# Change this if the cache needs to be invalidated on all build servers. -ARG TOUCH=1 +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} RUN apt-get update; \ DEBIAN_FRONTEND=noninteractive apt-get -y install \ make cmake gcc gdb strace valgrind \ - uuid-dev libssl-dev libcurl4-openssl-dev \ + uuid-dev \ curl vim cpio zip unzip doxygen sudo \ python3-dev python3-pip python3-setuptools python3-tk RUN pip3 install wheel virtualenv numpy cython -WORKDIR /home/build/oz -COPY ./ ./ +RUN useradd -m -u 800 -G sudo --shell /bin/bash -p '' me +USER me +WORKDIR /home/me -# Optional: Run as a regular user -RUN useradd -u 800 -g users build; \ - apt-get -y install sudo; \ - echo 'build ALL = (ALL) NOPASSWD: ALL' >> /etc/sudoers; \ - chown -R build /home/build -USER build +# SOURCE CODE FROM BUILD CONTEXT COPIED IN +COPY --chown=800 ./ oz/ +WORKDIR /home/me/oz diff --git a/scripts/Dockerfile-buster b/scripts/Dockerfile-buster index abf7e26..d58ac67 100644 --- a/scripts/Dockerfile-buster +++ b/scripts/Dockerfile-buster @@ -20,18 +20,16 @@ ARG TOUCH=1 RUN apt-get update; \ DEBIAN_FRONTEND=noninteractive apt-get -y install \ make cmake gcc gdb strace valgrind \ - uuid-dev libssl-dev libcurl4-openssl-dev \ + uuid-dev \ curl vim cpio zip unzip doxygen sudo \ python3-dev python3-pip python3-setuptools python3-tk RUN pip3 install wheel virtualenv numpy cython -WORKDIR /home/build/oz -COPY ./ ./ +RUN useradd -m -u 800 -G sudo --shell /bin/bash -p '' me +USER me +WORKDIR /home/me -# Optional: Run as a regular user -RUN useradd -u 800 -g users build; \ - apt-get -y install sudo; \ - echo 'build ALL = (ALL) NOPASSWD: ALL' >> /etc/sudoers; \ - chown -R build /home/build -USER build +# SOURCE CODE FROM BUILD CONTEXT COPIED IN +COPY --chown=800 ./ oz/ +WORKDIR /home/me/oz diff --git a/scripts/Dockerfile-centos7 b/scripts/Dockerfile-centos7 index 47e5509..0f88382 100644 --- a/scripts/Dockerfile-centos7 +++ b/scripts/Dockerfile-centos7 @@ -14,7 +14,7 @@ FROM centos:centos7 -RUN yum -y install epel-release; \ +RUN yum -y install epel-release && \ yum -y install \ make cmake3 gcc-c++ libgomp gdb strace \ uuid uuid-devel openssl openssl-devel valgrind-devel libxslt \ @@ -30,23 +30,10 @@ RUN /bin/rm -f /usr/bin/pip3; \ test -r /usr/bin/python3 || ln -s python3.6 /usr/bin/python3; \ test -r /usr/bin/pip3 || ln -s /usr/local/bin/pip3 /usr/bin/pip3 -# Add ~300 packages to allow Doxygen to generate a single-file refman.pdf -# Hint: if tex bails out on e.g. 'tabu.sty': yum whatprovides */tabu.sty -#RUN yum -y install texlive ghostscript \ -# texlive-epstopdf texlive-xtab texlive-multirow \ -# texlive-adjustbox texlive-sectsty texlive-tocloft +RUN useradd -m -u 800 -G wheel --shell /bin/bash -p '' me +USER me +WORKDIR /home/me -WORKDIR /home/build/oz -COPY ./ ./ - -# Optional: Run as a regular user -RUN adduser -u 800 -g users -G wheel build; \ - yum -y install sudo; \ - echo 'build ALL = (ALL) NOPASSWD: ALL' >> /etc/sudoers; \ - chown -R build /home/build -USER build - -### Usage example: -# -# docker build --pull -t oz -f scripts/Dockerfile-centos7 . -# docker run --rm -it --cap-add sys_ptrace -v ${HOME}/.sdcfg:/home/build/.sdcfg -e OPENZGY_TOKEN=`sdutil auth idtoken` oz +# SOURCE CODE FROM BUILD CONTEXT COPIED IN +COPY --chown=800 ./ oz/ +WORKDIR /home/me/oz diff --git a/scripts/Dockerfile-centos8 b/scripts/Dockerfile-centos8 index beb86ce..4ea16f9 100644 --- a/scripts/Dockerfile-centos8 +++ b/scripts/Dockerfile-centos8 @@ -13,16 +13,17 @@ # limitations under the License. FROM centos:centos8 +ENV LINUXDISTRO=centos8 -# Change this if the cache needs to be invalidated on all build servers. -ARG TOUCH=1 +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} RUN dnf -y install epel-release dnf-plugins-core; \ dnf config-manager --set-enabled powertools; \ dnf -y install \ make cmake gcc-c++ libgomp gdb strace \ - uuid uuid-devel openssl openssl-devel valgrind-devel libxslt \ - curl curl-devel bzip2 less zip unzip which sudo doxygen java \ + uuid uuid-devel valgrind-devel libxslt \ + curl bzip2 less zip unzip which sudo doxygen java \ python2 python3 python3-devel python3-tkinter RUN python3 -m ensurepip; \ @@ -33,51 +34,15 @@ RUN python3 -m ensurepip; \ # tigervnc-server openssh-server dbus-x11 \ # xterm firefox emacs ImageMagick icewm ksysguard -# Add ~300 packages to allow Doxygen to generate a single-file refman.pdf -#RUN dnf -y install texlive \ -# texlive-epstopdf texlive-tabu texlive-multirow \ -# texlive-adjustbox texlive-sectsty texlive-tocloft - -# --- TEMPORARY KLUDGES -- # -RUN dnf -y install libarchive # CMake bug, deps to newer version are missing. - -# Workaround for a bug in the Azure SDK or one of ite dependencies, -# sometimes looking for the certificate file in the wrong place. - +# CMake bug, deps to newer version are missing. +RUN dnf -y install libarchive +# sometimes Azure SDK looks for the certificate file in the wrong place. RUN test -r /etc/ssl/cert.pem || ln -s /etc/pki/tls/cert.pem /etc/ssl/cert.pem -WORKDIR /home/build/oz -COPY ./ ./ - -# Optional: Run as a regular user -RUN adduser -u 800 -g users -G wheel build; \ - dnf -y install sudo; \ - echo 'build ALL = (ALL) NOPASSWD: ALL' >> /etc/sudoers; \ - chown -R build /home/build -USER build +RUN useradd -m -u 800 -G wheel --shell /bin/bash -p '' me +USER me +WORKDIR /home/me -# Currently most of the temporary and result folders end up in the source tree; -# this makes it difficult to map the source folder instead of copying source -# into the docker image. -# For python builds, --bdist-dir and --dist-dir help somewhat but is not perfect. -# -# testdata/Empty-v1.zgy -# testdata/Empty-v3.zgy -# python/OpenZGY.egg-info/* -# python/build/* -# native/build/* -# wrapper/build/* -# wrapper/OpenZgyBindings.egg-info/* -# -# Currently some tests consume data outside the source tree. -# python/openzgy/test/white.py -> two of the Salt2 files -# wrapper/show.py -> displays Salt2 by default. -# native/src/test/test_api.cpp -> TinyHCA.zgy -# Other current issues: -# Test iocontext.defaults fails when hack token is set. -# test/test_iocontext.cpp:51 - -### Usage example: -# -# docker build --pull -t oz -f Dockerfile-centos8 . -# docker run --rm -it --cap-add sys_ptrace -v ${HOME}/.sdcfg:/home/build/.sdcfg -e OPENZGY_TOKEN=`sdutil auth idtoken` oz +# SOURCE CODE FROM BUILD CONTEXT COPIED IN +COPY --chown=800 ./ oz/ +WORKDIR /home/me/oz diff --git a/scripts/Dockerfile-focal b/scripts/Dockerfile-focal index 7dab7eb..cc88f7e 100644 --- a/scripts/Dockerfile-focal +++ b/scripts/Dockerfile-focal @@ -13,30 +13,24 @@ # limitations under the License. FROM ubuntu:focal +ENV LINUXDISTRO=focal -# Change this if the cache needs to be invalidated on all build servers. -ARG TOUCH=1 +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} RUN apt-get update; \ DEBIAN_FRONTEND=noninteractive apt-get -y install \ make cmake gcc gdb strace valgrind \ - uuid-dev libssl-dev libcurl4-openssl-dev \ + uuid-dev \ curl vim cpio zip unzip doxygen sudo \ python3-dev python3-pip python3-setuptools python3-tk -# Add ~300 packages to allow Doxygen to generate a single-file refman.pdf -#RUN apt-get update; \ -# apt-get -y install pdftk texlive \ -# texlive-font-utils texlive-latex-extra - RUN pip3 install wheel virtualenv numpy cython -WORKDIR /home/build/oz -COPY ./ ./ +RUN useradd -m -u 800 -G sudo --shell /bin/bash -p '' me +USER me +WORKDIR /home/me -# Optional: Run as a regular user -RUN useradd -u 800 -g users build; \ - apt-get -y install sudo; \ - echo 'build ALL = (ALL) NOPASSWD: ALL' >> /etc/sudoers; \ - chown -R build /home/build -USER build +# SOURCE CODE FROM BUILD CONTEXT COPIED IN +COPY --chown=800 ./ oz/ +WORKDIR /home/me/oz diff --git a/scripts/gethead.sh b/scripts/gethead.sh new file mode 100755 index 0000000..b2978b9 --- /dev/null +++ b/scripts/gethead.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# Crude replacement for "git rev-parse HEAD" to be used if git is not +# installed or if most of the .git folder has been excluded by .dockerignore. +# Beware that this might give the wrong result in some circumstances. + +function gethead { + gitdir="${1:-.}/.git" + if [ -r "${gitdir}/HEAD" ] + then + read hash ref < "${gitdir}/HEAD" + if [ "x$hash" = "xref:" -a "x$ref" != "x" -a -r "${gitdir}/$ref" ] + then + read hash < "${gitdir}/$ref" + fi + else + hash=no-hash-available + fi + echo $hash +} + +gethead "$1" diff --git a/sd-env/Dockerfile b/sd-env/Dockerfile deleted file mode 100644 index 007eedf..0000000 --- a/sd-env/Dockerfile +++ /dev/null @@ -1,89 +0,0 @@ -FROM centos:centos7 - -# Get the latest and greatest CentOS? Not recommended. -# Some basic packages won't upgrade properly when inside docker. -# Also, the run command will normally be cached so it is a bit -# hit or miss which versions we actually end up with. -# Instead, trust the package maintainer to integrate important -# security patches in a timely manner. Or hope that security -# issues usually only apply to the host anyway. -#RUN yum -y update - -# The current version of seismic-drive is build using a non standard -# toolchain with gcc 4.9.2. That needs to be downloaded separately. -# A somewhat better approach is to install devtoolset-3 on top of -# centos 7. This will give us that particular compiler and also -# the entire toolchain that comes with it. The downside is that this -# is going to install ~500 packages. - -RUN yum install -y centos-release-scl && yum install -y devtoolset-3 - -# If you are going to run "sdutil auth login", this needs a full graphical -# environment which you can connect to with vnc. This will pull in ~500 -# packages so don't do it if you don't need it. The alternative is to -# pull in your ~/.sdcfg file from outside the docker environment. - -RUN yum install -y epel-release && yum install -y icewm tigervnc-server firefox - -# Install other packages the build depends on. -# devtoolset-3 might have pulled some of them as dependencies, -# but it doesn't harm to do them again. - -RUN yum install -y make which git emacs sudo cmake3 libcurl-devel openssl-devel -RUN yum install -y python-pip && pip install --upgrade pip && pip install egg colorama flask requests - -# libcurl in CentOS 7 has serious performance issues. Download and -# build from source. Preferably using a mirror. Use RUN not ADD -# because I don't want to invalidate the Docker cache and rebuild -# curl on every invocation. -ARG CURL=7.66.0 -#ADD https://curl.haxx.se/download/curl-$CURL.tar.bz2 /root/curl-$CURL.tar.bz2 -#ADD https://dl.uxnr.de/mirror/curl/curl-$CURL.tar.bz2 /root/curl-$CURL.tar.bz2 -RUN curl -sS -o /root/curl-$CURL.tar.bz2 https://dl.uxnr.de/mirror/curl/curl-$CURL.tar.bz2 - -# Build the curl source downloaded earlier and replace the one we have. -# Caveat: Replacing the system version of curl that several other packages -# depend on. Applications compiled against curl 7.29.0 will now dynamically -# link with $CURL. This might not end well. The reason I do it this way -# is to make sure libsdapi and its dependents use a consistent version. -RUN set -e; cd /root; tar jxf curl-$CURL.tar.bz2; cd curl-$CURL; ./configure --prefix /usr --libdir=/usr/lib64; make; rpm -e --nodeps libcurl-devel libcurl curl; make install - -# A regular user, not root, should be used for development. -RUN useradd -G wheel -p '' me - -# Run a script that drops root privileges and switches to the same -# numerical userid as the user that started the docker image. -# This user will be allowed to sudo back to root if required. -# PID 1 will be a bash shell, needed to partly fix the problem of -# zombies. Bash correctly reaps adopted processes but it doesn't -# propagate signals. So "docker stop" causes an unclean exit. -# https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/ -# The "set -a" is just a trick to avoid having the shell exec the script. -ENTRYPOINT ["/bin/bash"] -CMD ["-c", "set -a; /home/me/tools/switchuser.sh"] - -# Misc. configuration goes here. -RUN mkdir -p /home/me/.vnc; echo 'xterm & /usr/bin/icewm; vncserver -kill ${DISPLAY}' > /home/me/.vnc/xstartup; chmod 755 /home/me/.vnc/xstartup - -# Assuming that the work area is ~me/seismic-drive-client-api, -# make sdutil available globally without further installation. -RUN rm -f /bin/sdutil; (echo '#!/bin/bash'; echo 'exec env PYTHONPATH=/home/me/seismic-store-sdutil python /home/me/seismic-store-sdutil/sdutil.py' '"$@"') > /bin/sdutil; chmod 755 /bin/sdutil - -# The current directory may hold ad-hoc tools for debugging -# and usage examples. -COPY . /home/me/tools - - -### Usage example: -# -# docker build --pull -t sd-env:latest . -# -#docker build -t sd-env:latest . -# -#docker run -it -p 5901:5901 \ # vnc access -# -v ${HOME}/.ssh:/home/me/.ssh \ # ssh credentials -# -v ${HOME}/.sdcfg:/home/me/.sdcfg \ # seismic-drive cred -# -v ${WORKAREA}:/home/me/seismic-store-client-api-cpp \ # source code -# -v ${WORKAREA2}:/home/me/seismic-store-sdutil \ # source code -# --cap-add sys_ptrace \ # debugging -# sd-env:latest diff --git a/sd-env/Dockerfile-bionic b/sd-env/Dockerfile-bionic index b3fb7ec..1c14776 100644 --- a/sd-env/Dockerfile-bionic +++ b/sd-env/Dockerfile-bionic @@ -1,75 +1,183 @@ -FROM ubuntu:bionic - -# If you are going to run "sdutil auth login", this needs a full graphical -# environment which you can connect to with vnc. This will pull in ~500 -# packages so don't do it if you don't need it. The alternative is to -# pull in your ~/.sdcfg file from outside the docker environment. - -RUN apt-get update && apt-get -y install icewm xterm tightvncserver firefox - -# Install other packages the build depends on. -RUN apt-get -y install cmake curl g++ libcurl3-dev libssl-dev zip python python-pip git emacs vim sudo pkg-config -#RUN pip install --upgrade pip ## NOT! Latest pip is incompatible with xenial. -RUN pip install egg colorama flask requests - -# Azure prerequisites. Have patience. -RUN find / \( -name \*.so\* -o -name \*.a \) -type f -print0 | \ - sort -z | xargs -r0 md5sum > /root/before.md5; \ - find / -type f -print | sort -o /root/before.lst; true -RUN mkdir -p /opt && \ - cd /opt && \ - git clone https://github.com/microsoft/vcpkg.git && \ - cd vcpkg && \ - ./bootstrap-vcpkg.sh -disableMetrics +# Copyright 2017-2021, Schlumberger +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG variant=cloud + +############################################################################# +### SDAPI build prerequisites ########################################### +############################################################################# + +FROM ubuntu:bionic AS sdapi-base +ENV LINUXDISTRO=bionic + +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} + +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get -y install \ + g++ curl libcurl4-openssl-dev libssl-dev zip git vim sudo pkg-config cpio +RUN useradd -m -u 800 -G sudo --shell /bin/bash -p '' me +WORKDIR /home/me + +# vcpkg needs a newer CMake. +RUN curl -LSs -o /root/cmake.tar.gz https://github.com/Kitware/CMake/releases/download/v3.20.5/cmake-3.20.5.tar.gz && \ + tar zxf /root/cmake.tar.gz -C /root && cd /root/cmake-3.20.5 && \ + ./bootstrap -- -DCMAKE_BUILD_TYPE:STRING=Release && make -j4 && make install + +############################################################################# +### SDAPI third party dependencies (have patience) ###################### +############################################################################# + +FROM sdapi-base AS sdapi-manual +ARG vcpkg_branch=a6ef376f0d757c8b695b12f53d573f99a524e594 + +RUN mkdir -p /opt/vcpkg && chown me /opt/vcpkg +USER me +RUN git clone https://github.com/microsoft/vcpkg.git /opt/vcpkg && \ + cd /opt/vcpkg && git checkout ${vcpkg_branch} && \ + cd /opt/vcpkg && ./bootstrap-vcpkg.sh -disableMetrics RUN cd /opt/vcpkg; ./vcpkg install azure-storage-cpp RUN cd /opt/vcpkg; ./vcpkg install azure-storage-blobs-cpp -RUN find / \( -name \*.so\* -o -name \*.a \) -type f -print0 | \ - sort -z | xargs -r0 md5sum > /root/after.md5; \ - find / -type f -print | sort -o /root/after.lst; true - -# A regular user, not root, should be used for development. -RUN groupadd -r admin; useradd -G admin --shell /bin/bash -p '' me - -# Run a script that drops root privileges and switches to the same -# numerical userid as the user that started the docker image. -# This user will be allowed to sudo back to root if required. -# PID 1 will be a bash shell, needed to partly fix the problem of -# zombies. Bash correctly reaps adopted processes but it doesn't -# propagate signals. So "docker stop" causes an unclean exit. -# https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/ -# The "set -a" is just a trick to avoid having the shell exec the script. -ENTRYPOINT ["/bin/bash"] -CMD ["-c", "set -a; /home/me/tools/switchuser.sh"] - -# Misc. configuration goes here. -RUN mkdir -p /home/me/.vnc; echo 'xterm & /usr/bin/icewm; vncserver -kill ${DISPLAY}' > /home/me/.vnc/xstartup; chmod 755 /home/me/.vnc/xstartup - -# Assuming that the work area is ~me/seismic-drive-client-api, -# make sdutil available globally without further installation. -RUN rm -f /bin/sdutil; (echo '#!/bin/bash'; echo 'exec env PYTHONPATH=/home/me/seismic-store-sdutil python /home/me/seismic-store-sdutil/sdutil.py' '"$@"') > /bin/sdutil; chmod 755 /bin/sdutil - -# The current directory may hold ad-hoc tools for debugging -# and usage examples. -COPY . /home/me/tools + +############################################################################# +### Environment is ready, build SDAPI now! ############################## +############################################################################# + +FROM sdapi-manual AS sdapi-build + +# SOURCE CODE FROM BUILD CONTEXT COPIED IN +COPY --chown=800 seismic-store-cpp-lib /home/me/sdapi/ +COPY --chown=800 seismic-dms-sdapi /home/me/sdapi-slb/ +COPY --chown=800 ["sd-env/build-template.sh", "sd-env/*.patch", "/home/me/" ] +USER me + +RUN patch -p1 -N -d /home/me/sdapi -i /home/me/cmakelists2.patch || true +RUN test ! -d /home/me/sdapi-slb || (\ + cd /home/me/sdapi-slb && \ + find src/core src/lib/auth -print | cpio -pduv ../sdapi) +ARG AZURE_BUILDID +ENV AZURE_BUILDID=${AZURE_BUILDID} +RUN ./build-template.sh + +############################################################################# +### OpenZGY source code ################################################## +############################################################################# + +FROM ubuntu:bionic AS openzgy-source-vanilla ENV LINUXDISTRO=bionic -RUN (echo export LINUXDISTRO=$LINUXDISTRO; \ - echo export PS1='"\[\e[31;1m\]${LINUXDISTRO}\[\e[0m\] \[\e[32m\]\h\[\e[0m\] \W \$ "') \ - >> /home/me/.bash_profile -# Optional... -#RUN apt-get -y install xfce4 xfce4-goodies tightvncserver firefox -#RUN apt-get -y install openssh-server openssh-client -#RUN echo Remember to do /etc/init.d/ssh start +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} +RUN apt-get update; \ + DEBIAN_FRONTEND=noninteractive apt-get -y install \ + make cmake gcc gdb strace valgrind \ + uuid-dev \ + curl vim cpio zip unzip doxygen sudo \ + python3-dev python3-pip python3-setuptools python3-tk -### Usage example: -# -#docker build --pull -f Dockerfile-bionic -t sd-env-bionic:latest . -# -#docker run -it -p 5901:5901 \ # vnc access -# -v ${HOME}/.ssh:/home/me/.ssh \ # ssh credentials -# -v ${HOME}/.sdcfg:/home/me/.sdcfg \ # seismic-drive cred -# -v ${WORKAREA}:/home/me/seismic-store-client-api-cpp \ # source code -# -v ${WORKAREA2}:/home/me/seismic-store-sdutil \ # source code -# --cap-add sys_ptrace \ # debugging -# sd-env-bionic:latest +RUN pip3 install wheel virtualenv numpy cython + +RUN useradd -m -u 800 -G sudo --shell /bin/bash -p '' me +USER me +WORKDIR /home/me + +# SOURCE CODE FROM BUILD CONTEXT COPIED IN +COPY --chown=800 LICENSE.txt oz/LICENSE.txt +COPY --chown=800 Makefile oz/Makefile +COPY --chown=800 .git/ oz/.git/ +COPY --chown=800 doc/ oz/doc/ +COPY --chown=800 external/ oz/external/ +COPY --chown=800 native/ oz/native/ +COPY --chown=800 python/ oz/python/ +COPY --chown=800 scripts/ oz/scripts/ +COPY --chown=800 sd-env/ oz/sd-env/ +COPY --chown=800 testdata/ oz/testdata/ +COPY --chown=800 wrapper/ oz/wrapper/ +COPY --chown=800 ["private/grabtoken*.sh", "LICENSE.txt", "oz/private/"] +WORKDIR /home/me/oz + +############################################################################# +### OpenZGY source code with SDAPI binaries added ####################### +############################################################################# + +FROM openzgy-source-vanilla AS openzgy-source-cloud +COPY --from=sdapi-build --chown=800 /home/me/sdapi_linux64.tar.gz /home/me/ +#(debugging)COPY --from=sdapi-manual /opt/vcpkg /opt/vcpkg + +############################################################################# +### Environment is ready, build OPENZGY now! ############################ +############################################################################# + +FROM openzgy-source-${variant} AS openzgy-build +ARG AZURE_BUILDID +ENV AZURE_BUILDID=${AZURE_BUILDID} +RUN make -j 8 SD_ZIPFILE=/home/me/sdapi_linux64.tar.gz build testscripts + +############################################################################# +### Minimal docker image with OpenZGY Python and C++ installed ########## +############################################################################# + +FROM ubuntu:bionic AS openzgy-minimal + +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} + +RUN apt-get update; apt-get -y install python3 python3-pip + +COPY --from=openzgy-build /home/me/oz/build/deploy/ /home/me/oz/build/deploy/ +WORKDIR /home/me/oz +RUN python3 -m pip install build/deploy/pure/OpenZGY-*.whl +RUN python3 -m pip install build/deploy/sdglue/*/SdGlue-*.whl || true +RUN python3 -m pip install build/deploy/wrapper/*/OpenZgyBindings-*.whl +RUN du -skc build/deploy/native/* && ls -l build/deploy + +############################################################################# +### Add unit tests to the minimal image ################################# +############################################################################# + +FROM openzgy-minimal AS openzgy-testenv + +RUN tar xvf build/deploy/testscripts.tar && \ + python3 -m pip install virtualenv && \ + apt-get update && apt-get -y install bzip2 curl && \ + useradd -m -u 800 -G sudo --shell /bin/bash -p '' me && \ + chown -R 800 /home/me + +# Enable to make it simpler to extract the SDAPI SDK, for use e.g. by +# the old ZGY-Cloud library which doesn't have this kind of all-in-one build. +# Unfortunately this won't work wth variant=plain. +COPY --from=sdapi-build --chown=800 /home/me/sdapi_linux64.tar.gz /home/me/ +COPY --from=sdapi-build --chown=800 /home/me/realname.txt /home/me/ +USER me + +ENV CLIENT_ID="" \ + CLIENT_SECRET="" \ + OPENZGY_SDURL="" \ + OPENZGY_SDAPIKEY="" \ + OPENZGY_TOKEN="" \ + OPENZGY_TESTDATA="/home/me/oz/build/testdata" \ + OPENZGY_SDTESTDATA="sd://sntc/testdata" \ + OPENZGY_SDTESTSINK="sd://sntc/testsink/d" + +############################################################################# +### Run unit tests using the minimal image ############################## +############################################################################# + +FROM openzgy-testenv AS openzgy-test +RUN echo IN openzgy-test && ls +RUN native/src/runtests.sh +#RUN native/sdglue/runtests.sh +RUN wrapper/runtests.sh +RUN python/runtests.sh diff --git a/sd-env/Dockerfile-buster b/sd-env/Dockerfile-buster index 1e1bcec..5cb95fc 100644 --- a/sd-env/Dockerfile-buster +++ b/sd-env/Dockerfile-buster @@ -1,75 +1,183 @@ -FROM debian:buster -RUN apt-get update; apt-get -y install make gcc g++ valgrind gdb strace lcov xsltproc cpio zip unzip doxygen sudo vim less uuid-dev libssl-dev pkg-config - -# If you are going to run "sdutil auth login", this needs a full graphical -# environment which you can connect to with vnc. This will pull in ~500 -# packages so don't do it if you don't need it. The alternative is to -# pull in your ~/.sdcfg file from outside the docker environment. - -#RUN apt-get update && apt-get -y install icewm xterm tightvncserver firefox - -# Install other packages the build depends on. -RUN apt-get -y install cmake curl g++ libcurl3-dev zip python python-pip git -RUN pip install egg colorama flask requests - -# Azure prerequisites. Have patience. -RUN find / \( -name \*.so\* -o -name \*.a \) -type f -print0 | \ - sort -z | xargs -r0 md5sum > /root/before.md5; \ - find / -type f -print | sort -o /root/before.lst; true -RUN mkdir -p /opt && \ - cd /opt && \ - git clone https://github.com/microsoft/vcpkg.git && \ - cd vcpkg && \ - ./bootstrap-vcpkg.sh -disableMetrics +# Copyright 2017-2021, Schlumberger +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG variant=cloud + +############################################################################# +### SDAPI build prerequisites ########################################### +############################################################################# + +FROM debian:buster AS sdapi-base +ENV LINUXDISTRO=buster + +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} + +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get -y install \ + g++ curl make libcurl4-openssl-dev libssl-dev zip git vim sudo pkg-config cpio +RUN useradd -m -u 800 -G sudo --shell /bin/bash -p '' me +WORKDIR /home/me + +# vcpkg needs a newer CMake. +RUN curl -LSs -o /root/cmake.tar.gz https://github.com/Kitware/CMake/releases/download/v3.20.5/cmake-3.20.5.tar.gz && \ + tar zxf /root/cmake.tar.gz -C /root && cd /root/cmake-3.20.5 && \ + ./bootstrap -- -DCMAKE_BUILD_TYPE:STRING=Release && make -j4 && make install + +############################################################################# +### SDAPI third party dependencies (have patience) ###################### +############################################################################# + +FROM sdapi-base AS sdapi-manual +ARG vcpkg_branch=a6ef376f0d757c8b695b12f53d573f99a524e594 + +RUN mkdir -p /opt/vcpkg && chown me /opt/vcpkg +USER me +RUN git clone https://github.com/microsoft/vcpkg.git /opt/vcpkg && \ + cd /opt/vcpkg && git checkout ${vcpkg_branch} && \ + cd /opt/vcpkg && ./bootstrap-vcpkg.sh -disableMetrics RUN cd /opt/vcpkg; ./vcpkg install azure-storage-cpp RUN cd /opt/vcpkg; ./vcpkg install azure-storage-blobs-cpp -RUN find / \( -name \*.so\* -o -name \*.a \) -type f -print0 | \ - sort -z | xargs -r0 md5sum > /root/after.md5; \ - find / -type f -print | sort -o /root/after.lst; true - -# A regular user, not root, should be used for development. -RUN useradd -G sudo --shell /bin/bash -p '' me - -# Run a script that drops root privileges and switches to the same -# numerical userid as the user that started the docker image. -# This user will be allowed to sudo back to root if required. -# PID 1 will be a bash shell, needed to partly fix the problem of -# zombies. Bash correctly reaps adopted processes but it doesn't -# propagate signals. So "docker stop" causes an unclean exit. -# https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/ -# The "set -a" is just a trick to avoid having the shell exec the script. -ENTRYPOINT ["/bin/bash"] -CMD ["-c", "set -a; /home/me/tools/switchuser.sh"] - -# Misc. configuration goes here. -RUN mkdir -p /home/me/.vnc; echo 'xterm & /usr/bin/icewm; vncserver -kill ${DISPLAY}' > /home/me/.vnc/xstartup; chmod 755 /home/me/.vnc/xstartup - -# Assuming that the work area is ~me/seismic-drive-client-api, -# make sdutil available globally without further installation. -RUN rm -f /bin/sdutil; (echo '#!/bin/bash'; echo 'exec env PYTHONPATH=/home/me/seismic-store-sdutil python /home/me/seismic-store-sdutil/sdutil.py' '"$@"') > /bin/sdutil; chmod 755 /bin/sdutil - -# The current directory may hold ad-hoc tools for debugging -# and usage examples. -COPY . /home/me/tools + +############################################################################# +### Environment is ready, build SDAPI now! ############################## +############################################################################# + +FROM sdapi-manual AS sdapi-build + +# SOURCE CODE FROM BUILD CONTEXT COPIED IN +COPY --chown=800 seismic-store-cpp-lib /home/me/sdapi/ +COPY --chown=800 seismic-dms-sdapi /home/me/sdapi-slb/ +COPY --chown=800 ["sd-env/build-template.sh", "sd-env/*.patch", "/home/me/" ] +USER me + +RUN patch -p1 -N -d /home/me/sdapi -i /home/me/cmakelists2.patch || true +RUN test ! -d /home/me/sdapi-slb || (\ + cd /home/me/sdapi-slb && \ + find src/core src/lib/auth -print | cpio -pduv ../sdapi) +ARG AZURE_BUILDID +ENV AZURE_BUILDID=${AZURE_BUILDID} +RUN ./build-template.sh + +############################################################################# +### OpenZGY source code ################################################## +############################################################################# + +FROM debian:buster AS openzgy-source-vanilla ENV LINUXDISTRO=buster -RUN (echo export LINUXDISTRO=$LINUXDISTRO; \ - echo export PS1='"\[\e[31;1m\]${LINUXDISTRO}\[\e[0m\] \[\e[32m\]\h\[\e[0m\] \W \$ "') \ - >> /home/me/.bash_profile -# Optional... -#RUN apt-get -y install xfce4 xfce4-goodies tightvncserver firefox -#RUN apt-get -y install openssh-server openssh-client -#RUN echo Remember to do /etc/init.d/ssh start +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} +RUN apt-get update; \ + DEBIAN_FRONTEND=noninteractive apt-get -y install \ + make cmake gcc gdb strace valgrind \ + uuid-dev \ + curl vim cpio zip unzip doxygen sudo \ + python3-dev python3-pip python3-setuptools python3-tk -### Usage example: -# -#docker build --pull -f Dockerfile-buster -t sd-env-buster:latest . -# -#docker run -it -p 5901:5901 \ # vnc access -# -v ${HOME}/.ssh:/home/me/.ssh \ # ssh credentials -# -v ${HOME}/.sdcfg:/home/me/.sdcfg \ # seismic-drive cred -# -v ${WORKAREA}:/home/me/seismic-store-client-api-cpp \ # source code -# -v ${WORKAREA2}:/home/me/seismic-store-sdutil \ # source code -# --cap-add sys_ptrace \ # debugging -# sd-env-buster:latest +RUN pip3 install wheel virtualenv numpy cython + +RUN useradd -m -u 800 -G sudo --shell /bin/bash -p '' me +USER me +WORKDIR /home/me + +# SOURCE CODE FROM BUILD CONTEXT COPIED IN +COPY --chown=800 LICENSE.txt oz/LICENSE.txt +COPY --chown=800 Makefile oz/Makefile +COPY --chown=800 .git/ oz/.git/ +COPY --chown=800 doc/ oz/doc/ +COPY --chown=800 external/ oz/external/ +COPY --chown=800 native/ oz/native/ +COPY --chown=800 python/ oz/python/ +COPY --chown=800 scripts/ oz/scripts/ +COPY --chown=800 sd-env/ oz/sd-env/ +COPY --chown=800 testdata/ oz/testdata/ +COPY --chown=800 wrapper/ oz/wrapper/ +COPY --chown=800 ["private/grabtoken*.sh", "LICENSE.txt", "oz/private/"] +WORKDIR /home/me/oz + +############################################################################# +### OpenZGY source code with SDAPI binaries added ####################### +############################################################################# + +FROM openzgy-source-vanilla AS openzgy-source-cloud +COPY --from=sdapi-build --chown=800 /home/me/sdapi_linux64.tar.gz /home/me/ +#(debugging)COPY --from=sdapi-manual /opt/vcpkg /opt/vcpkg + +############################################################################# +### Environment is ready, build OPENZGY now! ############################ +############################################################################# + +FROM openzgy-source-${variant} AS openzgy-build +ARG AZURE_BUILDID +ENV AZURE_BUILDID=${AZURE_BUILDID} +RUN make -j 8 SD_ZIPFILE=/home/me/sdapi_linux64.tar.gz build testscripts + +############################################################################# +### Minimal docker image with OpenZGY Python and C++ installed ########## +############################################################################# + +FROM debian:buster AS openzgy-minimal + +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} + +RUN apt-get update; apt-get -y install python3 python3-pip + +COPY --from=openzgy-build /home/me/oz/build/deploy/ /home/me/oz/build/deploy/ +WORKDIR /home/me/oz +RUN python3 -m pip install build/deploy/pure/OpenZGY-*.whl +RUN python3 -m pip install build/deploy/sdglue/*/SdGlue-*.whl || true +RUN python3 -m pip install build/deploy/wrapper/*/OpenZgyBindings-*.whl +RUN du -skc build/deploy/native/* && ls -l build/deploy + +############################################################################# +### Add unit tests to the minimal image ################################# +############################################################################# + +FROM openzgy-minimal AS openzgy-testenv + +RUN tar xvf build/deploy/testscripts.tar && \ + python3 -m pip install virtualenv && \ + apt-get update && apt-get -y install bzip2 curl && \ + useradd -m -u 800 -G sudo --shell /bin/bash -p '' me && \ + chown -R 800 /home/me + +# Enable to make it simpler to extract the SDAPI SDK, for use e.g. by +# the old ZGY-Cloud library which doesn't have this kind of all-in-one build. +# Unfortunately this won't work wth variant=plain. +COPY --from=sdapi-build --chown=800 /home/me/sdapi_linux64.tar.gz /home/me/ +COPY --from=sdapi-build --chown=800 /home/me/realname.txt /home/me/ +USER me + +ENV CLIENT_ID="" \ + CLIENT_SECRET="" \ + OPENZGY_SDURL="" \ + OPENZGY_SDAPIKEY="" \ + OPENZGY_TOKEN="" \ + OPENZGY_TESTDATA="/home/me/oz/build/testdata" \ + OPENZGY_SDTESTDATA="sd://sntc/testdata" \ + OPENZGY_SDTESTSINK="sd://sntc/testsink/d" + +############################################################################# +### Run unit tests using the minimal image ############################## +############################################################################# + +FROM openzgy-testenv AS openzgy-test +RUN echo IN openzgy-test && ls +RUN native/src/runtests.sh +#RUN native/sdglue/runtests.sh +RUN wrapper/runtests.sh +RUN python/runtests.sh diff --git a/sd-env/Dockerfile-centos7 b/sd-env/Dockerfile-centos7 new file mode 100644 index 0000000..e6401db --- /dev/null +++ b/sd-env/Dockerfile-centos7 @@ -0,0 +1,238 @@ +# Copyright 2017-2021, Schlumberger +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG variant=cloud + +############################################################################# +### Devtoolset ######################################################### +############################################################################# + +FROM centos:centos7 AS sdapi-toolset-centos7 +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} +RUN yum install -y centos-release-scl && yum install -y devtoolset-7 + +############################################################################# +### SDAPI build prerequisites ########################################### +############################################################################# + +FROM sdapi-toolset-centos7 AS sdapi-base +# The SDAPI environment in "centos7" and "omega" are identical, +# use the same label to prevent a cache miss. +ENV LINUXDISTRO=omega + +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} + +RUN yum install -y epel-release && \ + yum install -y \ + make which git sudo cmake3 libcurl-devel openssl-devel bzip2 patch \ + autoconf expat-devel gettext-devel zlib-devel perl-CPAN perl-devel +RUN useradd -m -u 800 -G wheel --shell /bin/bash -p '' me +WORKDIR /home/me + +# Build GIT from sources because the newer git 2.x is needed for Azure. +# Install in /usr/local/bin. +ARG GITVER=2.18.0 +RUN curl -sS -o /root/git-$GITVER.tar.gz https://mirrors.edge.kernel.org/pub/software/scm/git/git-$GITVER.tar.gz +RUN set -e; \ + tar zxf /root/git-$GITVER.tar.gz -C /root; \ + cd /root/git-$GITVER; \ + make configure; \ + ./configure --prefix /usr/local; \ + make; \ + make install + +############################################################################# +### SDAPI third party dependencies (have patience) ###################### +############################################################################# + +FROM sdapi-base AS sdapi-vcpkg +ARG vcpkg_branch=a6ef376f0d757c8b695b12f53d573f99a524e594 + +RUN mkdir -p /opt/vcpkg && chown me /opt/vcpkg +USER me +RUN git clone https://github.com/microsoft/vcpkg.git /opt/vcpkg && \ + cd /opt/vcpkg && git checkout ${vcpkg_branch} && \ + cd /opt/vcpkg && \ + scl enable devtoolset-7 './bootstrap-vcpkg.sh -disableMetrics' +RUN cd /opt/vcpkg; scl enable devtoolset-7 './vcpkg install azure-storage-cpp' +RUN cd /opt/vcpkg; scl enable devtoolset-7 './vcpkg install azure-storage-blobs-cpp' + +############################################################################# +### Need a newer CURL ################################################### +############################################################################# + +FROM sdapi-vcpkg AS sdapi-manual +USER root + +# libcurl in CentOS 7 has serious performance issues. Download and +# build from source. Preferably using a mirror. Use RUN not ADD +# because I don't want to invalidate the Docker cache and rebuild +# curl on every invocation. +ARG CURL=7.74.0 +RUN curl -sSL -o /root/curl-$CURL.tar.bz2 https://curl.se/download/curl-$CURL.tar.bz2 + +# Build the curl source downloaded earlier and replace the one we have. +# Caveat: Replacing the system version of curl that several other packages +# depend on. Applications compiled against curl 7.29.0 will now dynamically +# link with $CURL. This might not end well. The reason I do it this way +# is to make sure libsdapi and its dependents use a consistent version. +# Caveat: The vcpkg dependencies might have their own idea. +RUN cd /root && \ + tar jxf curl-$CURL.tar.bz2 && \ + cd curl-$CURL && ./configure --prefix /usr --libdir=/usr/lib64 && \ + make && \ + rpm -e --nodeps libcurl-devel libcurl curl && \ + make install +USER me + +############################################################################# +### Environment is ready, build SDAPI now! ############################## +############################################################################# + +FROM sdapi-manual AS sdapi-build + +# SOURCE CODE FROM BUILD CONTEXT COPIED IN +COPY --chown=800 seismic-store-cpp-lib /home/me/sdapi/ +COPY --chown=800 seismic-dms-sdapi /home/me/sdapi-slb/ +COPY --chown=800 ["sd-env/build-template.sh", "sd-env/*.patch", "/home/me/" ] +USER me + +RUN patch -p1 -N -d /home/me/sdapi -i /home/me/cmakelists2.patch || true +RUN test ! -d /home/me/sdapi-slb || (\ + cd /home/me/sdapi-slb && \ + find src/core src/lib/auth -print | cpio -pduv ../sdapi) +ARG AZURE_BUILDID +ENV AZURE_BUILDID=${AZURE_BUILDID} +RUN scl enable devtoolset-7 ./build-template.sh + +############################################################################# +### OpenZGY source code ################################################## +############################################################################# + +FROM centos:centos7 AS openzgy-source-vanilla +ENV LINUXDISTRO=centos7 + +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} + +RUN yum -y install epel-release && \ + yum -y install \ + which python36 python36-devel python36-setuptools sudo make cmake3 \ + bzip2 gcc-c++ +RUN python3.6 -m ensurepip; \ + python3.6 -m pip install --upgrade pip; \ + python3.6 -m pip install wheel virtualenv numpy cython +RUN /bin/rm -f /usr/bin/pip3; \ + test -r /usr/bin/python3 || ln -s python3.6 /usr/bin/python3; \ + test -r /usr/bin/pip3 || ln -s /usr/local/bin/pip3 /usr/bin/pip3 + +## Note! libcurl is too old, but OpenZGY shouldn't link with it +## explicitly, so as long as linkage is dynamic it should not matter. + +RUN useradd -m -u 800 -G wheel --shell /bin/bash -p '' me +USER me +WORKDIR /home/me + +# SOURCE CODE FROM BUILD CONTEXT COPIED IN +COPY --chown=800 LICENSE.txt oz/LICENSE.txt +COPY --chown=800 Makefile oz/Makefile +COPY --chown=800 .git/ oz/.git/ +COPY --chown=800 doc/ oz/doc/ +COPY --chown=800 external/ oz/external/ +COPY --chown=800 native/ oz/native/ +COPY --chown=800 python/ oz/python/ +COPY --chown=800 scripts/ oz/scripts/ +COPY --chown=800 sd-env/ oz/sd-env/ +COPY --chown=800 testdata/ oz/testdata/ +COPY --chown=800 wrapper/ oz/wrapper/ +COPY --chown=800 ["private/grabtoken*.sh", "LICENSE.txt", "oz/private/"] +WORKDIR /home/me/oz + +############################################################################# +### OpenZGY source code with SDAPI binaries added ####################### +############################################################################# + +FROM openzgy-source-vanilla AS openzgy-source-cloud +COPY --from=sdapi-build --chown=800 /home/me/sdapi_linux64.tar.gz /home/me/ +#(debugging)COPY --from=sdapi-manual /opt/vcpkg /opt/vcpkg + +############################################################################# +### Environment is ready, build OPENZGY now! ############################ +############################################################################# + +FROM openzgy-source-${variant} AS openzgy-build +ARG AZURE_BUILDID +ENV AZURE_BUILDID=${AZURE_BUILDID} +RUN make -j 8 SD_ZIPFILE=/home/me/sdapi_linux64.tar.gz build testscripts + +############################################################################# +### Minimal docker image with OpenZGY Python and C++ installed ########## +############################################################################# + +FROM centos:centos7 AS openzgy-minimal + +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} + +RUN yum -y install python3 libgomp; python3 -m pip install --upgrade pip +# Workaround for a bug in the Azure SDK or one of its dependencies. +RUN test -r /etc/ssl/cert.pem || ln -s /etc/pki/tls/cert.pem /etc/ssl/cert.pem + +COPY --from=openzgy-build /home/me/oz/build/deploy/ /home/me/oz/build/deploy/ +WORKDIR /home/me/oz +RUN python3 -m pip install build/deploy/pure/OpenZGY-*.whl +RUN python3 -m pip install build/deploy/sdglue/*/SdGlue-*.whl || true +RUN python3 -m pip install build/deploy/wrapper/*/OpenZgyBindings-*.whl +RUN du -skc build/deploy/native/* && ls -l build/deploy + +############################################################################# +### Add unit tests to the minimal image ################################# +############################################################################# + +FROM openzgy-minimal AS openzgy-testenv + +RUN tar xvf build/deploy/testscripts.tar && \ + python3 -m pip install virtualenv && \ + yum -y install bzip2 curl valgrind sudo && \ + useradd -m -u 800 -G wheel --shell /bin/bash -p '' me && \ + chown -R 800 /home/me + +# Enable to make it simpler to extract the SDAPI SDK, for use e.g. by +# the old ZGY-Cloud library which doesn't have this kind of all-in-one build. +# Unfortunately this won't work wth variant=plain. +COPY --from=sdapi-build --chown=800 /home/me/sdapi_linux64.tar.gz /home/me/ +COPY --from=sdapi-build --chown=800 /home/me/realname.txt /home/me/ +USER me + +ENV CLIENT_ID="" \ + CLIENT_SECRET="" \ + OPENZGY_SDURL="" \ + OPENZGY_SDAPIKEY="" \ + OPENZGY_TOKEN="" \ + OPENZGY_TESTDATA="/home/me/oz/build/testdata" \ + OPENZGY_SDTESTDATA="sd://sntc/testdata" \ + OPENZGY_SDTESTSINK="sd://sntc/testsink/d" + +############################################################################# +### Run unit tests using the minimal image ############################## +############################################################################# + +FROM openzgy-testenv AS openzgy-test +RUN echo IN openzgy-test && ls +RUN native/src/runtests.sh +#RUN native/sdglue/runtests.sh +RUN wrapper/runtests.sh +RUN python/runtests.sh diff --git a/sd-env/Dockerfile-centos8 b/sd-env/Dockerfile-centos8 index 8b36eaa..5e2cb19 100644 --- a/sd-env/Dockerfile-centos8 +++ b/sd-env/Dockerfile-centos8 @@ -1,70 +1,211 @@ -FROM centos:centos8 +# Copyright 2017-2021, Schlumberger +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG variant=cloud + +############################################################################# +### SDAPI build prerequisites ########################################### +############################################################################# + +FROM centos:centos8 AS sdapi-base +ENV LINUXDISTRO=centos8 + +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} RUN dnf install -y \ make gcc-c++ libcurl-devel openssl-devel \ - which git sudo cmake patch python2 unzip zip diffutils -RUN echo dnf -y install \ - tigervnc-server openssh-server dbus-x11 \ - xterm firefox emacs ImageMagick icewm -RUN pip2 install --upgrade pip && pip2 install egg colorama flask requests - -# Azure prerequisites. Have patience. -RUN find / \( -name \*.so\* -o -name \*.a \) -type f -print0 | \ - sort -z | xargs -r0 md5sum > /root/before.md5; \ - find / -type f -print | sort -o /root/before.lst; true -RUN mkdir -p /opt && \ - cd /opt && \ - git clone https://github.com/microsoft/vcpkg.git && \ - cd vcpkg && \ - ./bootstrap-vcpkg.sh -disableMetrics + which git sudo cmake patch unzip zip diffutils +RUN useradd -m -u 800 -G wheel --shell /bin/bash -p '' me +WORKDIR /home/me + +# CMake bug, deps to newer version are missing. +RUN dnf -y install libarchive + +############################################################################# +### SDAPI third party dependencies (have patience) ###################### +############################################################################# + +FROM sdapi-base AS sdapi-manual +ARG vcpkg_branch=a6ef376f0d757c8b695b12f53d573f99a524e594 + +RUN mkdir -p /opt/vcpkg && chown me /opt/vcpkg +USER me +RUN git clone https://github.com/microsoft/vcpkg.git /opt/vcpkg && \ + cd /opt/vcpkg && git checkout ${vcpkg_branch} && \ + cd /opt/vcpkg && ./bootstrap-vcpkg.sh -disableMetrics RUN cd /opt/vcpkg; ./vcpkg install azure-storage-cpp RUN cd /opt/vcpkg; ./vcpkg install azure-storage-blobs-cpp -RUN find / \( -name \*.so\* -o -name \*.a \) -type f -print0 | \ - sort -z | xargs -r0 md5sum > /root/after.md5; \ - find / -type f -print | sort -o /root/after.lst; true - -# --- TEMPORARY KLUDGES -- # -RUN dnf -y install libarchive # CMake bug, deps to newer version are missing. - -RUN useradd -G wheel -p '' me - -# Run a script that drops root privileges and switches to the same -# numerical userid as the user that started the docker image. -# This user will be allowed to sudo back to root if required. -# PID 1 will be a bash shell, needed to partly fix the problem of -# zombies. Bash correctly reaps adopted processes but it doesn't -# propagate signals. So "docker stop" causes an unclean exit. -# https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/ -# The "set -a" is just a trick to avoid having the shell exec the script. -ENTRYPOINT ["/bin/bash"] -CMD ["-c", "set -a; /home/me/tools/switchuser.sh"] - -# Misc. configuration goes here. -RUN mkdir -p /home/me/.vnc; echo 'xterm & /usr/bin/icewm; vncserver -kill ${DISPLAY}' > /home/me/.vnc/xstartup; chmod 755 /home/me/.vnc/xstartup - -# Assuming that the work area is ~me/seismic-drive-client-api, -# make sdutil available globally without further installation. -RUN rm -f /bin/sdutil; (echo '#!/bin/bash'; echo 'exec env PYTHONPATH=/home/me/seismic-store-sdutil python /home/me/seismic-store-sdutil/sdutil.py' '"$@"') > /bin/sdutil; chmod 755 /bin/sdutil - -# The current directory may hold ad-hoc tools for debugging -# and usage examples. -COPY . /home/me/tools + +############################################################################# +### Environment is ready, build SDAPI now! ############################## +############################################################################# + +FROM sdapi-manual AS sdapi-build + +# SOURCE CODE FROM BUILD CONTEXT COPIED IN +COPY --chown=800 seismic-store-cpp-lib /home/me/sdapi/ +COPY --chown=800 seismic-dms-sdapi /home/me/sdapi-slb/ +COPY --chown=800 ["sd-env/build-template.sh", "sd-env/*.patch", "/home/me/" ] +USER me + +RUN patch -p1 -N -d /home/me/sdapi -i /home/me/cmakelists2.patch || true +RUN test ! -d /home/me/sdapi-slb || (\ + cd /home/me/sdapi-slb && \ + find src/core src/lib/auth -print | cpio -pduv ../sdapi) +ARG AZURE_BUILDID +ENV AZURE_BUILDID=${AZURE_BUILDID} +RUN ./build-template.sh + +############################################################################# +### OpenZGY source code ################################################## +############################################################################# + +FROM centos:centos8 AS openzgy-source-vanilla ENV LINUXDISTRO=centos8 -RUN (echo export LINUXDISTRO=$LINUXDISTRO; \ - echo export PS1='"\[\e[31;1m\]${LINUXDISTRO}\[\e[0m\] \[\e[32m\]\h\[\e[0m\] \W \$ "') \ - >> /home/me/.bash_profile +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} -### Usage example: -# -# docker build --pull -t sd-env:latest . -# -#docker build -t sd-env:latest . -# -#docker run -it -p 5901:5901 \ # vnc access -# -v ${HOME}/.ssh:/home/me/.ssh \ # ssh credentials -# -v ${HOME}/.sdcfg:/home/me/.sdcfg \ # seismic-drive cred -# -v ${WORKAREA}:/home/me/seismic-store-client-api-cpp \ # source code -# -v ${WORKAREA2}:/home/me/seismic-store-sdutil \ # source code -# --cap-add sys_ptrace \ # debugging -# sd-env:latest +RUN dnf -y install epel-release dnf-plugins-core; \ + dnf config-manager --set-enabled powertools; \ + dnf -y install \ + make cmake gcc-c++ libgomp gdb strace \ + uuid uuid-devel valgrind-devel libxslt \ + curl bzip2 less zip unzip which sudo doxygen java \ + python2 python3 python3-devel python3-tkinter + +RUN python3 -m ensurepip; \ + python3 -m pip install --upgrade pip; \ + python3 -m pip install wheel virtualenv numpy cython; + +# CMake bug, deps to newer version are missing. +RUN dnf -y install libarchive +# sometimes Azure SDK looks for the certificate file in the wrong place. +RUN test -r /etc/ssl/cert.pem || ln -s /etc/pki/tls/cert.pem /etc/ssl/cert.pem + +RUN useradd -m -u 800 -G wheel --shell /bin/bash -p '' me +USER me +WORKDIR /home/me + +# SOURCE CODE FROM BUILD CONTEXT COPIED IN +COPY --chown=800 LICENSE.txt oz/LICENSE.txt +COPY --chown=800 Makefile oz/Makefile +COPY --chown=800 .git/ oz/.git/ +COPY --chown=800 doc/ oz/doc/ +COPY --chown=800 external/ oz/external/ +COPY --chown=800 native/ oz/native/ +COPY --chown=800 python/ oz/python/ +COPY --chown=800 scripts/ oz/scripts/ +COPY --chown=800 sd-env/ oz/sd-env/ +COPY --chown=800 testdata/ oz/testdata/ +COPY --chown=800 wrapper/ oz/wrapper/ +COPY --chown=800 ["private/grabtoken*.sh", "LICENSE.txt", "oz/private/"] +WORKDIR /home/me/oz + +############################################################################# +### OpenZGY source code with SDAPI binaries added ####################### +############################################################################# + +FROM openzgy-source-vanilla AS openzgy-source-cloud +COPY --from=sdapi-build --chown=800 /home/me/sdapi_linux64.tar.gz /home/me/ +#(debugging)COPY --from=sdapi-manual /opt/vcpkg /opt/vcpkg + +############################################################################# +### Environment is ready, build OPENZGY now! ############################ +############################################################################# + +FROM openzgy-source-${variant} AS openzgy-build +ARG AZURE_BUILDID +ENV AZURE_BUILDID=${AZURE_BUILDID} +RUN make -j 8 SD_ZIPFILE=/home/me/sdapi_linux64.tar.gz build testscripts + +############################################################################# +### Minimal docker image with OpenZGY Python and C++ installed ########## +############################################################################# + +FROM centos:centos8 AS openzgy-minimal + +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} + +RUN dnf -y install python3 libgomp; python3 -m pip install --upgrade pip +# Workaround for a bug in the Azure SDK or one of its dependencies. +RUN test -r /etc/ssl/cert.pem || ln -s /etc/pki/tls/cert.pem /etc/ssl/cert.pem + +COPY --from=openzgy-build /home/me/oz/build/deploy/ /home/me/oz/build/deploy/ +WORKDIR /home/me/oz +RUN python3 -m pip install build/deploy/pure/OpenZGY-*.whl +RUN python3 -m pip install build/deploy/sdglue/*/SdGlue-*.whl || true +RUN python3 -m pip install build/deploy/wrapper/*/OpenZgyBindings-*.whl +RUN du -skc build/deploy/native/* && ls -l build/deploy + +############################################################################# +### Add unit tests to the minimal image ################################# +############################################################################# + +FROM openzgy-minimal AS openzgy-testenv + +RUN tar xvf build/deploy/testscripts.tar && \ + python3 -m pip install virtualenv && \ + dnf -y install bzip2 curl valgrind sudo && \ + useradd -m -u 800 -G wheel --shell /bin/bash -p '' me && \ + chown -R 800 /home/me + +# Enable these to allow the "test" image to run the copytimes.sh test. +# Note that the oldtools folder has not been committed to git. +#COPY --chown=800 oldtools/ oldtools/ +#COPY --chown=800 private/*.sh private/ +#COPY --chown=800 oldtools/dropcache /usr/local/bin/dropcache +#RUN chmod 4555 /usr/local/bin/dropcache + +# Enable running sdutil for ad-hoc tests. +#RUN dnf -y install unzip; \ +# (mkdir /usr/local/sdutil; \ +# cd /usr/local/sdutil; \ +# unzip /home/build/oz/oldtools/sdutil-2.2.50.zip); \ +# sed -i -e '1s/python$/python3/' /usr/local/sdutil/sdutil.py; \ +# chmod 755 /usr/local/sdutil/sdutil.py; \ +# ln -s /usr/local/sdutil/sdutil.py /usr/local/bin/sdutil; \ +# pip3 install -r /usr/local/sdutil/requirements.txt; \ +# mkdir /home/build/.sdcfg; \ +# ln -s /host/data/slbauth.tk /home/build/.sdcfg/slbauth.tk; \ +# cp -b -S .orig oldtools/config.yaml /usr/local/sdutil/sdlib/config.yaml + +# Enable to make it simpler to extract the SDAPI SDK, for use e.g. by +# the old ZGY-Cloud library which doesn't have this kind of all-in-one build. +# Unfortunately this won't work wth variant=plain. +COPY --from=sdapi-build --chown=800 /home/me/sdapi_linux64.tar.gz /home/me/ +COPY --from=sdapi-build --chown=800 /home/me/realname.txt /home/me/ +USER me + +ENV CLIENT_ID="" \ + CLIENT_SECRET="" \ + OPENZGY_SDURL="" \ + OPENZGY_SDAPIKEY="" \ + OPENZGY_TOKEN="" \ + OPENZGY_TESTDATA="/home/me/oz/build/testdata" \ + OPENZGY_SDTESTDATA="sd://sntc/testdata" \ + OPENZGY_SDTESTSINK="sd://sntc/testsink/d" + +############################################################################# +### Run unit tests using the minimal image ############################## +############################################################################# + +FROM openzgy-testenv AS openzgy-test +RUN echo IN openzgy-test && ls +RUN native/src/runtests.sh +#RUN native/sdglue/runtests.sh +RUN wrapper/runtests.sh +RUN python/runtests.sh diff --git a/sd-env/Dockerfile-fedora b/sd-env/Dockerfile-fedora index 61aa6b8..04f9400 100644 --- a/sd-env/Dockerfile-fedora +++ b/sd-env/Dockerfile-fedora @@ -1,73 +1,87 @@ -FROM fedora:31 - -# Get the latest and greatest CentOS? Not recommended. -# Some basic packages won't upgrade properly when inside docker. -# Also, the run command will normally be cached so it is a bit -# hit or miss which versions we actually end up with. -# Instead, trust the package maintainer to integrate important -# security patches in a timely manner. Or hope that security -# issues usually only apply to the host anyway. -#RUN yum -y update - -RUN yum install -y gcc-c++ make which git emacs sudo cmake3 libcurl-devel openssl-devel patch hostname python3 python-pip unzip zip findutils - -RUN pip install --upgrade pip && pip install egg colorama flask requests - -# Azure prerequisites. Have patience. -RUN find / \( -name \*.so\* -o -name \*.a \) -type f -print0 | \ - sort -z | xargs -r0 md5sum > /root/before.md5; \ - find / -type f -print | sort -o /root/before.lst; true -RUN mkdir -p /opt && \ - cd /opt && \ - git clone https://github.com/microsoft/vcpkg.git && \ - cd vcpkg && \ - ./bootstrap-vcpkg.sh -disableMetrics +# Copyright 2017-2021, Schlumberger +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG variant=cloud + +############################################################################# +### SDAPI build prerequisites ########################################### +############################################################################# + +FROM fedora:31 AS sdapi-base +ENV LINUXDISTRO=fedora + +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} + +RUN yum install -y \ + gcc-c++ make which git sudo cmake3 libcurl-devel openssl-devel \ + patch hostname unzip zip findutils cpio +RUN useradd -m -u 800 -G wheel --shell /bin/bash -p '' me +WORKDIR /home/me + +############################################################################# +### SDAPI third party dependencies (have patience) ###################### +############################################################################# + +FROM sdapi-base AS sdapi-manual +ARG vcpkg_branch=a6ef376f0d757c8b695b12f53d573f99a524e594 + +RUN mkdir -p /opt/vcpkg && chown me /opt/vcpkg +USER me +RUN git clone https://github.com/microsoft/vcpkg.git /opt/vcpkg && \ + cd /opt/vcpkg && git checkout ${vcpkg_branch} && \ + cd /opt/vcpkg && ./bootstrap-vcpkg.sh -disableMetrics RUN cd /opt/vcpkg; ./vcpkg install azure-storage-cpp RUN cd /opt/vcpkg; ./vcpkg install azure-storage-blobs-cpp -RUN find / \( -name \*.so\* -o -name \*.a \) -type f -print0 | \ - sort -z | xargs -r0 md5sum > /root/after.md5; \ - find / -type f -print | sort -o /root/after.lst; true - -# A regular user, not root, should be used for development. -RUN useradd -G wheel -p '' me - -# Run a script that drops root privileges and switches to the same -# numerical userid as the user that started the docker image. -# This user will be allowed to sudo back to root if required. -# PID 1 will be a bash shell, needed to partly fix the problem of -# zombies. Bash correctly reaps adopted processes but it doesn't -# propagate signals. So "docker stop" causes an unclean exit. -# https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/ -# The "set -a" is just a trick to avoid having the shell exec the script. -ENTRYPOINT ["/bin/bash"] -CMD ["-c", "set -a; /home/me/tools/switchuser.sh"] - -# Misc. configuration goes here. -RUN mkdir -p /home/me/.vnc; echo 'xterm & /usr/bin/icewm; vncserver -kill ${DISPLAY}' > /home/me/.vnc/xstartup; chmod 755 /home/me/.vnc/xstartup - -# Assuming that the work area is ~me/seismic-drive-client-api, -# make sdutil available globally without further installation. -RUN rm -f /bin/sdutil; (echo '#!/bin/bash'; echo 'exec env PYTHONPATH=/home/me/seismic-store-sdutil python /home/me/seismic-store-sdutil/sdutil.py' '"$@"') > /bin/sdutil; chmod 755 /bin/sdutil - -# The current directory may hold ad-hoc tools for debugging -# and usage examples. -COPY . /home/me/tools -ENV LINUXDISTRO=fedora -RUN (echo export LINUXDISTRO=$LINUXDISTRO; \ - echo export PS1='"\[\e[31;1m\]${LINUXDISTRO}\[\e[0m\] \[\e[32m\]\h\[\e[0m\] \W \$ "') \ - >> /home/me/.bash_profile +############################################################################# +### Environment is ready, build SDAPI now! ############################## +############################################################################# -### Usage example: -# -# docker build --pull -t sd-env-fedora:latest . -# -#docker build -t sd-env:latest . -# -#docker run -it -p 5901:5901 \ # vnc access -# -v ${HOME}/.ssh:/home/me/.ssh \ # ssh credentials -# -v ${HOME}/.sdcfg:/home/me/.sdcfg \ # seismic-drive cred -# -v ${WORKAREA}:/home/me/seismic-store-client-api-cpp \ # source code -# -v ${WORKAREA2}:/home/me/seismic-store-sdutil \ # source code -# --cap-add sys_ptrace \ # debugging -# sd-env-fedora:latest +FROM sdapi-manual AS sdapi-build + +# SOURCE CODE FROM BUILD CONTEXT COPIED IN +COPY --chown=800 seismic-store-cpp-lib /home/me/sdapi/ +COPY --chown=800 seismic-dms-sdapi /home/me/sdapi-slb/ +COPY --chown=800 ["sd-env/build-template.sh", "sd-env/*.patch", "/home/me/" ] +USER me + +RUN patch -p1 -N -d /home/me/sdapi -i /home/me/cmakelists2.patch || true +RUN test ! -d /home/me/sdapi-slb || (\ + cd /home/me/sdapi-slb && \ + find src/core src/lib/auth -print | cpio -pduv ../sdapi) +ARG AZURE_BUILDID +ENV AZURE_BUILDID=${AZURE_BUILDID} +RUN ./build-template.sh + +############################################################################# +### OpenZGY is not supported for this distro. ################### +### Add dummy targets to maybe simplify the Makefile. ################### +############################################################################# + +FROM alpine AS openzgy-source-vanilla +FROM openzgy-source-vanilla AS openzgy-source-cloud + +### Produce the deploy folder that the OpenZGY builder would have made. +### This makes no sense for variant=vanilla as deploy would be empty. +FROM openzgy-source-${variant} AS openzgy-build +COPY --from=sdapi-build /home/me/sdapi_linux64.tar.gz /home/me/ +COPY --from=sdapi-build /home/me/realname.txt /home/me/ +RUN d=/home/me/oz/build/deploy/sdapi/$(cat /home/me/realname.txt) && \ + /bin/mkdir -p $(dirname ${d}) && \ + /bin/cp /home/me/sdapi_linux64.tar.gz ${d} + +FROM alpine AS openzgy-minimal +FROM openzgy-minimal AS openzgy-testenv +FROM openzgy-testenv AS openzgy-test diff --git a/sd-env/Dockerfile-focal b/sd-env/Dockerfile-focal index ab60b36..d5716a8 100644 --- a/sd-env/Dockerfile-focal +++ b/sd-env/Dockerfile-focal @@ -1,75 +1,178 @@ -FROM ubuntu:focal +# Copyright 2017-2021, Schlumberger +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG variant=cloud + +############################################################################# +### SDAPI build prerequisites ########################################### +############################################################################# -# If you are going to run "sdutil auth login", this needs a full graphical -# environment which you can connect to with vnc. This will pull in ~500 -# packages so don't do it if you don't need it. The alternative is to -# pull in your ~/.sdcfg file from outside the docker environment. +FROM ubuntu:focal AS sdapi-base +ENV LINUXDISTRO=focal + +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} -# Install other packages the build depends on. RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get -y install \ - cmake curl g++ libcurl3-dev libssl-dev zip \ - python3 python3-pip git vim sudo pkg-config - -# Azure prerequisites. Have patience. -RUN find / \( -name \*.so\* -o -name \*.a \) -type f -print0 | \ - sort -z | xargs -r0 md5sum > /root/before.md5; \ - find / -type f -print | sort -o /root/before.lst; true -RUN mkdir -p /opt && \ - cd /opt && \ - git clone https://github.com/microsoft/vcpkg.git && \ - cd vcpkg && \ - ./bootstrap-vcpkg.sh -disableMetrics + g++ cmake curl libcurl4-openssl-dev libssl-dev zip git vim sudo pkg-config cpio +RUN useradd -m -u 800 -G sudo --shell /bin/bash -p '' me +WORKDIR /home/me + +############################################################################# +### SDAPI third party dependencies (have patience) ###################### +############################################################################# + +FROM sdapi-base AS sdapi-manual +ARG vcpkg_branch=a6ef376f0d757c8b695b12f53d573f99a524e594 + +RUN mkdir -p /opt/vcpkg && chown me /opt/vcpkg +USER me +RUN git clone https://github.com/microsoft/vcpkg.git /opt/vcpkg && \ + cd /opt/vcpkg && git checkout ${vcpkg_branch} && \ + cd /opt/vcpkg && ./bootstrap-vcpkg.sh -disableMetrics RUN cd /opt/vcpkg; ./vcpkg install azure-storage-cpp RUN cd /opt/vcpkg; ./vcpkg install azure-storage-blobs-cpp -RUN find / \( -name \*.so\* -o -name \*.a \) -type f -print0 | \ - sort -z | xargs -r0 md5sum > /root/after.md5; \ - find / -type f -print | sort -o /root/after.lst; true - -# A regular user, not root, should be used for development. -RUN groupadd -r admin; useradd -G admin --shell /bin/bash -p '' me - -# Run a script that drops root privileges and switches to the same -# numerical userid as the user that started the docker image. -# This user will be allowed to sudo back to root if required. -# PID 1 will be a bash shell, needed to partly fix the problem of -# zombies. Bash correctly reaps adopted processes but it doesn't -# propagate signals. So "docker stop" causes an unclean exit. -# https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/ -# The "set -a" is just a trick to avoid having the shell exec the script. -ENTRYPOINT ["/bin/bash"] -CMD ["-c", "set -a; /home/me/tools/switchuser.sh"] - -# Misc. configuration goes here. -RUN mkdir -p /home/me/.vnc; echo 'xterm & /usr/bin/icewm; vncserver -kill ${DISPLAY}' > /home/me/.vnc/xstartup; chmod 755 /home/me/.vnc/xstartup - -# Assuming that the work area is ~me/seismic-drive-client-api, -# make sdutil available globally without further installation. -RUN rm -f /bin/sdutil; (echo '#!/bin/bash'; echo 'exec env PYTHONPATH=/home/me/seismic-store-sdutil python /home/me/seismic-store-sdutil/sdutil.py' '"$@"') > /bin/sdutil; chmod 755 /bin/sdutil - -# The current directory may hold ad-hoc tools for debugging -# and usage examples. -COPY . /home/me/tools + +############################################################################# +### Environment is ready, build SDAPI now! ############################## +############################################################################# + +FROM sdapi-manual AS sdapi-build + +# SOURCE CODE FROM BUILD CONTEXT COPIED IN +COPY --chown=800 seismic-store-cpp-lib /home/me/sdapi/ +COPY --chown=800 seismic-dms-sdapi /home/me/sdapi-slb/ +COPY --chown=800 ["sd-env/build-template.sh", "sd-env/*.patch", "/home/me/" ] +USER me + +RUN patch -p1 -N -d /home/me/sdapi -i /home/me/cmakelists2.patch || true +RUN test ! -d /home/me/sdapi-slb || (\ + cd /home/me/sdapi-slb && \ + find src/core src/lib/auth -print | cpio -pduv ../sdapi) +ARG AZURE_BUILDID +ENV AZURE_BUILDID=${AZURE_BUILDID} +RUN ./build-template.sh + +############################################################################# +### OpenZGY source code ################################################## +############################################################################# + +FROM ubuntu:focal AS openzgy-source-vanilla ENV LINUXDISTRO=focal -RUN (echo export LINUXDISTRO=$LINUXDISTRO; \ - echo export PS1='"\[\e[31;1m\]${LINUXDISTRO}\[\e[0m\] \[\e[32m\]\h\[\e[0m\] \W \$ "') \ - >> /home/me/.bash_profile -# Optional... -#RUN DEBIAN_FRONTEND=noninteractive apt-get -y install icewm xterm -#RUN apt-get -y install xfce4 xfce4-goodies tightvncserver firefox emacs -#RUN apt-get -y install openssh-server openssh-client -#RUN echo Remember to do /etc/init.d/ssh start +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} +RUN apt-get update; \ + DEBIAN_FRONTEND=noninteractive apt-get -y install \ + make cmake gcc gdb strace valgrind \ + uuid-dev \ + curl vim cpio zip unzip doxygen sudo \ + python3-dev python3-pip python3-setuptools python3-tk -### Usage example: -# -#docker build --pull -f Dockerfile-focal -t sd-env-focal:latest . -# -#docker run -it -p 5901:5901 \ # vnc access -# -v ${HOME}/.ssh:/home/me/.ssh \ # ssh credentials -# -v ${HOME}/.sdcfg:/home/me/.sdcfg \ # seismic-drive cred -# -v ${WORKAREA}:/home/me/seismic-store-client-api-cpp \ # source code -# -v ${WORKAREA2}:/home/me/seismic-store-sdutil \ # source code -# --cap-add sys_ptrace \ # debugging -# sd-env-focal:latest +RUN pip3 install wheel virtualenv numpy cython + +RUN useradd -m -u 800 -G sudo --shell /bin/bash -p '' me +USER me +WORKDIR /home/me + +# SOURCE CODE FROM BUILD CONTEXT COPIED IN +COPY --chown=800 LICENSE.txt oz/LICENSE.txt +COPY --chown=800 Makefile oz/Makefile +COPY --chown=800 .git/ oz/.git/ +COPY --chown=800 doc/ oz/doc/ +COPY --chown=800 external/ oz/external/ +COPY --chown=800 native/ oz/native/ +COPY --chown=800 python/ oz/python/ +COPY --chown=800 scripts/ oz/scripts/ +COPY --chown=800 sd-env/ oz/sd-env/ +COPY --chown=800 testdata/ oz/testdata/ +COPY --chown=800 wrapper/ oz/wrapper/ +COPY --chown=800 ["private/grabtoken*.sh", "LICENSE.txt", "oz/private/"] +WORKDIR /home/me/oz + +############################################################################# +### OpenZGY source code with SDAPI binaries added ####################### +############################################################################# + +FROM openzgy-source-vanilla AS openzgy-source-cloud +COPY --from=sdapi-build --chown=800 /home/me/sdapi_linux64.tar.gz /home/me/ +#(debugging)COPY --from=sdapi-manual /opt/vcpkg /opt/vcpkg + +############################################################################# +### Environment is ready, build OPENZGY now! ############################ +############################################################################# + +FROM openzgy-source-${variant} AS openzgy-build +ARG AZURE_BUILDID +ENV AZURE_BUILDID=${AZURE_BUILDID} +RUN make -j 8 SD_ZIPFILE=/home/me/sdapi_linux64.tar.gz build testscripts + +############################################################################# +### Minimal docker image with OpenZGY Python and C++ installed ########## +############################################################################# + +FROM ubuntu:focal AS openzgy-minimal + +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} + +RUN apt-get update; apt-get -y install python3 python3-pip + +COPY --from=openzgy-build /home/me/oz/build/deploy/ /home/me/oz/build/deploy/ +WORKDIR /home/me/oz +RUN python3 -m pip install build/deploy/pure/OpenZGY-*.whl +RUN python3 -m pip install build/deploy/sdglue/*/SdGlue-*.whl || true +RUN python3 -m pip install build/deploy/wrapper/*/OpenZgyBindings-*.whl +RUN du -skc build/deploy/native/* && ls -l build/deploy + +############################################################################# +### Add unit tests to the minimal image ################################# +############################################################################# + +FROM openzgy-minimal AS openzgy-testenv + +RUN tar xvf build/deploy/testscripts.tar && \ + python3 -m pip install virtualenv && \ + apt-get update && apt-get -y install bzip2 curl && \ + useradd -m -u 800 -G sudo --shell /bin/bash -p '' me && \ + chown -R 800 /home/me + +# Enable to make it simpler to extract the SDAPI SDK, for use e.g. by +# the old ZGY-Cloud library which doesn't have this kind of all-in-one build. +# Unfortunately this won't work wth variant=plain. +COPY --from=sdapi-build --chown=800 /home/me/sdapi_linux64.tar.gz /home/me/ +COPY --from=sdapi-build --chown=800 /home/me/realname.txt /home/me/ +USER me + +ENV CLIENT_ID="" \ + CLIENT_SECRET="" \ + OPENZGY_SDURL="" \ + OPENZGY_SDAPIKEY="" \ + OPENZGY_TOKEN="" \ + OPENZGY_TESTDATA="/home/me/oz/build/testdata" \ + OPENZGY_SDTESTDATA="sd://sntc/testdata" \ + OPENZGY_SDTESTSINK="sd://sntc/testsink/d" + +############################################################################# +### Run unit tests using the minimal image ############################## +############################################################################# + +FROM openzgy-testenv AS openzgy-test +RUN echo IN openzgy-test && ls +RUN native/src/runtests.sh +#RUN native/sdglue/runtests.sh +RUN wrapper/runtests.sh +RUN python/runtests.sh diff --git a/sd-env/Dockerfile-omega b/sd-env/Dockerfile-omega index 0e2b701..0c48f5d 100644 --- a/sd-env/Dockerfile-omega +++ b/sd-env/Dockerfile-omega @@ -1,28 +1,44 @@ -FROM centos:centos7 +# Copyright 2017-2021, Schlumberger +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. -# Get the latest and greatest CentOS? Not recommended. -# Some basic packages won't upgrade properly when inside docker. -# Also, the run command will normally be cached so it is a bit -# hit or miss which versions we actually end up with. -# Instead, trust the package maintainer to integrate important -# security patches in a timely manner. Or hope that security -# issues usually only apply to the host anyway. -#RUN yum -y update +ARG variant=cloud -# The current version of seismic-drive needs gcc >= 4.9.2. -# Install devtoolset-3 on top of centos 7. Or a later version. -# The downside is that this might install ~500 packages. +############################################################################# +### Devtoolset ######################################################### +############################################################################# +FROM centos:centos7 AS sdapi-toolset-centos7 +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} RUN yum install -y centos-release-scl && yum install -y devtoolset-7 -# Install other packages the build depends on. -# The devtoolset might have pulled some of them as dependencies, -# but it doesn't harm to do them again. +############################################################################# +### SDAPI build prerequisites ########################################### +############################################################################# + +FROM sdapi-toolset-centos7 AS sdapi-base +ENV LINUXDISTRO=omega -RUN yum install -y epel-release -RUN yum install -y make which git sudo cmake3 libcurl-devel openssl-devel bzip2 patch -RUN yum install -y autoconf expat-devel gettext-devel zlib-devel perl-CPAN perl-devel -RUN yum install -y python-pip && pip install --upgrade pip\<21 && pip install egg colorama flask requests +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} + +RUN yum install -y epel-release && \ + yum install -y \ + make which git sudo cmake3 libcurl-devel openssl-devel bzip2 patch \ + autoconf expat-devel gettext-devel zlib-devel perl-CPAN perl-devel +RUN useradd -m -u 800 -G wheel --shell /bin/bash -p '' me +WORKDIR /home/me # Build GIT from sources because the newer git 2.x is needed for Azure. # Install in /usr/local/bin. @@ -36,82 +52,185 @@ RUN set -e; \ make; \ make install -# Azure prerequisites. Have patience. -RUN find / \( -name \*.so\* -o -name \*.a \) -type f -print0 | \ - sort -z | xargs -r0 md5sum > /root/before.md5; \ - find / -type f -print | sort -o /root/before.lst; true -RUN mkdir -p /opt && \ - cd /opt && \ - git clone https://github.com/microsoft/vcpkg.git && \ - cd vcpkg && \ +############################################################################# +### SDAPI third party dependencies (have patience) ###################### +############################################################################# + +FROM sdapi-base AS sdapi-vcpkg +ARG vcpkg_branch=a6ef376f0d757c8b695b12f53d573f99a524e594 + +RUN mkdir -p /opt/vcpkg && chown me /opt/vcpkg +USER me +RUN git clone https://github.com/microsoft/vcpkg.git /opt/vcpkg && \ + cd /opt/vcpkg && git checkout ${vcpkg_branch} && \ + cd /opt/vcpkg && \ scl enable devtoolset-7 './bootstrap-vcpkg.sh -disableMetrics' RUN cd /opt/vcpkg; scl enable devtoolset-7 './vcpkg install azure-storage-cpp' RUN cd /opt/vcpkg; scl enable devtoolset-7 './vcpkg install azure-storage-blobs-cpp' -RUN find / \( -name \*.so\* -o -name \*.a \) -type f -print0 | \ - sort -z | xargs -r0 md5sum > /root/after.md5; \ - find / -type f -print | sort -o /root/after.lst; true -# If you are going to run "sdutil auth login", this needs a full graphical -# environment which you can connect to with vnc. This will pull in ~500 -# packages so don't do it if you don't need it. The alternative is to -# pull in your ~/.sdcfg file from outside the docker environment. +############################################################################# +### Need a newer CURL ################################################### +############################################################################# -#RUN yum install -y epel-release && yum install -y icewm tigervnc-server firefox emacs +FROM sdapi-vcpkg AS sdapi-manual +USER root # libcurl in CentOS 7 has serious performance issues. Download and # build from source. Preferably using a mirror. Use RUN not ADD # because I don't want to invalidate the Docker cache and rebuild # curl on every invocation. ARG CURL=7.74.0 -#ADD https://curl.haxx.se/download/curl-$CURL.tar.bz2 /root/curl-$CURL.tar.bz2 -#ADD https://dl.uxnr.de/mirror/curl/curl-$CURL.tar.bz2 /root/curl-$CURL.tar.bz2 -#ADD https://curl.se/download/curl-$CURL.tar.bz2 /root/curl-$CURL.tar.bz2 -RUN curl -sS -o /root/curl-$CURL.tar.bz2 https://curl.se/download/curl-$CURL.tar.bz2 +RUN curl -sSL -o /root/curl-$CURL.tar.bz2 https://curl.se/download/curl-$CURL.tar.bz2 # Build the curl source downloaded earlier and replace the one we have. # Caveat: Replacing the system version of curl that several other packages # depend on. Applications compiled against curl 7.29.0 will now dynamically # link with $CURL. This might not end well. The reason I do it this way # is to make sure libsdapi and its dependents use a consistent version. -RUN set -e; cd /root; tar jxf curl-$CURL.tar.bz2; cd curl-$CURL; ./configure --prefix /usr --libdir=/usr/lib64; make; rpm -e --nodeps libcurl-devel libcurl curl; make install - -# A regular user, not root, should be used for development. -RUN useradd -G wheel -p '' me - -# Run a script that drops root privileges and switches to the same -# numerical userid as the user that started the docker image. -# This user will be allowed to sudo back to root if required. -# PID 1 will be a bash shell, needed to partly fix the problem of -# zombies. Bash correctly reaps adopted processes but it doesn't -# propagate signals. So "docker stop" causes an unclean exit. -# https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/ -# The "set -a" is just a trick to avoid having the shell exec the script. -ENTRYPOINT ["/bin/bash"] -CMD ["-c", "set -a; /home/me/tools/switchuser.sh"] - -# Misc. configuration goes here. -RUN mkdir -p /home/me/.vnc; echo 'xterm & /usr/bin/icewm; vncserver -kill ${DISPLAY}' > /home/me/.vnc/xstartup; chmod 755 /home/me/.vnc/xstartup - -# Assuming that the work area is ~me/seismic-drive-client-api, -# make sdutil available globally without further installation. -RUN rm -f /bin/sdutil; (echo '#!/bin/bash'; echo 'exec env PYTHONPATH=/home/me/seismic-store-sdutil python /home/me/seismic-store-sdutil/sdutil.py' '"$@"') > /bin/sdutil; chmod 755 /bin/sdutil - -# The current directory may hold ad-hoc tools for debugging -# and usage examples. -COPY . /home/me/tools +# Caveat: The vcpkg dependencies might have their own idea. +RUN cd /root && \ + tar jxf curl-$CURL.tar.bz2 && \ + cd curl-$CURL && ./configure --prefix /usr --libdir=/usr/lib64 && \ + make && \ + rpm -e --nodeps libcurl-devel libcurl curl && \ + make install +USER me + +############################################################################# +### Environment is ready, build SDAPI now! ############################## +############################################################################# + +FROM sdapi-manual AS sdapi-build + +# SOURCE CODE FROM BUILD CONTEXT COPIED IN +COPY --chown=800 seismic-store-cpp-lib /home/me/sdapi/ +COPY --chown=800 seismic-dms-sdapi /home/me/sdapi-slb/ +COPY --chown=800 ["sd-env/build-template.sh", "sd-env/*.patch", "/home/me/" ] +USER me + +RUN patch -p1 -N -d /home/me/sdapi -i /home/me/cmakelists2.patch || true +RUN test ! -d /home/me/sdapi-slb || (\ + cd /home/me/sdapi-slb && \ + find src/core src/lib/auth -print | cpio -pduv ../sdapi) +ARG AZURE_BUILDID +ENV AZURE_BUILDID=${AZURE_BUILDID} +RUN scl enable devtoolset-7 ./build-template.sh + +############################################################################# +### OpenZGY source code ################################################## +############################################################################# + +FROM sdapi-toolset-centos7 AS openzgy-source-vanilla ENV LINUXDISTRO=omega -RUN (echo export LINUXDISTRO=$LINUXDISTRO; \ - echo export PS1='"\[\e[31;1m\]${LINUXDISTRO}\[\e[0m\] \[\e[32m\]\h\[\e[0m\] \W \$ "') \ - >> /home/me/.bash_profile -### Usage example: -# -# docker build --pull -f Dockerfile-omega -t sd-env-omega:latest . -# -#docker run -it -p 5901:5901 \ # vnc access -# -v ${HOME}/.ssh:/home/me/.ssh \ # ssh credentials -# -v ${HOME}/.sdcfg:/home/me/.sdcfg \ # seismic-drive cred -# -v ${WORKAREA}:/home/me/seismic-store-client-api-cpp \ # source code -# -v ${WORKAREA2}:/home/me/seismic-store-sdutil \ # source code -# --cap-add sys_ptrace \ # debugging -# sd-env:latest +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} + +RUN yum -y install epel-release && \ + yum -y install \ + which python36 python36-devel python36-setuptools sudo make cmake3 \ + bzip2 +RUN python3.6 -m ensurepip; \ + python3.6 -m pip install --upgrade pip; \ + python3.6 -m pip install wheel virtualenv numpy cython +RUN /bin/rm -f /usr/bin/pip3; \ + test -r /usr/bin/python3 || ln -s python3.6 /usr/bin/python3; \ + test -r /usr/bin/pip3 || ln -s /usr/local/bin/pip3 /usr/bin/pip3 + +## Note! libcurl is too old, but OpenZGY shouldn't link with it +## explicitly, so as long as linkage is dynamic it should not matter. + +RUN useradd -m -u 800 -G wheel --shell /bin/bash -p '' me +USER me +WORKDIR /home/me + +# SOURCE CODE FROM BUILD CONTEXT COPIED IN +COPY --chown=800 LICENSE.txt oz/LICENSE.txt +COPY --chown=800 Makefile oz/Makefile +COPY --chown=800 .git/ oz/.git/ +COPY --chown=800 doc/ oz/doc/ +COPY --chown=800 external/ oz/external/ +COPY --chown=800 native/ oz/native/ +COPY --chown=800 python/ oz/python/ +COPY --chown=800 scripts/ oz/scripts/ +COPY --chown=800 sd-env/ oz/sd-env/ +COPY --chown=800 testdata/ oz/testdata/ +COPY --chown=800 wrapper/ oz/wrapper/ +COPY --chown=800 ["private/grabtoken*.sh", "LICENSE.txt", "oz/private/"] +WORKDIR /home/me/oz + +############################################################################# +### OpenZGY source code with SDAPI binaries added ####################### +############################################################################# + +FROM openzgy-source-vanilla AS openzgy-source-cloud +COPY --from=sdapi-build --chown=800 /home/me/sdapi_linux64.tar.gz /home/me/ +#(debugging)COPY --from=sdapi-manual /opt/vcpkg /opt/vcpkg + +############################################################################# +### Environment is ready, build OPENZGY now! ############################ +############################################################################# + +FROM openzgy-source-${variant} AS openzgy-build +ARG AZURE_BUILDID +ENV AZURE_BUILDID=${AZURE_BUILDID} +RUN scl enable devtoolset-7 'make -j 8 SD_ZIPFILE=/home/me/sdapi_linux64.tar.gz build testscripts' + +############################################################################# +### Minimal docker image with OpenZGY Python and C++ installed ########## +############################################################################# + +FROM centos:centos7 AS openzgy-minimal + +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} + +RUN yum -y install python3 libgomp; python3 -m pip install --upgrade pip +# Workaround for a bug in the Azure SDK or one of its dependencies. +RUN test -r /etc/ssl/cert.pem || ln -s /etc/pki/tls/cert.pem /etc/ssl/cert.pem + +COPY --from=openzgy-build /home/me/oz/build/deploy/ /home/me/oz/build/deploy/ +WORKDIR /home/me/oz +RUN python3 -m pip install build/deploy/pure/OpenZGY-*.whl +RUN python3 -m pip install build/deploy/sdglue/*/SdGlue-*.whl || true +RUN python3 -m pip install build/deploy/wrapper/*/OpenZgyBindings-*.whl +RUN du -skc build/deploy/native/* && ls -l build/deploy + +############################################################################# +### Add unit tests to the minimal image ################################# +############################################################################# + +FROM openzgy-minimal AS openzgy-testenv + +RUN tar xvf build/deploy/testscripts.tar && \ + python3 -m pip install virtualenv && \ + yum -y install bzip2 curl valgrind sudo && \ + useradd -m -u 800 -G wheel --shell /bin/bash -p '' me && \ + chown -R 800 /home/me + +# Enable to make it simpler to extract the SDAPI SDK, for use e.g. by +# the old ZGY-Cloud library which doesn't have this kind of all-in-one build. +# Unfortunately this won't work wth variant=plain. +COPY --from=sdapi-build --chown=800 /home/me/sdapi_linux64.tar.gz /home/me/ +COPY --from=sdapi-build --chown=800 /home/me/realname.txt /home/me/ +USER me + +ENV CLIENT_ID="" \ + CLIENT_SECRET="" \ + OPENZGY_SDURL="" \ + OPENZGY_SDAPIKEY="" \ + OPENZGY_TOKEN="" \ + OPENZGY_TESTDATA="/home/me/oz/build/testdata" \ + OPENZGY_SDTESTDATA="sd://sntc/testdata" \ + OPENZGY_SDTESTSINK="sd://sntc/testsink/d" + +############################################################################# +### Run unit tests using the minimal image ############################## +############################################################################# + +FROM openzgy-testenv AS openzgy-test +RUN echo IN openzgy-test && ls +RUN native/src/runtests.sh +#RUN native/sdglue/runtests.sh +RUN wrapper/runtests.sh +RUN python/runtests.sh diff --git a/sd-env/Dockerfile-omega-dynamic b/sd-env/Dockerfile-omega-dynamic deleted file mode 100644 index 3a51596..0000000 --- a/sd-env/Dockerfile-omega-dynamic +++ /dev/null @@ -1,154 +0,0 @@ -# ============================================================================ -# Copyright 2017-2021, Schlumberger -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================ - -# COPIED FROM: -# os-seismic-store-cpp-lib/devops/docker/build.centos7.dockerfile - -# base image -FROM centos/devtoolset-7-toolchain-centos7 - -# build as root -USER 0 - -# build dependencies -ARG CMAKE_VERSION=3.19.1 - -# library dependencies -ARG LIB_ZLIB_VERSION=1.2.11 -ARG LIB_OPENSSL_VERSION=1.1.1g -ARG LIB_CURL_VERSION=7.74.0 -ARG LIB_BOOST_VERSION=1.73.0 -ARG LIB_UUID_VERSION=1.0.3 -ARG LIB_XML2_VERSION=2.9.10 -ARG LIB_CPPREST_VERSION=2.10.16 -ARG LIB_AZURE_STORAGE_VERSION=7.5.0 - -# library path -ARG LIBRARIES_INSTALL_PATH=/usr/local - -# install required build tools via packet manager -RUN yum update -y && yum install -y wget which git libtool autoconf perl-devel python-devel xz-devel patch - -# temporary working directory -WORKDIR /tmp - -# [CMAKE] -RUN wget https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz \ - && tar -zxvf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz -C /usr/local \ - && ln -s /usr/local/cmake-${CMAKE_VERSION}-Linux-x86_64/bin/cmake /usr/bin/cmake \ - && ln -s /usr/local/cmake-${CMAKE_VERSION}-Linux-x86_64/bin/ctest /usr/bin/ctest \ - && rm -rf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz - -# [ZLIB] -RUN wget https://www.zlib.net/zlib-${LIB_ZLIB_VERSION}.tar.gz \ - && tar -zxvf zlib-${LIB_ZLIB_VERSION}.tar.gz \ - && cd zlib-${LIB_ZLIB_VERSION} \ - && ./configure --prefix=${LIBRARIES_INSTALL_PATH} \ - && make -j $(nproc) \ - && make install \ - && cd .. \ - && rm -rf zlib-${LIB_ZLIB_VERSION}.tar.gz \ - && rm -rf zlib-${LIB_ZLIB_VERSION} - -# [OPENSSL] -RUN wget https://www.openssl.org/source/openssl-${LIB_OPENSSL_VERSION}.tar.gz \ - && tar -zxvf openssl-${LIB_OPENSSL_VERSION}.tar.gz \ - && cd openssl-${LIB_OPENSSL_VERSION} \ - && ./config --prefix=${LIBRARIES_INSTALL_PATH} \ - && make -j $(nproc) \ - && make install_sw \ - && cd .. \ - && rm -rf openssl-${LIB_OPENSSL_VERSION}.tar.gz \ - && rm -rf openssl-${LIB_OPENSSL_VERSION} - -# [BOOST] -RUN wget https://dl.bintray.com/boostorg/release/${LIB_BOOST_VERSION}/source/boost_$(echo "$LIB_BOOST_VERSION" | tr . _).tar.gz \ - && tar -zxvf boost_$(echo "$LIB_BOOST_VERSION" | tr . _).tar.gz \ - && cd boost_$(echo "$LIB_BOOST_VERSION" | tr . _) \ - && ./bootstrap.sh --prefix=${LIBRARIES_INSTALL_PATH} \ - && ./b2 stage -j $(nproc) threading=multi link=shared -q \ - && ./b2 install threading=multi link=shared \ - && ln -svf detail/sha1.hpp ${LIBRARIES_INSTALL_PATH}/include/boost/uuid/sha1.hpp \ - && cd .. \ - && rm -rf boost_$(echo "$LIB_BOOST_VERSION" | tr . _).tar.gz \ - && rm -rf boost_$(echo "$LIB_BOOST_VERSION" | tr . _) - -# [UUID] -RUN wget https://vorboss.dl.sourceforge.net/project/libuuid/libuuid-${LIB_UUID_VERSION}.tar.gz \ - && tar -zxvf libuuid-${LIB_UUID_VERSION}.tar.gz \ - && cd libuuid-${LIB_UUID_VERSION} \ - && ./configure --prefix=${LIBRARIES_INSTALL_PATH} \ - && make -j $(nproc) \ - && make install \ - && cd .. \ - && rm -rf libuuid-${LIB_UUID_VERSION}.tar.gz \ - && rm -rf libuuid-${LIB_UUID_VERSION} - -# [XML2] -RUN wget https://github.com/GNOME/libxml2/archive/v${LIB_XML2_VERSION}.tar.gz \ - && tar -zxvf v${LIB_XML2_VERSION}.tar.gz \ - && cd libxml2-${LIB_XML2_VERSION} \ - && ./autogen.sh --prefix=${LIBRARIES_INSTALL_PATH} \ - && make -j $(nproc) \ - && make install \ - && cd .. \ - && rm -rf v${LIB_XML2_VERSION}.tar.gz \ - && rm -rf libxml2-${LIB_XML2_VERSION} - -# [CCPRESTSDK] -RUN git clone -b v${LIB_CPPREST_VERSION} https://github.com/microsoft/cpprestsdk.git cpprestsdk --recursive \ - && cd cpprestsdk \ - && mkdir build \ - && cd build \ - && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} .. \ - && make -j $(nrpoc) \ - && make install \ - && cd ../.. \ - && rm -rf cpprestsdk - -# [AZURESTORAGECPP] -RUN git clone -b v${LIB_AZURE_STORAGE_VERSION} https://github.com/Azure/azure-storage-cpp.git azure-storage-cpp --recursive \ - && cd azure-storage-cpp/Microsoft.WindowsAzure.Storage \ - && mkdir build.release \ - && cd build.release \ - && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} .. \ - && make -j $(nproc) \ - && make install \ - && cd ../../.. \ - && rm -rf azure-storage-cpp - -# [CURL] -RUN git clone -b curl-$(echo "$LIB_CURL_VERSION" | tr . _) https://github.com/curl/curl.git curl --recursive \ - && cd curl \ - && mkdir build \ - && cd build \ - && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} .. \ - && make -j $(nrpoc) \ - && make install \ - && cd ../.. \ - && rm -rf curl - -# Additional lines not in the original: -RUN yum install -y sudo -RUN useradd -G wheel -p '' me -USER me -ENV HOME=/home/me -ENV LINUXDISTRO=omega-dynamic -RUN (echo export LINUXDISTRO=$LINUXDISTRO; \ - echo export PS1='"\[\e[31;1m\]${LINUXDISTRO}\[\e[0m\] \[\e[32m\]\h\[\e[0m\] \W \$ "') \ - >> /home/me/.bash_profile -ENTRYPOINT /bin/bash -WORKDIR /home/me diff --git a/sd-env/Dockerfile-omega-static b/sd-env/Dockerfile-omega-static deleted file mode 100644 index c061e42..0000000 --- a/sd-env/Dockerfile-omega-static +++ /dev/null @@ -1,458 +0,0 @@ -# ============================================================================ -# Copyright 2017-2021, Schlumberger -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================ - -# COPIED FROM: -# os-seismic-store-cpp-lib/devops/docker/build.centos7.staticdeps.dockerfile - -# base image -FROM centos/devtoolset-7-toolchain-centos7 AS dev - -# build as root -USER 0 - -# build dependencies -ARG CMAKE_VERSION=3.19.1 - -# install required build tools via packet manager -RUN yum update -y && yum install -y wget which git libtool autoconf perl-devel python-devel xz-devel patch - -# temporary working directory -WORKDIR /tmp - -# [CMAKE] -RUN wget https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz \ - && tar -zxvf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz -C /usr/local \ - && ln -s /usr/local/cmake-${CMAKE_VERSION}-Linux-x86_64/bin/cmake /usr/bin/cmake \ - && ln -s /usr/local/cmake-${CMAKE_VERSION}-Linux-x86_64/bin/ctest /usr/bin/ctest \ - && ln -s /usr/local/cmake-${CMAKE_VERSION}-Linux-x86_64/bin/cpack /usr/bin/cpack \ - && ln -s /usr/local/cmake-${CMAKE_VERSION}-Linux-x86_64/bin/ccmake /usr/bin/ccmake \ - && rm -rf cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz - -FROM dev as rest-dev - -# library dependencies -ARG LIB_ZLIB_VERSION=1.2.11 -ARG LIB_OPENSSL_VERSION=1.1.1g -ARG LIB_CURL_VERSION=7.74.0 -ARG LIB_UUID_VERSION=1.0.3 - - -# library path -ARG LIBRARIES_INSTALL_PATH=/usr/local - - -# -# if we want to avoid adding shared libraries as depdendencies ( since in linux most of them export all their symbols) -# we need to see if static libraries with Position Indepdent Code are built ( aka, .a that can be used to build .so later on) -# -# the analysis is done with : -# for slib in /usr/local/lib*/*.a; do echo $slib; readelf --relocs ${slib} | egrep -c '(GOT|PLT|JUMP_SLO)'; done -# -# aka : for all archives, read relocations, see if they are pointing to the global offset table, the procedure linkage table or are calls to shared libraries ( jump ) -# not quite sure this is exhaustive as this indicates _some relocatable code present_ not absence of relocations without indirections. -# -# otherwise we'd have to play with visibiliy at library build time, linker version scripts etc. - -# [ZLIB] -# build both static libraries (without PIC) and shared libraries. -RUN wget https://www.zlib.net/zlib-${LIB_ZLIB_VERSION}.tar.gz \ - && tar -zxvf zlib-${LIB_ZLIB_VERSION}.tar.gz \ - && cd /tmp/zlib-${LIB_ZLIB_VERSION} \ - && CFLAGS=-fPIC ./configure --prefix=${LIBRARIES_INSTALL_PATH} --static \ - && make -j $(nproc) \ - && make install -WORKDIR /tmp -RUN rm -rf zlib-${LIB_ZLIB_VERSION}.tar.gz \ - && rm -rf zlib-${LIB_ZLIB_VERSION} - -# [OPENSSL] -# uuuuh. this has TCC implications does it not ? not making it static then. -# build it statically anyways... -RUN wget https://www.openssl.org/source/openssl-${LIB_OPENSSL_VERSION}.tar.gz \ - && tar -zxvf openssl-${LIB_OPENSSL_VERSION}.tar.gz \ - && cd /tmp/openssl-${LIB_OPENSSL_VERSION} \ - && ./config --prefix=${LIBRARIES_INSTALL_PATH} no-shared \ - && make -j $(nproc) \ - && make install_sw -WORKDIR /tmp -RUN rm -rf openssl-${LIB_OPENSSL_VERSION}.tar.gz \ - && rm -rf openssl-${LIB_OPENSSL_VERSION} - -# consider instead -# RUN yum install -y openssl-libs.x86_64 openssl-devel.x86_64 -# and only use system ones - -# [UUID] -# this builds both static libraries ( without fPIC ) and shared libraries -RUN wget https://vorboss.dl.sourceforge.net/project/libuuid/libuuid-${LIB_UUID_VERSION}.tar.gz \ - && tar -zxvf libuuid-${LIB_UUID_VERSION}.tar.gz \ - && cd /tmp/libuuid-${LIB_UUID_VERSION} \ - && ./configure --prefix=${LIBRARIES_INSTALL_PATH} --with-pic --enable-shared=no --enable-static=yes \ - && make -j $(nproc) \ - && make install -WORKDIR /tmp -RUN rm -rf libuuid-${LIB_UUID_VERSION}.tar.gz \ - && rm -rf libuuid-${LIB_UUID_VERSION} - -# [CURL] -# this is not equivalent to the system one built with libtool ... soname, versions are not done the same way. -# may require a patch for locally built nghttp2? or http3 libraries -RUN git clone -b curl-$(echo "$LIB_CURL_VERSION" | tr . _) https://github.com/curl/curl.git curl --recursive -WORKDIR /tmp/curl/build -RUN cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} -DBUILD_SHARED_LIBS=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=ON .. -RUN make -j $(nproc) && make install -WORKDIR /tmp -RUN rm -rf curl - -FROM rest-dev as azure-dev - -ARG LIB_BOOST_VERSION=1.73.0 -ARG LIB_XML2_VERSION=2.9.10 -ARG LIB_CPPREST_VERSION=2.10.16 -# library path -ARG LIBRARIES_INSTALL_PATH=/usr/local - -# [BOOST] -RUN wget https://dl.bintray.com/boostorg/release/${LIB_BOOST_VERSION}/source/boost_$(echo "$LIB_BOOST_VERSION" | tr . _).tar.gz \ - && tar -zxvf boost_$(echo "$LIB_BOOST_VERSION" | tr . _).tar.gz \ - && cd boost_$(echo "$LIB_BOOST_VERSION" | tr . _) \ - && ./bootstrap.sh --prefix=${LIBRARIES_INSTALL_PATH} \ - && ./b2 stage -j $(nproc) threading=multi link=static cxxflags='-fPIC' linkflags='-pie' -q \ - && ./b2 install threading=multi link=static cxxflags='-fPIC' linkflags='-pie' \ - && ln -svf detail/sha1.hpp ${LIBRARIES_INSTALL_PATH}/include/boost/uuid/sha1.hpp -WORKDIR /tmp -RUN rm -rf boost_$(echo "$LIB_BOOST_VERSION" | tr . _).tar.gz \ - && rm -rf boost_$(echo "$LIB_BOOST_VERSION" | tr . _) - - -# [XML2] -RUN wget https://github.com/GNOME/libxml2/archive/v${LIB_XML2_VERSION}.tar.gz \ - && tar -zxvf v${LIB_XML2_VERSION}.tar.gz \ - && cd /tmp/libxml2-${LIB_XML2_VERSION} \ - && ./autogen.sh --prefix=${LIBRARIES_INSTALL_PATH} --with-pic --enable-static=yes --enable-shared=no \ - && make -j $(nproc) \ - && make install -WORKDIR /tmp -RUN rm -rf v${LIB_XML2_VERSION}.tar.gz && rm -rf libxml2-${LIB_XML2_VERSION} - - -# [CCPRESTSDK] -RUN git clone -b v${LIB_CPPREST_VERSION} https://github.com/microsoft/cpprestsdk.git cpprestsdk --recursive -WORKDIR /tmp/cpprestsdk/build -RUN cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} -DBUILD_SHARED_LIBS=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DBoost_USE_STATIC_LIBS=ON .. -RUN make -j $(nproc ) && make install -WORKDIR /tmp -RUN rm -rf cpprestsdk - - -FROM azure-dev as azure-storage-dev - -ARG LIB_AZURE_STORAGE_VERSION=7.5.0 -# library path -ARG LIBRARIES_INSTALL_PATH=/usr/local - -# [AZURESTORAGECPP] -# most likely needs a patch to build properly with non-system curl found. -RUN git clone -b v${LIB_AZURE_STORAGE_VERSION} https://github.com/Azure/azure-storage-cpp.git azure-storage-cpp --recursive -WORKDIR /tmp/azure-storage-cpp/Microsoft.WindowsAzure.Storage/build.release -RUN cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} -DBUILD_SHARED_LIBS=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DBoost_USE_STATIC_LIBS=ON .. -RUN make -j $(nproc) && make install -WORKDIR /tmp -RUN rm -rf azure-storage-cpp - - -# packages depdending on libcurl - -FROM azure-storage-dev AS aws-dev - -ARG AWS_SDK_CPP_RELEASE_TAG=1.8.123 -# library path : args have to be repeated after every FROM ? or maybe I just need to declare it before the very first one? -ARG LIBRARIES_INSTALL_PATH=/usr/local - -# it requires a patch... -# [AWSCPPSDK] -# these are tags not branches. -#RUN git clone -b ${AWS_SDK_CPP_RELEASE_TAG} --recursive https://github.com/aws/aws-sdk-cpp aws-sdk-cpp -# a patch is required to correctly build non-system CURL built with CMake -ARG AWS_SDK_CPP_PATCHED_COMMIT=95b4403042458bb1de9697052d6da43c09579ee8 -RUN git clone --recursive https://github.com/alichnewsky/aws-sdk-cpp aws-sdk-cpp -WORKDIR /tmp/aws-sdk-cpp -RUN git checkout ${AWS_SDK_CPP_PATCHED_COMMIT} -WORKDIR /tmp/aws-sdk-cpp/build -RUN cmake \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} \ - -DBUILD_SHARED_LIBS=OFF \ - -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ - -DBUILD_ONLY="s3" \ - .. -RUN make -j $(nproc) && make install -WORKDIR /tmp -RUN rm -rf aws-sdk-cpp - -FROM aws-dev AS gcloud-dev - -# plenty of patches in order to build from cmake packages. -# pretty old, to be reviewed. - -ARG LIB_CRC32C_VERSION=1.0.6 -ARG LIB_C_ARES_VERSION=1_14_0 -ARG LIB_NGHTTP2_RELEASE=1.42.0 -ARG LIB_PROTOBUF_VERSION=3.11.3 -ARG LIB_ABSEIL_RELEASE=20200225.2 -ARG LIB_GRPC_VERSION=1.29.1 - -# library path : args have to be repeated after every FROM ? or maybe I just need to declare it before the very first one? -ARG LIBRARIES_INSTALL_PATH=/usr/local - -# review sdapi build because of this. - -# [ CRC32C ] -WORKDIR /tmp -RUN wget -q https://github.com/google/crc32c/archive/${LIB_CRC32C_VERSION}.tar.gz -RUN tar -xf ${LIB_CRC32C_VERSION}.tar.gz - -RUN cmake \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} \ - -DBUILD_SHARED_LIBS=NO \ - -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ - -DCRC32C_BUILD_TESTS=OFF \ - -DCRC32C_BUILD_BENCHMARKS=OFF \ - -DCRC32C_USE_GLOG=OFF \ - -H/tmp/crc32c-${LIB_CRC32C_VERSION} -B/tmp/crc32c-${LIB_CRC32C_VERSION}/cmake-out/crc32c - -RUN cmake --build /tmp/crc32c-${LIB_CRC32C_VERSION}/cmake-out/crc32c \ - --target install -- -j $( nproc ) - -RUN rm -rf /tmp/${LIB_CRC32C_VERSION}.tar.gz -RUN rm -rf /tmp/crc32c-${LIB_CRC32C_VERSION} - -# do I need this for a static lib ? -# centos does not have this -# as a result protoc, grpc code generators don't run... -# otherwise you need ENV LD_LIBRARY_PATH set... at build only... -#RUN echo /usr/local/lib64 > /etc/ld.so.conf.d/local.conf -#RUN ldconfig - -# [C-ARES] : if we rebuild a modern one, it should go into our build of CURL as well, not just nghttp2 for gRPC - -RUN wget -q https://github.com/c-ares/c-ares/archive/cares-${LIB_C_ARES_VERSION}.tar.gz -RUN tar -xf cares-${LIB_C_ARES_VERSION}.tar.gz - -# this does not install c-ares as a CMake package -# -#RUN ./buildconf && ./configure && make -j $( nproc ) -#RUN make install -# installs in /usr/local/lib : not in /etc/ld.so.conf.d/local.conf - -RUN cmake \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} \ - -DCARES_STATIC=ON \ - -DCARES_SHARED=OFF \ - -DCARES_STATIC_PIC=ON \ - -H/tmp/c-ares-cares-${LIB_C_ARES_VERSION} \ - -B/tmp/c-ares-cares-${LIB_C_ARES_VERSION}/cmake-out - -RUN cmake --build /tmp/c-ares-cares-${LIB_C_ARES_VERSION}/cmake-out \ - --target install -- -j $( nproc ) - -RUN rm -rf /tmp/cares-${LIB_C_ARES_VERSION}.tar.gz -RUN rm -rf /tmp/c-ares-cares-${LIB_C_ARES_VERSION} - -RUN echo $(which curl) -# centos does not have this -# as a result protoc, grpc code generators don't run... -# otherwise you need ENV LD_LIBRARY_PATH set... at build only... -RUN echo /usr/local/lib > /etc/ld.so.conf.d/local.conf -RUN echo /usr/local/lib64 >> /etc/ld.so.conf.d/local.conf -RUN ldconfig - -RUN curl -sL https://github.com/nghttp2/nghttp2/releases/download/v${LIB_NGHTTP2_RELEASE}/nghttp2-${LIB_NGHTTP2_RELEASE}.tar.gz -o nghttp2.tar.gz -RUN tar -xf nghttp2.tar.gz - -RUN cmake \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} \ - -DENABLE_STATIC_LIB=ON \ - -DENABLE_SHARED_LIB=OFF \ - -DENABLE_LIB_ONLY=ON \ - -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ - -DENABLE_ARES=ON \ - -H/tmp/nghttp2-${LIB_NGHTTP2_RELEASE} \ - -B/tmp/nghttp2-${LIB_NGHTTP2_RELEASE}/cmake-out - -RUN cmake --build /tmp/nghttp2-${LIB_NGHTTP2_RELEASE}/cmake-out \ - --target install -- -j $( nproc ) - -RUN rm -rf /tmp/nghttp2.tar.gz -RUN rm -rf /tmp/nghttp2-${LIB_NGHTTP2_RELEASE} - -# rebuld CURL with ENABLE_ARES=ON USE_NGHTTP2=ON ? - -RUN wget -q https://github.com/google/protobuf/archive/v${LIB_PROTOBUF_VERSION}.tar.gz -RUN tar -xf v${LIB_PROTOBUF_VERSION}.tar.gz -RUN cmake \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} \ - -DBUILD_SHARED_LIBS=OFF \ - -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ - -Dprotobuf_BUILD_TESTS=OFF \ - -H/tmp/protobuf-${LIB_PROTOBUF_VERSION}/cmake \ - -B/tmp/protobuf-${LIB_PROTOBUF_VERSION}/cmake/cmake-out - -RUN cmake --build /tmp/protobuf-${LIB_PROTOBUF_VERSION}/cmake/cmake-out \ - --target install -- -j $( nproc ) - -RUN rm -rf /tmp/v${LIB_PROTOBUF_VERSION}.tar.gz -RUN rm -rf /tmp/protobuf-${LIB_PROTOBUF_VERSION} - - -RUN curl -sL https://github.com/abseil/abseil-cpp/archive/${LIB_ABSEIL_RELEASE}.tar.gz -o ${LIB_ABSEIL_RELEASE}.tar.gz -RUN tar xf ${LIB_ABSEIL_RELEASE}.tar.gz -RUN rm -rf ${LIB_ABSEIL_RELEASE}.tar.gz - - -# 2020-06-12 -# google-cloud-cpp super build says absl/base/options.h needs to be patched -# -RUN perl -pi -e 's@#define ABSL_OPTION_USE_STD_ANY 2@#define ABSL_OPTION_USE_STD_ANY 0@g' /tmp/abseil-cpp-${LIB_ABSEIL_RELEASE}/absl/base/options.h -RUN perl -pi -e 's@#define ABSL_OPTION_USE_STD_OPTIONAL 2@#define ABSL_OPTION_USE_STD_OPTIONAL 0@g' /tmp/abseil-cpp-${LIB_ABSEIL_RELEASE}/absl/base/options.h -RUN perl -pi -e 's@#define ABSL_OPTION_USE_STD_STRING_VIEW 2@#define ABSL_OPTION_USE_STD_STRING_VIEW 0@g' /tmp/abseil-cpp-${LIB_ABSEIL_RELEASE}/absl/base/options.h -RUN perl -pi -e 's@#define ABSL_OPTION_USE_STD_VARIANT 2@#define ABSL_OPTION_USE_STD_VARIANT 0@g' /tmp/abseil-cpp-${LIB_ABSEIL_RELEASE}/absl/base/options.h -# verify the patch worked. -RUN [[ "$( egrep '^#define ABSL_OPTION_USE_STD_(.*) 2$' /tmp/abseil-cpp-${LIB_ABSEIL_RELEASE}/absl/base/options.h |wc -l )" == "0" ]] - - -RUN cmake \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} \ - -DBUILD_TESTING=OFF \ - -DBUILD_SHARED_LIBS=NO \ - -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ - -H/tmp/abseil-cpp-${LIB_ABSEIL_RELEASE} \ - -B/tmp/abseil-cpp-${LIB_ABSEIL_RELEASE}/cmake-out - -RUN cmake --build /tmp/abseil-cpp-${LIB_ABSEIL_RELEASE}/cmake-out \ - --target install -- -j $( nproc ) - -RUN rm -rf /tmp/abseil-cpp-${LIB_ABSEIL_RELEASE} - -RUN curl -sL https://github.com/grpc/grpc/archive/v${LIB_GRPC_VERSION}.tar.gz -o v${LIB_GRPC_VERSION}.tar.gz -RUN tar -xf v${LIB_GRPC_VERSION}.tar.gz -RUN rm -rf v${LIB_GRPC_VERSION}.tar.gz - -# needed? -#ENV PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/usr/local/lib64/pkgconfig -#ENV LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64 -#ENV PATH=/usr/local/bin:${PATH} -# this does not install gRPC as a CMake package... -# -#RUN make -j $( nproc ) -#RUN make install - -RUN cmake \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} \ - -DBUILD_SHARED_LIBS=NO \ - -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ - -DgRPC_BUILD_TESTS=OFF \ - -DgRPC_ZLIB_PROVIDER=package \ - -DgRPC_SSL_PROVIDER=package \ - -DgRPC_CARES_PROVIDER=package \ - -DgRPC_PROTOBUF_PROVIDER=package \ - -DgRPC_ABSL_PROVIDER=package \ - -H/tmp/grpc-${LIB_GRPC_VERSION} \ - -B/tmp/grpc-${LIB_GRPC_VERSION}/cmake-out - -RUN cmake --build /tmp/grpc-${LIB_GRPC_VERSION}/cmake-out \ - --target install -- -j $( nproc ) - -RUN rm -rf /tmp/grpc-${LIB_GRPC_VERSION} - - -FROM gcloud-dev AS gcs-dev -ARG LIB_NLOHMANN_JSON_RELEASE_TAG=v3.9.1 -ARG GOOGLE_CLOUD_CPP_RELEASE_TAG=1.22.0 -# library path : args have to be repeated after every FROM ? or maybe I just need to declare it before the very first one? -ARG LIBRARIES_INSTALL_PATH=/usr/local - -WORKDIR /tmp - -# this is a header-only library so, we don't ask for static libs with position independent code -RUN git clone --depth 1 --branch ${LIB_NLOHMANN_JSON_RELEASE_TAG} https://github.com/nlohmann/json -RUN cmake \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} \ - -H/tmp/json -B/tmp/json/cmake-out -RUN cmake --build /tmp/json/cmake-out --target install -- -j $(nproc) -RUN rm -rf /tmp/json - - -# only build google-cloud-cpp with the storage_client api. no other, from code generation or otherwise - -# some benchmarks require CURL 7.64.0 features at compilation time but do not check. -# this is OK in this build _because_ we have a newer static libcurl - -RUN curl -sL https://github.com/googleapis/google-cloud-cpp/archive/v${GOOGLE_CLOUD_CPP_RELEASE_TAG}.tar.gz -o ${GOOGLE_CLOUD_CPP_RELEASE_TAG}.tar.gz -RUN tar -xf ${GOOGLE_CLOUD_CPP_RELEASE_TAG}.tar.gz -RUN rm -rf ${GOOGLE_CLOUD_CPP_RELEASE_TAG}.tar.gz - -# to run with GRPC in GOOGLE CLOUD STORAGE it looks like it needs a patch - -# NOT YET CONTRIBUTED -#RUN perl -pi -e 's/google_cloud_cpp_proto_library\(/include\(CompileProtos\)\ngoogle_cloud_cpp_proto_library\(/g' /tmp/google-cloud-cpp-${GOOGLE_CLOUD_CPP_RELEASE_TAG}/google/cloud/storage/CMakeLists.txt -#RUN perl -pi -e 's/if \(\$\{GOOGLE_CLOUD_CPP_ENABLE_GRPC\}\)/if \(\$\{GOOGLE_CLOUD_CPP_ENABLE_GRPC\} OR \$\{GOOGLE_CLOUD_CPP_STORAGE_ENABLE_GRPC\}\)/g' /tmp/google-cloud-cpp-${GOOGLE_CLOUD_CPP_RELEASE_TAG}/CMakeLists.txt -RUN perl -pi -e 's/foreach \(_library /foreach (_library storage /g' /tmp/google-cloud-cpp-${GOOGLE_CLOUD_CPP_RELEASE_TAG}/CMakeLists.txt -RUN perl -pi -e 's/google_cloud_cpp_proto_library\(/file\(\MAKE_DIRECTORY \$\{CMAKE_CURRENT_BINARY_DIR\}\/internal)\ngoogle_cloud_cpp_proto_library\(/g' /tmp/google-cloud-cpp-${GOOGLE_CLOUD_CPP_RELEASE_TAG}/google/cloud/storage/CMakeLists.txt -RUN perl -pi -e 's/ LOCAL_INCLUDE/ \$\{CMAKE_CURRENT_SOURCE_DIR\}\/internal LOCAL_INCLUDE/g' /tmp/google-cloud-cpp-${GOOGLE_CLOUD_CPP_RELEASE_TAG}/google/cloud/storage/CMakeLists.txt - -RUN cmake \ - -DCMAKE_INSTALL_PREFIX=${LIBRARIES_INSTALL_PATH} \ - -DBUILD_SHARED_LIBS=NO \ - -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ - -DGOOGLE_CLOUD_CPP_DEPENDENCY_PROVIDER=package \ - -DGOOGLE_CLOUD_CPP_GMOCK_PROVIDER=external \ - -DGOOGLE_CLOUD_CPP_ENABLE=storage \ - -DBUILD_TESTING=OFF \ - -DGOOGLE_CLOUD_CPP_STORAGE_ENABLE_GRPC=ON \ - -H/tmp/google-cloud-cpp-${GOOGLE_CLOUD_CPP_RELEASE_TAG} \ - -B/tmp/google-cloud-cpp-${GOOGLE_CLOUD_CPP_RELEASE_TAG}/cmake-out - -RUN cmake --build /tmp/google-cloud-cpp-${GOOGLE_CLOUD_CPP_RELEASE_TAG}/cmake-out \ - --target install -- -j $( nproc ) - -RUN rm -rf /tmp/google-cloud-cpp-${GOOGLE_CLOUD_CPP_RELEASE_TAG} - -FROM gcs-dev AS sdapi-dev - - - - -FROM sdapi-dev AS sdapi-cicd - -# Additional lines not in the original: -RUN yum install -y sudo -RUN useradd -G wheel -p '' me -USER me -ENV HOME=/home/me -ENV LINUXDISTRO=omega-dynamic -RUN (echo export LINUXDISTRO=$LINUXDISTRO; \ - echo export PS1='"\[\e[31;1m\]${LINUXDISTRO}\[\e[0m\] \[\e[32m\]\h\[\e[0m\] \W \$ "') \ - >> /home/me/.bash_profile -ENTRYPOINT /bin/bash -WORKDIR /home/me diff --git a/sd-env/Dockerfile-stretch b/sd-env/Dockerfile-stretch index 4d72811..be3e3a7 100644 --- a/sd-env/Dockerfile-stretch +++ b/sd-env/Dockerfile-stretch @@ -1,75 +1,79 @@ -FROM debian:stretch -RUN apt-get update; apt-get -y install make gcc g++ valgrind gdb strace lcov xsltproc cpio zip unzip doxygen sudo vim less uuid-dev libssl1.0-dev +# Copyright 2017-2021, Schlumberger +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. -# If you are going to run "sdutil auth login", this needs a full graphical -# environment which you can connect to with vnc. This will pull in ~500 -# packages so don't do it if you don't need it. The alternative is to -# pull in your ~/.sdcfg file from outside the docker environment. +ARG variant=cloud -#RUN apt-get update && apt-get -y install icewm xterm tightvncserver firefox +############################################################################# +### SDAPI build prerequisites ########################################### +############################################################################# -# Install other packages the build depends on. -RUN apt-get -y install cmake curl g++ libcurl3-dev zip python python-pip git pkg-config -RUN pip install egg colorama flask requests +FROM debian:stretch AS sdapi-base +ENV LINUXDISTRO=stretch -# Azure prerequisites. Have patience. -# Currently fails with compiler errors using gcc 6.3.0 -RUN find / \( -name \*.so\* -o -name \*.a \) -type f -print0 | \ - sort -z | xargs -r0 md5sum > /root/before.md5; \ - find / -type f -print | sort -o /root/before.lst; true -#RUN mkdir -p /opt && \ -# cd /opt && \ -# git clone https://github.com/microsoft/vcpkg.git && \ -# cd vcpkg && \ -# ./bootstrap-vcpkg.sh -disableMetrics -#RUN cd /opt/vcpkg; ./vcpkg install azure-storage-cpp -RUN find / \( -name \*.so\* -o -name \*.a \) -type f -print0 | \ - sort -z | xargs -r0 md5sum > /root/after.md5; \ - find / -type f -print | sort -o /root/after.lst; true +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} -# A regular user, not root, should be used for development. -RUN useradd -G sudo --shell /bin/bash -p '' me +RUN apt-get update && \ + apt-get -y install \ + make gcc g++ valgrind lcov xsltproc cpio zip unzip sudo vim less \ + uuid-dev libssl1.0-dev cmake curl g++ libcurl3-dev zip git pkg-config +RUN useradd -m -u 800 -G sudo --shell /bin/bash -p '' me +WORKDIR /home/me -# Run a script that drops root privileges and switches to the same -# numerical userid as the user that started the docker image. -# This user will be allowed to sudo back to root if required. -# PID 1 will be a bash shell, needed to partly fix the problem of -# zombies. Bash correctly reaps adopted processes but it doesn't -# propagate signals. So "docker stop" causes an unclean exit. -# https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/ -# The "set -a" is just a trick to avoid having the shell exec the script. -ENTRYPOINT ["/bin/bash"] -CMD ["-c", "set -a; /home/me/tools/switchuser.sh"] +############################################################################# +### SDAPI third party dependencies (have patience) ###################### +############################################################################# -# Misc. configuration goes here. -RUN mkdir -p /home/me/.vnc; echo 'xterm & /usr/bin/icewm; vncserver -kill ${DISPLAY}' > /home/me/.vnc/xstartup; chmod 755 /home/me/.vnc/xstartup +FROM sdapi-base AS sdapi-manual -# Assuming that the work area is ~me/seismic-drive-client-api, -# make sdutil available globally without further installation. -RUN rm -f /bin/sdutil; (echo '#!/bin/bash'; echo 'exec env PYTHONPATH=/home/me/seismic-store-sdutil python /home/me/seismic-store-sdutil/sdutil.py' '"$@"') > /bin/sdutil; chmod 755 /bin/sdutil +############################################################################# +### Environment is ready, build SDAPI now! ############################## +############################################################################# -# The current directory may hold ad-hoc tools for debugging -# and usage examples. -COPY . /home/me/tools -ENV LINUXDISTRO=stretch -RUN (echo export LINUXDISTRO=$LINUXDISTRO; \ - echo export PS1='"\[\e[31;1m\]${LINUXDISTRO}\[\e[0m\] \[\e[32m\]\h\[\e[0m\] \W \$ "') \ - >> /home/me/.bash_profile +FROM sdapi-manual AS sdapi-build -# Optional... -#RUN apt-get -y install xfce4 xfce4-goodies tightvncserver firefox -#RUN apt-get -y install openssh-server openssh-client -#RUN echo Remember to do /etc/init.d/ssh start +# SOURCE CODE FROM BUILD CONTEXT COPIED IN +COPY --chown=800 seismic-store-cpp-lib /home/me/sdapi/ +COPY --chown=800 seismic-dms-sdapi /home/me/sdapi-slb/ +COPY --chown=800 ["sd-env/build-template.sh", "sd-env/*.patch", "/home/me/" ] +USER me +RUN patch -p1 -N -d /home/me/sdapi -i /home/me/cmakelists2.patch || true +RUN test ! -d /home/me/sdapi-slb || (\ + cd /home/me/sdapi-slb && \ + find src/core src/lib/auth -print | cpio -pduv ../sdapi) +ARG AZURE_BUILDID +ENV AZURE_BUILDID=${AZURE_BUILDID} +RUN ./build-template.sh -### Usage example: -# -#docker build --pull -f Dockerfile-stretch -t sd-env-stretch:latest . -# -#docker run -it -p 5901:5901 \ # vnc access -# -v ${HOME}/.ssh:/home/me/.ssh \ # ssh credentials -# -v ${HOME}/.sdcfg:/home/me/.sdcfg \ # seismic-drive cred -# -v ${WORKAREA}:/home/me/seismic-store-client-api-cpp \ # source code -# -v ${WORKAREA2}:/home/me/seismic-store-sdutil \ # source code -# --cap-add sys_ptrace \ # debugging -# sd-env-stretch:latest +############################################################################# +### OpenZGY is not supported for this distro. ################### +### Add dummy targets to maybe simplify the Makefile. ################### +############################################################################# + +FROM alpine AS openzgy-source-vanilla +FROM openzgy-source-vanilla AS openzgy-source-cloud + +### Produce the deploy folder that the OpenZGY builder would have made. +### This makes no sense for variant=vanilla as deploy would be empty. +FROM openzgy-source-${variant} AS openzgy-build +COPY --from=sdapi-build /home/me/sdapi_linux64.tar.gz /home/me/ +COPY --from=sdapi-build /home/me/realname.txt /home/me/ +RUN d=/home/me/oz/build/deploy/sdapi/$(cat /home/me/realname.txt) && \ + /bin/mkdir -p $(dirname ${d}) && \ + /bin/cp /home/me/sdapi_linux64.tar.gz ${d} + +FROM alpine AS openzgy-minimal +FROM openzgy-minimal AS openzgy-testenv +FROM openzgy-testenv AS openzgy-test diff --git a/sd-env/Dockerfile-xenial b/sd-env/Dockerfile-xenial index fbc14c7..6990c3f 100644 --- a/sd-env/Dockerfile-xenial +++ b/sd-env/Dockerfile-xenial @@ -1,62 +1,78 @@ -FROM ubuntu:xenial - -# If you are going to run "sdutil auth login", this needs a full graphical -# environment which you can connect to with vnc. This will pull in ~500 -# packages so don't do it if you don't need it. The alternative is to -# pull in your ~/.sdcfg file from outside the docker environment. - -RUN apt-get update && apt-get -y install icewm xterm tightvncserver firefox - -# Install other packages the build depends on. -RUN apt-get -y install cmake curl g++ libcurl3-dev libssl-dev zip python python-pip git emacs vim sudo pkg-config -#RUN pip install --upgrade pip ## NOT! Latest pip is incompatible with xenial. -RUN pip install egg colorama flask requests - -# Azure prerequisites. NOT IN THIS CONFIG (Compiler too old) - -# A regular user, not root, should be used for development. -RUN groupadd -r admin; useradd -G admin --shell /bin/bash -p '' me - -# Run a script that drops root privileges and switches to the same -# numerical userid as the user that started the docker image. -# This user will be allowed to sudo back to root if required. -# PID 1 will be a bash shell, needed to partly fix the problem of -# zombies. Bash correctly reaps adopted processes but it doesn't -# propagate signals. So "docker stop" causes an unclean exit. -# https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/ -# The "set -a" is just a trick to avoid having the shell exec the script. -ENTRYPOINT ["/bin/bash"] -CMD ["-c", "set -a; /home/me/tools/switchuser.sh"] - -# Misc. configuration goes here. -RUN mkdir -p /home/me/.vnc; echo 'xterm & /usr/bin/icewm; vncserver -kill ${DISPLAY}' > /home/me/.vnc/xstartup; chmod 755 /home/me/.vnc/xstartup - -# Assuming that the work area is ~me/seismic-drive-client-api, -# make sdutil available globally without further installation. -RUN rm -f /bin/sdutil; (echo '#!/bin/bash'; echo 'exec env PYTHONPATH=/home/me/seismic-store-sdutil python /home/me/seismic-store-sdutil/sdutil.py' '"$@"') > /bin/sdutil; chmod 755 /bin/sdutil - -# The current directory may hold ad-hoc tools for debugging -# and usage examples. -COPY . /home/me/tools +# Copyright 2017-2021, Schlumberger +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG variant=cloud + +############################################################################# +### SDAPI build prerequisites ########################################### +############################################################################# + +FROM ubuntu:xenial AS sdapi-base ENV LINUXDISTRO=xenial -RUN (echo export LINUXDISTRO=$LINUXDISTRO; \ - echo export PS1='"\[\e[31;1m\]${LINUXDISTRO}\[\e[0m\] \[\e[32m\]\h\[\e[0m\] \W \$ "') \ - >> /home/me/.bash_profile -# Optional... -#RUN apt-get -y install xfce4 xfce4-goodies tightvncserver firefox -#RUN apt-get -y install openssh-server openssh-client -#RUN echo Remember to do /etc/init.d/ssh start +ARG CLEAN_BUILD_COUNTER=1 +ENV CLEAN_BUILD_COUNTER=${CLEAN_BUILD_COUNTER} +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get -y install \ + g++ cmake curl libcurl3-dev libssl-dev zip git vim sudo pkg-config cpio +RUN useradd -m -u 800 -G sudo --shell /bin/bash -p '' me +WORKDIR /home/me -### Usage example: -# -#docker build --pull -f Dockerfile-xenial -t sd-env-xenial:latest . -# -#docker run -it -p 5901:5901 \ # vnc access -# -v ${HOME}/.ssh:/home/me/.ssh \ # ssh credentials -# -v ${HOME}/.sdcfg:/home/me/.sdcfg \ # seismic-drive cred -# -v ${WORKAREA}:/home/me/seismic-store-client-api-cpp \ # source code -# -v ${WORKAREA2}:/home/me/seismic-store-sdutil \ # source code -# --cap-add sys_ptrace \ # debugging -# sd-env-xenial:latest +############################################################################# +### SDAPI third party dependencies (have patience) ###################### +############################################################################# + +FROM sdapi-base AS sdapi-manual + +############################################################################# +### Environment is ready, build SDAPI now! ############################## +############################################################################# + +FROM sdapi-manual AS sdapi-build + +# SOURCE CODE FROM BUILD CONTEXT COPIED IN +COPY --chown=800 seismic-store-cpp-lib /home/me/sdapi/ +COPY --chown=800 seismic-dms-sdapi /home/me/sdapi-slb/ +COPY --chown=800 ["sd-env/build-template.sh", "sd-env/*.patch", "/home/me/" ] +USER me + +RUN patch -p1 -N -d /home/me/sdapi -i /home/me/cmakelists2.patch || true +RUN test ! -d /home/me/sdapi-slb || (\ + cd /home/me/sdapi-slb && \ + find src/core src/lib/auth -print | cpio -pduv ../sdapi) +ARG AZURE_BUILDID +ENV AZURE_BUILDID=${AZURE_BUILDID} +RUN ./build-template.sh + +############################################################################# +### OpenZGY is not supported for this distro. ################### +### Add dummy targets to maybe simplify the Makefile. ################### +############################################################################# + +FROM alpine AS openzgy-source-vanilla +FROM openzgy-source-vanilla AS openzgy-source-cloud + +### Produce the deploy folder that the OpenZGY builder would have made. +### This makes no sense for variant=vanilla as deploy would be empty. +FROM openzgy-source-${variant} AS openzgy-build +COPY --from=sdapi-build /home/me/sdapi_linux64.tar.gz /home/me/ +COPY --from=sdapi-build /home/me/realname.txt /home/me/ +RUN d=/home/me/oz/build/deploy/sdapi/$(cat /home/me/realname.txt) && \ + /bin/mkdir -p $(dirname ${d}) && \ + /bin/cp /home/me/sdapi_linux64.tar.gz ${d} + +FROM alpine AS openzgy-minimal +FROM openzgy-minimal AS openzgy-testenv +FROM openzgy-testenv AS openzgy-test diff --git a/sd-env/Makefile b/sd-env/Makefile index af4ecef..7c153dc 100644 --- a/sd-env/Makefile +++ b/sd-env/Makefile @@ -2,62 +2,110 @@ # Point to where you cloned SDAPI, and where you want its binaries to go. CWD := $(shell pwd) -WORKAREA = $(abspath $(CWD)/../os-seismic-store-cpp-lib) -#WORKAREA2 = $(abspath $(CWD)/../seismic-store-sdutil) -WORKAREA3 = $(abspath $(CWD)/../seismic-service-bin) - -DISTROS = centos stretch xenial bionic focal buster omega fedora centos8 -#DISTROS += omega-static omega-dynamic -BUILD_ALL = $(addprefix build-,$(DISTROS)) +WORKAREA = $(abspath $(CWD)/../seismic-store-cpp-lib) +DISTROS = centos7 stretch xenial bionic focal buster omega fedora centos8 +DISTROS_OPENZGY = centos7 bionic focal buster centos8 +MANUAL_ALL = $(addprefix manual-,$(DISTROS)) RUN_ALL = $(addprefix run-,$(DISTROS)) +FINAL_ALL = $(addprefix final-,$(DISTROS)) -.PHONY: build run all clean clobber $(BUILD_ALL) $(RUN_ALL) - -RUNARGS = -it +.PHONY: help manual final run clean clobber +#.PHONY $(MANUAL_ALL) $(RUN_ALL) $(FINAL_ALL) +# .PHONY doesn't play well with pattern rules. +RUNARGS = -it --user 800 RUNARGS += --cap-add sys_ptrace -#RUNARGS += -v $(HOME)/.ssh:/home/me/.ssh -#RUNARGS += -v $(HOME)/.sdcfg:/home/me/.sdcfg RUNARGS += -v $(WORKAREA):/home/me/sdapi:ro -#RUNARGS += -v $(WORKAREA2):/home/me/seismic-store-sdutil:ro -RUNARGS += -v $(CWD)/build.sh:/home/me/build.sh +RUNARGS += -v $(CWD)/build-template.sh:/home/me/build.sh +RUNCRED = -e OPENZGY_TOKEN -e OPENZGY_SDAPIKEY -e OPENZGY_SDURL + +PULL=--pull +#PULL= # This Makefile does not support parallel execution with -j N # The only really time consuming part is to build the Azure # prerequisites, and the task for that will enable parallel itself. .NOTPARALLEL: -all: - @echo "Remember to update the paths at the top of this Makefile." +help: + @echo + @echo "Make target for one-click builds:" @echo - @echo " SDAPI source is now $(WORKAREA)" - @echo " SDAPI target is now $(WORKAREA3)" + @echo " make final -- Build, compile, test everything." + @echo " make final-DIST -- Build, compile, test for DIST only." @echo - @echo "Available make targets, typically run in this order:" + @echo "Make targets for manual builds, typically run in this order:" @echo - @echo " make clobber -- Removes docker instances but not images" - @echo " make build -- Rebuilds images, orphaning any old ones" - @echo " make run -- Create instances but don't start them" - @echo " make xterm -- Start instances in individual windows" + @echo " make clobber -- Removes docker instances but not images" + @echo " make manual -- Rebuilds images used for manual builds" + @echo " Source mapped from $(WORKAREA)" + @echo " make run -- Create instances but don't start them" + @echo " make xterm -- Start instances in individual windows" + @echo + @echo 'To manually build one distro only, use e.g. manual-xenial and' + @echo 'run-xenial. Then start with "docker start -ai sd-xenial"' + @echo 'instead of "make xterm".' + @echo + @echo 'Note that manual builds expect to find the SDAPI source at' + @echo "$(WORKAREA)" + @echo 'in the host. The source will be mapped as a volume into the' + @echo 'container. Any patching needs to be done outside. "make final"' + @echo 'will instead copy the source and will handle patching itself.' @echo - @echo "To build one distro only, use e.g. build-xenial and run-xenial" - @echo 'then start that one with "docker start -ai sd-xenial"' -build: $(BUILD_ALL) - $(RM) build.sh +final: $(FINAL_ALL) + +manual: $(MANUAL_ALL) run: $(RUN_ALL) -build.sh: build-template.sh - /bin/cp $^ $@ - sed -i \ - -e 's;^#NEEDS.*;# -- GENERATED FILE -- MAY BE OVERWRITTEN -- DO NOT CHECK IN --;' \ - -e 's;^WORKAREA=.*;WORKAREA=${WORKAREA};' \ - -e 's;^WORKAREA3=.*;WORKAREA3=${WORKAREA3};' \ - $@ +FRC: + +manual-%: FRC + docker build $(PULL) -f Dockerfile-$* --target sdapi-manual -t sd-env-$*:manual .. + docker rmi sd-env-$*:manual-old || true + docker tag sd-env-$*:manual sd-env-$*:manual-old || true + +run-%: FRC + docker rm --force sd-$* || true + docker create $(RUNARGS) --name sd-$* sd-env-$*:manual + +# This would work, letting the tests run as part of the final +# container build. But there will be no seismic store parameters +# passed in. And no attempt to control caching by naming the +# intermediate stages. +#final-%: FRC +# docker build $(PULL) -f Dockerfile-$* --target openzgy-test -t sd-env-$*:oztest .. + +final-%: FRC + mkdir -p ../seismic-dms-sdapi ../seismic-store-cpp-lib ../private + $(RM) -f oztests.iid + docker build $(PULL) -f Dockerfile-$* --target sdapi-manual -t sd-env-$*:manual .. + docker build -f Dockerfile-$* --target sdapi-build -t sd-env-$*:sdbuild .. + docker build -f Dockerfile-$* --target openzgy-build -t sd-env-$*:ozbuild .. + docker build -f Dockerfile-$* --target openzgy-testenv -t sd-env-$*:oztests --iidfile oztests.iid .. + docker rmi sd-env-$*:manual-old || true + docker rmi sd-env-$*:sdbuild-old || true + docker rmi sd-env-$*:ozbuild-old || true + docker rmi sd-env-$*:oztests-old || true + docker tag sd-env-$*:manual sd-env-$*:manual-old || true + docker tag sd-env-$*:sdbuild sd-env-$*:sdbuild-old || true + docker tag sd-env-$*:ozbuild sd-env-$*:ozbuild-old || true + docker tag sd-env-$*:oztests sd-env-$*:oztests-old || true + $(RM) -f oztests.iid + rmdir --ignore-fail-on-non-empty ../seismic-dms-sdapi ../seismic-store-cpp-lib ../private + +testonly-%: + docker run --rm $(RUNCRED) sd-env-$*:oztests native/src/runtests.sh + docker run --rm $(RUNCRED) sd-env-$*:oztests native/sdglue/runtests.sh + docker run --rm $(RUNCRED) sd-env-$*:oztests wrapper/runtests.sh + docker run --rm $(RUNCRED) sd-env-$*:oztests python/runtests.sh + +test-%: final-% testonly-% + @echo "Tests for $* are complete" .PHONY: xterm xterm: - xterm -sl 256 -T 'centos (gcc 4.9.2)' -geometry 200x24+50+100 -e docker start -ai sd-centos & + xterm -sl 256 -T 'centos (gcc 7.3.1)' -geometry 200x24+50+100 -e docker start -ai sd-centos7 & @sleep 2 xterm -sl 256 -T 'Debian stretch (gcc 6.3.0)' -geometry 200x24+100+200 -e docker start -ai sd-stretch & @sleep 2 @@ -74,89 +122,51 @@ xterm: xterm -sl 256 -T 'fedora (gcc 9.3.1)' -geometry 200x24+400+800 -e docker start -ai sd-fedora & @sleep 2 xterm -sl 256 -T 'centos8 (gcc 8.4.1)' -geometry 200x24+450+900 -e docker start -ai sd-centos8 & -# @sleep 2 -# xterm -sl 256 -T 'omega-static (gcc 7.3.1)' -geometry 200x24+500+1000 -e docker start -ai sd-omega-static & -# @sleep 2 -# xterm -sl 256 -T 'omega-dynamic (gcc 7.3.1)' -geometry 200x24+550+1100 -e docker start -ai sd-omega-dynamic & - -#Can no longer be built because devtoolset-4 is EOL. -#This is a problem if building somewhere the image isn't cached. -#build-centos: -# docker build -t sd-env:latest . - -build-xenial: - docker build --pull -f Dockerfile-xenial -t sd-env-xenial:latest . - -build-bionic: - docker build --pull -f Dockerfile-bionic -t sd-env-bionic:latest . - -build-focal: - docker build --pull -f Dockerfile-focal -t sd-env-focal:latest . - -build-stretch: - docker build --pull -f Dockerfile-stretch -t sd-env-stretch:latest . - -build-buster: - docker build --pull -f Dockerfile-buster -t sd-env-buster:latest . - -build-omega: - docker build --pull -f Dockerfile-omega -t sd-env-omega:latest . - -build-omega-static: - docker build --pull -f Dockerfile-omega-static -t sd-env-omega-static:latest . - -build-omega-dynamic: - docker build --pull -f Dockerfile-omega-dynamic -t sd-env-omega-dynamic:latest . -build-fedora: - docker build --pull -f Dockerfile-fedora -t sd-env-fedora:latest . - -build-centos8: - docker build --pull -f Dockerfile-centos8 -t sd-env-centos8:latest . - -run-centos: build.sh - docker create $(RUNARGS) --name sd-centos sd-env:latest - -run-xenial: build.sh - docker create $(RUNARGS) --name sd-xenial sd-env-xenial:latest - -run-bionic: build.sh - docker create $(RUNARGS) --name sd-bionic sd-env-bionic:latest - -run-focal: build.sh - docker create $(RUNARGS) --name sd-focal sd-env-focal:latest - -run-stretch: build.sh - docker create $(RUNARGS) --name sd-stretch sd-env-stretch:latest - -run-buster: build.sh - docker create $(RUNARGS) --name sd-buster sd-env-buster:latest - -run-omega: build.sh - docker create $(RUNARGS) --name sd-omega sd-env-omega:latest - -run-omega-static: build.sh - docker create $(RUNARGS) --name sd-omega-static sd-env-omega-static:latest - -run-omega-dynamic: build.sh - docker create $(RUNARGS) --name sd-omega-dynamic sd-env-omega-dynamic:latest - -run-fedora: build.sh - docker create $(RUNARGS) --name sd-fedora sd-env-fedora:latest - -run-centos8: build.sh - docker create $(RUNARGS) --name sd-centos8 sd-env-centos8:latest - -clean: - $(RM) build.sh - -clobber: clean +# This is only valid if all tasks has run on the same machine, e.g. +# with a "make final". All deployed files are unpacked on top of each +# other. So if there are files with the same name that in theory +# should have the same contents the last one wins. TODO check. +# Part of the mechanism for checking is already in place. +# Should iterate with "prev and "next". if "next" is a backup +# file then it should match "prev". + +.PHONY: copyout +copyout: + $(RM) -rf deploy + (for distro in $(DISTROS); do \ + id=$$(docker create sd-env-$${distro}:ozbuild) && \ + docker cp $${id}:/home/me/oz/build/deploy - | \ + tar xf - --backup --suffix ~$${prev}~ && \ + docker rm $${id} > /dev/null; \ + prev=$${distro}; \ + done) + @echo "find deploy -type f -print | sort | xargs md5sum" + find deploy -type f -name \*~ -print0 | sort -z | xargs -r0 rm + +# Caveat: this only works on local builds where the timestamp can be preseved. +# Caveat: Make sure all images used in FROM lines are listed here. +# Pull all the base images, but not more frequently than every 24 hours. +# If this is called before any container build then the --pull option +# can be removed from "docker build". Docker is now rate limiting pulls +# to 100 per 6 hours, and apparently they also count pulls that do nothing +# because the image is already up to date. + +.PHONY: pull +pull: + touch -d yesterday pull-needed.timestamp + $(MAKE) pull-done.timestamp + +pull-done.timestamp: pull-needed.timestamp + docker pull centos:centos7 + docker pull centos:centos8 + docker pull debian:buster + docker pull debian:stretch + docker pull fedora:31 + docker pull ubuntu:bionic + docker pull ubuntu:focal + docker pull ubuntu:xenial + touch pull-done.timestamp + +clobber clean: docker rm --force $(patsubst %,sd-%,$(DISTROS)) || true - -# Note: As of 30-Jun-2021 this kludge is needed... -.PHONY: fix-cmake -fix-cmake: - docker cp sd-omega:/opt/vcpkg/scripts/buildsystems/vcpkg.cmake vcpkg.cmake - docker cp vcpkg.cmake sd-bionic:/opt/vcpkg/scripts/buildsystems/vcpkg.cmake - docker cp vcpkg.cmake sd-buster:/opt/vcpkg/scripts/buildsystems/vcpkg.cmake - $(RM) vcpkg.cmake diff --git a/sd-env/README-details.md b/sd-env/README-details.md new file mode 100644 index 0000000..7625ee7 --- /dev/null +++ b/sd-env/README-details.md @@ -0,0 +1,137 @@ +## Detailed description of the Dockerfiles + +There is one multi-stage Dockerfile for each supported distribution. +You can use the --target option to adjust what you want to build. + +You might not care. Reading these instructions is optional. + +### Manual build of SDAPI only. + +Pass ```--target=sdapi-manual``` to docker build or use make +manual-${distro}. This will create a docker image with all +prerequisites for building SDAPI but won't actually build it. This is +convenient for debugging. + +Note that the dependencies installed using vcpkg always refer to a +specific hash of the vcpkg tool. The reason is that the "git clone" +used to fetch vcpkg will normally get cached by docker. So even when a +new vcpkg is available it won't be consumed until the cache is +invalidated for some other reason. Such as a change im the base image. +This random behavior is not acceptable. + +After doing this you should create a docker image e.g. by running make +run-${distro} or using the appropriate "docker create" or "docker run" +command. Start the image using "docker attach" or "make xterm". The +latter produces harmless but noisy error messages if you are only +building a single distro. + +When using this approach the source code will be outside the docker +image and made available to the image by a volume mount. If the source +needs to be patched then this needs to be done outside. + +Unlike the next stages this target needs no build context. +So you can run "docker build" in an empty or almost empty +folder to save time sending data to the daemon. + +To build the software type ./build-template.sh inside the image. Add +"Debug" if you want. Copy the result out of the image. The last line +of output shows how. If build-template.sh doesn't fill your needs then +take a look at the README file in +[seismic-store-cpp-lib](https://community.opengroup.org/osdu/platform/domain-data-mgmt-services/seismic/seismic-dms-suite/seismic-store-cpp-lib) + +A plain "make manual" will set up build images for all supported +distros, and a "make run" will create but not start them. Typing +"make xterm" will then start all of them, each in a separate window. + +### Build SDAPI only. + +Pass ```--target=sdapi-build``` to go one step further and create an image +where the SDAPI is already built. When using this target the source +code will be copied into the image before building starts. Unlike the +manual procedure the sdapi-build target assumes that the source code +that was cloned is completely unmodified. The build will automatically +run some required patches. + +### Build both SDAPI and OpenZGY + +Pass ```--target=openzgy-build``` to create an image where both SDAPI +and OpenZGY are built but no tests are run. + +### Build a ready to use environment + +Pass ```--target=openzgy-minimal``` to create an image that can be +used to experiment with both the pure and the wrapped C++ Python +versions. There will be no source code or intermediate output. Only +the deployed result. + +Note that you might not want to bother with this target because the +next (openzgy-test) image includes both this setup and some ready to +run unit tests. The main reason for building the "minimal" image in a +separate step is that if you look at that target inside the Dockerfile +you can see exactly what dependencies are required at runtime. + +### Final result + +Pass ```--target=openzgy-test``` or just omit the target to add some +unit test scripts to the image and run the on-prem tests. Tests using +seismic store need to be run manually. + +To run all tests including seismic store test, run the image as a +container and set the required OPENZGY_ environmnent varibles for +credentials. Example assuming the environment on the host is already +good: + +```sh +env="-e OPENZGY_TOKEN -e OPENZGY_SDURL -e OPENZGY_SDAPIKEY" +for script in \ + native/src/runtests.sh \ + native/sdglue/runtests.sh \ + wrapper/runtests.sh \ + python/runtests.sh +do + docker run --rm -it ${env} openzgy-test-centos8:latest $script +done +``` + +The tar file used to deploy OpenZGY can be copied out from this image. + +### Building without seismic store support + +To support on-prem data only, pass ```--build-arg variant=vanilla``` +which will remove SDAPI from the image that builds OpenZGY. + +Current versions of docker will run the stages that build Seismic +Store even when the final image doesn't need them. Docker buildkit +will reportedly handle it correctly. If performance is an issue and +the experimantal buildkit is not an option then make a copy of the +Dockerfile and delete these stages: + +- sdapi-base +- sdapi-manual +- sdapi-build +- openzgy-source-cloud + +If building on a local developer machine for the current architecture +and cloud support is not needed then it might be simpler to skip +docker completely. Just run "make build" or "make" at the top level. +Building with docker can be more work for those not already familiar +with that environment. + +### Caching of docker images + +You only need to build the final "openzgy-test" target if all you want +is a ready to deploy OpenZGY. You might however want to build the +sdapi-build and openzgy-build intermediate targets as well so you can +tag those intermediate stages with a proper name. There should be no +additional cost and nothing more is built. Only the label is added. +The labels simplify keeping one and only one image cached to speed up +builds. See the Makefile for details. + +### CentOS 7 vs. Omega + +The CentOS 7 build uses devtoolset-7 (with g++ 7) to build SDAPI +because SDAPI core requires gcc 4.9.2 or later, and Azure Storage +requires gcc 7 or later. OpenZGY is still built with the default +compiler. In contrast, the Omega build tries to follow whatever the +Omega team uses. Currently the Omega build will compile everything +with devtoolset-7. diff --git a/sd-env/README.md b/sd-env/README.md index d956564..58a75cd 100644 --- a/sd-env/README.md +++ b/sd-env/README.md @@ -1,71 +1,30 @@ -## Contents of sd-env/ +## Contents of sd-env -Most of the files in the sd-env folder are used for building SDAPI -inside a docker container for various architectures. They might -require some tweaking before use. You don't need these files and you -don't need docker if you just want to build a single version of the -code that will run on your current architecture. The README.md file in -[os-seismic-store-cpp-lib](https://dev.azure.com/slb-des-ext-collaboration/open-data-ecosystem/_git/os-seismic-store-cpp-lib) -explains how to build the software by hand. +The Makefile and the Dockerfiles in the sd-env folder can be used to +build SDAPI (the seismic store development kit) and/or OpenZGY. -That being said, the docker files might help setting up the -prerequisites correctly. And using docker avoids polluting your -current environment with a lot of extra packages. The downside is that -if you are not already familiar with docker then this approach might -involve more effort. And the scripts here need to do more and are thus -somewhat more complex than building by hand. +Quick start: -## Building - -```bash -cd sd-env -# edit Makefile, change the first few lines to point to your work areas. -make clobber -make build -make run -docker start -ai sd-centos # or sd-buster, sd-stretch, sd-bionic, sd-xenial, ... -build.sh -exit -# copy the resulting tarball to seismic-service-bin -# Repeat for the other environments, starting at the "docker start" step. +```sh +git clone https://community.opengroup.org/osdu/platform/domain-data-mgmt-services/seismic/open-zgy.git open-zgy +git clone --recursive https://community.opengroup.org/osdu/platform/domain-data-mgmt-services/seismic/seismic-dms-suite/seismic-store-cpp-lib.git open-zgy/seismic-store-cpp-lib +make final-${distro} ``` -As a convenience, after "make run" you could also run "make xterm" -which does a "docker start" for all the environments, each in their -own terminal window. - -## Explanation: - -The makefile is currently set up to mount the source code as a volume. -If needed this can be changed to have "docker build" embed the source -code inside the image. - -Carefully check the output of each build. The procedure might need -some tweaking. In particular you might need to edit build.sh. - -The "make build" will create 9 docker images, one for each supported -ZGY-Cloud environment. You only need to re-run that steps if the -environment changes, e.g. if there is a compiler patch or if the base -image changes. - -"make run" creates 9 corresponding containers with the source code -mounted as volumes. Technically those can also be re-used unless you -have built new images. If you are paranoid about always starting from -a clean image then do "make clobber; make run" before building. That -only takes a few seconds. - -Caveat: The CentOS 7 build is currently broken because devtoolset-4 is no longer available. A newer devtoolset might work, but there is a risk that consumers (i.e. OpenZGY, and software linking with OpenZGY) will then be forced to use the same non-default compilers. The current situation is that SDAPI requires gcc 4.9.2 or later while OpenZGY for Centos/RedHat 7 works with the default gcc 4.8.5 compiler. Devtoolset-4 does a good job of ensuring that the SDAPI code compiled in that environment can be linked with the libc and libc++ delivered with gcc 4.8.5. Good luck with that if you instead try to compile gcc 4.9.2 yourself. - -As for the "copy the resulting tarball" step, the build script prints -out the command to do this. The command has to be executed outside the -image, so the script cannot actually run it. - -## VNC - -Most of the docker files include a graphical environment that can be -useful for testing and debugging. If you just need to build the -software you don't need to bother with that. - -To access the GUI you should execute "vncserver" inside the image and -"vncviewer :1" on the host. You will also need to export the VNC port -from the docker image. +This will build SDAPI, build OpenZGY, and run the OpenZGY unit tests. +Currently supported in the distro parameter is +- stretch +- xenial +- bionic +- focal +- buster +- omega +- fedora +- centos8 + +The resulting docker image can be used to experiment with both the +pure and the wrapped C++ Python versions. The image also contains a +tar file that can be copied out of the image for deploying OpenZGY. + +For an explanation of the more obscure targets you might want to build, +see the [detailed readme file](README-details.md). diff --git a/sd-env/build-template.sh b/sd-env/build-template.sh index b678eca..60787b3 100755 --- a/sd-env/build-template.sh +++ b/sd-env/build-template.sh @@ -1,9 +1,5 @@ #!/bin/bash -e -#NEEDS TO BE SET -WORKAREA= -WORKAREA3= - # Note: To build the SAuth aware version of SDAPI the osdu source code # needs to be patched with 7 files (4 new, 3 modified) from the old # seismic-store-client-api-cpp repository: @@ -25,34 +21,27 @@ WORKAREA3= # causing crc32c and sdapi to disagreee about where # the libraries should be installed. -if [ -x /bin/cmake3 ]; then - CMAKE=/bin/cmake3 -elif [ -x /usr/bin/cmake3 ]; then - CMAKE=/usr/bin/cmake3 -elif [ -x /bin/cmake ]; then - CMAKE=/bin/cmake -else - CMAKE=/usr/bin/cmake -fi +CMAKE=cmake3; type 2>/dev/null $CMAKE || CMAKE=cmake + SRC=../sdapi/src cd ${HOME} -rm -rf build sdapi_linux64_osdu.tar.gz; mkdir build; cd build +rm -rf build sdapi_linux64_osdu.tar.gz realname.txt; mkdir build; cd build AZUREMSG="(with Google support only)" AZUREDEF= if [ -r /opt/vcpkg/scripts/buildsystems/vcpkg.cmake ] then AZUREMSG="(with Google and Azure support)" - AZUREDEF="-DCMAKE_TOOLCHAIN_FILE=/opt/vcpkg/scripts/buildsystems/vcpkg.cmake -DOPTIONAL_STORAGE_PROVIDERS_ENABLED:STRING=azure;azure-curl" + AZUREDEF="-DCMAKE_TOOLCHAIN_FILE=/opt/vcpkg/scripts/buildsystems/vcpkg.cmake -DOPTIONAL_STORAGE_PROVIDERS_ENABLED:STRING=azure-curl" elif [ -r /usr/local/lib/libazurestorage.so ] then AZUREMSG="(with Google and (dynamic?) Azure support)" - AZUREDEF="-DOPTIONAL_STORAGE_PROVIDERS_ENABLED:STRING=azure;azure-curl" + AZUREDEF="-DOPTIONAL_STORAGE_PROVIDERS_ENABLED:STRING=azure-curl" elif [ -r /usr/local/lib/libazurestorage.a ] then AZUREMSG="(with Google and (static?) Azure support)" - AZUREDEF="-DOPTIONAL_STORAGE_PROVIDERS_ENABLED:STRING=azure;azure-curl" + AZUREDEF="-DOPTIONAL_STORAGE_PROVIDERS_ENABLED:STRING=azure-curl" fi #Version on commandline? @@ -82,6 +71,8 @@ $CMAKE -DCMAKE_BUILD_TYPE=${1:-Release} ${VERSIONDEF} ${AZUREDEF} ${SRC} # there was confusion about where the binaries ended up. #make || true #test -x crc32c/lib64 || ln -s lib crc32c/lib64 +# This is new... centos7 builds, should't hurt others I think. +test -e /usr/local/include/crc32c || sudo ln -s /home/me/sdapi/src/third-party/crc32c/include/crc32c /usr/local/include/ # This kludge is needed as of June 2021 but has to be applied outside # the build container because inside the source is readonly. @@ -101,19 +92,35 @@ make rm -rf tmp mkdir -p tmp/include tmp/lib/linux64 +function gethead { + gitdir="${1:-.}/.git" + if [ -r "${gitdir}/HEAD" ] + then + read hash ref < "${gitdir}/HEAD" + if [ "x$hash" = "xref:" -a "x$ref" != "x" -a -r "${gitdir}/$ref" ] + then + read hash < "${gitdir}/$ref" + fi + else + hash=no-hash-available + fi + echo $hash +} + # Capture the hash of the OSDU part of SDAPI, and the version of some # packages installed by vcpkg. -echo "LINUX: ${LINUXDISTRO:-unknown}" -echo "SDAPI: $(cd /home/me/sdapi && git rev-parse HEAD)" > tmp/version.txt +echo "LINUX: ${LINUXDISTRO:-unknown}" > tmp/version.txt +echo "SDAPI: $(gethead /home/me/sdapi)" >> tmp/version.txt if [ -x /opt/vcpkg/vcpkg ] then - echo "VCPKG: $(cd /opt/vcpkg && git rev-parse HEAD)" >> tmp/version.txt || true + echo "VCPKG: $(gethead /opt/vcpkg)" >> tmp/version.txt echo "" >> tmp/version.txt echo "AZURE:" >> tmp/version.txt sudo date > /dev/null 2>&1 # Skip the first-time lecture. sudo /opt/vcpkg/vcpkg list >> tmp/version.txt || true fi echo "" >> tmp/version.txt +echo "DYNAMIC libsdapi.so" >> tmp/version.txt ldd libsdapi.so >> tmp/version.txt || true cp -a -t tmp/include ${SRC}/src/core/*.h ${SRC}/src/lib/accessors/*.h @@ -148,7 +155,11 @@ then tarball=sdapi_linux64_osdu.tar.gz fi +# If the SDK is to be used e.g. in ZGY-Cloud it may need to be renamed and +# copied out of the container. The following might help. +echo ${PLATFORM}/${tarball} > ${HOME}/realname.txt + echo "Successful build of ${LINUXDISTRO:-unknown} ${1:-Release} configuration ${AZUREMSG}" echo "Now run this command outside the docker container:" echo -echo "docker cp $(hostname):/home/me/sdapi_linux64.tar.gz ${WORKAREA3}/${PLATFORM}/${tarball}" +echo "docker cp $(hostname):/home/me/sdapi_linux64.tar.gz seismic-service-bin/${PLATFORM}/${tarball}" diff --git a/sd-env/cmakelists1.patch b/sd-env/cmakelists1.patch new file mode 100644 index 0000000..6a88d58 --- /dev/null +++ b/sd-env/cmakelists1.patch @@ -0,0 +1,23 @@ +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -239,11 +239,16 @@ if(AZURE_CURL_PROVIDER_ENABLED) + find_library( LZMA_LIBRARY lzma ) + find_library( Z_LIBRARY z ) + +- find_package( libxml2 CONFIG REQUIRED) ++ #find_package( libxml2 CONFIG REQUIRED ) ++ # This is WRONG in several different ways but will at least build on ++ # the 6 Linux configs (all using docker) that I tested. If the ++ # environment has both the system library and the one from vcpkg ++ # installed then it is somewhat undefined which headers and which ++ # binaries are picked up. And whether they match. ++ set( LibXml2_FOUND true ) ++ set( LIBXML2_INCLUDE_DIR "/opt/vcpkg/installed/x64-linux/include/libxml" ) ++ set( LIBXML2_INCLUDE_DIRS ${LIBXML2_INCLUDE_DIR} ) + set( LIBXML2_LIBRARY ${XML2_LIBRARY} CACHE FILEPATH "path to libxml2 library" ) +- +- find_package(LibXml2 CONFIG REQUIRED ) +- + if(LibXml2_FOUND AND NOT TARGET LibXml2::LibXml2) + message( STATUS "manually constructing LibXml2::LibXml2") + diff --git a/sd-env/cmakelists2.patch b/sd-env/cmakelists2.patch new file mode 100644 index 0000000..559bdbe --- /dev/null +++ b/sd-env/cmakelists2.patch @@ -0,0 +1,38 @@ +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 4ed9a83..32b5d61 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -238,24 +238,9 @@ if(AZURE_CURL_PROVIDER_ENABLED) + find_library( XML2_LIBRARY xml2 ) + find_library( LZMA_LIBRARY lzma ) + find_library( Z_LIBRARY z ) ++ include(CMakeFindDependencyMacro) ++ find_dependency(LibXml2) + +- find_package( libxml2 CONFIG REQUIRED) +- set( LIBXML2_LIBRARY ${XML2_LIBRARY} CACHE FILEPATH "path to libxml2 library" ) +- +- find_package(LibXml2 CONFIG REQUIRED ) +- +- if(LibXml2_FOUND AND NOT TARGET LibXml2::LibXml2) +- message( STATUS "manually constructing LibXml2::LibXml2") +- +- add_library(LibXml2::LibXml2 UNKNOWN IMPORTED) +- set_target_properties(LibXml2::LibXml2 PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${LIBXML2_INCLUDE_DIRS}") +- set_target_properties(LibXml2::LibXml2 PROPERTIES INTERFACE_COMPILE_OPTIONS "${LIBXML2_DEFINITIONS}") +- set_property(TARGET LibXml2::LibXml2 APPEND PROPERTY IMPORTED_LOCATION "${LIBXML2_LIBRARY}" ) +- +- # the magic line that makes statically linked libxml2 with lzma and lz work is here... +- set_property(TARGET LibXml2::LibXml2 PROPERTY IMPORTED_LINK_INTERFACE_LIBRARIES "${LZMA_LIBRARY};${Z_LIBRARY}") +- +- endif() + endif() + + find_package(azure-core-cpp CONFIG REQUIRED ) +@@ -644,4 +629,4 @@ if(BUILD_BENCHMARKS) + COMMENT "Running Performance Benchmarks" + ) + +-endif() +\ No newline at end of file ++endif() diff --git a/sd-env/cmakelists3.patch b/sd-env/cmakelists3.patch new file mode 100644 index 0000000..70e4fcc --- /dev/null +++ b/sd-env/cmakelists3.patch @@ -0,0 +1,25 @@ +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 4ed9a83..9bd652e 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -239,10 +239,11 @@ if(AZURE_CURL_PROVIDER_ENABLED) + find_library( LZMA_LIBRARY lzma ) + find_library( Z_LIBRARY z ) + +- find_package( libxml2 CONFIG REQUIRED) ++ include(CMakeFindDependencyMacro) ++ find_dependency(LibXml2) ++ + set( LIBXML2_LIBRARY ${XML2_LIBRARY} CACHE FILEPATH "path to libxml2 library" ) + +- find_package(LibXml2 CONFIG REQUIRED ) + + if(LibXml2_FOUND AND NOT TARGET LibXml2::LibXml2) + message( STATUS "manually constructing LibXml2::LibXml2") +@@ -644,4 +645,4 @@ if(BUILD_BENCHMARKS) + COMMENT "Running Performance Benchmarks" + ) + +-endif() +\ No newline at end of file ++endif() diff --git a/sd-env/switchuser.sh b/sd-env/switchuser.sh deleted file mode 100755 index 6d7986a..0000000 --- a/sd-env/switchuser.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - -# When the image starts up, expect that ~me/.ssh and maybe others -# will be mapped to folders in the host. The problem is that me's -# numeric user and group ids are unlikely to match those of the mapped -# files. Solve this by changing the numerical ids for user me. -# The end result is that files created by the docker image in folders -# that were mapped from the host will have the correct owner. - -uid=$(stat 2> /dev/null -c '%u' /home/me/.ssh) -gid=$(stat 2> /dev/null -c '%g' /home/me/.ssh) - -if [ x$uid = x -o x$uid = x0 -o x$gid = x -o x$gid = x0 ] -then - uid=$(stat 2> /dev/null -c '%u' /home/me/.sdcfg) - gid=$(stat 2> /dev/null -c '%g' /home/me/.sdcfg) -fi - -if [ x$uid = x -o x$uid = x0 -o x$gid = x -o x$gid = x0 ] -then - echo >&2 "Cannot get uid from ~/.ssh or ~/.sdcfg." - echo >&2 "Running as the default \"me\" user id 1000:1000." - uid=1000 - gid=1000 -fi - -sed -i -e "s/^me:x:[0-9]*:[0-9]*:/me:x:${uid}:${gid}:/" /etc/passwd -sed -i -e "s/^me:x:[0-9]*:/me:x:${gid}:/" /etc/group - -# The "new" me user must own all the files below ~me, -# but don't change .ssh or other folders which are probably -# mapped from outside. -# TODO, don't hard code what to change. It depends on the distro. -# Use e.g. find /home/me -xdev, which *almost* works but is will -# also list the actual mount points. -chown me:me /home/me -chown -R me:me /home/me/{.bash*,.mozilla,.emacs,.vnc,tools} 2>/dev/null - -# Switch to the correct user. -# In the CentOS 7 image, also switch the toolchain. -TOOLSET=$(ls /etc/scl/prefixes/devtoolset-* 2>/dev/null|tail -1) -if [ x$TOOLSET != x ] -then - exec sudo -u me -i /bin/bash -c "scl enable $(basename $TOOLSET) /bin/bash" -else - exec sudo -u me -i -fi diff --git a/wrapper/setup.py b/wrapper/setup.py index 6c1704e..e0d42e5 100644 --- a/wrapper/setup.py +++ b/wrapper/setup.py @@ -25,7 +25,7 @@ nativebin = os.path.join( os.getenv("MYPLATFORM", ".")) print('nativebin = "' + nativebin + '"') -version = "0.2." + os.getenv("AZURE_BUILDID", "dev0") +version = "0.2." + (os.getenv("AZURE_BUILDID", "dev0") or "dev0") if os.name == 'nt': binaries = ['OpenZGY.dll', 'zfp.dll', 'sdapi.dll'] -- GitLab