occystrap 0.2.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- occystrap-0.4.0/.github/workflows/codeql-analysis.yml +54 -0
- occystrap-0.4.0/.github/workflows/functional-tests.yml +79 -0
- occystrap-0.4.0/.github/workflows/python-unit-tests.yml +33 -0
- {occystrap-0.2.0/occystrap.egg-info → occystrap-0.4.0}/PKG-INFO +28 -1
- {occystrap-0.2.0 → occystrap-0.4.0}/README.md +27 -0
- occystrap-0.4.0/deploy/.stestr.conf +3 -0
- occystrap-0.4.0/deploy/ansible/ci.yml +211 -0
- occystrap-0.4.0/deploy/occystrap_ci/testdata/deletion_layers/Dockerfile +10 -0
- occystrap-0.4.0/deploy/occystrap_ci/tests/test_dir_deep_images.py +33 -0
- occystrap-0.4.0/deploy/occystrap_ci/tests/test_oci_hello_world.py +52 -0
- occystrap-0.4.0/deploy/occystrap_ci/tests/test_whiteout.py +80 -0
- occystrap-0.4.0/deploy/requirements.txt +1 -0
- occystrap-0.4.0/deploy/setup.cfg +24 -0
- occystrap-0.4.0/deploy/setup.py +20 -0
- occystrap-0.4.0/deploy/test-requirements.txt +2 -0
- occystrap-0.4.0/deploy/tox.ini +30 -0
- occystrap-0.4.0/occystrap/__init__.py +0 -0
- occystrap-0.4.0/occystrap/common.py +40 -0
- occystrap-0.4.0/occystrap/constants.py +186 -0
- {occystrap-0.2.0 → occystrap-0.4.0}/occystrap/docker_registry.py +75 -24
- occystrap-0.4.0/occystrap/main.py +137 -0
- {occystrap-0.2.0 → occystrap-0.4.0}/occystrap/output_directory.py +52 -30
- occystrap-0.4.0/occystrap/output_mounts.py +155 -0
- occystrap-0.4.0/occystrap/output_ocibundle.py +53 -0
- {occystrap-0.2.0 → occystrap-0.4.0}/occystrap/output_tarfile.py +0 -5
- occystrap-0.4.0/occystrap/tests/__init__.py +0 -0
- {occystrap-0.2.0 → occystrap-0.4.0}/occystrap/util.py +9 -1
- {occystrap-0.2.0 → occystrap-0.4.0/occystrap.egg-info}/PKG-INFO +28 -1
- occystrap-0.4.0/occystrap.egg-info/SOURCES.txt +46 -0
- occystrap-0.4.0/occystrap.egg-info/pbr.json +1 -0
- {occystrap-0.2.0 → occystrap-0.4.0}/occystrap.egg-info/requires.txt +2 -0
- occystrap-0.4.0/requirements.txt +6 -0
- {occystrap-0.2.0 → occystrap-0.4.0}/test-requirements.txt +2 -1
- {occystrap-0.2.0 → occystrap-0.4.0}/tools/flake8wrap.sh +1 -1
- {occystrap-0.2.0 → occystrap-0.4.0}/tox.ini +4 -17
- occystrap-0.2.0/occystrap/constants.py +0 -2
- occystrap-0.2.0/occystrap/main.py +0 -78
- occystrap-0.2.0/occystrap.egg-info/SOURCES.txt +0 -27
- occystrap-0.2.0/occystrap.egg-info/pbr.json +0 -1
- occystrap-0.2.0/requirements.txt +0 -4
- {occystrap-0.2.0 → occystrap-0.4.0}/AUTHORS +0 -0
- {occystrap-0.2.0 → occystrap-0.4.0}/LICENSE +0 -0
- {occystrap-0.2.0/occystrap → occystrap-0.4.0/deploy/occystrap_ci}/__init__.py +0 -0
- {occystrap-0.2.0/occystrap → occystrap-0.4.0/deploy/occystrap_ci}/tests/__init__.py +0 -0
- {occystrap-0.2.0 → occystrap-0.4.0}/occystrap/docker_extract.py +0 -0
- {occystrap-0.2.0 → occystrap-0.4.0}/occystrap.egg-info/dependency_links.txt +0 -0
- {occystrap-0.2.0 → occystrap-0.4.0}/occystrap.egg-info/entry_points.txt +0 -0
- {occystrap-0.2.0 → occystrap-0.4.0}/occystrap.egg-info/not-zip-safe +0 -0
- {occystrap-0.2.0 → occystrap-0.4.0}/occystrap.egg-info/top_level.txt +0 -0
- {occystrap-0.2.0 → occystrap-0.4.0}/release.sh +0 -0
- {occystrap-0.2.0 → occystrap-0.4.0}/setup.cfg +0 -0
- {occystrap-0.2.0 → occystrap-0.4.0}/setup.py +0 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: "CodeQL"
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master, ]
|
|
6
|
+
pull_request:
|
|
7
|
+
# The branches below must be a subset of the branches above
|
|
8
|
+
branches: [master]
|
|
9
|
+
schedule:
|
|
10
|
+
- cron: '0 17 * * 2'
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
analyze:
|
|
14
|
+
name: Analyze
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout repository
|
|
19
|
+
uses: actions/checkout@v2
|
|
20
|
+
with:
|
|
21
|
+
# We must fetch at least the immediate parents so that if this is
|
|
22
|
+
# a pull request then we can checkout the head.
|
|
23
|
+
fetch-depth: 2
|
|
24
|
+
|
|
25
|
+
# If this run was triggered by a pull request event, then checkout
|
|
26
|
+
# the head of the pull request instead of the merge commit.
|
|
27
|
+
- run: git checkout HEAD^2
|
|
28
|
+
if: ${{ github.event_name == 'pull_request' }}
|
|
29
|
+
|
|
30
|
+
# Initializes the CodeQL tools for scanning.
|
|
31
|
+
- name: Initialize CodeQL
|
|
32
|
+
uses: github/codeql-action/init@v1
|
|
33
|
+
# Override language selection by uncommenting this and choosing your languages
|
|
34
|
+
# with:
|
|
35
|
+
# languages: go, javascript, csharp, python, cpp, java
|
|
36
|
+
|
|
37
|
+
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
|
38
|
+
# If this step fails, then you should remove it and run the build manually (see below)
|
|
39
|
+
- name: Autobuild
|
|
40
|
+
uses: github/codeql-action/autobuild@v1
|
|
41
|
+
|
|
42
|
+
# ℹ️ Command-line programs to run using the OS shell.
|
|
43
|
+
# 📚 https://git.io/JvXDl
|
|
44
|
+
|
|
45
|
+
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
|
46
|
+
# and modify them (or add more) to build your code if your project
|
|
47
|
+
# uses a compiled language
|
|
48
|
+
|
|
49
|
+
#- run: |
|
|
50
|
+
# make bootstrap
|
|
51
|
+
# make release
|
|
52
|
+
|
|
53
|
+
- name: Perform CodeQL Analysis
|
|
54
|
+
uses: github/codeql-action/analyze@v1
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
name: Functional tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- master
|
|
7
|
+
pull_request:
|
|
8
|
+
branches:
|
|
9
|
+
- master
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
functional:
|
|
13
|
+
runs-on: self-hosted
|
|
14
|
+
timeout-minutes: 120
|
|
15
|
+
|
|
16
|
+
# NOTE(mikal): git repos are checked out to /srv/github/_work/{repo}/{repo}
|
|
17
|
+
# which is available as GITHUB_WORKSPACE. You can find other environment
|
|
18
|
+
# variables at https://docs.github.com/en/actions/learn-github-actions/environment-variables
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- name: Remove previous unfinished runs
|
|
22
|
+
uses: n1hility/cancel-previous-runs@v2
|
|
23
|
+
with:
|
|
24
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
25
|
+
|
|
26
|
+
- name: Get rid of sudo error messages
|
|
27
|
+
run: |
|
|
28
|
+
hostname=$(cat /etc/hostname)
|
|
29
|
+
sudo chmod ugo+rw /etc/hosts
|
|
30
|
+
echo "127.0.1.1 $hostname" >> /etc/hosts
|
|
31
|
+
|
|
32
|
+
- name: Install minimum dependencies
|
|
33
|
+
run: |
|
|
34
|
+
sudo apt-get update
|
|
35
|
+
sudo apt-get dist-upgrade -y
|
|
36
|
+
sudo apt-get install -y python3 python3-dev python3-pip python3-wheel apparmor docker.io runc
|
|
37
|
+
sudo systemctl restart apparmor
|
|
38
|
+
|
|
39
|
+
- name: Log docker setup
|
|
40
|
+
run: |
|
|
41
|
+
sudo chown debian.debian /var/run/docker.sock
|
|
42
|
+
|
|
43
|
+
echo "/var/run/docker.sock:"
|
|
44
|
+
sudo ls -l /var/run/docker.sock
|
|
45
|
+
|
|
46
|
+
- name: Checkout occystrap
|
|
47
|
+
uses: actions/checkout@v3
|
|
48
|
+
with:
|
|
49
|
+
path: occystrap
|
|
50
|
+
fetch-depth: 0
|
|
51
|
+
|
|
52
|
+
- name: Build occystrap wheel and install it
|
|
53
|
+
run: |
|
|
54
|
+
cd /srv/ci/runner/_work/occystrap/occystrap/occystrap
|
|
55
|
+
rm -f dist/*
|
|
56
|
+
python3 setup.py sdist bdist_wheel
|
|
57
|
+
sudo pip3 install dist/occystrap*.whl
|
|
58
|
+
|
|
59
|
+
- name: Run a local docker registry to talk to, and populate it with test data
|
|
60
|
+
run: |
|
|
61
|
+
docker run -d -p 5000:5000 --restart=always --name registry registry:2
|
|
62
|
+
cd /srv/ci/runner/_work/occystrap/occystrap/occystrap/deploy/occystrap_ci/testdata
|
|
63
|
+
|
|
64
|
+
for img in deletion_layers; do
|
|
65
|
+
cd $img
|
|
66
|
+
docker build -t localhost:5000/occystrap_$img:latest .
|
|
67
|
+
docker push localhost:5000/occystrap_$img:latest
|
|
68
|
+
cd /srv/ci/runner/_work/occystrap/occystrap/occystrap/deploy/occystrap_ci/testdata
|
|
69
|
+
done
|
|
70
|
+
|
|
71
|
+
- name: Run functional tests
|
|
72
|
+
run: |
|
|
73
|
+
cd /srv/ci/runner/_work/occystrap/occystrap/occystrap/deploy
|
|
74
|
+
sudo pip3 install -r requirements.txt
|
|
75
|
+
sudo pip3 install -r test-requirements.txt
|
|
76
|
+
|
|
77
|
+
# This needs to run as root because some of the tests require
|
|
78
|
+
# escalated permissions.
|
|
79
|
+
sudo stestr run --concurrency=5
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# This workflow will install Python dependencies, run tests and lint with a single version of Python
|
|
2
|
+
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
|
|
3
|
+
|
|
4
|
+
name: Python application
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches:
|
|
9
|
+
- master
|
|
10
|
+
pull_request:
|
|
11
|
+
branches:
|
|
12
|
+
- master
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
lint:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- name: Checkout code with two commits
|
|
20
|
+
uses: actions/checkout@v2
|
|
21
|
+
with:
|
|
22
|
+
fetch-depth: 2
|
|
23
|
+
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
run: |
|
|
26
|
+
python -m pip install --upgrade pip
|
|
27
|
+
sudo apt-get update
|
|
28
|
+
sudo apt-get dist-upgrade -y
|
|
29
|
+
sudo apt-get install -y -q tox
|
|
30
|
+
|
|
31
|
+
- name: Lint with flake8
|
|
32
|
+
run: |
|
|
33
|
+
tox -eflake8
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: occystrap
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: occystrap: docker and OCI container tools
|
|
5
5
|
Home-page: https://github.com/shakenfist/occystrap
|
|
6
6
|
Author: Michael Still
|
|
@@ -84,6 +84,33 @@ Description: # Occy Strap
|
|
|
84
84
|
|
|
85
85
|
Note that layers delete files from previous layers with files named ".wh.$previousfilename". These files are _not_ processed in the expanded layers, so that they are visible to the user. They are however processed in the merged layer named for the manifest file.
|
|
86
86
|
|
|
87
|
+
## Generating an OCI runtime bundle
|
|
88
|
+
|
|
89
|
+
This isn't fully supported yet, but you can extract an image to an OCI image bundle
|
|
90
|
+
with the following command:
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
occystrap fetch-to-oci registry-1.docker.io library/hello-world latest bar
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
You should then be able to run that container by doing something like:
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
cd bar
|
|
100
|
+
sudo apt-get install runc
|
|
101
|
+
sudo runc run id-0001
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Supporting non-default architectures
|
|
105
|
+
|
|
106
|
+
Docker image repositories can store multiple versions of a single image, with each image corresponding to a different (operating system, cpu architecture, cpu variant) tuple. Occy Strap supports letting you specify which to use with global command line flags. Occy Strap defaults to linux amd64 if you don't specify something different. For example, to fetch the linux arm64 v8 image for busybox, you would run:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
occystrap --os linux --architecture arm64 --variant v8 \
|
|
110
|
+
fetch-to-extracted registry-1.docker.io library/busybox \
|
|
111
|
+
latest busybox
|
|
112
|
+
```
|
|
113
|
+
|
|
87
114
|
|
|
88
115
|
Platform: UNKNOWN
|
|
89
116
|
Classifier: Intended Audience :: Information Technology
|
|
@@ -75,3 +75,30 @@ occystrap fetch-to-extracted --expand quay.io \
|
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
Note that layers delete files from previous layers with files named ".wh.$previousfilename". These files are _not_ processed in the expanded layers, so that they are visible to the user. They are however processed in the merged layer named for the manifest file.
|
|
78
|
+
|
|
79
|
+
## Generating an OCI runtime bundle
|
|
80
|
+
|
|
81
|
+
This isn't fully supported yet, but you can extract an image to an OCI image bundle
|
|
82
|
+
with the following command:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
occystrap fetch-to-oci registry-1.docker.io library/hello-world latest bar
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
You should then be able to run that container by doing something like:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
cd bar
|
|
92
|
+
sudo apt-get install runc
|
|
93
|
+
sudo runc run id-0001
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Supporting non-default architectures
|
|
97
|
+
|
|
98
|
+
Docker image repositories can store multiple versions of a single image, with each image corresponding to a different (operating system, cpu architecture, cpu variant) tuple. Occy Strap supports letting you specify which to use with global command line flags. Occy Strap defaults to linux amd64 if you don't specify something different. For example, to fetch the linux arm64 v8 image for busybox, you would run:
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
occystrap --os linux --architecture arm64 --variant v8 \
|
|
102
|
+
fetch-to-extracted registry-1.docker.io library/busybox \
|
|
103
|
+
latest busybox
|
|
104
|
+
```
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
- hosts: localhost
|
|
2
|
+
gather_facts: yes
|
|
3
|
+
connection: ssh
|
|
4
|
+
vars:
|
|
5
|
+
identifier: unknown
|
|
6
|
+
source_path: "/home/jenkins/src/occystrap/"
|
|
7
|
+
base_image: "debian:11"
|
|
8
|
+
base_image_user: "debian"
|
|
9
|
+
|
|
10
|
+
tasks:
|
|
11
|
+
- name: Create the namespace
|
|
12
|
+
shell: sf-client namespace create "{{identifier}}"
|
|
13
|
+
|
|
14
|
+
- name: Create a network for outgoing traffic
|
|
15
|
+
sf_network:
|
|
16
|
+
netblock: "10.0.0.0/24"
|
|
17
|
+
name: "public"
|
|
18
|
+
namespace: "{{identifier}}"
|
|
19
|
+
register: publicnetwork
|
|
20
|
+
|
|
21
|
+
- name: Log network details
|
|
22
|
+
debug:
|
|
23
|
+
msg:
|
|
24
|
+
- "Public network is {{publicnetwork['meta']['uuid']}}"
|
|
25
|
+
|
|
26
|
+
- name: Setup cloud-config to add a password to CI nodes for debugging
|
|
27
|
+
set_fact:
|
|
28
|
+
userdata_decoded: |
|
|
29
|
+
#cloud-config
|
|
30
|
+
ssh_pwauth: True
|
|
31
|
+
chpasswd: { expire: False }
|
|
32
|
+
|
|
33
|
+
users:
|
|
34
|
+
- name: ciuser
|
|
35
|
+
lock-passwd: False
|
|
36
|
+
sudo: [ "ALL=(ALL) NOPASSWD:ALL" ]
|
|
37
|
+
shell: /bin/bash
|
|
38
|
+
# This password hash is generated with mkpasswd --method=SHA-512 --rounds=4096
|
|
39
|
+
passwd: "$6$rounds=4096$jBqTFFRr$75ehRH5AtiUxWMlFf1Ji.szp1NCjut2WiiD./QHsfWbCfKKjX1bs6MtBcWedlqKwcBKEPP/oLinTbH6gwcwUA1"
|
|
40
|
+
|
|
41
|
+
- name: Encode user data
|
|
42
|
+
set_fact:
|
|
43
|
+
userdata_encoded: "{{ userdata_decoded | b64encode }}"
|
|
44
|
+
|
|
45
|
+
- name: Create a primary instance
|
|
46
|
+
sf_instance:
|
|
47
|
+
name: "primary"
|
|
48
|
+
cpu: 4
|
|
49
|
+
ram: 4096
|
|
50
|
+
disks:
|
|
51
|
+
- "100@{{base_image}}"
|
|
52
|
+
networkspecs:
|
|
53
|
+
- network_uuid="{{publicnetwork['meta']['uuid']}}",float=True
|
|
54
|
+
ssh_key: "{{ lookup('file', '/home/jenkins/id_ci.pub') }}"
|
|
55
|
+
namespace: "{{identifier}}"
|
|
56
|
+
user_data: "{{userdata_encoded}}"
|
|
57
|
+
state: present
|
|
58
|
+
register: primary
|
|
59
|
+
|
|
60
|
+
- name: Add primary node to ansible
|
|
61
|
+
add_host:
|
|
62
|
+
hostname: primary
|
|
63
|
+
egress_ip: "{{primary['meta']['network_interfaces'][0]['ipv4']}}"
|
|
64
|
+
ansible_host: "{{primary['meta']['network_interfaces'][0]['floating']}}"
|
|
65
|
+
ansible_ssh_host: "{{primary['meta']['network_interfaces'][0]['floating']}}"
|
|
66
|
+
ansible_ssh_extra_args: "-o StrictHostKeyChecking=no -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null"
|
|
67
|
+
ansible_ssh_user: "{{base_image_user}}"
|
|
68
|
+
ansible_ssh_private_key_file: "/home/jenkins/id_ci"
|
|
69
|
+
groups: occystrapall
|
|
70
|
+
|
|
71
|
+
- name: Log instance details
|
|
72
|
+
debug:
|
|
73
|
+
msg:
|
|
74
|
+
- "Primary: is {{primary['meta']['uuid']}} at {{primary['meta']['network_interfaces'][0]['ipv4']}}, {{primary['meta']['network_interfaces'][0]['floating']}}"
|
|
75
|
+
|
|
76
|
+
- name: Ensure we have somewhere to write the build details to
|
|
77
|
+
file:
|
|
78
|
+
path: "{{ lookup('env', 'WORKSPACE') }}/{{ lookup('env', 'BUILD_TAG') }}"
|
|
79
|
+
state: directory
|
|
80
|
+
mode: "0755"
|
|
81
|
+
|
|
82
|
+
- name: Write details of instances to workspace
|
|
83
|
+
copy:
|
|
84
|
+
content: |
|
|
85
|
+
{% for svr in groups.occystrapall %}
|
|
86
|
+
export {{ svr | replace('-', '_') }}={{hostvars[svr]['ansible_ssh_host']}}
|
|
87
|
+
{% endfor %}
|
|
88
|
+
|
|
89
|
+
export identifier={{identifier}}
|
|
90
|
+
export source_path={{source_path}}
|
|
91
|
+
export nodes="{{ groups.occystrapall | join(' ') | replace('-', '_') }}"
|
|
92
|
+
dest: "{{ lookup('env', 'WORKSPACE') }}/{{ lookup('env', 'BUILD_TAG') }}/ci-environment.sh"
|
|
93
|
+
owner: jenkins
|
|
94
|
+
group: jenkins
|
|
95
|
+
mode: u=r,g=r,o=r
|
|
96
|
+
|
|
97
|
+
- name: Log environment details path
|
|
98
|
+
debug:
|
|
99
|
+
msg: "Environment details written to {{ lookup('env', 'WORKSPACE') }}/{{ lookup('env', 'BUILD_TAG') }}/ci-environment.sh"
|
|
100
|
+
|
|
101
|
+
- name: Build Occystrap wheel
|
|
102
|
+
shell: |
|
|
103
|
+
rm dist/*
|
|
104
|
+
python3 setup.py sdist bdist_wheel
|
|
105
|
+
args:
|
|
106
|
+
chdir: "{{source_path}}"
|
|
107
|
+
|
|
108
|
+
- name: Determine wheel filename
|
|
109
|
+
shell: ls dist | egrep "occystrap.*\.whl"
|
|
110
|
+
args:
|
|
111
|
+
chdir: "{{source_path}}"
|
|
112
|
+
register: occystrap_wheel_file_complex
|
|
113
|
+
|
|
114
|
+
- name: Extract the wheel filename
|
|
115
|
+
set_fact:
|
|
116
|
+
occystrap_wheel_file: "{{occystrap_wheel_file_complex.stdout}}"
|
|
117
|
+
|
|
118
|
+
- debug:
|
|
119
|
+
msg: "Occystrap wheel file: {{occystrap_wheel_file}}"
|
|
120
|
+
|
|
121
|
+
- name: Wait for all instances to present an "OpenSSH" prompt
|
|
122
|
+
wait_for:
|
|
123
|
+
port: 22
|
|
124
|
+
host: "{{hostvars[item]['ansible_ssh_host']}}"
|
|
125
|
+
search_regex: OpenSSH
|
|
126
|
+
delay: 10
|
|
127
|
+
with_items: "{{ groups['occystrapall'] }}"
|
|
128
|
+
|
|
129
|
+
- hosts: primary
|
|
130
|
+
gather_facts: yes
|
|
131
|
+
become: true
|
|
132
|
+
vars:
|
|
133
|
+
source_path: "/home/jenkins/src/occystrap/"
|
|
134
|
+
|
|
135
|
+
tasks:
|
|
136
|
+
- name: Install minimum dependencies
|
|
137
|
+
apt:
|
|
138
|
+
name:
|
|
139
|
+
- git
|
|
140
|
+
- python3
|
|
141
|
+
- python3-dev
|
|
142
|
+
- python3-pip
|
|
143
|
+
- python3-wheel
|
|
144
|
+
- apparmor
|
|
145
|
+
- docker.io
|
|
146
|
+
- runc
|
|
147
|
+
state: latest
|
|
148
|
+
|
|
149
|
+
- name: Restart apparmor
|
|
150
|
+
service:
|
|
151
|
+
name: apparmor
|
|
152
|
+
enabled: yes
|
|
153
|
+
state: restarted
|
|
154
|
+
|
|
155
|
+
- name: Copy occystrap wheel file
|
|
156
|
+
copy:
|
|
157
|
+
src: "{{source_path}}/dist/{{hostvars['localhost']['occystrap_wheel_file']}}"
|
|
158
|
+
dest: "/root/{{hostvars['localhost']['occystrap_wheel_file']}}"
|
|
159
|
+
|
|
160
|
+
- name: Install Occystrap
|
|
161
|
+
shell: pip3 install "/root/{{hostvars['localhost']['occystrap_wheel_file']}}"
|
|
162
|
+
|
|
163
|
+
- name: Run a local docker registry for us to talk to
|
|
164
|
+
shell: docker run -d -p 5000:5000 --restart=always --name registry registry:2
|
|
165
|
+
|
|
166
|
+
- name: Make a /srv/occystrap directory
|
|
167
|
+
file:
|
|
168
|
+
path: /srv/occystrap
|
|
169
|
+
state: directory
|
|
170
|
+
owner: "{{base_image_user}}"
|
|
171
|
+
group: "{{base_image_user}}"
|
|
172
|
+
|
|
173
|
+
- hosts: primary
|
|
174
|
+
gather_facts: yes
|
|
175
|
+
become: no
|
|
176
|
+
vars:
|
|
177
|
+
source_path: "/home/jenkins/src/occystrap/"
|
|
178
|
+
|
|
179
|
+
tasks:
|
|
180
|
+
- name: Copy occystrap CI tests and data as the default user
|
|
181
|
+
synchronize:
|
|
182
|
+
src: "{{source_path}}"
|
|
183
|
+
dest: "/srv/occystrap/"
|
|
184
|
+
use_ssh_args: yes
|
|
185
|
+
recursive: yes
|
|
186
|
+
|
|
187
|
+
- hosts: primary
|
|
188
|
+
gather_facts: yes
|
|
189
|
+
become: true
|
|
190
|
+
vars:
|
|
191
|
+
source_path: "/home/jenkins/src/occystrap/"
|
|
192
|
+
|
|
193
|
+
tasks:
|
|
194
|
+
- name: Populate the registry with test images
|
|
195
|
+
shell: |
|
|
196
|
+
cd {{item}}
|
|
197
|
+
docker build -t localhost:5000/occystrap_{{item}}:latest .
|
|
198
|
+
docker push localhost:5000/occystrap_{{item}}:latest
|
|
199
|
+
args:
|
|
200
|
+
chdir: /srv/occystrap/deploy/occystrap_ci/testdata
|
|
201
|
+
with_items:
|
|
202
|
+
- deletion_layers
|
|
203
|
+
|
|
204
|
+
- name: Replace a localhost entry with our own
|
|
205
|
+
lineinfile:
|
|
206
|
+
path: /etc/hosts
|
|
207
|
+
regexp: '^127\.0\.0\.1'
|
|
208
|
+
line: 127.0.0.1 localhost primary
|
|
209
|
+
owner: root
|
|
210
|
+
group: root
|
|
211
|
+
mode: "0644"
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
import tempfile
|
|
4
|
+
import testtools
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
from occystrap import docker_registry
|
|
8
|
+
from occystrap import output_directory
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
logging.basicConfig(level=logging.INFO, format='%(message)s')
|
|
12
|
+
LOG = logging.getLogger()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class DirDeepImageTestCase(testtools.TestCase):
|
|
16
|
+
def test_deep_image(self):
|
|
17
|
+
image = 'library/ubuntu'
|
|
18
|
+
tag = 'latest'
|
|
19
|
+
|
|
20
|
+
with tempfile.TemporaryDirectory() as tempdir:
|
|
21
|
+
oci = output_directory.DirWriter(
|
|
22
|
+
image, tag, tempdir, expand=True)
|
|
23
|
+
img = docker_registry.Image(
|
|
24
|
+
'registry-1.docker.io', image, tag, 'linux', 'amd64', '')
|
|
25
|
+
for image_element in img.fetch(fetch_callback=oci.fetch_callback):
|
|
26
|
+
oci.process_image_element(*image_element)
|
|
27
|
+
oci.finalize()
|
|
28
|
+
oci.write_bundle()
|
|
29
|
+
|
|
30
|
+
self.assertTrue(
|
|
31
|
+
os.path.exists(os.path.join(tempdir, 'manifest')))
|
|
32
|
+
self.assertTrue(
|
|
33
|
+
os.path.exists(os.path.join(tempdir, 'manifest/usr/bin/dash')))
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from oslo_concurrency import processutils
|
|
3
|
+
import sys
|
|
4
|
+
import tempfile
|
|
5
|
+
import testtools
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
from occystrap import docker_registry
|
|
9
|
+
from occystrap import output_ocibundle
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
logging.basicConfig(level=logging.INFO, format='%(message)s')
|
|
13
|
+
LOG = logging.getLogger()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _exec(cmd, cwd=None):
|
|
17
|
+
sys.stderr.write('\n----- Exec: %s -----\n' % cmd)
|
|
18
|
+
out, err = processutils.execute(cmd, cwd=cwd, shell=True)
|
|
19
|
+
for line in out.split('\n'):
|
|
20
|
+
sys.stderr.write('out: %s\n' % line)
|
|
21
|
+
sys.stderr.write('\n')
|
|
22
|
+
for line in err.split('\n'):
|
|
23
|
+
sys.stderr.write('err: %s\n' % line)
|
|
24
|
+
sys.stderr.write('\n----- End: %s -----\n' % cmd)
|
|
25
|
+
return out, err
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# Make sure we haven't broken sudo entirely in the test suite
|
|
29
|
+
class SudoTestCase(testtools.TestCase):
|
|
30
|
+
def test_sudo(self):
|
|
31
|
+
out, err = _exec('sudo echo $(( 4 + 6 ))')
|
|
32
|
+
self.assertEqual('', err)
|
|
33
|
+
self.assertTrue('10' in out)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class OCIHelloWorldTestCase(testtools.TestCase):
|
|
37
|
+
def test_hello_world(self):
|
|
38
|
+
image = 'library/hello-world'
|
|
39
|
+
tag = 'latest'
|
|
40
|
+
|
|
41
|
+
with tempfile.TemporaryDirectory() as tempdir:
|
|
42
|
+
oci = output_ocibundle.OCIBundleWriter(image, tag, tempdir)
|
|
43
|
+
img = docker_registry.Image(
|
|
44
|
+
'registry-1.docker.io', image, tag, 'linux', 'amd64', '')
|
|
45
|
+
for image_element in img.fetch(fetch_callback=oci.fetch_callback):
|
|
46
|
+
oci.process_image_element(*image_element)
|
|
47
|
+
oci.finalize()
|
|
48
|
+
oci.write_bundle()
|
|
49
|
+
|
|
50
|
+
out, err = _exec('sudo runc run OCIHellWorld', cwd=tempdir)
|
|
51
|
+
self.assertEqual('', err)
|
|
52
|
+
self.assertTrue('Hello from Docker!' in out)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
from oslo_concurrency import processutils
|
|
5
|
+
import tempfile
|
|
6
|
+
import testtools
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
from occystrap import docker_registry
|
|
10
|
+
from occystrap import output_ocibundle
|
|
11
|
+
from occystrap import output_mounts
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
logging.basicConfig(level=logging.INFO, format='%(message)s')
|
|
15
|
+
LOG = logging.getLogger()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class WhiteoutsTestCase(testtools.TestCase):
|
|
19
|
+
def test_whiteouts_ocibundle(self):
|
|
20
|
+
image = 'occystrap_deletion_layers'
|
|
21
|
+
tag = 'latest'
|
|
22
|
+
|
|
23
|
+
with tempfile.TemporaryDirectory() as tempdir:
|
|
24
|
+
oci = output_ocibundle.OCIBundleWriter(image, tag, tempdir)
|
|
25
|
+
img = docker_registry.Image(
|
|
26
|
+
'localhost:5000', image, tag, 'linux', 'amd64', '',
|
|
27
|
+
secure=False)
|
|
28
|
+
for image_element in img.fetch(fetch_callback=oci.fetch_callback):
|
|
29
|
+
oci.process_image_element(*image_element)
|
|
30
|
+
oci.finalize()
|
|
31
|
+
oci.write_bundle()
|
|
32
|
+
|
|
33
|
+
self.assertTrue(
|
|
34
|
+
os.path.exists(os.path.join(tempdir, 'rootfs')))
|
|
35
|
+
self.assertFalse(
|
|
36
|
+
os.path.exists(os.path.join(tempdir, 'rootfs/file')))
|
|
37
|
+
self.assertFalse(
|
|
38
|
+
os.path.exists(os.path.join(tempdir, 'rootfs/.wh.file')))
|
|
39
|
+
self.assertFalse(
|
|
40
|
+
os.path.exists(os.path.join(tempdir, 'rootfs/directory')))
|
|
41
|
+
self.assertTrue(
|
|
42
|
+
os.path.exists(os.path.join(tempdir, 'rootfs/anotherfile')))
|
|
43
|
+
self.assertTrue(
|
|
44
|
+
os.path.exists(os.path.join(tempdir, 'rootfs/anotherdirectory')))
|
|
45
|
+
self.assertFalse(
|
|
46
|
+
os.path.exists(os.path.join(tempdir,
|
|
47
|
+
'rootfs/anotherdirectory/.wh..wh..opq')))
|
|
48
|
+
|
|
49
|
+
def test_whiteouts_mounts(self):
|
|
50
|
+
image = 'occystrap_deletion_layers'
|
|
51
|
+
tag = 'latest'
|
|
52
|
+
|
|
53
|
+
with tempfile.TemporaryDirectory() as tempdir:
|
|
54
|
+
oci = output_mounts.MountWriter(image, tag, tempdir)
|
|
55
|
+
img = docker_registry.Image(
|
|
56
|
+
'localhost:5000', image, tag, 'linux', 'amd64', '',
|
|
57
|
+
secure=False)
|
|
58
|
+
for image_element in img.fetch(fetch_callback=oci.fetch_callback):
|
|
59
|
+
oci.process_image_element(*image_element)
|
|
60
|
+
oci.finalize()
|
|
61
|
+
oci.write_bundle()
|
|
62
|
+
|
|
63
|
+
self.assertTrue(
|
|
64
|
+
os.path.exists(os.path.join(tempdir, 'rootfs')))
|
|
65
|
+
self.assertFalse(
|
|
66
|
+
os.path.exists(os.path.join(tempdir, 'rootfs/file')))
|
|
67
|
+
self.assertFalse(
|
|
68
|
+
os.path.exists(os.path.join(tempdir, 'rootfs/.wh.file')))
|
|
69
|
+
self.assertFalse(
|
|
70
|
+
os.path.exists(os.path.join(tempdir, 'rootfs/directory')))
|
|
71
|
+
self.assertTrue(
|
|
72
|
+
os.path.exists(os.path.join(tempdir, 'rootfs/anotherfile')))
|
|
73
|
+
self.assertTrue(
|
|
74
|
+
os.path.exists(os.path.join(tempdir, 'rootfs/anotherdirectory')))
|
|
75
|
+
self.assertFalse(
|
|
76
|
+
os.path.exists(os.path.join(tempdir,
|
|
77
|
+
'rootfs/anotherdirectory/.wh..wh..opq')))
|
|
78
|
+
|
|
79
|
+
processutils.execute('umount %s' % os.path.join(tempdir, 'rootfs'),
|
|
80
|
+
shell=True)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
oslo.concurrency # apache2
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
[metadata]
|
|
2
|
+
name = occystrap_ci
|
|
3
|
+
summary = Occy Strap CI: test and validation for Occy Strap
|
|
4
|
+
license = Apache2
|
|
5
|
+
author = Michael Still
|
|
6
|
+
author-email = mikal@stillhq.com
|
|
7
|
+
home-page = https://www.madebymikal.com/category/occy-strap/
|
|
8
|
+
classifier =
|
|
9
|
+
Intended Audience :: Information Technology
|
|
10
|
+
Intended Audience :: System Administrators
|
|
11
|
+
License :: OSI Approved :: Apache Software License
|
|
12
|
+
Operating System :: POSIX :: Linux
|
|
13
|
+
Programming Language :: Python
|
|
14
|
+
Programming Language :: Python :: 3
|
|
15
|
+
Programming Language :: Python :: 3.7
|
|
16
|
+
|
|
17
|
+
[files]
|
|
18
|
+
packages =
|
|
19
|
+
occystrap_ci
|
|
20
|
+
|
|
21
|
+
[entry_points]
|
|
22
|
+
|
|
23
|
+
[pbr]
|
|
24
|
+
skip_changelog = True
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
12
|
+
# implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import setuptools
|
|
17
|
+
|
|
18
|
+
setuptools.setup(
|
|
19
|
+
setup_requires=['pbr'],
|
|
20
|
+
pbr=True)
|