occystrap 0.3.0__py3-none-any.whl → 0.4.1__py3-none-any.whl

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 (39) hide show
  1. occystrap/_version.py +34 -0
  2. occystrap/filters/__init__.py +10 -0
  3. occystrap/filters/base.py +67 -0
  4. occystrap/filters/exclude.py +136 -0
  5. occystrap/filters/inspect.py +179 -0
  6. occystrap/filters/normalize_timestamps.py +123 -0
  7. occystrap/filters/search.py +177 -0
  8. occystrap/inputs/__init__.py +1 -0
  9. occystrap/inputs/base.py +40 -0
  10. occystrap/inputs/docker.py +171 -0
  11. occystrap/inputs/registry.py +260 -0
  12. occystrap/inputs/tarfile.py +88 -0
  13. occystrap/main.py +330 -31
  14. occystrap/outputs/__init__.py +1 -0
  15. occystrap/outputs/base.py +46 -0
  16. occystrap/{output_directory.py → outputs/directory.py} +10 -9
  17. occystrap/outputs/docker.py +137 -0
  18. occystrap/{output_mounts.py → outputs/mounts.py} +2 -1
  19. occystrap/{output_ocibundle.py → outputs/ocibundle.py} +1 -1
  20. occystrap/outputs/registry.py +240 -0
  21. occystrap/{output_tarfile.py → outputs/tarfile.py} +18 -2
  22. occystrap/pipeline.py +297 -0
  23. occystrap/tarformat.py +122 -0
  24. occystrap/tests/test_inspect.py +355 -0
  25. occystrap/tests/test_tarformat.py +199 -0
  26. occystrap/uri.py +231 -0
  27. occystrap/util.py +67 -38
  28. occystrap-0.4.1.dist-info/METADATA +444 -0
  29. occystrap-0.4.1.dist-info/RECORD +38 -0
  30. {occystrap-0.3.0.dist-info → occystrap-0.4.1.dist-info}/WHEEL +1 -1
  31. {occystrap-0.3.0.dist-info → occystrap-0.4.1.dist-info}/entry_points.txt +0 -1
  32. occystrap/docker_extract.py +0 -36
  33. occystrap/docker_registry.py +0 -192
  34. occystrap-0.3.0.dist-info/METADATA +0 -131
  35. occystrap-0.3.0.dist-info/RECORD +0 -20
  36. occystrap-0.3.0.dist-info/pbr.json +0 -1
  37. {occystrap-0.3.0.dist-info → occystrap-0.4.1.dist-info/licenses}/AUTHORS +0 -0
  38. {occystrap-0.3.0.dist-info → occystrap-0.4.1.dist-info/licenses}/LICENSE +0 -0
  39. {occystrap-0.3.0.dist-info → occystrap-0.4.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,444 @@
1
+ Metadata-Version: 2.4
2
+ Name: occystrap
3
+ Version: 0.4.1
4
+ Summary: occystrap: docker and OCI container tools
5
+ Author-email: Michael Still <mikal@stillhq.com>
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/shakenfist/occystrap
8
+ Project-URL: Bug Tracker, https://github.com/shakenfist/occystrap/issues
9
+ Classifier: Intended Audience :: Information Technology
10
+ Classifier: Intended Audience :: System Administrators
11
+ Classifier: Operating System :: POSIX :: Linux
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Programming Language :: Python :: 3
14
+ Requires-Python: >=3.7
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ License-File: AUTHORS
18
+ Requires-Dist: click>=7.1.1
19
+ Requires-Dist: requests
20
+ Requires-Dist: requests-unixsocket
21
+ Requires-Dist: prettytable
22
+ Requires-Dist: oslo.concurrency
23
+ Requires-Dist: shakenfist-utilities
24
+ Provides-Extra: test
25
+ Requires-Dist: coverage; extra == "test"
26
+ Requires-Dist: testtools; extra == "test"
27
+ Requires-Dist: mock; extra == "test"
28
+ Requires-Dist: stestr; extra == "test"
29
+ Requires-Dist: flake8; extra == "test"
30
+ Dynamic: license-file
31
+
32
+ # Occy Strap
33
+
34
+ Occy Strap is a simple set of Docker and OCI container tools, which can be used
35
+ either for container forensics or for implementing an OCI orchestrator,
36
+ depending on your needs. This is a very early implementation, so be braced for
37
+ impact.
38
+
39
+ ## Quick Start with URI-Style Commands
40
+
41
+ The recommended way to use Occy Strap is with the new URI-style `process` and
42
+ `search` commands:
43
+
44
+ ```
45
+ # Download from registry to tarball
46
+ occystrap process registry://docker.io/library/busybox:latest tar://busybox.tar
47
+
48
+ # Download from registry to directory
49
+ occystrap process registry://docker.io/library/centos:7 dir://centos7
50
+
51
+ # Export from local Docker to tarball with timestamp normalization
52
+ occystrap process docker://myimage:v1 tar://output.tar -f normalize-timestamps
53
+
54
+ # Search for files in an image
55
+ occystrap search registry://docker.io/library/busybox:latest "bin/*sh"
56
+ ```
57
+
58
+ ## The `process` Command
59
+
60
+ The `process` command takes a source URI, a destination URI, and optional
61
+ filters:
62
+
63
+ ```
64
+ occystrap process SOURCE DESTINATION [-f FILTER]...
65
+ ```
66
+
67
+ ### Input URI Schemes
68
+
69
+ - `registry://HOST/IMAGE:TAG` - Docker/OCI registry
70
+ - `docker://IMAGE:TAG` - Local Docker daemon
71
+ - `tar:///path/to/file.tar` - Docker-save format tarball
72
+
73
+ ### Output URI Schemes
74
+
75
+ - `tar:///path/to/output.tar` - Create tarball
76
+ - `dir:///path/to/directory` - Extract to directory
77
+ - `oci:///path/to/bundle` - Create OCI runtime bundle
78
+ - `mounts:///path/to/directory` - Create overlay mounts
79
+ - `docker://IMAGE:TAG` - Load into local Docker daemon
80
+ - `registry://HOST/IMAGE:TAG` - Push to Docker/OCI registry
81
+
82
+ ### URI Options
83
+
84
+ Options can be passed as query parameters:
85
+
86
+ ```
87
+ # Extract with unique names and expansion
88
+ occystrap process registry://docker.io/library/busybox:latest \
89
+ "dir://merged?unique_names=true&expand=true"
90
+
91
+ # Use custom Docker socket
92
+ occystrap process "docker://myimage:v1?socket=/run/podman/podman.sock" \
93
+ tar://output.tar
94
+ ```
95
+
96
+ ### Filters
97
+
98
+ Filters transform or inspect image elements as they pass through the pipeline:
99
+
100
+ ```
101
+ # Normalize timestamps for reproducible builds
102
+ occystrap process registry://docker.io/library/busybox:latest \
103
+ tar://busybox.tar -f normalize-timestamps
104
+
105
+ # Normalize with custom timestamp
106
+ occystrap process registry://docker.io/library/busybox:latest \
107
+ tar://busybox.tar -f "normalize-timestamps:ts=1609459200"
108
+
109
+ # Search while creating output (prints matches AND creates tarball)
110
+ occystrap process registry://docker.io/library/busybox:latest \
111
+ tar://busybox.tar -f "search:pattern=*.conf"
112
+
113
+ # Chain multiple filters
114
+ occystrap process registry://docker.io/library/busybox:latest \
115
+ tar://busybox.tar -f normalize-timestamps -f "search:pattern=bin/*"
116
+
117
+ # Record layer metadata to a JSONL file (inspect filter)
118
+ occystrap process docker://myimage:v1 registry://myregistry/myimage:v1 \
119
+ -f "inspect:file=layers-before.jsonl" \
120
+ -f normalize-timestamps \
121
+ -f "inspect:file=layers-after.jsonl"
122
+
123
+ # Exclude files matching glob patterns from layers
124
+ occystrap process registry://docker.io/library/python:3.11 \
125
+ tar://python.tar -f "exclude:pattern=**/.git/**"
126
+
127
+ # Exclude multiple patterns (comma-separated)
128
+ occystrap process registry://docker.io/library/python:3.11 \
129
+ tar://python.tar -f "exclude:pattern=**/.git/**,**/__pycache__/**,**/*.pyc"
130
+
131
+ # Load image directly into local Docker daemon
132
+ occystrap process registry://docker.io/library/busybox:latest \
133
+ docker://busybox:latest
134
+
135
+ # Load into Podman
136
+ occystrap process registry://docker.io/library/busybox:latest \
137
+ "docker://busybox:latest?socket=/run/podman/podman.sock"
138
+
139
+ # Push image to a registry
140
+ occystrap process docker://myimage:v1 \
141
+ registry://myregistry.example.com/myuser/myimage:v1
142
+
143
+ # Push to registry with authentication
144
+ occystrap --username myuser --password mytoken \
145
+ process tar://image.tar registry://ghcr.io/myorg/myimage:latest
146
+ ```
147
+
148
+ ## The `search` Command
149
+
150
+ Search for files in container image layers:
151
+
152
+ ```
153
+ occystrap search SOURCE PATTERN [--regex] [--script-friendly]
154
+ ```
155
+
156
+ Examples:
157
+
158
+ ```
159
+ # Search registry image
160
+ occystrap search registry://docker.io/library/busybox:latest "bin/*sh"
161
+
162
+ # Search local Docker image
163
+ occystrap search docker://myimage:v1 "*.conf"
164
+
165
+ # Search tarball with regex
166
+ occystrap search --regex tar://image.tar ".*\.py$"
167
+
168
+ # Machine-parseable output
169
+ occystrap search --script-friendly registry://docker.io/library/busybox:latest "*sh"
170
+ ```
171
+
172
+ ## Legacy Commands (Deprecated)
173
+
174
+ The following commands are deprecated but still work for backwards
175
+ compatibility. They will be removed in a future version.
176
+
177
+ ### Downloading an image from a repository and storing as a tarball
178
+
179
+ Let's say we want to download an image from a repository and store it as a
180
+ local tarball. This is a common thing to want to do in airgapped environments
181
+ for example. You could do this with docker with a `docker pull; docker save`.
182
+ The Occy Strap equivalent is:
183
+
184
+ ```
185
+ occystrap fetch-to-tarfile registry-1.docker.io library/busybox latest busybox.tar
186
+ ```
187
+
188
+ **New equivalent:**
189
+ ```
190
+ occystrap process registry://registry-1.docker.io/library/busybox:latest tar://busybox.tar
191
+ ```
192
+
193
+ In this example we're pulling from the Docker Hub (registry-1.docker.io), and
194
+ are downloading busybox's latest version into a tarball named `busybox.tar`.
195
+ This tarball can be loaded with `docker load -i busybox.tar` on an airgapped
196
+ Docker environment.
197
+
198
+ ### Repeatable builds with normalized timestamps
199
+
200
+ To make builds more repeatable, you can normalize file access and modification
201
+ times in the image layers. This is useful when you want to ensure that the
202
+ same image content produces the same tarball hash, regardless of when the
203
+ files were originally created:
204
+
205
+ ```
206
+ occystrap fetch-to-tarfile --normalize-timestamps registry-1.docker.io library/busybox latest busybox.tar
207
+ ```
208
+
209
+ **New equivalent:**
210
+ ```
211
+ occystrap process registry://registry-1.docker.io/library/busybox:latest tar://busybox.tar -f normalize-timestamps
212
+ ```
213
+
214
+ This will set all timestamps in the layer tarballs to 0 (Unix epoch: January
215
+ 1, 1970). You can also specify a custom timestamp:
216
+
217
+ ```
218
+ occystrap fetch-to-tarfile --normalize-timestamps --timestamp 1609459200 registry-1.docker.io library/busybox latest busybox.tar
219
+ ```
220
+
221
+ **New equivalent:**
222
+ ```
223
+ occystrap process registry://registry-1.docker.io/library/busybox:latest tar://busybox.tar -f "normalize-timestamps:ts=1609459200"
224
+ ```
225
+
226
+ When timestamps are normalized, the layer SHAs are recalculated and the
227
+ manifest is updated to reflect the new hashes. This ensures the tarball
228
+ structure remains consistent and valid.
229
+
230
+ ### Downloading an image from a repository and storing as an extracted tarball
231
+
232
+ The format of the tarball in the previous example is two JSON configuration
233
+ files and a series of image layers as tarballs inside the main tarball. You
234
+ can write these elements to a directory instead of to a tarball if you'd like
235
+ to inspect them:
236
+
237
+ ```
238
+ occystrap fetch-to-extracted registry-1.docker.io library/centos 7 centos7
239
+ ```
240
+
241
+ **New equivalent:**
242
+ ```
243
+ occystrap process registry://registry-1.docker.io/library/centos:7 dir://centos7
244
+ ```
245
+
246
+ ### Downloading an image to a merged directory
247
+
248
+ In scenarios where image layers are likely to be reused between images, you
249
+ can save disk space by downloading images to a directory which contains more
250
+ than one image:
251
+
252
+ ```
253
+ occystrap fetch-to-extracted --use-unique-names registry-1.docker.io \
254
+ homeassistant/home-assistant latest merged_images
255
+ ```
256
+
257
+ **New equivalent:**
258
+ ```
259
+ occystrap process registry://registry-1.docker.io/homeassistant/home-assistant:latest \
260
+ "dir://merged_images?unique_names=true"
261
+ ```
262
+
263
+ ### Storing an image tarfile in a merged directory
264
+
265
+ Sometimes you have image tarfiles instead of images in a registry:
266
+
267
+ ```
268
+ occystrap tarfile-to-extracted --use-unique-names file.tar merged_images
269
+ ```
270
+
271
+ **New equivalent:**
272
+ ```
273
+ occystrap process tar://file.tar "dir://merged_images?unique_names=true"
274
+ ```
275
+
276
+ ### Exploring the contents of layers and overwritten files
277
+
278
+ If you'd like the layers to be expanded from their tarballs to the filesystem:
279
+
280
+ ```
281
+ occystrap fetch-to-extracted --expand quay.io \
282
+ ukhomeofficedigital/centos-base latest ukhomeoffice-centos
283
+ ```
284
+
285
+ **New equivalent:**
286
+ ```
287
+ occystrap process registry://quay.io/ukhomeofficedigital/centos-base:latest \
288
+ "dir://ukhomeoffice-centos?expand=true"
289
+ ```
290
+
291
+ ### Generating an OCI runtime bundle
292
+
293
+ ```
294
+ occystrap fetch-to-oci registry-1.docker.io library/hello-world latest bar
295
+ ```
296
+
297
+ **New equivalent:**
298
+ ```
299
+ occystrap process registry://registry-1.docker.io/library/hello-world:latest oci://bar
300
+ ```
301
+
302
+ ### Searching image layers for files
303
+
304
+ ```
305
+ occystrap search-layers registry-1.docker.io library/busybox latest "bin/*sh"
306
+ ```
307
+
308
+ **New equivalent:**
309
+ ```
310
+ occystrap search registry://registry-1.docker.io/library/busybox:latest "bin/*sh"
311
+ ```
312
+
313
+ ### Working with local Docker or Podman daemon
314
+
315
+ ```
316
+ occystrap docker-to-tarfile library/busybox latest busybox.tar
317
+ ```
318
+
319
+ **New equivalent:**
320
+ ```
321
+ occystrap process docker://library/busybox:latest tar://busybox.tar
322
+ ```
323
+
324
+ For Podman:
325
+ ```
326
+ occystrap process "docker://myimage:latest?socket=/run/podman/podman.sock" tar://output.tar
327
+ ```
328
+
329
+ Note: Podman doesn't run a daemon by default. You need to start the socket
330
+ service first:
331
+
332
+ ```
333
+ # For rootless Podman
334
+ systemctl --user start podman.socket
335
+
336
+ # For rootful Podman
337
+ sudo systemctl start podman.socket
338
+ ```
339
+
340
+ ## Authenticating with private registries
341
+
342
+ To fetch images from private registries (such as GitLab Container Registry,
343
+ AWS ECR, or private Docker Hub repositories), use the `--username` and
344
+ `--password` global options:
345
+
346
+ ```
347
+ occystrap --username myuser --password mytoken \
348
+ process registry://registry.gitlab.com/mygroup/myimage:latest tar://output.tar
349
+ ```
350
+
351
+ You can also use environment variables to avoid putting credentials on the
352
+ command line:
353
+
354
+ ```
355
+ export OCCYSTRAP_USERNAME=myuser
356
+ export OCCYSTRAP_PASSWORD=mytoken
357
+ occystrap process registry://registry.gitlab.com/mygroup/myimage:latest tar://output.tar
358
+ ```
359
+
360
+ For GitLab Container Registry, the username is typically your GitLab username
361
+ and the password is a personal access token with `read_registry` scope.
362
+
363
+ ## Supporting non-default architectures
364
+
365
+ Docker image repositories can store multiple versions of a single image, with
366
+ each image corresponding to a different (operating system, cpu architecture,
367
+ cpu variant) tuple. Occy Strap supports letting you specify which to use with
368
+ global command line flags. Occy Strap defaults to linux amd64 if you don't
369
+ specify something different:
370
+
371
+ ```
372
+ occystrap --os linux --architecture arm64 --variant v8 \
373
+ process registry://registry-1.docker.io/library/busybox:latest dir://busybox
374
+ ```
375
+
376
+ Or via URI query parameters:
377
+
378
+ ```
379
+ occystrap process "registry://registry-1.docker.io/library/busybox:latest?os=linux&arch=arm64&variant=v8" \
380
+ dir://busybox
381
+ ```
382
+
383
+ ## Development
384
+
385
+ ### Install for Development
386
+
387
+ ```
388
+ pip install -e ".[test]"
389
+ ```
390
+
391
+ ### Pre-commit Hooks
392
+
393
+ This project uses pre-commit hooks to validate code before commits. Install them
394
+ with:
395
+
396
+ ```
397
+ pip install pre-commit
398
+ pre-commit install
399
+ ```
400
+
401
+ The hooks run:
402
+ - `actionlint` - GitHub Actions workflow validation
403
+ - `shellcheck` - Shell script linting
404
+ - `tox -eflake8` - Python code style checks
405
+ - `tox -epy3` - Unit tests
406
+
407
+ To run the hooks manually:
408
+
409
+ ```
410
+ pre-commit run --all-files
411
+ ```
412
+
413
+ ### Running Tests
414
+
415
+ Unit tests are in `occystrap/tests/` and can be run with:
416
+
417
+ ```
418
+ tox -epy3
419
+ ```
420
+
421
+ Functional tests are in `deploy/occystrap_ci/tests/` and are run in CI.
422
+
423
+ ### Releasing
424
+
425
+ Releases are automated via GitHub Actions. Push a version tag to trigger the
426
+ pipeline:
427
+
428
+ ```
429
+ git tag -s v0.5.0 -m "Release v0.5.0"
430
+ git push origin v0.5.0
431
+ ```
432
+
433
+ The workflow builds the package, signs the tag with Sigstore, publishes to
434
+ PyPI, and creates a GitHub Release. See [RELEASE-SETUP.md](RELEASE-SETUP.md)
435
+ for one-time configuration steps.
436
+
437
+ ## Documentation
438
+
439
+ For more detailed documentation, see the [docs/](docs/) directory:
440
+
441
+ - [Installation](docs/installation.md) - Getting started guide
442
+ - [Command Reference](docs/command-reference.md) - Complete CLI reference
443
+ - [Pipeline Architecture](docs/pipeline.md) - How the pipeline works
444
+ - [Use Cases](docs/use-cases.md) - Common scenarios and examples
@@ -0,0 +1,38 @@
1
+ occystrap/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ occystrap/_version.py,sha256=k7cu0JKra64gmMNU_UfA5sw2eNc_GRvf3QmesiYAy8g,704
3
+ occystrap/common.py,sha256=Zm4hHpn8RgSXp0W86HhZzpyXq19QIsLJgp9SxK_1QQg,1300
4
+ occystrap/constants.py,sha256=kmOt-12settGbDTW1efpT3UENRQouG9f0ZjgOqWdrIA,4399
5
+ occystrap/main.py,sha256=bo87uuAJYCZq0YL-EnjpNUsbiaySyvpYPgi-SQF2uaE,15521
6
+ occystrap/pipeline.py,sha256=oiWXB6Wrjl32jC0MI0HksATjxcUQ7o5ntKm864BZxnA,10849
7
+ occystrap/tarformat.py,sha256=Fw5GPntymn7mNzDNiCQr55iNtDQ2GYqes9yBYT1XtJE,4113
8
+ occystrap/uri.py,sha256=uKwy2hb0i1Pjf2QpwSBTobgcH2ve1WNsYSK0n2GpkK8,6858
9
+ occystrap/util.py,sha256=eYZOkamk6hWyFuN4W8NoimR23A_FG1cMl_AfT7vJbEw,3987
10
+ occystrap/filters/__init__.py,sha256=ZT9J7QX4tuEeEJEnty-pGcQQPxv_7lj6ymELleMR_wU,383
11
+ occystrap/filters/base.py,sha256=D1Li3mgNFzrn6BBL7pz35IUGUVWcqwWBfHYXqfQQ1-8,2375
12
+ occystrap/filters/exclude.py,sha256=RrISggbuSMIWOEi1SPKpnorTa6cJVKlIBwAPHxI99D0,4749
13
+ occystrap/filters/inspect.py,sha256=saxsO5vCcZ1-7exkboTa4bkzmglFXY9Fi6U9Q66iV8g,6101
14
+ occystrap/filters/normalize_timestamps.py,sha256=-oM05xtwuf8qjiAZ2jUJDqRLdom10H5KE9_QlPJOQUk,4663
15
+ occystrap/filters/search.py,sha256=ftxTTsHS44L0BvxgFb09hFKC1t0znIj8zEDCK6-5lbo,6782
16
+ occystrap/inputs/__init__.py,sha256=mbLK9EG2LauQqSJ-hqCyW0P2VCZNeG68mqT14FI8jmA,66
17
+ occystrap/inputs/base.py,sha256=xLXp19fSO1Ks8eXETvOQkI3gUu42rI1OdhM_yuIJSts,1271
18
+ occystrap/inputs/docker.py,sha256=QRGJ_LGLbuSaNN-HsgRembHrIAoP3JbyQwH7hF470vI,6420
19
+ occystrap/inputs/registry.py,sha256=hQaqQ09sruuhkZl0KcZdCNIES2dZgJVWt8i20kIyDHk,10572
20
+ occystrap/inputs/tarfile.py,sha256=7OHT4TYckI6zyAMwpUr-8B3Mg8T4M9qTVTHCJ_pFlDI,2898
21
+ occystrap/outputs/__init__.py,sha256=E_-OfS5WtQi-yWMQTSviAlC8enO6IH88ZcOYCY_IjCw,38
22
+ occystrap/outputs/base.py,sha256=TiucjT_XB_f8-QjWOFhhwSFyrS66mK6T8W8GYT1uKYI,1471
23
+ occystrap/outputs/directory.py,sha256=MGZVIDqc3sNk5p3rd1wMgEO3u9_yvfLgE_y5_8Bu81w,11496
24
+ occystrap/outputs/docker.py,sha256=AxCpYotlMnaBci5NObzKLEsHbXNYP3TuzPMffBxHQw0,4585
25
+ occystrap/outputs/mounts.py,sha256=-rMNbetDW_rZO5gkLFtTYtuPTDhuzyhYg9CZXeuq_TQ,6433
26
+ occystrap/outputs/ocibundle.py,sha256=tK09wZ7bCjeVnqoGsz6MF38Ma36hI9OofHEzG5HBtI4,2155
27
+ occystrap/outputs/registry.py,sha256=qlhSaa4y7G_zC31MqItEtkWz3Ks83a_g4JlBj8RHleI,8633
28
+ occystrap/outputs/tarfile.py,sha256=AHY6UvBo2WPG7nj5FHE7GRzouuxpFnQkwZEHz_KCLRY,2310
29
+ occystrap/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ occystrap/tests/test_inspect.py,sha256=HA1ogCLyy5SCFWpesyVkhp6mL95k2XhGuCcAPQ5kMSc,11209
31
+ occystrap/tests/test_tarformat.py,sha256=6q3tG7UtLpX274rjngvgQ8HCUk7lN17TMiXXjxdN2OA,7156
32
+ occystrap-0.4.1.dist-info/licenses/AUTHORS,sha256=toKLUaf9c-NkNow00B_akwMGcGtm-S_ihcC_eql9qWc,34
33
+ occystrap-0.4.1.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
34
+ occystrap-0.4.1.dist-info/METADATA,sha256=HDKdBAasvpNlirXiQUt4qXOuQRBvaLSNl4DG-yovdRw,13194
35
+ occystrap-0.4.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
36
+ occystrap-0.4.1.dist-info/entry_points.txt,sha256=Uba7wHWknje_I2ZN1sGOpmP4twuQ1XEsOa5o28bvc2Y,49
37
+ occystrap-0.4.1.dist-info/top_level.txt,sha256=06nN7FHq2z_Jpp2PZNm3rGOGUA1cIGlUr6MEZrqgOlc,10
38
+ occystrap-0.4.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.34.2)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,3 +1,2 @@
1
1
  [console_scripts]
2
2
  occystrap = occystrap.main:cli
3
-
@@ -1,36 +0,0 @@
1
- #!/usr/bin/python3
2
-
3
- # Call me like this:
4
- # docker-image-extract tarfile.tar extracted
5
-
6
- import tarfile
7
- import json
8
- import os
9
- import sys
10
-
11
- image_path = sys.argv[1]
12
- extracted_path = sys.argv[2]
13
-
14
- with tarfile.open(image_path) as image:
15
- manifest = json.loads(image.extractfile('manifest.json').read())
16
- print('Manifest: %s' % manifest)
17
-
18
- config = json.loads(image.extractfile(manifest[0]['Config']).read())
19
- print('Config: %s' % config)
20
-
21
- for layer in manifest[0]['Layers']:
22
- print('Found layer: %s' % layer)
23
- layer_tar = tarfile.open(fileobj=image.extractfile(layer))
24
-
25
- for tarinfo in layer_tar:
26
- print(' ... %s' % tarinfo.name)
27
- if tarinfo.isdev():
28
- print(' --> skip device files')
29
- continue
30
-
31
- dest = os.path.join(extracted_path, tarinfo.name)
32
- if not tarinfo.isdir() and os.path.exists(dest):
33
- print(' --> remove old version of file')
34
- os.unlink(dest)
35
-
36
- layer_tar.extract(tarinfo, path=extracted_path)