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.
Files changed (52) hide show
  1. occystrap-0.4.0/.github/workflows/codeql-analysis.yml +54 -0
  2. occystrap-0.4.0/.github/workflows/functional-tests.yml +79 -0
  3. occystrap-0.4.0/.github/workflows/python-unit-tests.yml +33 -0
  4. {occystrap-0.2.0/occystrap.egg-info → occystrap-0.4.0}/PKG-INFO +28 -1
  5. {occystrap-0.2.0 → occystrap-0.4.0}/README.md +27 -0
  6. occystrap-0.4.0/deploy/.stestr.conf +3 -0
  7. occystrap-0.4.0/deploy/ansible/ci.yml +211 -0
  8. occystrap-0.4.0/deploy/occystrap_ci/testdata/deletion_layers/Dockerfile +10 -0
  9. occystrap-0.4.0/deploy/occystrap_ci/tests/test_dir_deep_images.py +33 -0
  10. occystrap-0.4.0/deploy/occystrap_ci/tests/test_oci_hello_world.py +52 -0
  11. occystrap-0.4.0/deploy/occystrap_ci/tests/test_whiteout.py +80 -0
  12. occystrap-0.4.0/deploy/requirements.txt +1 -0
  13. occystrap-0.4.0/deploy/setup.cfg +24 -0
  14. occystrap-0.4.0/deploy/setup.py +20 -0
  15. occystrap-0.4.0/deploy/test-requirements.txt +2 -0
  16. occystrap-0.4.0/deploy/tox.ini +30 -0
  17. occystrap-0.4.0/occystrap/__init__.py +0 -0
  18. occystrap-0.4.0/occystrap/common.py +40 -0
  19. occystrap-0.4.0/occystrap/constants.py +186 -0
  20. {occystrap-0.2.0 → occystrap-0.4.0}/occystrap/docker_registry.py +75 -24
  21. occystrap-0.4.0/occystrap/main.py +137 -0
  22. {occystrap-0.2.0 → occystrap-0.4.0}/occystrap/output_directory.py +52 -30
  23. occystrap-0.4.0/occystrap/output_mounts.py +155 -0
  24. occystrap-0.4.0/occystrap/output_ocibundle.py +53 -0
  25. {occystrap-0.2.0 → occystrap-0.4.0}/occystrap/output_tarfile.py +0 -5
  26. occystrap-0.4.0/occystrap/tests/__init__.py +0 -0
  27. {occystrap-0.2.0 → occystrap-0.4.0}/occystrap/util.py +9 -1
  28. {occystrap-0.2.0 → occystrap-0.4.0/occystrap.egg-info}/PKG-INFO +28 -1
  29. occystrap-0.4.0/occystrap.egg-info/SOURCES.txt +46 -0
  30. occystrap-0.4.0/occystrap.egg-info/pbr.json +1 -0
  31. {occystrap-0.2.0 → occystrap-0.4.0}/occystrap.egg-info/requires.txt +2 -0
  32. occystrap-0.4.0/requirements.txt +6 -0
  33. {occystrap-0.2.0 → occystrap-0.4.0}/test-requirements.txt +2 -1
  34. {occystrap-0.2.0 → occystrap-0.4.0}/tools/flake8wrap.sh +1 -1
  35. {occystrap-0.2.0 → occystrap-0.4.0}/tox.ini +4 -17
  36. occystrap-0.2.0/occystrap/constants.py +0 -2
  37. occystrap-0.2.0/occystrap/main.py +0 -78
  38. occystrap-0.2.0/occystrap.egg-info/SOURCES.txt +0 -27
  39. occystrap-0.2.0/occystrap.egg-info/pbr.json +0 -1
  40. occystrap-0.2.0/requirements.txt +0 -4
  41. {occystrap-0.2.0 → occystrap-0.4.0}/AUTHORS +0 -0
  42. {occystrap-0.2.0 → occystrap-0.4.0}/LICENSE +0 -0
  43. {occystrap-0.2.0/occystrap → occystrap-0.4.0/deploy/occystrap_ci}/__init__.py +0 -0
  44. {occystrap-0.2.0/occystrap → occystrap-0.4.0/deploy/occystrap_ci}/tests/__init__.py +0 -0
  45. {occystrap-0.2.0 → occystrap-0.4.0}/occystrap/docker_extract.py +0 -0
  46. {occystrap-0.2.0 → occystrap-0.4.0}/occystrap.egg-info/dependency_links.txt +0 -0
  47. {occystrap-0.2.0 → occystrap-0.4.0}/occystrap.egg-info/entry_points.txt +0 -0
  48. {occystrap-0.2.0 → occystrap-0.4.0}/occystrap.egg-info/not-zip-safe +0 -0
  49. {occystrap-0.2.0 → occystrap-0.4.0}/occystrap.egg-info/top_level.txt +0 -0
  50. {occystrap-0.2.0 → occystrap-0.4.0}/release.sh +0 -0
  51. {occystrap-0.2.0 → occystrap-0.4.0}/setup.cfg +0 -0
  52. {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.2.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,3 @@
1
+ [DEFAULT]
2
+ test_path=./occystrap_ci/tests
3
+ top_dir=./
@@ -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,10 @@
1
+ FROM ubuntu
2
+ RUN echo "test" > file
3
+ RUN mkdir directory
4
+ RUN echo "test" > directory/directoryfile
5
+ RUN echo "test" > anotherfile
6
+ RUN mkdir anotherdirectory
7
+ RUN echo "test" > anotherdirectory/anotherfile
8
+
9
+ RUN rm file
10
+ RUN rm -rf directory
@@ -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)