Compare commits

...

103 Commits

Author SHA1 Message Date
Zack Brady
0674e0ab30 merge pull request #229 from zackbradys/vagrant
removed vagrant scripts
2024-04-15 09:36:24 -04:00
Zack Brady
d645c52135 removed vagrant scripts 2024-04-14 08:45:51 -04:00
Zack Brady
44baab3213 merge pull request #227 from zackbradys/helmifying
helmifying hauler
2024-04-11 22:02:37 -04:00
Zack Brady
1a317b0172 merge pull request #226 from zackbradys/testdata
updated hauler testdata
2024-04-11 21:57:37 -04:00
Zack Brady
128cb3b252 last bit of updates and formatting of chart 2024-04-07 00:23:49 -04:00
Zack Brady
91ff998634 updated hauler testdata 2024-04-06 15:19:53 -04:00
Zack Brady
8ac1ecaf29 adding functionality and cleaning up 2024-04-06 02:06:33 -04:00
Zack Brady
7447aad20a added initial helm chart 2024-04-06 00:28:59 -04:00
Zack Brady
003456d8ab merge pull request #225 from zackbradys/main
removed tag in release workflow
2024-04-05 21:36:26 -04:00
Zack Brady
f44b8b93af removed tag in release workflow 2024-04-05 21:32:58 -04:00
Zack Brady
e405840642 merge pull request #224 from zackbradys/main
fixed image ref in release workflow
2024-04-05 20:45:53 -04:00
Zack Brady
8c9aa909b0 updated/fixed image ref in release workflow 2024-04-05 20:43:36 -04:00
Zack Brady
8670489520 merge pull request #223 from zackbradys/main
fixed platforms in release workflow
2024-04-05 20:04:57 -04:00
Zack Hodgson Brady
f20d4052a4 updated/fixed platforms in release workflow 2024-04-05 20:02:00 -04:00
Zack Brady
c84bca43d2 updated/cleaned github actions (#222)
* cleaned up unit test workflow
* updated/cleaned up release workflow
* fixed workflow typo
2024-04-05 16:12:49 -07:00
Claus Albøge
6863d91f69 Make Product Registry configurable (#194)
Co-authored-by: Claus Albøge <ca@netic.dk>
2024-04-05 14:40:26 -07:00
Zack Brady
16eea6ac2a updated fileserver directory name (#219) 2024-04-05 14:36:39 -07:00
Adam Martin
f6f227567c Merge pull request #221 from amartin120/fix-file-logging
fix logging for files
2024-04-01 12:45:58 -04:00
Adam Martin
eb810c16f5 fix logging for files
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-04-01 12:23:05 -04:00
Adam Martin
b18f55ea60 Merge pull request #220 from amartin120/temp-override
temp dir override for `hauler store load`
2024-04-01 10:40:31 -04:00
Adam Martin
4bbe622073 add extra info for the tempdir override flag
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-04-01 09:39:34 -04:00
Adam Martin
ea5bcb36ae tempdir override flag for load
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-04-01 09:34:26 -04:00
Adam Martin
5c7daddfef Merge pull request #218 from amartin120/remove-cache-flag
deprecate misleading cache flag from store
2024-03-29 13:48:51 -04:00
Adam Martin
7083f3a4f3 deprecate the cache flag instead of remove
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-03-29 13:40:24 -04:00
Adam Martin
8541d73a0d Merge pull request #217 from amartin120/logging-updates
better logging when adding to store
2024-03-29 11:36:45 -04:00
Adam Martin
49d705d14c Merge pull request #216 from amartin120/cosign-update
update to v2.2.3 of RGS cosign fork
2024-03-29 11:36:29 -04:00
Clayton Castro
722851d809 Merge pull request #215 from clanktron/container
add container definition
2024-03-28 16:20:35 -07:00
clayton
82aedc867a switch to using bci-golang as builder image 2024-03-28 13:53:22 -07:00
clayton
e8fb37c6ed fix: ensure /tmp for hauler store load 2024-03-28 13:49:01 -07:00
Adam Martin
545b3f8acd added the copy back for now
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-03-28 16:16:05 -04:00
Adam Martin
3ae92fe20a remove copy at the image sync not needed with cosign update
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-03-28 15:00:00 -04:00
Adam Martin
35538bf45a removed misleading cache flag
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-03-28 14:24:37 -04:00
Adam Martin
b6701bbfbc better logging when adding to store
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-03-28 14:16:22 -04:00
Adam Martin
14738c3cd6 update to v2.2.3 of our cosign fork
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-03-28 13:11:26 -04:00
clayton
0657fd80fe add: dockerignore 2024-03-27 02:25:12 -07:00
clayton
d132e8b8e0 add: Dockerfile 2024-03-27 02:25:06 -07:00
Adam Martin
29367c152e Merge pull request #213 from rancherfederal/dependabot/go_modules/google.golang.org/protobuf-1.33.0
Bump google.golang.org/protobuf from 1.31.0 to 1.33.0
2024-03-26 14:58:08 -04:00
Adam Martin
185ae6bd74 Merge pull request #212 from rancherfederal/dependabot/go_modules/github.com/docker/docker-25.0.5incompatible
Bump github.com/docker/docker from 25.0.1+incompatible to 25.0.5+incompatible
2024-03-26 14:57:57 -04:00
dependabot[bot]
b6c78d3925 Bump google.golang.org/protobuf from 1.31.0 to 1.33.0
Bumps google.golang.org/protobuf from 1.31.0 to 1.33.0.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-26 13:04:41 +00:00
dependabot[bot]
e718d40744 Bump github.com/docker/docker
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 25.0.1+incompatible to 25.0.5+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v25.0.1...v25.0.5)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-26 13:03:05 +00:00
Zack Brady
1505bfb3af merge pull request #207 from zackbradys/main
updated and added new logos
2024-03-20 08:17:00 -04:00
Zack Hodgson Brady
e27b5b3cd1 updated and added new logos 2024-03-19 18:22:21 -04:00
Zack Brady
0472c8fc65 merge pull request #203 from zackbradys/main
updated github files
2024-03-11 09:28:08 -04:00
Zack Hodgson Brady
70a48f2efe updated github files 2024-03-10 16:45:41 -04:00
Adam Martin
bb2a8bfbec Merge pull request #197 from fgiudici/file_name_option
Fix --name option in "store add file" command
2024-02-27 08:33:09 -05:00
Adam Martin
2779c649c2 Merge pull request #195 from rancherfederal/dependabot/go_modules/helm.sh/helm/v3-3.14.2
Bump helm.sh/helm/v3 from 3.14.1 to 3.14.2
2024-02-27 08:00:57 -05:00
Francesco Giudici
8120537af2 Fix --name option in "store add file" command
Fixes: #196

Signed-off-by: Francesco Giudici <francesco.giudici@suse.com>
2024-02-27 09:54:48 +01:00
dependabot[bot]
9cdab516f0 Bump helm.sh/helm/v3 from 3.14.1 to 3.14.2
Bumps [helm.sh/helm/v3](https://github.com/helm/helm) from 3.14.1 to 3.14.2.
- [Release notes](https://github.com/helm/helm/releases)
- [Commits](https://github.com/helm/helm/compare/v3.14.1...v3.14.2)

---
updated-dependencies:
- dependency-name: helm.sh/helm/v3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-27 00:21:10 +00:00
Adam Martin
d136d1bfd2 Merge pull request #191 from atanasdinov/cosign-error-code
Exit with status code 1 if cosign is not configured
2024-02-23 08:49:25 -05:00
Atanas Dinov
003560c3b3 Exit with status code 1 if cosign is not configured 2024-02-23 10:39:47 +02:00
Adam Martin
1b9d057f7a Merge pull request #188 from amartin120/registry-flag
add registry flag to sync cli to match annotation functionality
2024-02-22 08:57:44 -05:00
Adam Martin
2764e2d3ea Merge pull request #187 from amartin120/fix-exitcode
fix exit code on error
2024-02-22 08:57:31 -05:00
Zack Brady
360049fe19 reverting changes for logos (#189) 2024-02-21 14:35:07 -07:00
Brandon
79b240d17f Merge pull request #186 from rancherfederal/bdev
adding graphics to README.md
2024-02-20 06:50:36 -05:00
bgulla
214704bcfb adding graphics 2024-02-20 06:46:51 -05:00
Adam Martin
ef73fff01a fix exit code on error
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-02-19 16:45:04 -05:00
Adam Martin
0c6fdc86da add registry flag to cli for sync 2024-02-19 10:10:47 -05:00
Zack Brady
7fb537a31a merge pull request #184 from zackbradys/main
updated `readme` and `install.sh` for hauler `v1.0.0`
2024-02-17 22:12:44 -05:00
Zack Brady
6ca7fb6255 updated readme and removed roadmap 2024-02-17 15:00:59 -05:00
Zack Brady
d70a867283 updated/cleaned up install.sh 2024-02-17 10:53:10 -05:00
Adam Martin
46ea8b5df9 Merge pull request #180 from amartin120/remove-deprecated-cmds
remove deprecated commands
2024-02-17 09:09:05 -05:00
Adam Martin
5592ec0f88 remove deprecated commands
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-02-16 09:10:29 -05:00
Adam Martin
e8254371c0 Merge pull request #177 from amartin120/add-login
add login command
2024-02-16 08:16:58 -05:00
Adam Martin
8d2a84d27c Merge pull request #179 from rancherfederal/dependabot/go_modules/helm.sh/helm/v3-3.14.1
Bump helm.sh/helm/v3 from 3.14.0 to 3.14.1
2024-02-16 08:14:00 -05:00
Adam Martin
72734ecc76 Merge pull request #178 from amartin120/bug-file-name
bug-fix: handle complex file names
2024-02-16 08:13:28 -05:00
dependabot[bot]
4759879a5d Bump helm.sh/helm/v3 from 3.14.0 to 3.14.1
Bumps [helm.sh/helm/v3](https://github.com/helm/helm) from 3.14.0 to 3.14.1.
- [Release notes](https://github.com/helm/helm/releases)
- [Commits](https://github.com/helm/helm/compare/v3.14.0...v3.14.1)

---
updated-dependencies:
- dependency-name: helm.sh/helm/v3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-16 04:48:57 +00:00
Adam Martin
dbcfe13fb6 bug-fix: handle complex file names
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-02-15 19:55:38 -05:00
Adam Martin
cd8d4f6e46 add login command
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-02-15 15:54:23 -05:00
Adam Martin
e15c8d54fa Merge pull request #176 from amartin120/info-totals
update to add size totals and cosign artifacts to the `info` command
2024-02-15 12:39:17 -05:00
Adam Martin
ccd529ab48 update to add size totals and cosign bits to the info command
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-02-14 13:03:36 -05:00
Adam Martin
3cf4afe6d1 Merge pull request #173 from amartin120/sync-annotations
image spec manifest annotations - key/platform/registry
2024-02-12 13:10:13 -05:00
Adam Martin
0c55d00d49 switch the 'apply the registry override first in a image sync
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-02-11 10:58:31 -05:00
Adam Martin
6c2b97042e switch the 'not a multi-arch image' log message to be debug
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-02-11 10:37:40 -05:00
Adam Martin
be22e56f27 fix whitspace issue
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-02-10 23:32:42 -05:00
Adam Martin
c8ea279c0d add better logging for save
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-02-10 23:30:34 -05:00
Adam Martin
59ff02b52b add annotations for registry
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-02-10 22:38:11 -05:00
Adam Martin
8b3398018a add annotations for key and platform
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-02-10 21:07:29 -05:00
Adam Martin
ae80b482e4 Merge pull request #168 from amartin120/dep-updates
dependency bumps for security vuln fixes
2024-01-30 16:51:48 -05:00
Adam Martin
1ae496fb8b dep bumps for security vuln fixes
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-01-30 14:41:33 -05:00
Adam Martin
7919dccffc Merge pull request #167 from amartin120/prerelease-flag
release process checks tag to determine pre-release
2024-01-30 11:11:13 -05:00
Adam Martin
fc7a19c755 check tag to determine pre-release
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-01-30 10:57:40 -05:00
Adam Martin
ade0feccf0 Merge pull request #166 from clemenko/main
Update install.sh for file cleaning
2024-01-30 09:04:41 -05:00
Andy Clemenko
f78fdf5e3d Update install.sh
adding the old hauler binary to the cleanup
2024-01-30 08:55:57 -05:00
Andy Clemenko
85d6bc0233 Update install.sh for file cleaning
removing LICENSE and README.md files.
2024-01-30 08:41:07 -05:00
Adam Martin
d1499b7738 Merge pull request #164 from amartin120/cosign-updates
Add `--platform` flag to image processes and RGS flavored cosign setup improvement.
2024-01-29 14:46:18 -05:00
Adam Martin
27acb239e4 clean up makefile 2024-01-29 13:41:53 -05:00
Adam Martin
e8d084847d remove extra debug statement
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-01-28 21:15:27 -05:00
Adam Martin
e70379870f another fix for the unit test gh action
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-01-28 19:51:22 -05:00
Adam Martin
a05d21c052 add platform flag for image add and sync
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-01-28 19:48:16 -05:00
Adam Martin
8256aa55ce adjust unit test gh action for latest updates 2024-01-28 19:46:55 -05:00
Adam Martin
0e6c3690b1 bump cosign version to v2.2.2+carbide.2 2024-01-28 19:45:05 -05:00
Adam Martin
a977cec50c improve cosign setup
Signed-off-by: Adam Martin <adam.martin@rancherfederal.com>
2024-01-28 12:08:31 -05:00
Adam Martin
5edc96d152 Merge pull request #162 from zackbradys/main
updated archive default name
2024-01-24 09:19:48 -05:00
Zack Hodgson Brady
fbafa60da5 updated archive default name 2024-01-23 22:49:20 -05:00
Adam Martin
cc917af0f2 Merge pull request #159 from amartin120/store-fileserver
Store fileserver
2024-01-22 15:12:45 -05:00
Adam Martin
f76160d8be Merge pull request #160 from amartin120/add-license
add license file
2024-01-22 15:12:05 -05:00
Adam Martin
b24b25d557 add license file 2024-01-22 15:06:09 -05:00
Adam Martin
d9e298b725 adjust to make registry and fileserver subcommands 2024-01-22 13:40:58 -05:00
Adam Martin
e14453f730 add fileserver option for store serve 2024-01-22 11:31:46 -05:00
Zack Brady
990ade9cd0 merge pull request #152 from zackbradys/main
updated readme and hauler `install.sh`
2023-12-20 19:56:57 -05:00
Zack Hodgson Brady
aecd37d192 added homebrew install instructions 2023-12-20 19:46:55 -05:00
Zack Brady
02f4946ead Merge branch 'rancherfederal:main' into main 2023-12-20 00:31:44 -05:00
Zack Hodgson Brady
978dc659f8 updated hauler version and automated default version 2023-12-19 21:24:04 -05:00
77 changed files with 1956 additions and 1427 deletions

8
.dockerignore Normal file
View File

@@ -0,0 +1,8 @@
*
!cmd
!go.mod
!go.sum
!internal
!Makefile
!pkg
!static

View File

@@ -2,32 +2,50 @@
name: Bug Report
about: Create a report to help us improve!
title: '[BUG]'
labels: 'kind/bug'
labels: 'bug'
assignees: ''
---
<!-- Thank you for helping us to improve Hauler! We welcome all bug reports. Please fill out each area of the template so we can better help you. Comments like this will be hidden when you post but you can delete them if you wish. -->
<!-- Thank you for helping us to improve Hauler! We welcome all bug reports. Please fill out each area of the template so we can better assist you. Comments like this will be hidden when you submit, but you can delete them if you wish. -->
**Environmental Info:**
*
<!-- Provide the output of "uname -a" -->
-
**Hauler Version:**
*
**System CPU architecture, OS, and Version:**
* <!-- Provide the output from "uname -a" on the system where Hauler is installed -->
<!-- Provide the output of "hauler version" -->
**Describe the bug:**
* <!-- A clear and concise description of the bug. -->
-
**Steps To Reproduce:**
* <!-- A clear and concise way to reproduce the bug. -->
**Describe the Bug:**
**Expected behavior:**
* <!-- A clear and concise description of what you expected to happen, without the bug. -->
<!-- Provide a clear and concise description of the bug -->
**Actual behavior:**
* <!-- A clear and concise description of what actually happened. -->
-
**Additional context / logs:**
* <!-- Add any other context and/or logs about the problem here. -->
**Steps to Reproduce:**
<!-- Provide a clear and concise way to reproduce the bug -->
-
**Expected Behavior:**
<!-- Provide a clear and concise description of what you expected to happen -->
-
**Actual Behavior:**
<!-- Provide a clear and concise description of what actually happens -->
-
**Additional Context:**
<!-- Provide any other context and/or logs about the bug -->
-

View File

@@ -1,21 +1,33 @@
---
name: Feature Request
about: Create a report to help us improve!
about: Submit a request for us to improve!
title: '[RFE]'
labels: 'kind/rfe'
labels: 'enhancement'
assignees: ''
---
<!-- Thanks for helping us to improve Hauler! We welcome all requests for enhancements (RFEs). Please fill out each area of the template so we can better help you. Comments like this will be hidden when you post but you can delete them if you wish. -->
<!-- Thank you for helping us to improve Hauler! We welcome all requests for enhancements (RFEs). Please fill out each area of the template so we can better assist you. Comments like this will be hidden when you submit, but you can delete them if you wish. -->
**Is your feature request related to a problem? Please describe.**
* <!-- A clear and concise description of the problem. -->
**Is this RFE related to an Existing Problem? If so, please describe:**
**Describe the solution you'd like**
* <!-- A clear and concise description of what you want to happen. -->
<!-- Provide a clear and concise description of the problem -->
**Describe alternatives you've considered**
* <!-- A clear and concise description of any alternative solutions or features you've considered. -->
-
**Additional context**
* <!-- Add any other context or screenshots about the feature request here. -->
**Describe Proposed Solution(s):**
<!-- Provide a clear and concise description of what you want to happen -->
-
**Describe Possible Alternatives:**
<!-- Provide a clear and concise description of any alternative solutions or features you've considered -->
-
**Additional Context:**
<!-- Provide a clear and concise description of the problem -->
-

View File

@@ -1,20 +1,36 @@
**Please check below, if the PR fulfills these requirements:**
- [ ] The commit message follows the guidelines.
- [ ] Tests for the changes have been added (for bug fixes / features).
- [ ] Docs have been added / updated (for bug fixes / features).
- [ ] Commit(s) and code follow the repositories guidelines.
- [ ] Test(s) have been added or updated to support these change(s).
- [ ] Doc(s) have been added or updated to support these change(s).
<!-- Comments like this will be hidden when you submit, but you can delete them if you wish. -->
**What kind of change does this PR introduce?**
* <!-- Bug fix, feature, docs update, ... -->
**Associated Links:**
**What is the current behavior?**
* <!-- You can also link to an open issue here -->
<!-- Provide any associated or linked related to these change(s) -->
**What is the new behavior (if this is a feature change)?**
* <!-- What changes did this PR introduce? -->
-
**Does this PR introduce a breaking change?**
* <!-- What changes might users need to make in their application due to this PR? -->
**Types of Changes:**
**Other information**:
* <!-- Any additional information -->
<!-- What is the type of change? Bugfix, Feature, Breaking Change, etc... -->
-
**Proposed Changes:**
<!-- Provide the high level and low level description of your change(s) so we can better understand these change(s) -->
-
**Verification/Testing of Changes:**
<!-- How can the changes be verified? Provide the steps necessary to reproduce and verify the proposed change(s) -->
-
**Additional Context:**
<!-- Provide any additional information, such as if this is a small or large or complex change. Feel free to kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc... -->
-

View File

@@ -1,30 +1,64 @@
name: CI
name: Release Workflow
on:
workflow_dispatch:
push:
tags:
tags:
- '*'
jobs:
goreleaser:
go-release:
name: Go Release Job
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v2
- name: Set Up Go
uses: actions/setup-go@v5
with:
go-version: 1.21.x
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2
- name: Run Go Releaser
uses: goreleaser/goreleaser-action@v5
with:
distribution: goreleaser
version: latest
args: release --rm-dist
args: release --clean -p 1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}
container-release:
name: Container Release Job
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set Up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and Push to GitHub Container Registry
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ghcr.io/${{ github.repository }}:${{ github.ref_name }}

View File

@@ -1,39 +1,37 @@
name: Unit Test
name: Unit Test Workflow
on:
workflow_dispatch:
push:
paths-ignore:
- "**.md"
- ".github/**"
- "!.github/workflows/unittest.yaml"
branches:
- main
pull_request:
paths-ignore:
- "**.md"
- ".github/**"
- "!.github/workflows/unitcoverage.yaml"
workflow_dispatch: {}
branches:
- main
jobs:
test:
unit-test:
name: Unit Tests
runs-on: ubuntu-latest
timeout-minutes: 20
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Go
uses: actions/setup-go@v2
- name: Set Up Go
uses: actions/setup-go@v5
with:
go-version: 1.21.x
- name: Run Unit Tests
run: |
mkdir -p cmd/hauler/binaries
touch cmd/hauler/binaries/dummy.txt
go test -race -covermode=atomic -coverprofile=coverage.out ./pkg/... ./internal/... ./cmd/...
- name: On Failure, Launch Debug Session
if: ${{ failure() }}
uses: mxschmitt/action-tmate@v3
timeout-minutes: 5
- name: Upload Results To Codecov
uses: codecov/codecov-action@v1
with:
files: ./coverage.out
verbose: true # optional (default = false)
timeout-minutes: 10

7
.gitignore vendored
View File

@@ -18,13 +18,10 @@ artifacts
local-artifacts
airgap-scp.sh
# test artifacts
*.tar*
*.out
# generated
dist/
tmp/
bin/
/store/
/registry/
/registry/
cmd/hauler/binaries

View File

@@ -3,9 +3,14 @@ before:
hooks:
- go mod tidy
- go mod download
- rm -rf cmd/hauler/binaries
release:
prerelease: auto
env:
- vpkg=github.com/rancherfederal/hauler/internal/version
- cosign_version=v2.2.3+carbide.1
builds:
- main: cmd/hauler/main.go
@@ -18,6 +23,12 @@ builds:
- arm64
ldflags:
- -s -w -X {{ .Env.vpkg }}.gitVersion={{ .Version }} -X {{ .Env.vpkg }}.gitCommit={{ .ShortCommit }} -X {{ .Env.vpkg }}.gitTreeState={{if .IsGitDirty}}dirty{{else}}clean{{end}} -X {{ .Env.vpkg }}.buildDate={{ .Date }}
hooks:
pre:
- mkdir -p cmd/hauler/binaries
- wget -P cmd/hauler/binaries/ https://github.com/rancher-government-carbide/cosign/releases/download/{{ .Env.cosign_version }}/cosign-{{ .Os }}-{{ .Arch }}{{ if eq .Os "windows" }}.exe{{ end }}
post:
- rm -rf cmd/hauler/binaries
env:
- CGO_ENABLED=0

25
Dockerfile Normal file
View File

@@ -0,0 +1,25 @@
FROM registry.suse.com/bci/golang:1.21 AS builder
RUN zypper --non-interactive install make bash wget ca-certificates
COPY . /build
WORKDIR /build
RUN make build
RUN echo "hauler:x:1001:1001::/home:" > /etc/passwd \
&& echo "hauler:x:1001:hauler" > /etc/group \
&& mkdir /store \
&& mkdir /fileserver \
&& mkdir /registry
FROM scratch
COPY --from=builder /var/lib/ca-certificates/ca-bundle.pem /etc/ssl/certs/ca-certificates.crt
COPY --from=builder /etc/passwd /etc/passwd
COPY --from=builder /etc/group /etc/group
COPY --from=builder --chown=hauler:hauler /home/. /home
COPY --from=builder --chown=hauler:hauler /tmp/. /tmp
COPY --from=builder --chown=hauler:hauler /store/. /store
COPY --from=builder --chown=hauler:hauler /registry/. /registry
COPY --from=builder --chown=hauler:hauler /fileserver/. /fileserver
COPY --from=builder --chown=hauler:hauler /build/bin/hauler /
USER hauler
ENTRYPOINT [ "/hauler" ]

177
LICENSE Normal file
View File

@@ -0,0 +1,177 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@@ -1,23 +1,27 @@
SHELL:=/bin/bash
GO_BUILD_ENV=GOOS=linux GOARCH=amd64
GO_FILES=$(shell go list ./... | grep -v /vendor/)
BUILD_VERSION=$(shell cat VERSION)
BUILD_TAG=$(BUILD_VERSION)
COSIGN_VERSION=v2.2.3+carbide.1
.SILENT:
all: fmt vet install test
build:
rm -rf cmd/hauler/binaries;\
mkdir -p cmd/hauler/binaries;\
wget -P cmd/hauler/binaries/ https://github.com/rancher-government-carbide/cosign/releases/download/$(COSIGN_VERSION)/cosign-$(shell go env GOOS)-$(shell go env GOARCH);\
mkdir bin;\
GOENV=GOARCH=$(uname -m) CGO_ENABLED=0 go build -o bin ./cmd/...;\
CGO_ENABLED=0 go build -o bin ./cmd/...;\
build-all: fmt vet
goreleaser build --rm-dist --snapshot
install:
GOENV=GOARCH=$(uname -m) CGO_ENABLED=0 go install ./cmd/...;\
rm -rf cmd/hauler/binaries;\
mkdir -p cmd/hauler/binaries;\
wget -P cmd/hauler/binaries/ https://github.com/rancher-government-carbide/cosign/releases/download/$(COSIGN_VERSION)/cosign-$(shell go env GOOS)-$(shell go env GOARCH);\
CGO_ENABLED=0 go install ./cmd/...;\
vet:
go vet $(GO_FILES)

View File

@@ -1,32 +1,36 @@
# Rancher Government Hauler
![rancher-government-hauler-logo](/static/rgs-hauler-logo.png)
## Airgap Swiss Army Knife
> ⚠️ This project is still in active development and *not* Generally Available (GA). Most of the core functionality and features are ready, but may have breaking changes. Please review the [Release Notes](https://github.com/rancherfederal/hauler/releases) for more information!
> ⚠️ **Please Note:** Hauler and the Hauler Documentation are recently Generally Available (GA).
`Rancher Government Hauler` simplifies the airgap experience without requiring users to adopt a specific workflow. **Hauler** simplifies the airgapping process, by representing assets (images, charts, files, etc...) as content and collections to allow users to easily fetch, store, package, and distribute these assets with declarative manifests or through the command line.
`Rancher Government Hauler` simplifies the airgap experience without requiring operators to adopt a specific workflow. **Hauler** simplifies the airgapping process, by representing assets (images, charts, files, etc...) as content and collections to allow operators to easily fetch, store, package, and distribute these assets with declarative manifests or through the command line.
`Hauler` does this by storing contents and collections as OCI Artifacts and allows users to serve contents and collections with an embedded registry and fileserver. Additionally, `Hauler` has the ability to store and inspect various non-image OCI Artifacts.
`Hauler` does this by storing contents and collections as OCI Artifacts and allows operators to serve contents and collections with an embedded registry and fileserver. Additionally, `Hauler` has the ability to store and inspect various non-image OCI Artifacts.
For more information, please review the **[Hauler Documentation](https://rancherfederal.github.io/hauler-docs)!**
## Installation
### Linux/Darwin
```bash
# install latest release
# installs latest release
curl -sfL https://get.hauler.dev | bash
# install specific release
curl -sfL https://get.hauler.dev | HAULER_VERSION=0.4.1 bash
```
### Windows
```bash
# coming soon
```
### Homebrew
```bash
# installs latest release
brew tap rancherfederal/homebrew-tap
brew install hauler
```
### Windows
```bash
# coming soon
```
@@ -34,11 +38,7 @@ curl -sfL https://get.hauler.dev | HAULER_VERSION=0.4.1 bash
## Acknowledgements
`Hauler` wouldn't be possible without the open-source community, but there are a few projects that stand out:
* [go-containerregistry](https://github.com/google/go-containerregistry)
* [oras cli](https://github.com/oras-project/oras)
* [cosign](https://github.com/sigstore/cosign)
## Notices
**WARNING - Upcoming Deprecated Command(s):**
`hauler download` (alternatively, `dl`) and `hauler serve` (_not_ `hauler store serve`) commands are deprecated and will be removed in a future release.
- [oras cli](https://github.com/oras-project/oras)
- [cosign](https://github.com/sigstore/cosign)
- [go-containerregistry](https://github.com/google/go-containerregistry)

View File

@@ -1,50 +0,0 @@
# Hauler Roadmap
## \> v0.2.0
- Leverage `referrers` api to robustly link content/collection
- Support signing for all `artifact.OCI` contents
- Support encryption for `artifact.OCI` layers
- Support incremental updates to stores (some implementation of layer diffing)
- Safely embed container runtime for user created `collections` creation and transformation
- Better defaults/configuration/security around for long-lived embedded registry
- Better support multi-platform content
- Better leverage `oras` (`>=0.5.0`) for content relocation
- Store git repos as CAS in OCI format
## v0.2.0 - MVP 2
- Re-focus on cli and framework for oci content fetching and delivery
- Focus on initial key contents
- Files (local/remote)
- Charts (local/remote)
- Images
- Establish framework for `content` and `collections`
- Define initial `content` types (`file`, `chart`, `image`)
- Define initial `collection` types (`thickchart`, `k3s`)
- Define framework for manipulating OCI content (`artifact.OCI`, `artifact.Collection`)
## v0.1.0 - MVP 1
- Install single-node k3s cluster
- Support tarball and rpm installation methods
- Target narrow set of known Operating Systems to have OS-specific code if needed
- Serve container images
- Collect images from image list file
- Collect images from image archives
- Deploy docker registry
- Populate registry with all images
- Serve git repositories
- Collect repos
- Deploy git server (Caddy? NGINX?)
- Populate git server with repos
- Serve files
- Collect files from directory, including subdirectories
- Deploy caddy file server
- Populate file server with directory contents
- NOTE: "generic" option - most other use cases can be satisfied by a specially crafted file
server directory
## v0.0.x
- Install single-node k3s cluster into an Ubuntu machine using the tarball installation method

View File

@@ -1,49 +0,0 @@
## Hauler Vagrant machine
A Vagrantfile is provided to allow easy provisioning of a local air-gapped CentOS environment. Some artifacts need to be collected from the internet; below are the steps required for successfully provisioning this machine, downloading all dependencies, and installing k3s (without hauler) into this machine.
### First-time setup
1. Install vagrant, if needed: <https://www.vagrantup.com/downloads>
2. Install `vagrant-vbguest` plugin, as noted in the Vagrantfile:
```shell
vagrant plugin install vagrant-vbguest
```
3. Deploy Vagrant machine, disabling SELinux:
```shell
SELINUX=Disabled vagrant up
```
4. Access the Vagrant machine via SSH:
```shell
vagrant ssh
```
5. Run all prep scripts inside of the Vagrant machine:
> This script temporarily enables internet access from within the VM to allow downloading all dependencies. Even so, the air-gapped network configuration IS restored before completion.
```shell
sudo /opt/hauler/vagrant-scripts/prep-all.sh
```
All dependencies for all `vagrant-scripts/*-install.sh` scripts are now downloaded to the local
repository under `local-artifacts`.
### Installing k3s manually
1. Access the Vagrant machine via SSH:
```bash
vagrant ssh
```
2. Run the k3s install script inside of the Vagrant machine:
```shell
sudo /opt/hauler/vagrant-scripts/k3s-install.sh
```
### Installing RKE2 manually
1. Access the Vagrant machine via SSH:
```shell
vagrant ssh
```
2. Run the RKE2 install script inside of the Vagrant machine:
```shell
sudo /opt/hauler/vagrant-scripts/rke2-install.sh
```

65
Vagrantfile vendored
View File

@@ -1,65 +0,0 @@
##################################
# The vagrant-vbguest plugin is required for CentOS 7.
# Run the following command to install/update this plugin:
# vagrant plugin install vagrant-vbguest
##################################
Vagrant.configure("2") do |config|
config.vm.box = "centos/8"
config.vm.hostname = "airgap"
config.vm.network "private_network", type: "dhcp"
config.vm.synced_folder ".", "/vagrant"
config.vm.provider "virtualbox" do |vb|
vb.memory = "2048"
vb.cpus = "2"
config.vm.provision "airgap", type: "shell", run: "always",
inline: "/vagrant/vagrant-scripts/airgap.sh airgap"
end
# SELinux is Enforcing by default.
# To set SELinux as Disabled on a VM that has already been provisioned:
# SELINUX=Disabled vagrant up --provision-with=selinux
# To set SELinux as Permissive on a VM that has already been provsioned
# SELINUX=Permissive vagrant up --provision-with=selinux
config.vm.provision "selinux", type: "shell", run: "once" do |sh|
sh.upload_path = "/tmp/vagrant-selinux"
sh.env = {
'SELINUX': ENV['SELINUX'] || "Enforcing"
}
sh.inline = <<~SHELL
#!/usr/bin/env bash
set -eux -o pipefail
if ! type -p getenforce setenforce &>/dev/null; then
echo SELinux is Disabled
exit 0
fi
case "${SELINUX}" in
Disabled)
if mountpoint -q /sys/fs/selinux; then
setenforce 0
umount -v /sys/fs/selinux
fi
;;
Enforcing)
mountpoint -q /sys/fs/selinux || mount -o rw,relatime -t selinuxfs selinuxfs /sys/fs/selinux
setenforce 1
;;
Permissive)
mountpoint -q /sys/fs/selinux || mount -o rw,relatime -t selinuxfs selinuxfs /sys/fs/selinux
setenforce 0
;;
*)
echo "SELinux mode not supported: ${SELINUX}" >&2
exit 1
;;
esac
echo SELinux is $(getenforce)
SHELL
end
end

View File

@@ -31,9 +31,8 @@ func New() *cobra.Command {
pf.StringVarP(&ro.logLevel, "log-level", "l", "info", "")
// Add subcommands
addDownload(cmd)
addLogin(cmd)
addStore(cmd)
addServe(cmd)
addVersion(cmd)
addCompletion(cmd)

View File

@@ -1,45 +0,0 @@
package cli
import (
"github.com/spf13/cobra"
"github.com/rancherfederal/hauler/cmd/hauler/cli/download"
)
func addDownload(parent *cobra.Command) {
o := &download.Opts{}
cmd := &cobra.Command{
Use: "download",
Short: "Download OCI content from a registry and populate it on disk",
Long: `*** WARNING: Deprecated Command ***
The 'download (dl)' command is deprecated and will be removed in a future release of Hauler.
Locate OCI content based on it's reference in a compatible registry and download the contents to disk.
Note that the content type determines it's format on disk. Hauler's built in content types act as follows:
- File: as a file named after the pushed contents source name (ex: my-file.yaml:latest --> my-file.yaml)
- Image: as a .tar named after the image (ex: alpine:latest --> alpine:latest.tar)
- Chart: as a .tar.gz named after the chart (ex: loki:2.0.2 --> loki-2.0.2.tar.gz)`,
Example: `
# Download a file
hauler dl localhost:5000/my-file.yaml:latest
# Download an image
hauler dl localhost:5000/rancher/k3s:v1.22.2-k3s2
# Download a chart
hauler dl localhost:5000/hauler/longhorn:1.2.0`,
Aliases: []string{"dl"},
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, arg []string) error {
ctx := cmd.Context()
return download.Cmd(ctx, o, arg[0])
},
}
o.AddArgs(cmd)
parent.AddCommand(cmd)
}

View File

@@ -1,87 +0,0 @@
package download
import (
"context"
"encoding/json"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/v1/remote"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/spf13/cobra"
"oras.land/oras-go/pkg/content"
"oras.land/oras-go/pkg/oras"
"github.com/rancherfederal/hauler/pkg/consts"
"github.com/rancherfederal/hauler/internal/mapper"
"github.com/rancherfederal/hauler/pkg/log"
"github.com/rancherfederal/hauler/pkg/reference"
)
type Opts struct {
DestinationDir string
Username string
Password string
Insecure bool
PlainHTTP bool
}
func (o *Opts) AddArgs(cmd *cobra.Command) {
f := cmd.Flags()
f.StringVarP(&o.DestinationDir, "output", "o", "", "Directory to save contents to (defaults to current directory)")
f.StringVarP(&o.Username, "username", "u", "", "Username when copying to an authenticated remote registry")
f.StringVarP(&o.Password, "password", "p", "", "Password when copying to an authenticated remote registry")
f.BoolVar(&o.Insecure, "insecure", false, "Toggle allowing insecure connections when copying to a remote registry")
f.BoolVar(&o.PlainHTTP, "plain-http", false, "Toggle allowing plain http connections when copying to a remote registry")
}
func Cmd(ctx context.Context, o *Opts, ref string) error {
l := log.FromContext(ctx)
ropts := content.RegistryOptions{
Username: o.Username,
Password: o.Password,
Insecure: o.Insecure,
PlainHTTP: o.PlainHTTP,
}
rs, err := content.NewRegistry(ropts)
if err != nil {
return err
}
r, err := reference.Parse(ref)
if err != nil {
return err
}
desc, err := remote.Get(r, remote.WithAuthFromKeychain(authn.DefaultKeychain), remote.WithContext(ctx))
if err != nil {
return err
}
manifestData, err := desc.RawManifest()
if err != nil {
return err
}
var manifest ocispec.Manifest
if err := json.Unmarshal(manifestData, &manifest); err != nil {
return err
}
mapperStore, err := mapper.FromManifest(manifest, o.DestinationDir)
if err != nil {
return err
}
pushedDesc, err := oras.Copy(ctx, rs, r.Name(), mapperStore, "",
oras.WithAdditionalCachedMediaTypes(consts.DockerManifestSchema2))
if err != nil {
return err
}
l.Infof("downloaded [%s] with digest [%s]", pushedDesc.MediaType, pushedDesc.Digest.String())
return nil
}

75
cmd/hauler/cli/login.go Normal file
View File

@@ -0,0 +1,75 @@
package cli
import (
"context"
"strings"
"os"
"io"
"fmt"
"github.com/spf13/cobra"
"oras.land/oras-go/pkg/content"
"github.com/rancherfederal/hauler/pkg/cosign"
)
type Opts struct {
Username string
Password string
PasswordStdin bool
}
func (o *Opts) AddArgs(cmd *cobra.Command) {
f := cmd.Flags()
f.StringVarP(&o.Username, "username", "u", "", "Username")
f.StringVarP(&o.Password, "password", "p", "", "Password")
f.BoolVarP(&o.PasswordStdin, "password-stdin", "", false, "Take the password from stdin")
}
func addLogin(parent *cobra.Command) {
o := &Opts{}
cmd := &cobra.Command{
Use: "login",
Short: "Log in to a registry",
Example: `
# Log in to reg.example.com
hauler login reg.example.com -u bob -p haulin`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, arg []string) error {
ctx := cmd.Context()
if o.PasswordStdin {
contents, err := io.ReadAll(os.Stdin)
if err != nil {
return err
}
o.Password = strings.TrimSuffix(string(contents), "\n")
o.Password = strings.TrimSuffix(o.Password, "\r")
}
if o.Username == "" && o.Password == "" {
return fmt.Errorf("username and password required")
}
return login(ctx, o, arg[0])
},
}
o.AddArgs(cmd)
parent.AddCommand(cmd)
}
func login(ctx context.Context, o *Opts, registry string) error {
ropts := content.RegistryOptions{
Username: o.Username,
Password: o.Password,
}
err := cosign.RegistryLogin(ctx, nil, registry, ropts)
if err != nil {
return err
}
return nil
}

View File

@@ -1,57 +0,0 @@
package cli
import (
"github.com/spf13/cobra"
"github.com/rancherfederal/hauler/cmd/hauler/cli/serve"
)
func addServe(parent *cobra.Command) {
cmd := &cobra.Command{
Use: "serve",
Short: "Run one or more of hauler's embedded servers types",
Long: `*** WARNING: Deprecated Command ***
The 'serve' command is deprecated and will be removed in a future release of Hauler.`,
RunE: func(cmd *cobra.Command, args []string) error {
return cmd.Help()
},
}
cmd.AddCommand(
addServeFiles(),
addServeRegistry(),
)
parent.AddCommand(cmd)
}
func addServeFiles() *cobra.Command {
o := &serve.FilesOpts{}
cmd := &cobra.Command{
Use: "files",
Short: "Start a fileserver",
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
return serve.FilesCmd(ctx, o)
},
}
o.AddFlags(cmd)
return cmd
}
func addServeRegistry() *cobra.Command {
o := &serve.RegistryOpts{}
cmd := &cobra.Command{
Use: "registry",
Short: "Start a registry",
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
return serve.RegistryCmd(ctx, o)
},
}
o.AddFlags(cmd)
return cmd
}

View File

@@ -1,37 +0,0 @@
package serve
import (
"context"
"github.com/spf13/cobra"
"github.com/rancherfederal/hauler/internal/server"
)
type FilesOpts struct {
Root string
Port int
}
func (o *FilesOpts) AddFlags(cmd *cobra.Command) {
f := cmd.Flags()
f.StringVarP(&o.Root, "root", "r", ".", "Path to root of the directory to serve")
f.IntVarP(&o.Port, "port", "p", 8080, "Port to listen on")
}
func FilesCmd(ctx context.Context, o *FilesOpts) error {
cfg := server.FileConfig{
Root: o.Root,
Port: o.Port,
}
s, err := server.NewFile(ctx, cfg)
if err != nil {
return err
}
if err := s.ListenAndServe(); err != nil {
return err
}
return nil
}

View File

@@ -1,81 +0,0 @@
package serve
import (
"context"
"fmt"
"net/http"
"os"
"github.com/distribution/distribution/v3/configuration"
dcontext "github.com/distribution/distribution/v3/context"
"github.com/distribution/distribution/v3/version"
"github.com/spf13/cobra"
"github.com/rancherfederal/hauler/internal/server"
)
type RegistryOpts struct {
Root string
Port int
ConfigFile string
}
func (o *RegistryOpts) AddFlags(cmd *cobra.Command) {
f := cmd.Flags()
f.StringVarP(&o.Root, "root", "r", ".", "Path to root of the directory to serve")
f.IntVarP(&o.Port, "port", "p", 5000, "Port to listen on")
f.StringVarP(&o.ConfigFile, "config", "c", "", "Path to a config file, will override all other configs")
}
func RegistryCmd(ctx context.Context, o *RegistryOpts) error {
ctx = dcontext.WithVersion(ctx, version.Version)
cfg := o.defaultConfig()
if o.ConfigFile != "" {
ucfg, err := loadConfig(o.ConfigFile)
if err != nil {
return err
}
cfg = ucfg
}
s, err := server.NewRegistry(ctx, cfg)
if err != nil {
return err
}
if err := s.ListenAndServe(); err != nil {
return err
}
return nil
}
func loadConfig(filename string) (*configuration.Configuration, error) {
f, err := os.Open(filename)
if err != nil {
return nil, err
}
return configuration.Parse(f)
}
func (o *RegistryOpts) defaultConfig() *configuration.Configuration {
cfg := &configuration.Configuration{
Version: "0.1",
Storage: configuration.Storage{
"cache": configuration.Parameters{"blobdescriptor": "inmemory"},
"filesystem": configuration.Parameters{"rootdirectory": o.Root},
// TODO: Ensure this is toggleable via cli arg if necessary
// "maintenance": configuration.Parameters{"readonly.enabled": false},
},
}
cfg.Log.Level = "info"
cfg.HTTP.Addr = fmt.Sprintf(":%d", o.Port)
cfg.HTTP.Headers = http.Header{
"X-Content-Type-Options": []string{"nosniff"},
"Accept": []string{"application/vnd.dsse.envelope.v1+json, application/json"},
}
return cfg
}

View File

@@ -108,12 +108,28 @@ func addStoreLoad() *cobra.Command {
}
func addStoreServe() *cobra.Command {
o := &store.ServeOpts{RootOpts: rootStoreOpts}
cmd := &cobra.Command{
Use: "serve",
Short: "Expose the content of a local store through an OCI compliant server",
Short: "Expose the content of a local store through an OCI compliant registry or file server",
RunE: func(cmd *cobra.Command, args []string) error {
return cmd.Help()
},
}
cmd.AddCommand(
addStoreServeRegistry(),
addStoreServeFiles(),
)
return cmd
}
// RegistryCmd serves the embedded registry
func addStoreServeRegistry() *cobra.Command {
o := &store.ServeRegistryOpts{RootOpts: rootStoreOpts}
cmd := &cobra.Command{
Use: "registry",
Short: "Serve the embedded registry",
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
s, err := o.Store(ctx)
@@ -121,12 +137,36 @@ func addStoreServe() *cobra.Command {
return err
}
return store.ServeCmd(ctx, o, s)
},
}
o.AddFlags(cmd)
return store.ServeRegistryCmd(ctx, o, s)
},
}
return cmd
o.AddFlags(cmd)
return cmd
}
// FileServerCmd serves the file server
func addStoreServeFiles() *cobra.Command {
o := &store.ServeFilesOpts{RootOpts: rootStoreOpts}
cmd := &cobra.Command{
Use: "fileserver",
Short: "Serve the file server",
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
s, err := o.Store(ctx)
if err != nil {
return err
}
return store.ServeFilesCmd(ctx, o, s)
},
}
o.AddFlags(cmd)
return cmd
}
func addStoreSave() *cobra.Command {
@@ -156,7 +196,7 @@ func addStoreSave() *cobra.Command {
func addStoreInfo() *cobra.Command {
o := &store.InfoOpts{RootOpts: rootStoreOpts}
var allowedValues = []string{"image", "chart", "file", "all"}
var allowedValues = []string{"image", "chart", "file", "sigs", "atts", "sbom", "all"}
cmd := &cobra.Command{
Use: "info",

View File

@@ -33,7 +33,9 @@ func AddFileCmd(ctx context.Context, o *AddFileOpts, s *store.Layout, reference
cfg := v1alpha1.File{
Path: reference,
}
if len(o.Name) > 0 {
cfg.Name = o.Name
}
return storeFile(ctx, s, cfg)
}
@@ -50,24 +52,28 @@ func storeFile(ctx context.Context, s *store.Layout, fi v1alpha1.File) error {
return err
}
desc, err := s.AddOCI(ctx, f, ref.Name())
l.Infof("adding 'file' [%s] to the store as [%s]", fi.Path, ref.Name())
_, err = s.AddOCI(ctx, f, ref.Name())
if err != nil {
return err
}
l.Infof("added 'file' to store at [%s], with digest [%s]", ref.Name(), desc.Digest.String())
l.Infof("successfully added 'file' [%s]", ref.Name())
return nil
}
type AddImageOpts struct {
*RootOpts
Name string
Key string
Name string
Key string
Platform string
}
func (o *AddImageOpts) AddFlags(cmd *cobra.Command) {
f := cmd.Flags()
f.StringVarP(&o.Key, "key", "k", "", "(Optional) Path to the key for digital signature verification")
f.StringVarP(&o.Platform, "platform", "p", "", "(Optional) Specific platform to save. i.e. linux/amd64. Defaults to all if flag is omitted.")
}
func AddImageCmd(ctx context.Context, o *AddImageOpts, s *store.Layout, reference string) error {
@@ -86,23 +92,24 @@ func AddImageCmd(ctx context.Context, o *AddImageOpts, s *store.Layout, referenc
l.Infof("signature verified for image [%s]", cfg.Name)
}
return storeImage(ctx, s, cfg)
return storeImage(ctx, s, cfg, o.Platform)
}
func storeImage(ctx context.Context, s *store.Layout, i v1alpha1.Image) error {
func storeImage(ctx context.Context, s *store.Layout, i v1alpha1.Image, platform string) error {
l := log.FromContext(ctx)
l.Infof("adding 'image' [%s] to the store", i.Name)
r, err := name.ParseReference(i.Name)
if err != nil {
return err
}
err = cosign.SaveImage(ctx, s, r.Name())
err = cosign.SaveImage(ctx, s, r.Name(), platform)
if err != nil {
return err
}
l.Infof("added 'image' to store at [%s]", r.Name())
l.Infof("successfully added 'image' [%s]", r.Name())
return nil
}
@@ -139,7 +146,8 @@ func AddChartCmd(ctx context.Context, o *AddChartOpts, s *store.Layout, chartNam
func storeChart(ctx context.Context, s *store.Layout, cfg v1alpha1.Chart, opts *action.ChartPathOptions) error {
l := log.FromContext(ctx)
l.Infof("adding 'chart' [%s] to the store", cfg.Name)
// TODO: This shouldn't be necessary
opts.RepoURL = cfg.RepoURL
opts.Version = cfg.Version
@@ -158,11 +166,11 @@ func storeChart(ctx context.Context, s *store.Layout, cfg v1alpha1.Chart, opts *
if err != nil {
return err
}
desc, err := s.AddOCI(ctx, chrt, ref.Name())
_, err = s.AddOCI(ctx, chrt, ref.Name())
if err != nil {
return err
}
l.Infof("added 'chart' to store at [%s], with digest [%s]", ref.Name(), desc.Digest.String())
l.Infof("successfully added 'chart' [%s]", ref.Name())
return nil
}

View File

@@ -6,7 +6,6 @@ import (
"os"
"path/filepath"
"github.com/rancherfederal/hauler/pkg/layer"
"github.com/rancherfederal/hauler/pkg/store"
"github.com/spf13/cobra"
@@ -15,7 +14,6 @@ import (
const (
DefaultStoreName = "store"
DefaultCacheDir = "hauler"
)
type RootOpts struct {
@@ -25,8 +23,8 @@ type RootOpts struct {
func (o *RootOpts) AddArgs(cmd *cobra.Command) {
pf := cmd.PersistentFlags()
pf.StringVar(&o.CacheDir, "cache", "", "Location of where to store cache data (defaults to $XDG_CACHE_DIR/hauler)")
pf.StringVarP(&o.StoreDir, "store", "s", DefaultStoreName, "Location to create store at")
pf.StringVar(&o.CacheDir, "cache", "", "(deprecated flag and currently not used)")
}
func (o *RootOpts) Store(ctx context.Context) (*store.Layout, error) {
@@ -48,37 +46,9 @@ func (o *RootOpts) Store(ctx context.Context) (*store.Layout, error) {
return nil, err
}
// TODO: Do we want this to be configurable?
c, err := o.Cache(ctx)
if err != nil {
return nil, err
}
s, err := store.NewLayout(abs, store.WithCache(c))
s, err := store.NewLayout(abs)
if err != nil {
return nil, err
}
return s, nil
}
func (o *RootOpts) Cache(ctx context.Context) (layer.Cache, error) {
dir := o.CacheDir
if dir == "" {
// Default to $XDG_CACHE_HOME
cachedir, err := os.UserCacheDir()
if err != nil {
return nil, err
}
abs, _ := filepath.Abs(filepath.Join(cachedir, DefaultCacheDir))
if err := os.MkdirAll(abs, os.ModePerm); err != nil {
return nil, err
}
dir = abs
}
c := layer.NewFilesystemCache(dir)
return c, nil
}

View File

@@ -30,7 +30,7 @@ func (o *InfoOpts) AddFlags(cmd *cobra.Command) {
f := cmd.Flags()
f.StringVarP(&o.OutputFormat, "output", "o", "table", "Output format (table, json)")
f.StringVarP(&o.TypeFilter, "type", "t", "all", "Filter on type (image, chart, file)")
f.StringVarP(&o.TypeFilter, "type", "t", "all", "Filter on type (image, chart, file, sigs, atts, sbom)")
// TODO: Regex/globbing
}
@@ -66,14 +66,14 @@ func InfoCmd(ctx context.Context, o *InfoOpts, s *store.Layout) error {
return err
}
i := newItem(s, desc, internalManifest, internalDesc.Platform.Architecture, o)
i := newItem(s, desc, internalManifest, fmt.Sprintf("%s/%s", internalDesc.Platform.OS, internalDesc.Platform.Architecture), o)
var emptyItem item
if i != emptyItem {
items = append(items, i)
}
}
// handle single arch docker images
} else if desc.MediaType == consts.DockerManifestSchema2 {
// handle "non" multi-arch images
} else if desc.MediaType == consts.DockerManifestSchema2 || desc.MediaType == consts.OCIManifestSchema1 {
var m ocispec.Manifest
if err := json.NewDecoder(rc).Decode(&m); err != nil {
return err
@@ -90,11 +90,19 @@ func InfoCmd(ctx context.Context, o *InfoOpts, s *store.Layout) error {
if err := json.NewDecoder(rc).Decode(&internalManifest); err != nil {
return err
}
i := newItem(s, desc, m, internalManifest.Architecture, o)
var emptyItem item
if i != emptyItem {
items = append(items, i)
if internalManifest.Architecture != "" {
i := newItem(s, desc, m, fmt.Sprintf("%s/%s", internalManifest.OS, internalManifest.Architecture), o)
var emptyItem item
if i != emptyItem {
items = append(items, i)
}
} else {
i := newItem(s, desc, m, "-", o)
var emptyItem item
if i != emptyItem {
items = append(items, i)
}
}
// handle the rest
} else {
@@ -132,23 +140,27 @@ func InfoCmd(ctx context.Context, o *InfoOpts, s *store.Layout) error {
func buildTable(items ...item) {
// Create a table for the results
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"Reference", "Type", "Arch", "# Layers", "Size"})
table.SetHeader([]string{"Reference", "Type", "Platform", "# Layers", "Size"})
table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
table.SetRowLine(false)
table.SetAutoMergeCellsByColumnIndex([]int{0})
totalSize := int64(0)
for _, i := range items {
if i.Type != "" {
row := []string{
i.Reference,
i.Type,
i.Architecture,
i.Platform,
fmt.Sprintf("%d", i.Layers),
i.Size,
byteCountSI(i.Size),
}
totalSize += i.Size
table.Append(row)
}
}
table.SetFooter([]string{"", "", "", "Total", byteCountSI(totalSize)})
table.Render()
}
@@ -163,9 +175,9 @@ func buildJson(item ...item) string {
type item struct {
Reference string
Type string
Architecture string
Platform string
Layers int
Size string
Size int64
}
type byReferenceAndArch []item
@@ -174,22 +186,24 @@ func (a byReferenceAndArch) Len() int { return len(a) }
func (a byReferenceAndArch) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a byReferenceAndArch) Less(i, j int) bool {
if a[i].Reference == a[j].Reference {
return a[i].Architecture < a[j].Architecture
if a[i].Type == "image" && a[j].Type == "image" {
return a[i].Platform < a[j].Platform
}
if a[i].Type == "image" {
return true
}
if a[j].Type == "image" {
return false
}
return a[i].Type < a[j].Type
}
return a[i].Reference < a[j].Reference
}
func newItem(s *store.Layout, desc ocispec.Descriptor, m ocispec.Manifest, arch string, o *InfoOpts) item {
// skip listing cosign items
if desc.Annotations["kind"] == "dev.cosignproject.cosign/atts" ||
desc.Annotations["kind"] == "dev.cosignproject.cosign/sigs" ||
desc.Annotations["kind"] == "dev.cosignproject.cosign/sboms" {
return item{}
}
func newItem(s *store.Layout, desc ocispec.Descriptor, m ocispec.Manifest, plat string, o *InfoOpts) item {
var size int64 = 0
for _, l := range m.Layers {
size = +l.Size
size += l.Size
}
// Generate a human-readable content type
@@ -205,6 +219,15 @@ func newItem(s *store.Layout, desc ocispec.Descriptor, m ocispec.Manifest, arch
ctype = "image"
}
switch desc.Annotations["kind"] {
case "dev.cosignproject.cosign/sigs":
ctype = "sigs"
case "dev.cosignproject.cosign/atts":
ctype = "atts"
case "dev.cosignproject.cosign/sboms":
ctype = "sbom"
}
ref, err := reference.Parse(desc.Annotations[ocispec.AnnotationRefName])
if err != nil {
return item{}
@@ -217,9 +240,9 @@ func newItem(s *store.Layout, desc ocispec.Descriptor, m ocispec.Manifest, arch
return item{
Reference: ref.Name(),
Type: ctype,
Architecture: arch,
Platform: plat,
Layers: len(m.Layers),
Size: byteCountSI(size),
Size: size,
}
}

View File

@@ -14,11 +14,17 @@ import (
type LoadOpts struct {
*RootOpts
TempOverride string
}
func (o *LoadOpts) AddFlags(cmd *cobra.Command) {
f := cmd.Flags()
_ = f
// On Unix systems, the default is $TMPDIR if non-empty, else /tmp.
// On Windows, the default is GetTempPath, returning the first non-empty
// value from %TMP%, %TEMP%, %USERPROFILE%, or the Windows directory.
// On Plan 9, the default is /tmp.
f.StringVarP(&o.TempOverride, "tempdir", "t", "", "overrides the default directory for temporary files, as returned by your OS.")
}
// LoadCmd
@@ -28,7 +34,7 @@ func LoadCmd(ctx context.Context, o *LoadOpts, archiveRefs ...string) error {
for _, archiveRef := range archiveRefs {
l.Infof("loading content from [%s] to [%s]", archiveRef, o.StoreDir)
err := unarchiveLayoutTo(ctx, archiveRef, o.StoreDir)
err := unarchiveLayoutTo(ctx, archiveRef, o.StoreDir, o.TempOverride)
if err != nil {
return err
}
@@ -38,8 +44,8 @@ func LoadCmd(ctx context.Context, o *LoadOpts, archiveRefs ...string) error {
}
// unarchiveLayoutTo accepts an archived oci layout and extracts the contents to an existing oci layout, preserving the index
func unarchiveLayoutTo(ctx context.Context, archivePath string, dest string) error {
tmpdir, err := os.MkdirTemp("", "hauler")
func unarchiveLayoutTo(ctx context.Context, archivePath string, dest string, tempOverride string) error {
tmpdir, err := os.MkdirTemp(tempOverride, "hauler")
if err != nil {
return err
}

View File

@@ -19,7 +19,7 @@ type SaveOpts struct {
func (o *SaveOpts) AddArgs(cmd *cobra.Command) {
f := cmd.Flags()
f.StringVarP(&o.FileName, "filename", "f", "pkg.tar.zst", "Name of archive")
f.StringVarP(&o.FileName, "filename", "f", "haul.tar.zst", "Name of archive")
}
// SaveCmd

View File

@@ -17,30 +17,29 @@ import (
"github.com/rancherfederal/hauler/pkg/store"
"github.com/rancherfederal/hauler/internal/server"
"github.com/rancherfederal/hauler/pkg/log"
)
type ServeOpts struct {
type ServeRegistryOpts struct {
*RootOpts
Port int
RootDir string
ConfigFile string
Daemon bool
storedir string
}
func (o *ServeOpts) AddFlags(cmd *cobra.Command) {
func (o *ServeRegistryOpts) AddFlags(cmd *cobra.Command) {
f := cmd.Flags()
f.IntVarP(&o.Port, "port", "p", 5000, "Port to listen on")
f.StringVar(&o.RootDir, "directory", "registry", "Directory to use for registry backend (defaults to '$PWD/registry')")
f.IntVarP(&o.Port, "port", "p", 5000, "Port to listen on.")
f.StringVar(&o.RootDir, "directory", "registry", "Directory to use for backend. Defaults to $PWD/registry")
f.StringVarP(&o.ConfigFile, "config", "c", "", "Path to a config file, will override all other configs")
f.BoolVarP(&o.Daemon, "daemon", "d", false, "Toggle serving as a daemon")
}
// ServeCmd serves the embedded registry almost identically to how distribution/v3 does it
func ServeCmd(ctx context.Context, o *ServeOpts, s *store.Layout) error {
func ServeRegistryCmd(ctx context.Context, o *ServeRegistryOpts, s *store.Layout) error {
l := log.FromContext(ctx)
ctx = dcontext.WithVersion(ctx, version.Version)
tr := server.NewTempRegistry(ctx, o.RootDir)
@@ -55,7 +54,7 @@ func ServeCmd(ctx context.Context, o *ServeOpts, s *store.Layout) error {
tr.Close()
cfg := o.defaultConfig()
cfg := o.defaultRegistryConfig()
if o.ConfigFile != "" {
ucfg, err := loadConfig(o.ConfigFile)
if err != nil {
@@ -64,6 +63,7 @@ func ServeCmd(ctx context.Context, o *ServeOpts, s *store.Layout) error {
cfg = ucfg
}
l.Infof("starting registry on port [%d]", o.Port)
r, err := server.NewRegistry(ctx, cfg)
if err != nil {
return err
@@ -72,6 +72,50 @@ func ServeCmd(ctx context.Context, o *ServeOpts, s *store.Layout) error {
if err = r.ListenAndServe(); err != nil {
return err
}
return nil
}
type ServeFilesOpts struct {
*RootOpts
Port int
RootDir string
storedir string
}
func (o *ServeFilesOpts) AddFlags(cmd *cobra.Command) {
f := cmd.Flags()
f.IntVarP(&o.Port, "port", "p", 8080, "Port to listen on.")
f.StringVar(&o.RootDir, "directory", "fileserver", "Directory to use for backend. Defaults to $PWD/fileserver")
}
func ServeFilesCmd(ctx context.Context, o *ServeFilesOpts, s *store.Layout) error {
l := log.FromContext(ctx)
ctx = dcontext.WithVersion(ctx, version.Version)
opts := &CopyOpts{}
if err := CopyCmd(ctx, opts, s, "dir://"+o.RootDir); err != nil {
return err
}
cfg := server.FileConfig{
Root: o.RootDir,
Port: o.Port,
}
f, err := server.NewFile(ctx, cfg)
if err != nil {
return err
}
l.Infof("starting file server on port [%d]", o.Port)
if err := f.ListenAndServe(); err != nil {
return err
}
return nil
}
@@ -84,7 +128,7 @@ func loadConfig(filename string) (*configuration.Configuration, error) {
return configuration.Parse(f)
}
func (o *ServeOpts) defaultConfig() *configuration.Configuration {
func (o *ServeRegistryOpts) defaultRegistryConfig() *configuration.Configuration {
cfg := &configuration.Configuration{
Version: "0.1",
Storage: configuration.Storage{

View File

@@ -8,12 +8,11 @@ import (
"os"
"strings"
"github.com/mitchellh/go-homedir"
"github.com/spf13/cobra"
"helm.sh/helm/v3/pkg/action"
"k8s.io/apimachinery/pkg/util/yaml"
"github.com/mitchellh/go-homedir"
"github.com/rancherfederal/hauler/pkg/store"
"github.com/rancherfederal/hauler/pkg/apis/hauler.cattle.io/v1alpha1"
tchart "github.com/rancherfederal/hauler/pkg/collection/chart"
"github.com/rancherfederal/hauler/pkg/collection/imagetxt"
@@ -22,6 +21,8 @@ import (
"github.com/rancherfederal/hauler/pkg/content"
"github.com/rancherfederal/hauler/pkg/cosign"
"github.com/rancherfederal/hauler/pkg/log"
"github.com/rancherfederal/hauler/pkg/reference"
"github.com/rancherfederal/hauler/pkg/store"
)
type SyncOpts struct {
@@ -29,6 +30,9 @@ type SyncOpts struct {
ContentFiles []string
Key string
Products []string
Platform string
Registry string
ProductRegistry string
}
func (o *SyncOpts) AddFlags(cmd *cobra.Command) {
@@ -37,6 +41,9 @@ func (o *SyncOpts) AddFlags(cmd *cobra.Command) {
f.StringSliceVarP(&o.ContentFiles, "files", "f", []string{}, "Path to content files")
f.StringVarP(&o.Key, "key", "k", "", "(Optional) Path to the key for signature verification")
f.StringSliceVar(&o.Products, "products", []string{}, "Used for RGS Carbide customers to supply a product and version and Hauler will retrieve the images. i.e. '--product rancher=v2.7.6'")
f.StringVarP(&o.Platform, "platform", "p", "", "(Optional) Specific platform to save. i.e. linux/amd64. Defaults to all if flag is omitted.")
f.StringVarP(&o.Registry, "registry", "r", "", "(Optional) Default pull registry for image refs that are not specifying a registry name.")
f.StringVarP(&o.ProductRegistry, "product-registry", "c", "", "(Optional) Specific Product Registry to use. Defaults to RGS Carbide Registry (rgcrprod.azurecr.us).")
}
func SyncCmd(ctx context.Context, o *SyncOpts, s *store.Layout) error {
@@ -47,12 +54,19 @@ func SyncCmd(ctx context.Context, o *SyncOpts, s *store.Layout) error {
l.Infof("processing content file for product: '%s'", product)
parts := strings.Split(product, "=")
tag := strings.ReplaceAll(parts[1], "+", "-")
manifestLoc := fmt.Sprintf("%s/hauler/%s-manifest.yaml:%s", consts.CarbideRegistry, parts[0], tag)
ProductRegistry := o.ProductRegistry // cli flag
// if no cli flag use CarbideRegistry.
if o.ProductRegistry == "" {
ProductRegistry = consts.CarbideRegistry
}
manifestLoc := fmt.Sprintf("%s/hauler/%s-manifest.yaml:%s", ProductRegistry, parts[0], tag)
l.Infof("retrieving product manifest from: '%s'", manifestLoc)
img := v1alpha1.Image{
Name: manifestLoc,
}
err := storeImage(ctx, s, img)
err := storeImage(ctx, s, img, o.Platform)
if err != nil {
return err
}
@@ -135,14 +149,44 @@ func processContent(ctx context.Context, fi *os.File, o *SyncOpts, s *store.Layo
if err := yaml.Unmarshal(doc, &cfg); err != nil {
return err
}
a := cfg.GetAnnotations()
for _, i := range cfg.Spec.Images {
// Check if the user provided a registry. If a registry is provided in the annotation, use it for the images that don't have a registry in their ref name.
if a[consts.ImageAnnotationRegistry] != "" || o.Registry != ""{
newRef,_ := reference.Parse(i.Name)
newReg := o.Registry // cli flag
// if no cli flag but there was an annotation, use the annotation.
if o.Registry == "" && a[consts.ImageAnnotationRegistry] != "" {
newReg = a[consts.ImageAnnotationRegistry]
}
if newRef.Context().RegistryStr() == "" {
newRef,err = reference.Relocate(i.Name, newReg)
if err != nil {
return err
}
}
i.Name = newRef.Name()
}
// Check if the user provided a key.
if o.Key != "" || i.Key != "" {
key := o.Key
// Check if the user provided a key. The flag from the CLI takes precedence over the annotation. The individual image key takes precedence over both.
if a[consts.ImageAnnotationKey] != "" || o.Key != "" || i.Key != "" {
key := o.Key // cli flag
// if no cli flag but there was an annotation, use the annotation.
if o.Key == "" && a[consts.ImageAnnotationKey] != "" {
key, err = homedir.Expand(a[consts.ImageAnnotationKey])
if err != nil {
return err
}
}
// the individual image key trumps all
if i.Key != "" {
key, err = homedir.Expand(i.Key)
if err != nil {
return err
}
}
l.Debugf("key for image [%s]", key)
@@ -154,8 +198,19 @@ func processContent(ctx context.Context, fi *os.File, o *SyncOpts, s *store.Layo
}
l.Infof("signature verified for image [%s]", i.Name)
}
err = storeImage(ctx, s, i)
// Check if the user provided a platform. The flag from the CLI takes precedence over the annotation. The individual image platform takes precedence over both.
platform := o.Platform // cli flag
// if no cli flag but there was an annotation, use the annotation.
if o.Platform == "" && a[consts.ImageAnnotationPlatform] != "" {
platform = a[consts.ImageAnnotationPlatform]
}
// the individual image platform trumps all
if i.Platform != "" {
platform = i.Platform
}
err = storeImage(ctx, s, i, platform)
if err != nil {
return err
}

View File

@@ -2,12 +2,17 @@ package main
import (
"context"
"embed"
"os"
"github.com/rancherfederal/hauler/cmd/hauler/cli"
"github.com/rancherfederal/hauler/pkg/cosign"
"github.com/rancherfederal/hauler/pkg/log"
)
//go:embed binaries/*
var binaries embed.FS
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
@@ -15,7 +20,15 @@ func main() {
logger := log.NewLogger(os.Stdout)
ctx = logger.WithContext(ctx)
// ensure cosign binary is available
if err := cosign.EnsureBinaryExists(ctx, binaries); err != nil {
logger.Errorf("%v", err)
os.Exit(1)
}
if err := cli.New().ExecuteContext(ctx); err != nil {
logger.Errorf("%v", err)
cancel()
os.Exit(1)
}
}

View File

@@ -0,0 +1,21 @@
# HELM IGNORE OPTIONS:
# Patterns to ignore when building Helm packages.
# Supports shell glob matching, relative path matching, and negation (prefixed with !)
.DS_Store
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
*.swp
*.bak
*.tmp
*.orig
*~
.project
.idea/
*.tmproj
.vscode/

View File

@@ -0,0 +1,7 @@
apiVersion: v2
name: hauler
description: Hauler Helm Chart - Airgap Swiss Army Knife
icon: https://raw.githubusercontent.com/rancherfederal/hauler/main/static/rgs-hauler-logo-icon.svg
type: application
version: 0.1.0
appVersion: 1.0.2

View File

@@ -0,0 +1,33 @@
# Hauler Helm Chart
### Airgap Swiss Army Knife
`Rancher Government Hauler` simplifies the airgap experience without requiring operators to adopt a specific workflow. **Hauler** simplifies the airgapping process, by representing assets (images, charts, files, etc...) as content and collections to allow operators to easily fetch, store, package, and distribute these assets with declarative manifests or through the command line.
`Hauler` does this by storing contents and collections as OCI Artifacts and allows operators to serve contents and collections with an embedded registry and fileserver. Additionally, `Hauler` has the ability to store and inspect various non-image OCI Artifacts.
**GitHub Repostiory:** https://github.com/rancherfederal/hauler
**Documentation:** http://hauler.dev
---
| Type | Chart Version | App Version |
| ----------- | ------------- | ----------- |
| application | `0.1.0` | `1.0.2` |
## Installing the Chart
```bash
helm install hauler hauler/hauler -n hauler-system -f values.yaml
```
```bash
helm status hauler -n hauler-system
```
## Uninstalling the Chart
```bash
helm uninstall hauler -n hauler-system
```

View File

@@ -0,0 +1,33 @@
# Hauler Helm Chart
### Airgap Swiss Army Knife
`Rancher Government Hauler` simplifies the airgap experience without requiring operators to adopt a specific workflow. **Hauler** simplifies the airgapping process, by representing assets (images, charts, files, etc...) as content and collections to allow operators to easily fetch, store, package, and distribute these assets with declarative manifests or through the command line.
`Hauler` does this by storing contents and collections as OCI Artifacts and allows operators to serve contents and collections with an embedded registry and fileserver. Additionally, `Hauler` has the ability to store and inspect various non-image OCI Artifacts.
**GitHub Repostiory:** https://github.com/rancherfederal/hauler
**Documentation:** http://hauler.dev
---
| Type | Chart Version | App Version |
| ----------- | ------------- | ----------- |
| application | `0.1.0` | `1.0.2` |
## Installing the Chart
```bash
helm install hauler hauler/hauler -n hauler-system -f values.yaml
```
```bash
helm status hauler -n hauler-system
```
## Uninstalling the Chart
```bash
helm uninstall hauler -n hauler-system
```

View File

@@ -0,0 +1,62 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "hauler.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "hauler.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "hauler.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "hauler.labels" -}}
helm.sh/chart: {{ include "hauler.chart" . }}
{{ include "hauler.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "hauler.selectorLabels" -}}
app.kubernetes.io/name: {{ include "hauler.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "hauler.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "hauler.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,76 @@
{{- if .Values.haulerFileserver.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: hauler-fileserver
namespace: {{ .Release.Namespace }}
labels:
{{- include "hauler.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.haulerFileserver.replicas }}
selector:
matchLabels:
app: hauler-fileserver
{{- include "hauler.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
app: hauler-fileserver
{{- include "hauler.selectorLabels" . | nindent 8 }}
spec:
{{- if or .Values.haulerJobs.hauls.enabled .Values.haulerJobs.manifests.enabled }}
initContainers:
{{- if .Values.haulerJobs.hauls.enabled }}
- name: wait-for-hauler-hauls-job
image: {{ .Values.hauler.initContainers.image.repository }}:{{ .Values.hauler.initContainers.image.tag }}
imagePullPolicy: {{ .Values.hauler.initContainers.imagePullPolicy }}
args: ["wait", "--for=condition=complete", "job", "hauler-hauls-job", "--namespace", "{{ .Release.Namespace }}", "--timeout={{ .Values.hauler.initContainers.timeout }}"]
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
runAsNonRoot: true
runAsUser: 1001
seccompProfile:
type: RuntimeDefault
{{- end }}
{{- if .Values.haulerJobs.manifests.enabled }}
- name: wait-for-hauler-manifests-job
image: {{ .Values.hauler.initContainers.image.repository }}:{{ .Values.hauler.initContainers.image.tag }}
imagePullPolicy: {{ .Values.hauler.initContainers.imagePullPolicy }}
args: ["wait", "--for=condition=complete", "job", "hauler-manifests-job", "--namespace", "{{ .Release.Namespace }}", "--timeout={{ .Values.hauler.initContainers.timeout }}"]
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
runAsNonRoot: true
runAsUser: 1001
seccompProfile:
type: RuntimeDefault
{{- end }}
{{- end }}
containers:
- name: hauler-fileserver
image: {{ .Values.hauler.image.repository }}:{{ .Values.hauler.image.tag }}
imagePullPolicy: {{ .Values.hauler.imagePullPolicy }}
args: ["store", "serve", "fileserver", "--port", "{{ .Values.haulerFileserver.port }}"]
ports:
- containerPort: {{ .Values.haulerFileserver.port }}
volumeMounts:
- name: hauler-data
mountPath: /store
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
runAsNonRoot: true
runAsUser: 1001
seccompProfile:
type: RuntimeDefault
restartPolicy: Always
serviceAccountName: hauler-service-account
volumes:
- name: hauler-data
persistentVolumeClaim:
claimName: hauler-data
{{- end }}

View File

@@ -0,0 +1,27 @@
{{- if and .Values.haulerFileserver.enabled .Values.haulerFileserver.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hauler-fileserver
namespace: {{ .Release.Namespace }}
labels:
{{- include "hauler.labels" . | nindent 4 }}
spec:
rules:
- host: {{ .Values.haulerFileserver.ingress.hostname }}
http:
paths:
- backend:
service:
name: hauler-fileserver
port:
number: {{ .Values.haulerFileserver.service.ports.targetPort }}
path: /
pathType: Prefix
{{- if .Values.haulerFileserver.ingress.tls.enabled }}
tls:
- hosts:
- {{ .Values.haulerFileserver.ingress.hostname }}
secretName: {{ .Values.haulerFileserver.ingress.tls.secretName }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,18 @@
{{- if and .Values.haulerFileserver.enabled .Values.haulerFileserver.service.enabled }}
apiVersion: v1
kind: Service
metadata:
name: hauler-fileserver
namespace: {{ .Release.Namespace }}
labels:
{{- include "hauler.labels" . | nindent 4 }}
spec:
selector:
app: hauler-fileserver
ports:
- name: hauler-fileserver
protocol: {{ .Values.haulerFileserver.service.ports.protocol }}
port: {{ .Values.haulerFileserver.service.ports.port }}
targetPort: {{ .Values.haulerFileserver.service.ports.targetPort }}
type: {{ .Values.haulerFileserver.service.type }}
{{- end }}

View File

@@ -0,0 +1,76 @@
{{- if .Values.haulerRegistry.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: hauler-registry
namespace: {{ .Release.Namespace }}
labels:
{{- include "hauler.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.haulerRegistry.replicas }}
selector:
matchLabels:
app: hauler-registry
{{- include "hauler.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
app: hauler-registry
{{- include "hauler.selectorLabels" . | nindent 8 }}
spec:
{{- if or .Values.haulerJobs.hauls.enabled .Values.haulerJobs.manifests.enabled }}
initContainers:
{{- if .Values.haulerJobs.hauls.enabled }}
- name: wait-for-hauler-hauls-job
image: {{ .Values.hauler.initContainers.image.repository }}:{{ .Values.hauler.initContainers.image.tag }}
imagePullPolicy: {{ .Values.hauler.initContainers.imagePullPolicy }}
args: ["wait", "--for=condition=complete", "job", "hauler-hauls-job", "--namespace", "{{ .Release.Namespace }}", "--timeout={{ .Values.hauler.initContainers.timeout }}"]
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
runAsNonRoot: true
runAsUser: 1001
seccompProfile:
type: RuntimeDefault
{{- end }}
{{- if .Values.haulerJobs.manifests.enabled }}
- name: wait-for-hauler-manifests-job
image: {{ .Values.hauler.initContainers.image.repository }}:{{ .Values.hauler.initContainers.image.tag }}
imagePullPolicy: {{ .Values.hauler.initContainers.imagePullPolicy }}
args: ["wait", "--for=condition=complete", "job", "hauler-manifests-job", "--namespace", "{{ .Release.Namespace }}", "--timeout={{ .Values.hauler.initContainers.timeout }}"]
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
runAsNonRoot: true
runAsUser: 1001
seccompProfile:
type: RuntimeDefault
{{- end }}
{{- end }}
containers:
- name: hauler-registry
image: {{ .Values.hauler.image.repository }}:{{ .Values.hauler.image.tag }}
imagePullPolicy: {{ .Values.hauler.imagePullPolicy }}
args: ["store", "serve", "registry", "--port", "{{ .Values.haulerRegistry.port }}"]
ports:
- containerPort: {{ .Values.haulerRegistry.port }}
volumeMounts:
- name: hauler-data
mountPath: /store
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
runAsNonRoot: true
runAsUser: 1001
seccompProfile:
type: RuntimeDefault
restartPolicy: Always
serviceAccountName: hauler-service-account
volumes:
- name: hauler-data
persistentVolumeClaim:
claimName: hauler-data
{{- end }}

View File

@@ -0,0 +1,28 @@
{{- if and .Values.haulerRegistry.enabled .Values.haulerRegistry.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hauler-registry
namespace: {{ .Release.Namespace }}
labels:
{{- include "hauler.labels" . | nindent 4 }}
spec:
rules:
- host: {{ .Values.haulerRegistry.ingress.hostname }}
http:
paths:
- backend:
service:
name: hauler-registry
port:
number: {{ .Values.haulerRegistry.service.ports.targetPort }}
path: /
pathType: Prefix
{{- if .Values.haulerRegistry.ingress.tls.enabled }}
tls:
- hosts:
- {{ .Values.haulerRegistry.ingress.hostname }}
secretName: {{ .Values.haulerRegistry.ingress.tls.secretName }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,18 @@
{{- if and .Values.haulerRegistry.enabled .Values.haulerRegistry.service.enabled }}
apiVersion: v1
kind: Service
metadata:
name: hauler-registry
namespace: {{ .Release.Namespace }}
labels:
{{- include "hauler.labels" . | nindent 4 }}
spec:
selector:
app: hauler-registry
ports:
- name: hauler-registry
protocol: {{ .Values.haulerRegistry.service.ports.protocol }}
port: {{ .Values.haulerRegistry.service.ports.port }}
targetPort: {{ .Values.haulerRegistry.service.ports.targetPort }}
type: {{ .Values.haulerRegistry.service.type }}
{{- end }}

View File

@@ -0,0 +1,126 @@
{{- if .Values.haulerJobs.hauls.enabled }}
apiVersion: batch/v1
kind: Job
metadata:
name: hauler-hauls-job
namespace: {{ .Release.Namespace }}
labels:
{{- include "hauler.labels" . | nindent 4 }}
spec:
template:
spec:
initContainers:
- name: hauler-fetch-hauls
image: {{ .Values.haulerJobs.image.repository }}:{{ .Values.haulerJobs.image.tag }}
imagePullPolicy: {{ .Values.haulerJobs.imagePullPolicy }}
command: ["/bin/sh", "-c"]
args:
- |
{{- range .Values.haulerJobs.hauls.artifacts }}
curl -o /hauls/{{ .name }} {{ .path }} &&
{{- end }}
echo hauler fetch completed
volumeMounts:
- name: hauler-data
mountPath: /hauls
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
runAsNonRoot: true
runAsUser: 1001
seccompProfile:
type: RuntimeDefault
containers:
- name: hauler-load-hauls
image: {{ .Values.hauler.image.repository }}:{{ .Values.hauler.image.tag }}
imagePullPolicy: {{ .Values.hauler.imagePullPolicy }}
args:
- "store"
- "load"
{{- range .Values.haulerJobs.hauls.artifacts }}
- "/hauls/{{ .name }}"
{{- end }}
volumeMounts:
- name: hauler-data
mountPath: /hauls
- name: hauler-data
mountPath: /store
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
runAsNonRoot: true
runAsUser: 1001
seccompProfile:
type: RuntimeDefault
restartPolicy: OnFailure
volumes:
- name: hauler-data
persistentVolumeClaim:
claimName: hauler-data
{{- end }}
---
{{- if .Values.haulerJobs.manifests.enabled }}
apiVersion: batch/v1
kind: Job
metadata:
name: hauler-manifests-job
namespace: {{ .Release.Namespace }}
labels:
{{- include "hauler.labels" . | nindent 4 }}
spec:
template:
spec:
initContainers:
- name: hauler-fetch-manifests
image: {{ .Values.haulerJobs.image.repository }}:{{ .Values.haulerJobs.image.tag }}
imagePullPolicy: {{ .Values.haulerJobs.imagePullPolicy }}
command: ["/bin/sh", "-c"]
args:
- |
{{- range .Values.haulerJobs.manifests.artifacts }}
curl -o /manifests/{{ .name }} {{ .path }} &&
{{- end }}
echo hauler fetch completed
volumeMounts:
- name: hauler-data
mountPath: /manifests
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
runAsNonRoot: true
runAsUser: 1001
seccompProfile:
type: RuntimeDefault
containers:
- name: hauler-load-manifests
image: {{ .Values.hauler.image.repository }}:{{ .Values.hauler.image.tag }}
imagePullPolicy: {{ .Values.hauler.imagePullPolicy }}
args:
{{- range .Values.haulerJobs.manifests.artifacts }}
- "store"
- "sync"
- "--files"
- "/manifests/{{ .name }}"
{{- end }}
volumeMounts:
- name: hauler-data
mountPath: /manifests
- name: hauler-data
mountPath: /store
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
runAsNonRoot: true
runAsUser: 1001
seccompProfile:
type: RuntimeDefault
restartPolicy: OnFailure
volumes:
- name: hauler-data
persistentVolumeClaim:
claimName: hauler-data
{{- end }}

View File

@@ -0,0 +1,16 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: hauler-data
namespace: {{ .Release.Namespace }}
labels:
{{- include "hauler.labels" . | nindent 4 }}
spec:
accessModes:
- {{ .Values.hauler.data.pvc.accessModes }}
resources:
requests:
storage: {{ .Values.hauler.data.pvc.storageRequest }}
{{- if .Values.hauler.data.pvc.storageClass }}
storageClassName: {{ .Values.hauler.data.pvc.storageClass }}
{{- end }}

View File

@@ -0,0 +1,35 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: hauler-service-account
namespace: {{ .Release.Namespace }}
labels:
{{- include "hauler.labels" . | nindent 4 }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: hauler-role
namespace: {{ .Release.Namespace }}
labels:
{{- include "hauler.labels" . | nindent 4 }}
rules:
- apiGroups: ["batch"]
resources: ["jobs"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: hauler-role-binding
namespace: {{ .Release.Namespace }}
labels:
{{- include "hauler.labels" . | nindent 4 }}
roleRef:
kind: Role
name: hauler-role
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: hauler-service-account
namespace: {{ .Release.Namespace }}

View File

@@ -0,0 +1,94 @@
# Helm Chart Values for Hauler
# Docs: https://hauler.dev
hauler:
image:
repository: ghcr.io/rancherfederal/hauler
tag: v1.0.2
imagePullPolicy: Always
initContainers:
image:
repository: rancher/kubectl
tag: v1.27.0 # update to your kubernetes version
imagePullPolicy: Always
timeout: 1h
data:
pvc:
accessModes: ReadWriteMany
storageClass: longhorn # optional... will use default storage class
storageRequest: 48Gi # recommended size of 3x the artifact(s)
# Helm Chart Values for the Hauler Jobs
# Docs: https://rancherfederal.github.io/hauler-docs/docs/introduction/quickstart
haulerJobs:
image:
repository: rancher/shell
tag: v0.1.22
imagePullPolicy: Always
hauls:
enabled: true
artifacts:
- path: https://raw.githubusercontent.com/rancherfederal/hauler/main/testdata/haul.tar.zst
name: haul.tar.zst
# - path: /path/to/additional-hauls.tar.zst
# name: additional-hauls.tar.zst
manifests:
enabled: true
artifacts:
- path: https://raw.githubusercontent.com/rancherfederal/hauler/main/testdata/hauler-manifest.yaml
name: hauler-manifest.yaml
# - path: /path/to/additional-manifests.yaml
# name: additional-manifests.yaml
# Helm Chart Values for the Hauler Fileserver
# Docs: https://rancherfederal.github.io/hauler-docs/docs/guides-references/command-line/hauler-store#hauler-store-serve-fileserver
haulerFileserver:
enabled: true
port: 8080 # default port for the fileserver
replicas: 1
ingress:
enabled: true
hostname: fileserver.ranchers.io
tls:
enabled: true
source: secret # only supported source
secretName: tls-certs # must be created outside of this chart
service:
enabled: true
type: ClusterIP
ports:
protocol: TCP
port: 8080 # default port for the fileserver
targetPort: 8080 # default port for the fileserver
# Helm Chart Values for the Hauler Registry
# Docs: https://rancherfederal.github.io/hauler-docs/docs/guides-references/command-line/hauler-store#hauler-store-serve-registry
haulerRegistry:
enabled: true
port: 5000 # default port for the registry
replicas: 1
ingress:
enabled: true
hostname: registry.ranchers.io
tls:
enabled: true
source: secret # only supported source
secretName: tls-certs # must be created outside of this chart
service:
enabled: true
type: ClusterIP
ports:
protocol: TCP
port: 5000 # default port for the registry
targetPort: 5000 # default port for the registry

83
go.mod
View File

@@ -4,7 +4,7 @@ go 1.21
require (
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be
github.com/containerd/containerd v1.7.6
github.com/containerd/containerd v1.7.11
github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2
github.com/docker/go-metrics v0.0.1
github.com/google/go-containerregistry v0.16.1
@@ -14,17 +14,17 @@ require (
github.com/mitchellh/go-homedir v1.1.0
github.com/olekukonko/tablewriter v0.0.5
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.0-rc5
github.com/opencontainers/image-spec v1.1.0-rc6
github.com/pkg/errors v0.9.1
github.com/rs/zerolog v1.31.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/afero v1.10.0
github.com/spf13/cobra v1.7.0
golang.org/x/sync v0.4.0
helm.sh/helm/v3 v3.13.0
k8s.io/apimachinery v0.28.2
k8s.io/client-go v0.28.2
oras.land/oras-go v1.2.4
github.com/spf13/cobra v1.8.0
golang.org/x/sync v0.6.0
helm.sh/helm/v3 v3.14.2
k8s.io/apimachinery v0.29.0
k8s.io/client-go v0.29.0
oras.land/oras-go v1.2.5
)
require (
@@ -36,7 +36,7 @@ require (
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
github.com/Masterminds/squirrel v1.5.4 // indirect
github.com/Microsoft/hcsshim v0.11.0 // indirect
github.com/Microsoft/hcsshim v0.11.4 // indirect
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d // indirect
github.com/andybalholm/brotli v1.0.1 // indirect
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect
@@ -47,26 +47,27 @@ require (
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chai2010/gettext-go v1.0.2 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/cli v24.0.6+incompatible // indirect
github.com/docker/distribution v2.8.2+incompatible // indirect
github.com/docker/docker v24.0.6+incompatible // indirect
github.com/distribution/reference v0.5.0 // indirect
github.com/docker/cli v25.0.1+incompatible // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker v25.0.5+incompatible // indirect
github.com/docker/docker-credential-helpers v0.7.0 // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 // indirect
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/emicklei/go-restful/v3 v3.10.1 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch v5.7.0+incompatible // indirect
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/go-errors/errors v1.4.2 // indirect
github.com/go-gorp/gorp/v3 v3.1.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/logr v1.3.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
@@ -78,10 +79,11 @@ require (
github.com/gomodule/redigo v1.8.2 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/gosuri/uitable v0.0.4 // indirect
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
@@ -113,8 +115,8 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/nwaples/rardecode v1.1.0 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pierrec/lz4/v4 v4.1.2 // indirect
@@ -137,36 +139,37 @@ require (
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 // indirect
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 // indirect
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f // indirect
go.opentelemetry.io/otel v1.16.0 // indirect
go.opentelemetry.io/otel/metric v1.16.0 // indirect
go.opentelemetry.io/otel/trace v1.16.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 // indirect
go.opentelemetry.io/otel v1.19.0 // indirect
go.opentelemetry.io/otel/metric v1.19.0 // indirect
go.opentelemetry.io/otel/trace v1.19.0 // indirect
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/crypto v0.18.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/oauth2 v0.8.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/term v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/oauth2 v0.10.0 // indirect
golang.org/x/sys v0.16.0 // indirect
golang.org/x/term v0.16.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.3.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect
google.golang.org/grpc v1.54.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/grpc v1.58.3 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.28.2 // indirect
k8s.io/apiextensions-apiserver v0.28.2 // indirect
k8s.io/apiserver v0.28.2 // indirect
k8s.io/cli-runtime v0.28.2 // indirect
k8s.io/component-base v0.28.2 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
k8s.io/kubectl v0.28.2 // indirect
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect
k8s.io/api v0.29.0 // indirect
k8s.io/apiextensions-apiserver v0.29.0 // indirect
k8s.io/apiserver v0.29.0 // indirect
k8s.io/cli-runtime v0.29.0 // indirect
k8s.io/component-base v0.29.0 // indirect
k8s.io/klog/v2 v2.110.1 // indirect
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
k8s.io/kubectl v0.29.0 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect
sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

183
go.sum
View File

@@ -60,8 +60,8 @@ github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8
github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/Microsoft/hcsshim v0.11.0 h1:7EFNIY4igHEXUdj1zXgAyU3fLc7QfOKHbkldRVTBdiM=
github.com/Microsoft/hcsshim v0.11.0/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM=
github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8=
github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
@@ -102,14 +102,17 @@ github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be h1:J5BL
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w=
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
github.com/containerd/containerd v1.7.6 h1:oNAVsnhPoy4BTPQivLgTzI9Oleml9l/+eYIDYXRCYo8=
github.com/containerd/containerd v1.7.6/go.mod h1:SY6lrkkuJT40BVNO37tlYTSnKJnP5AXBc0fhx0q+TJ4=
github.com/containerd/containerd v1.7.11 h1:lfGKw3eU35sjV0aG2eYZTiwFEY1pCzxdzicHP3SZILw=
github.com/containerd/containerd v1.7.11/go.mod h1:5UluHxHTX2rdvYuZ5OJTC5m/KJNs0Zs9wVoJm9zf5ZE=
github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM=
github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k=
github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
@@ -120,37 +123,37 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2 h1:aBfCb7iqHmDEIp6fBvC/hQUddQfg+3qdYjwzaiP9Hnc=
github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2/go.mod h1:WHNsWjnIn2V1LYOrME7e8KxSeKunYHsxEm4am0BUtcI=
github.com/docker/cli v24.0.6+incompatible h1:fF+XCQCgJjjQNIMjzaSmiKJSCcfcXb3TWTcc7GAneOY=
github.com/docker/cli v24.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE=
github.com/docker/docker v24.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/cli v25.0.1+incompatible h1:mFpqnrS6Hsm3v1k7Wa/BO23oz0k121MTbTO1lpcGSkU=
github.com/docker/cli v25.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v25.0.5+incompatible h1:UmQydMduGkrD5nQde1mecF/YnSbTOaPeFIeP5C4W+DE=
github.com/docker/docker v25.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4=
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ=
github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI=
github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM=
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
@@ -172,10 +175,9 @@ github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpj
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
@@ -251,8 +253,9 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-containerregistry v0.16.1 h1:rUEt426sR6nyrL3gt+18ibRcvYpKYdpsa5ZW7MA08dQ=
github.com/google/go-containerregistry v0.16.1/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY1hLbf8eeGapA+vbFDCtQ=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -288,6 +291,8 @@ github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY=
github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=
@@ -410,23 +415,23 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo/v2 v2.9.4 h1:xR7vG4IXt5RWx6FfIjyAtsoMAtnc3C/rFXBBd2AjZwE=
github.com/onsi/ginkgo/v2 v2.9.4/go.mod h1:gCQYp2Q+kSoIj7ykSVb9nskRSsR6PUj4AiLywzIhbKM=
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI=
github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
github.com/opencontainers/image-spec v1.1.0-rc6 h1:XDqvyKsJEbRtATzkgItUqBA7QHk58yxX1Ov9HERHNqU=
github.com/opencontainers/image-spec v1.1.0-rc6/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
@@ -484,8 +489,8 @@ github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -539,12 +544,14 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s=
go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4=
go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo=
go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4=
go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs=
go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 h1:x8Z78aZx8cOF0+Kkazoc7lwUNMGy0LrzEMxTm4BbTxg=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1:62CPTSry9QZtOaSsE3tOzhx6LzDhHnXJ6xHeMNNiM6Q=
go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs=
go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY=
go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE=
go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8=
go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg=
go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo=
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY=
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -557,8 +564,8 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -593,8 +600,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -642,8 +649,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8=
golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -655,8 +662,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -706,14 +713,14 @@ golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -723,8 +730,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -780,8 +787,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo=
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss=
golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -849,8 +856,8 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 h1:0nDDozoAU19Qb2HwhXadU8OcsiO/09cnTqhUtq2MEOM=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -867,8 +874,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag=
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ=
google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -881,8 +888,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -903,8 +910,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
helm.sh/helm/v3 v3.13.0 h1:XPJKIU30K4JTQ6VX/6e0hFAmEIonYa8E7wx5aqv4xOc=
helm.sh/helm/v3 v3.13.0/go.mod h1:2PBEKsMWKLVZTojUOqMS3Eadv5mP43FBWrRgLNkNm9Y=
helm.sh/helm/v3 v3.14.2 h1:V71fv+NGZv0icBlr+in1MJXuUIHCiPG1hW9gEBISTIA=
helm.sh/helm/v3 v3.14.2/go.mod h1:2itvvDv2WSZXTllknfQo6j7u3VVgMAvm8POCDgYH424=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@@ -912,30 +919,30 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.28.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw=
k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg=
k8s.io/apiextensions-apiserver v0.28.2 h1:J6/QRWIKV2/HwBhHRVITMLYoypCoPY1ftigDM0Kn+QU=
k8s.io/apiextensions-apiserver v0.28.2/go.mod h1:5tnkxLGa9nefefYzWuAlWZ7RZYuN/765Au8cWLA6SRg=
k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ=
k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU=
k8s.io/apiserver v0.28.2 h1:rBeYkLvF94Nku9XfXyUIirsVzCzJBs6jMn3NWeHieyI=
k8s.io/apiserver v0.28.2/go.mod h1:f7D5e8wH8MWcKD7azq6Csw9UN+CjdtXIVQUyUhrtb+E=
k8s.io/cli-runtime v0.28.2 h1:64meB2fDj10/ThIMEJLO29a1oujSm0GQmKzh1RtA/uk=
k8s.io/cli-runtime v0.28.2/go.mod h1:bTpGOvpdsPtDKoyfG4EG041WIyFZLV9qq4rPlkyYfDA=
k8s.io/client-go v0.28.2 h1:DNoYI1vGq0slMBN/SWKMZMw0Rq+0EQW6/AK4v9+3VeY=
k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY=
k8s.io/component-base v0.28.2 h1:Yc1yU+6AQSlpJZyvehm/NkJBII72rzlEsd6MkBQ+G0E=
k8s.io/component-base v0.28.2/go.mod h1:4IuQPQviQCg3du4si8GpMrhAIegxpsgPngPRR/zWpzc=
k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ=
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM=
k8s.io/kubectl v0.28.2 h1:fOWOtU6S0smdNjG1PB9WFbqEIMlkzU5ahyHkc7ESHgM=
k8s.io/kubectl v0.28.2/go.mod h1:6EQWTPySF1fn7yKoQZHYf9TPwIl2AygHEcJoxFekr64=
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk=
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
oras.land/oras-go v1.2.4 h1:djpBY2/2Cs1PV87GSJlxv4voajVOMZxqqtq9AB8YNvY=
oras.land/oras-go v1.2.4/go.mod h1:DYcGfb3YF1nKjcezfX2SNlDAeQFKSXmf+qrFmrh4324=
k8s.io/api v0.29.0 h1:NiCdQMY1QOp1H8lfRyeEf8eOwV6+0xA6XEE44ohDX2A=
k8s.io/api v0.29.0/go.mod h1:sdVmXoz2Bo/cb77Pxi71IPTSErEW32xa4aXwKH7gfBA=
k8s.io/apiextensions-apiserver v0.29.0 h1:0VuspFG7Hj+SxyF/Z/2T0uFbI5gb5LRgEyUVE3Q4lV0=
k8s.io/apiextensions-apiserver v0.29.0/go.mod h1:TKmpy3bTS0mr9pylH0nOt/QzQRrW7/h7yLdRForMZwc=
k8s.io/apimachinery v0.29.0 h1:+ACVktwyicPz0oc6MTMLwa2Pw3ouLAfAon1wPLtG48o=
k8s.io/apimachinery v0.29.0/go.mod h1:eVBxQ/cwiJxH58eK/jd/vAk4mrxmVlnpBH5J2GbMeis=
k8s.io/apiserver v0.29.0 h1:Y1xEMjJkP+BIi0GSEv1BBrf1jLU9UPfAnnGGbbDdp7o=
k8s.io/apiserver v0.29.0/go.mod h1:31n78PsRKPmfpee7/l9NYEv67u6hOL6AfcE761HapDM=
k8s.io/cli-runtime v0.29.0 h1:q2kC3cex4rOBLfPOnMSzV2BIrrQlx97gxHJs21KxKS4=
k8s.io/cli-runtime v0.29.0/go.mod h1:VKudXp3X7wR45L+nER85YUzOQIru28HQpXr0mTdeCrk=
k8s.io/client-go v0.29.0 h1:KmlDtFcrdUzOYrBhXHgKw5ycWzc3ryPX5mQe0SkG3y8=
k8s.io/client-go v0.29.0/go.mod h1:yLkXH4HKMAywcrD82KMSmfYg2DlE8mepPR4JGSo5n38=
k8s.io/component-base v0.29.0 h1:T7rjd5wvLnPBV1vC4zWd/iWRbV8Mdxs+nGaoaFzGw3s=
k8s.io/component-base v0.29.0/go.mod h1:sADonFTQ9Zc9yFLghpDpmNXEdHyQmFIGbiuZbqAXQ1M=
k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
k8s.io/kubectl v0.29.0 h1:Oqi48gXjikDhrBF67AYuZRTcJV4lg2l42GmvsP7FmYI=
k8s.io/kubectl v0.29.0/go.mod h1:0jMjGWIcMIQzmUaMgAzhSELv5WtHo2a8pq67DtviAJs=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo=
oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
@@ -945,7 +952,7 @@ sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 h1:XX3Ajgzov2RKU
sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3/go.mod h1:9n16EZKMhXBNSiUC5kSdFQJkdH3zbxS/JoO619G1VAY=
sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 h1:W6cLQc5pnqM7vh3b7HvGNfXrJ/xL6BDMS0v1V/HHg5U=
sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3/go.mod h1:JWP1Fj0VWGHyw3YUPjXSQnRnrwezrZSrApfX5S0nIag=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=

View File

@@ -2,64 +2,68 @@
# Usage:
# - curl -sfL... | ENV_VAR=... bash
# - ENV_VAR=... bash ./install.sh
# - ./install.sh ENV_VAR=...
# Example:
# - ENV_VAR=... ./install.sh
#
# Install Usage:
# Install Latest Release
# - curl -sfL https://get.hauler.dev | bash
# - ./install.sh
#
# Install Specific Release
# - curl -sfL https://get.hauler.dev | HAULER_VERSION=0.4.1 bash
# - curl -sfL https://get.hauler.dev | HAULER_VERSION=1.0.0 bash
# - HAULER_VERSION=1.0.0 ./install.sh
#
# Uninstall Usage:
# - curl -sfL https://get.hauler.dev | HAULER_UNINSTALL=true bash
# - HAULER_UNINSTALL=true ./install.sh
#
# Documentation:
# - https://hauler.dev
# - https://github.com/rancherfederal/hauler
# set functions for debugging/logging
function info {
echo && echo "[INFO] Hauler: $1"
}
function verbose {
echo "$1"
}
function info {
echo && echo "[INFO] Hauler: $1"
}
function warn {
echo && echo "[WARN] Hauler: $1"
}
function fatal {
echo && echo "[ERROR] Hauler: $1"
exit 1
exit 0
}
# check for required dependencies
dependencies=("curl" "awk" "openssl" "tar" "rm")
for cmd in "${dependencies[@]}"; do
for cmd in sudo rm curl grep mkdir sed awk openssl tar; do
if ! command -v "$cmd" &> /dev/null; then
fatal "$cmd is not installed"
fi
done
# start hauler installation
info "Starting Installation..."
# set version environment variable
if [ -z "${HAULER_VERSION}" ]; then
version="${HAULER_VERSION:-$(curl -s https://api.github.com/repos/rancherfederal/hauler/releases/latest | grep '"tag_name":' | sed 's/.*"v\([^"]*\)".*/\1/')}"
else
version="${HAULER_VERSION}"
fi
# set version with an environment variable
version=${HAULER_VERSION:-0.4.1}
# set uninstall environment variable from argument or environment
if [ "${HAULER_UNINSTALL}" = "true" ]; then
# remove the hauler binary
sudo rm -f /usr/local/bin/hauler || fatal "Failed to Remove Hauler from /usr/local/bin"
# set verision with an argument
while [[ $# -gt 0 ]]; do
case "$1" in
HAULER_VERSION=*)
version="${1#*=}"
shift
;;
*)
shift
;;
esac
done
# remove the installation directory
rm -rf "$HOME/.hauler" || fatal "Failed to Remove Directory: $HOME/.hauler"
info "Hauler Uninstalled Successfully"
exit 0
fi
# detect the operating system
platform=$(uname -s | tr '[:upper:]' '[:lower:]')
@@ -89,25 +93,36 @@ case $arch in
;;
esac
# start hauler installation
info "Starting Installation..."
# display the version, platform, and architecture
verbose "- Version: v$version"
verbose "- Platform: $platform"
verbose "- Architecture: $arch"
# check if install directory exists, create it if not
if [ ! -d "$HOME/.hauler" ]; then
mkdir -p "$HOME/.hauler" || fatal "Failed to Create Directory: ~/.hauler"
fi
# change to install directory
cd "$HOME/.hauler" || fatal "Failed to Change Directory: ~/.hauler"
# download the checksum file
if ! curl -sOL "https://github.com/rancherfederal/hauler/releases/download/v${version}/hauler_${version}_checksums.txt"; then
if ! curl -sfOL "https://github.com/rancherfederal/hauler/releases/download/v${version}/hauler_${version}_checksums.txt"; then
fatal "Failed to Download: hauler_${version}_checksums.txt"
fi
# download the archive file
if ! curl -sOL "https://github.com/rancherfederal/hauler/releases/download/v${version}/hauler_${version}_${platform}_${arch}.tar.gz"; then
if ! curl -sfOL "https://github.com/rancherfederal/hauler/releases/download/v${version}/hauler_${version}_${platform}_${arch}.tar.gz"; then
fatal "Failed to Download: hauler_${version}_${platform}_${arch}.tar.gz"
fi
# start hauler checksum verification
info "Starting Checksum Verification..."
# Verify the Hauler checksum
# verify the Hauler checksum
expected_checksum=$(awk -v version="$version" -v platform="$platform" -v arch="$arch" '$2 == "hauler_"version"_"platform"_"arch".tar.gz" {print $1}' "hauler_${version}_checksums.txt")
determined_checksum=$(openssl dgst -sha256 "hauler_${version}_${platform}_${arch}.tar.gz" | awk '{print $2}')
@@ -129,21 +144,32 @@ tar -xzf "hauler_${version}_${platform}_${arch}.tar.gz" || fatal "Failed to Extr
# install the binary
case "$platform" in
linux)
install hauler /usr/local/bin || fatal "Failed to Install Hauler to /usr/local/bin"
sudo install -m 755 hauler /usr/local/bin || fatal "Failed to Install Hauler to /usr/local/bin"
;;
darwin)
install hauler /usr/local/bin || fatal "Failed to Install Hauler to /usr/local/bin"
sudo install -m 755 hauler /usr/local/bin || fatal "Failed to Install Hauler to /usr/local/bin"
;;
*)
fatal "Unsupported Platform or Architecture: $platform/$arch"
;;
esac
# clean up checksum(s)
rm -rf "hauler_${version}_checksums.txt" || warn "Failed to Remove: hauler_${version}_checksums.txt"
# clean up archive file(s)
rm -rf "hauler_${version}_${platform}_${arch}.tar.gz" || warn "Failed to Remove: hauler_${version}_${platform}_${arch}.tar.gz"
# add hauler to the path
if [ -f "$HOME/.bashrc" ]; then
echo "export PATH=$PATH:/usr/local/bin/" >> "$HOME/.bashrc"
source "$HOME/.bashrc"
elif [ -f "$HOME/.bash_profile" ]; then
echo "export PATH=$PATH:/usr/local/bin/" >> "$HOME/.bash_profile"
source "$HOME/.bash_profile"
elif [ -f "$HOME/.zshrc" ]; then
echo "export PATH=$PATH:/usr/local/bin/" >> "$HOME/.zshrc"
source "$HOME/.zshrc"
elif [ -f "$HOME/.profile" ]; then
echo "export PATH=$PATH:/usr/local/bin/" >> "$HOME/.profile"
source "$HOME/.profile"
else
echo "Failed to add /usr/local/bin to PATH: Unsupported Shell"
fi
# display success message
info "Successfully Installed at /usr/local/bin/hauler"

View File

@@ -21,8 +21,7 @@ type FileConfig struct {
// TODO: Better configs
func NewFile(ctx context.Context, cfg FileConfig) (Server, error) {
r := mux.NewRouter()
r.Handle("/", handlers.LoggingHandler(os.Stdout, http.FileServer(http.Dir(cfg.Root))))
r.PathPrefix("/").Handler(handlers.LoggingHandler(os.Stdout, http.StripPrefix("/", http.FileServer(http.Dir(cfg.Root)))))
if cfg.Root == "" {
cfg.Root = "."
}

View File

@@ -24,4 +24,8 @@ type Image struct {
// Path is the path to the cosign public key used for verifying image signatures
//Key string `json:"key,omitempty"`
Key string `json:"key"`
// Platform of the image to be pulled. If not specified, all platforms will be pulled.
//Platform string `json:"key,omitempty"`
Platform string `json:"platform"`
}

View File

@@ -25,6 +25,11 @@ func (h Http) Name(u *url.URL) string {
return ""
}
name, _ := url.PathUnescape(u.String())
if err != nil {
return ""
}
contentType := resp.Header.Get("Content-Type")
for _, v := range strings.Split(contentType, ",") {
t, _, err := mime.ParseMediaType(v)
@@ -36,7 +41,7 @@ func (h Http) Name(u *url.URL) string {
}
// TODO: Not this
return filepath.Base(u.String())
return filepath.Base(name)
}
func (h Http) Open(ctx context.Context, u *url.URL) (io.ReadCloser, error) {

View File

@@ -1,6 +1,7 @@
package image
import (
"fmt"
"github.com/google/go-containerregistry/pkg/authn"
gname "github.com/google/go-containerregistry/pkg/name"
gv1 "github.com/google/go-containerregistry/pkg/v1"
@@ -51,3 +52,29 @@ func NewImage(name string, opts ...remote.Option) (*Image, error) {
Image: img,
}, nil
}
func IsMultiArchImage(name string, opts ...remote.Option) (bool, error) {
ref, err := gname.ParseReference(name)
if err != nil {
return false, fmt.Errorf("parsing reference %q: %v", name, err)
}
defaultOpts := []remote.Option{
remote.WithAuthFromKeychain(authn.DefaultKeychain),
}
opts = append(opts, defaultOpts...)
desc, err := remote.Get(ref, opts...)
if err != nil {
return false, fmt.Errorf("getting image %q: %v", name, err)
}
_, err = desc.ImageIndex()
if err != nil {
// If the descriptor could not be converted to an image index, it's not a multi-arch image
return false, nil
}
// If the descriptor could be converted to an image index, it's a multi-arch image
return true, nil
}

View File

@@ -51,4 +51,7 @@ const (
KindAnnotation = "dev.cosignproject.cosign/image"
CarbideRegistry = "rgcrprod.azurecr.us"
ImageAnnotationKey = "hauler.dev/key"
ImageAnnotationPlatform = "hauler.dev/platform"
ImageAnnotationRegistry = "hauler.dev/registry"
)

View File

@@ -16,7 +16,7 @@ import (
)
var (
chartpath = "../../../testdata/podinfo-6.0.3.tgz"
chartpath = "../../../testdata/rancher-cluster-templates-0.4.4.tgz"
)
func TestNewChart(t *testing.T) {
@@ -48,13 +48,13 @@ func TestNewChart(t *testing.T) {
},
want: v1.Descriptor{
MediaType: consts.ChartLayerMediaType,
Size: 13524,
Size: 13102,
Digest: v1.Hash{
Algorithm: "sha256",
Hex: "e30b95a08787de69ffdad3c232d65cfb131b5b50c6fd44295f48a078fceaa44e",
Hex: "4b3bb4e474b54bf9057b298f8f11c239bb561396716d8cd5fc369c407fba2965",
},
Annotations: map[string]string{
ocispec.AnnotationTitle: "podinfo-6.0.3.tgz",
ocispec.AnnotationTitle: "rancher-cluster-templates-0.4.4.tgz",
},
},
wantErr: false,
@@ -72,18 +72,18 @@ func TestNewChart(t *testing.T) {
// TODO: Use a mock helm server
name: "should fetch a remote chart",
args: args{
name: "ingress-nginx",
opts: &action.ChartPathOptions{RepoURL: "https://kubernetes.github.io/ingress-nginx", Version: "4.0.16"},
name: "cert-manager",
opts: &action.ChartPathOptions{RepoURL: "https://charts.jetstack.io", Version: "1.14.4"},
},
want: v1.Descriptor{
MediaType: consts.ChartLayerMediaType,
Size: 38591,
Size: 80674,
Digest: v1.Hash{
Algorithm: "sha256",
Hex: "b0ea91f7febc6708ad9971871d2de6e8feb2072110c3add6dd7082d90753caa2",
Hex: "5775fdbc1881d6e510df76d38753af54b86bd14caa8edb28fdbb79527042dede",
},
Annotations: map[string]string{
ocispec.AnnotationTitle: "ingress-nginx-4.0.16.tgz",
ocispec.AnnotationTitle: "cert-manager-v1.14.4.tgz",
},
},
wantErr: false,

View File

@@ -1,29 +1,22 @@
package cosign
import (
"bufio"
"context"
"embed"
"fmt"
"io"
"net/http"
"os"
"os/exec"
"os/user"
"path/filepath"
"runtime"
"context"
"strings"
"encoding/json"
"time"
"bufio"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"oras.land/oras-go/pkg/content"
"github.com/rancherfederal/hauler/pkg/store"
"github.com/rancherfederal/hauler/pkg/artifacts/image"
"github.com/rancherfederal/hauler/pkg/log"
"github.com/rancherfederal/hauler/internal/mapper"
"github.com/rancherfederal/hauler/pkg/reference"
"github.com/rancherfederal/hauler/pkg/artifacts/file"
"github.com/rancherfederal/hauler/pkg/artifacts/file/getter"
"github.com/rancherfederal/hauler/pkg/apis/hauler.cattle.io/v1alpha1"
"github.com/rancherfederal/hauler/pkg/store"
"oras.land/oras-go/pkg/content"
)
const maxRetries = 3
@@ -32,7 +25,7 @@ const retryDelay = time.Second * 5
// VerifyFileSignature verifies the digital signature of a file using Sigstore/Cosign.
func VerifySignature(ctx context.Context, s *store.Layout, keyPath string, ref string) error {
operation := func() error {
cosignBinaryPath, err := ensureCosignBinary(ctx, s)
cosignBinaryPath, err := getCosignPath()
if err != nil {
return err
}
@@ -50,17 +43,65 @@ func VerifySignature(ctx context.Context, s *store.Layout, keyPath string, ref s
}
// SaveImage saves image and any signatures/attestations to the store.
func SaveImage(ctx context.Context, s *store.Layout, ref string) error {
func SaveImage(ctx context.Context, s *store.Layout, ref string, platform string) error {
l := log.FromContext(ctx)
operation := func() error {
cosignBinaryPath, err := ensureCosignBinary(ctx, s)
cosignBinaryPath, err := getCosignPath()
if err != nil {
return err
}
cmd := exec.Command(cosignBinaryPath, "save", ref, "--dir", s.Root)
output, err := cmd.CombinedOutput()
// check to see if the image is multi-arch
isMultiArch, err := image.IsMultiArchImage(ref)
if err != nil {
return fmt.Errorf("error adding image to store: %v, output: %s", err, output)
return err
}
l.Debugf("multi-arch image: %v", isMultiArch)
cmd := exec.Command(cosignBinaryPath, "save", ref, "--dir", s.Root)
// Conditionally add platform.
if platform != "" && isMultiArch {
l.Debugf("platform for image [%s]", platform)
cmd.Args = append(cmd.Args, "--platform", platform)
}
stdout, err := cmd.StdoutPipe()
if err != nil {
return err
}
stderr, err := cmd.StderrPipe()
if err != nil {
return err
}
// start the command after having set up the pipe
if err := cmd.Start(); err != nil {
return err
}
// read command's stdout line by line
output := bufio.NewScanner(stdout)
for output.Scan() {
l.Debugf(output.Text()) // write each line to your log, or anything you need
}
if err := output.Err(); err != nil {
cmd.Wait()
return err
}
// read command's stderr line by line
errors := bufio.NewScanner(stderr)
for errors.Scan() {
l.Errorf(errors.Text()) // write each line to your log, or anything you need
}
if err := errors.Err(); err != nil {
cmd.Wait()
return err
}
// Wait for the command to finish
err = cmd.Wait()
if err != nil {
return err
}
return nil
@@ -73,7 +114,7 @@ func SaveImage(ctx context.Context, s *store.Layout, ref string) error {
func LoadImages(ctx context.Context, s *store.Layout, registry string, ropts content.RegistryOptions) error {
l := log.FromContext(ctx)
cosignBinaryPath, err := ensureCosignBinary(ctx, s)
cosignBinaryPath, err := getCosignPath()
if err != nil {
return err
}
@@ -100,7 +141,7 @@ func LoadImages(ctx context.Context, s *store.Layout, registry string, ropts con
if err := cmd.Start(); err != nil {
return err
}
// read command's stdout line by line
output := bufio.NewScanner(stdout)
for output.Scan() {
@@ -132,17 +173,18 @@ func LoadImages(ctx context.Context, s *store.Layout, registry string, ropts con
// RegistryLogin - performs cosign login
func RegistryLogin(ctx context.Context, s *store.Layout, registry string, ropts content.RegistryOptions) error {
cosignBinaryPath, err := ensureCosignBinary(ctx, s)
log := log.FromContext(ctx)
cosignBinaryPath, err := getCosignPath()
if err != nil {
return err
}
cmd := exec.Command(cosignBinaryPath, "login", registry, "-u", ropts.Username, "-p", ropts.Password)
output, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("error logging into registry: %v, output: %s", err, output)
}
log.Infof(strings.Trim(string(output), "\n"))
return nil
}
@@ -157,7 +199,7 @@ func RetryOperation(ctx context.Context, operation func() error) error {
}
// Log the error for the current attempt.
l.Errorf("Error (attempt %d/%d): %v", attempt, maxRetries, err)
l.Errorf("error (attempt %d/%d): %v", attempt, maxRetries, err)
// If this is not the last attempt, wait before retrying.
if attempt < maxRetries {
@@ -169,157 +211,15 @@ func RetryOperation(ctx context.Context, operation func() error) error {
return fmt.Errorf("operation failed after %d attempts", maxRetries)
}
// ensureCosignBinary checks if the cosign binary exists in the specified directory and installs it if not.
func ensureCosignBinary(ctx context.Context, s *store.Layout) (string, error) {
l := log.FromContext(ctx)
// Get the current user's information
currentUser, err := user.Current()
func EnsureBinaryExists(ctx context.Context, bin embed.FS) error {
// Set up a path for the binary to be copied.
binaryPath, err := getCosignPath()
if err != nil {
return "", fmt.Errorf("Error: %v\n", err)
return fmt.Errorf("error: %v", err)
}
// Get the user's home directory
homeDir := currentUser.HomeDir
// Construct the path to the .hauler directory
haulerDir := filepath.Join(homeDir, ".hauler")
// Create the .hauler directory if it doesn't exist
if _, err := os.Stat(haulerDir); os.IsNotExist(err) {
// .hauler directory does not exist, create it
if err := os.MkdirAll(haulerDir, 0755); err != nil {
return "", fmt.Errorf("Error creating .hauler directory: %v\n", err)
}
l.Infof("Created .hauler directory at: %s", haulerDir)
}
// Check if the cosign binary exists in the specified directory.
binaryPath := filepath.Join(haulerDir, "cosign")
_, err = os.Stat(binaryPath)
if err == nil {
// Cosign binary is already installed in the specified directory.
return binaryPath, nil
}
// Cosign binary is not found.
l.Infof("Cosign binary not found. Checking to see if it exists in the store...")
// grab binary from store if it exists, otherwise try to download it from GitHub.
// if the binary has to be downloaded, then automatically add it to the store afterwards.
err = copyCosignFromStore(ctx, s, haulerDir)
if err != nil {
l.Warnf("%s", err)
err = downloadCosign(ctx, haulerDir)
if err != nil {
return "", err
}
err = addCosignToStore(ctx, s, binaryPath)
if err != nil {
return "", err
}
}
// Make the binary executable.
if err := os.Chmod(filepath.Join(haulerDir, "cosign"), 0755); err != nil {
return "", fmt.Errorf("error setting executable permission: %v", err)
}
return binaryPath, nil
}
// used to check if the cosign binary is in the store and if so copy it to the .hauler directory
func copyCosignFromStore(ctx context.Context, s *store.Layout, destDir string) error {
l := log.FromContext(ctx)
ref := "hauler/cosign:latest"
r, err := reference.Parse(ref)
if err != nil {
return err
}
found := false
if err := s.Walk(func(reference string, desc ocispec.Descriptor) error {
if !strings.Contains(reference, r.Name()) {
return nil
}
found = true
rc, err := s.Fetch(ctx, desc)
if err != nil {
return err
}
defer rc.Close()
var m ocispec.Manifest
if err := json.NewDecoder(rc).Decode(&m); err != nil {
return err
}
mapperStore, err := mapper.FromManifest(m, destDir)
if err != nil {
return err
}
pushedDesc, err := s.Copy(ctx, reference, mapperStore, "")
if err != nil {
return err
}
l.Infof("extracted [%s] from store with digest [%s]", ref, pushedDesc.Digest.String())
return nil
}); err != nil {
return err
}
if !found {
return fmt.Errorf("Reference [%s] not found in store. Hauler will attempt to download it from Github.", ref)
}
return nil
}
// adds the cosign binary to the store.
// this is to help with airgapped situations where you cannot access the internet.
func addCosignToStore(ctx context.Context, s *store.Layout, binaryPath string) error {
l := log.FromContext(ctx)
fi := v1alpha1.File{
Path: binaryPath,
}
copts := getter.ClientOptions{
NameOverride: fi.Name,
}
f := file.NewFile(fi.Path, file.WithClient(getter.NewClient(copts)))
ref, err := reference.NewTagged(f.Name(fi.Path), reference.DefaultTag)
if err != nil {
return err
}
desc, err := s.AddOCI(ctx, f, ref.Name())
if err != nil {
return err
}
l.Infof("added 'file' to store at [%s], with digest [%s]", ref.Name(), desc.Digest.String())
return nil
}
// used to check if the cosign binary is in the store and if so copy it to the .hauler directory
func downloadCosign(ctx context.Context, haulerDir string) error {
l := log.FromContext(ctx)
// Define the GitHub release URL and architecture-specific binary name.
releaseURL := "https://github.com/rancher-government-carbide/cosign/releases/latest/download"
// Determine the architecture and add it to the binary name.
arch := runtime.GOARCH
// Determine the architecture so that we pull the correct embedded binary.
arch := runtime.GOARCH
rOS := runtime.GOOS
binaryName := "cosign"
if rOS == "windows" {
@@ -327,35 +227,53 @@ func downloadCosign(ctx context.Context, haulerDir string) error {
} else {
binaryName = fmt.Sprintf("cosign-%s-%s", rOS, arch)
}
// Download the binary.
downloadURL := fmt.Sprintf("%s/%s", releaseURL, binaryName)
resp, err := http.Get(downloadURL)
if err != nil {
return fmt.Errorf("error downloading cosign binary: %v", err)
}
defer resp.Body.Close()
// Create the cosign binary file in the specified directory.
binaryFile, err := os.Create(filepath.Join(haulerDir, binaryName))
if err != nil {
return fmt.Errorf("error creating cosign binary: %v", err)
}
defer binaryFile.Close()
// retrieve the embedded binary
f, err := bin.ReadFile(fmt.Sprintf("binaries/%s", binaryName))
if err != nil {
return fmt.Errorf("error: %v", err)
}
// Copy the downloaded binary to the file.
_, err = io.Copy(binaryFile, resp.Body)
if err != nil {
return fmt.Errorf("error saving cosign binary: %v", err)
}
// write the binary to the filesystem
err = os.WriteFile(binaryPath, f, 0755)
if err != nil {
return fmt.Errorf("error: %v", err)
}
// Rename the binary to "cosign"
oldBinaryPath := filepath.Join(haulerDir, binaryName)
newBinaryPath := filepath.Join(haulerDir, "cosign")
if err := os.Rename(oldBinaryPath, newBinaryPath); err != nil {
return fmt.Errorf("error renaming cosign binary: %v", err)
}
l.Infof("Cosign binary downloaded and installed to %s", haulerDir)
return nil
}
// getCosignPath returns the binary path
func getCosignPath() (string, error) {
// Get the current user's information
currentUser, err := user.Current()
if err != nil {
return "", fmt.Errorf("error: %v", err)
}
// Get the user's home directory
homeDir := currentUser.HomeDir
// Construct the path to the .hauler directory
haulerDir := filepath.Join(homeDir, ".hauler")
// Create the .hauler directory if it doesn't exist
if _, err := os.Stat(haulerDir); os.IsNotExist(err) {
// .hauler directory does not exist, create it
if err := os.MkdirAll(haulerDir, 0755); err != nil {
return "", fmt.Errorf("error creating .hauler directory: %v", err)
}
}
// Determine the binary name.
rOS := runtime.GOOS
binaryName := "cosign"
if rOS == "windows" {
binaryName = "cosign.exe"
}
// construct path to binary
binaryPath := filepath.Join(haulerDir, binaryName)
return binaryPath, nil
}

View File

@@ -30,11 +30,13 @@ type Fields map[string]string
// NewLogger returns a new Logger
func NewLogger(out io.Writer) Logger {
output := zerolog.ConsoleWriter{Out: os.Stdout}
l := log.Output(output)
return &logger{
zl: l.With().Timestamp().Logger(),
}
customTimeFormat := "2006-01-02 15:04:05"
zerolog.TimeFieldFormat = customTimeFormat
output := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: customTimeFormat}
l := log.Output(output)
return &logger{
zl: l.With().Timestamp().Logger(),
}
}
// FromContext returns a Logger from a context if it exists

View File

@@ -25,6 +25,7 @@ type Reference interface {
// NewTagged will create a new docker.NamedTagged given a path-component
func NewTagged(n string, tag string) (gname.Reference, error) {
n = strings.Replace(strings.ToLower(n), "+", "-", -1)
repo, err := Parse(n)
if err != nil {
return nil, err

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 28.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="358.739px" height="301.861px" viewBox="0 0 358.739 301.861" enable-background="new 0 0 358.739 301.861"
xml:space="preserve">
<path fill="#F17203" d="M317.817,295.13H40.925c-19.036,0-34.612-15.575-34.612-34.612V44.196c0-19.036,15.575-34.612,34.612-34.612
h276.892c19.036,0,34.612,15.575,34.612,34.612v216.322C352.428,279.555,336.853,295.13,317.817,295.13z"/>
<g>
<path fill="#FFFFFF" d="M299.929,116.41h2.311c-5.574,0-10.366-3.95-11.431-9.422l-1.704-8.759
c-2.178-11.2-11.988-19.286-23.399-19.286h-33.5c-0.246,0-0.484,0.031-0.729,0.037v-2.649c0-17.332-14.051-31.383-31.383-31.383
H75.91c-17.333,0-31.383,14.051-31.383,31.383v52.419c0,0.254,0.032,0.499,0.038,0.752c-8.418,0.062-15.226,6.895-15.226,15.327
c0,8.472,6.867,15.339,15.339,15.339h31.175c0.119,0,0.229-0.032,0.347-0.035h25.26c21.78,0,41.302,13.571,48.841,34.004
l72.408,0.279c1.713,0.544,3.496,0.919,5.322,1.162c-2.776,4.551-4.824,9.589-5.9,14.987h-54.474
c-8.472,0-15.339,6.867-15.339,15.339c0,8.472,6.867,15.339,15.339,15.339h58.919c7.786,14.77,23.277,24.875,41.102,24.875
c25.615,0,46.454-20.839,46.454-46.455c0-9.042-2.637-17.461-7.124-24.607c13.918-3.213,24.305-15.657,24.305-30.552v-16.712
C331.312,130.461,317.262,116.41,299.929,116.41z M232.207,109.622h27.86l0.627,3.224c3.711,19.082,20.013,33.132,39.234,34.181
v0.063c0.388,0,0.705,0.316,0.705,0.704v16.712c0,0.388-0.316,0.704-0.705,0.704h-67.722c-0.35,0-0.609-0.271-0.663-0.605
c-0.014-0.326-0.036-0.649-0.041-0.978v-53.3C231.503,109.938,231.819,109.622,232.207,109.622z M168.358,163.528
c-15.333-20.984-40.12-34.074-66.899-34.074H75.91c-0.388,0-0.704-0.316-0.704-0.704V76.331c0-0.388,0.316-0.704,0.704-0.704
h124.186c0.388,0,0.704,0.316,0.704,0.704v86.717c0,0.202,0.001,0.404,0.003,0.605L168.358,163.528z M267.677,233.009
c-7.359,0-13.345-5.987-13.345-13.345s5.987-13.345,13.345-13.345s13.345,5.987,13.345,13.345S275.036,233.009,267.677,233.009z"/>
<path fill="#FFFFFF" d="M97.53,173.209c-25.615,0-46.454,20.839-46.454,46.454c0,25.615,20.839,46.455,46.454,46.455
s46.454-20.839,46.454-46.455C143.985,194.049,123.146,173.209,97.53,173.209z M97.53,233.009c-7.359,0-13.345-5.987-13.345-13.345
s5.987-13.345,13.345-13.345s13.345,5.987,13.345,13.345S104.889,233.009,97.53,233.009z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 28.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="477.791px" height="498.742px" viewBox="0 0 477.791 498.742" enable-background="new 0 0 477.791 498.742"
xml:space="preserve">
<path fill="#F17203" d="M375.348,301.805H98.456c-19.036,0-34.612-15.575-34.612-34.612V50.871
c0-19.036,15.575-34.612,34.612-34.612h276.892c19.036,0,34.612,15.575,34.612,34.612v216.322
C409.96,286.23,394.385,301.805,375.348,301.805z"/>
<g>
<path fill="#FFFFFF" d="M357.46,123.085h2.311c-5.574,0-10.366-3.95-11.431-9.422l-1.704-8.759
c-2.178-11.2-11.988-19.286-23.399-19.286h-33.5c-0.246,0-0.484,0.031-0.729,0.037v-2.649c0-17.332-14.051-31.383-31.383-31.383
H133.441c-17.333,0-31.383,14.051-31.383,31.383v52.419c0,0.254,0.032,0.499,0.038,0.752c-8.418,0.062-15.226,6.895-15.226,15.327
c0,8.472,6.867,15.339,15.339,15.339h31.175c0.119,0,0.229-0.032,0.347-0.035h25.26c21.78,0,41.302,13.571,48.841,34.004
l72.408,0.279c1.713,0.544,3.496,0.919,5.322,1.162c-2.776,4.551-4.824,9.589-5.9,14.987h-54.474
c-8.472,0-15.339,6.867-15.339,15.339c0,8.472,6.867,15.339,15.339,15.339h58.919c7.786,14.77,23.277,24.875,41.102,24.875
c25.615,0,46.454-20.839,46.454-46.455c0-9.042-2.637-17.461-7.124-24.607c13.918-3.213,24.305-15.657,24.305-30.552v-16.712
C388.844,137.136,374.793,123.085,357.46,123.085z M289.739,116.297h27.86l0.627,3.224c3.711,19.082,20.013,33.132,39.234,34.181
v0.063c0.388,0,0.705,0.316,0.705,0.704v16.712c0,0.388-0.316,0.704-0.705,0.704h-67.722c-0.35,0-0.609-0.271-0.663-0.605
c-0.014-0.326-0.036-0.649-0.041-0.978v-53.3C289.034,116.613,289.351,116.297,289.739,116.297z M225.889,170.203
c-15.333-20.984-40.12-34.074-66.899-34.074h-25.549c-0.388,0-0.704-0.316-0.704-0.704V83.006c0-0.388,0.316-0.704,0.704-0.704
h124.186c0.388,0,0.704,0.316,0.704,0.704v86.717c0,0.202,0.001,0.404,0.003,0.605L225.889,170.203z M325.209,239.684
c-7.359,0-13.345-5.987-13.345-13.345s5.987-13.345,13.345-13.345s13.345,5.987,13.345,13.345S332.567,239.684,325.209,239.684z"/>
<path fill="#FFFFFF" d="M155.062,179.884c-25.615,0-46.454,20.839-46.454,46.454c0,25.615,20.839,46.455,46.454,46.455
s46.454-20.839,46.454-46.455C201.516,200.724,180.677,179.884,155.062,179.884z M155.062,239.684
c-7.359,0-13.345-5.987-13.345-13.345s5.987-13.345,13.345-13.345s13.345,5.987,13.345,13.345S162.42,239.684,155.062,239.684z"/>
</g>
<path fill="#384745" d="M173.809,393.336h21.499v55.743c0,11.072,4.635,15.707,13.518,15.707c8.755,0,14.033-4.505,14.033-16.093
v-55.358h20.855v54.972c0,19.955-13.002,33.473-35.531,33.473c-21.114,0-34.374-12.359-34.374-31.541V393.336z"/>
<path fill="#384745" d="M117.429,393.336h21.757l29.353,86.898h-21.757l-5.408-16.479h-29.095l-5.276,16.479H88.206L117.429,393.336
z M117.429,447.793h18.666l-5.922-18.281c-2.06-6.179-2.961-14.932-2.961-14.932h-0.515c0,0-1.287,8.881-3.217,14.802
L117.429,447.793z"/>
<path fill="#384745" d="M329.804,393.336h57.547v15.963h-36.048v18.668h30.254v15.963h-30.254v20.34h37.335v15.963h-58.834V393.336z
"/>
<path fill="#384745" d="M399.84,393.336h35.79c16.994,0,28.452,8.239,28.452,24.202c0,13.004-8.885,20.858-17.51,23.561
c2.575,2.188,4.505,5.149,6.052,8.239c3.604,7.338,6.05,15.448,13.646,15.448c1.932,0,3.476-0.643,3.476-0.643l-1.674,15.32
c0,0-4.635,1.159-8.625,1.159c-10.299,0-16.221-3.992-22.273-17.767c-2.575-6.177-6.179-16.994-10.942-16.994h-4.893v34.374H399.84
V393.336z M421.339,408.914v21.369h7.724c6.182,0,13.39-1.93,13.39-11.198c0-7.596-4.893-10.171-10.815-10.171H421.339z"/>
<path fill="#384745" d="M259.227,393.072h21.565v71.151h36.286v16.012h-57.851V393.072z"/>
<path fill="#384745" d="M9.837,393.072h21.565v32.927h26.473v-32.927h21.565v87.163H57.874v-36.929H31.402v36.929H9.837V393.072z"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
static/rgs-hauler-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 28.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="633.948px" height="187.484px" viewBox="0 0 633.948 187.484" enable-background="new 0 0 633.948 187.484"
xml:space="preserve">
<path fill="#384745" d="M378.324,56.272h17.803v46.159c0,9.169,3.838,13.007,11.194,13.007c7.25,0,11.62-3.731,11.62-13.326v-45.84
h17.269v45.52c0,16.524-10.767,27.718-29.422,27.718c-17.484,0-28.464-10.234-28.464-26.118V56.272z"/>
<path fill="#384745" d="M331.638,56.272h18.016l24.306,71.957h-18.016l-4.478-13.645h-24.093l-4.369,13.645H307.44L331.638,56.272z
M331.638,101.366h15.457l-4.904-15.138c-1.706-5.117-2.452-12.365-2.452-12.365h-0.427c0,0-1.065,7.354-2.663,12.257
L331.638,101.366z"/>
<path fill="#384745" d="M507.499,56.272h47.653v13.219h-29.85v15.459h25.052v13.219h-25.052v16.843h30.916v13.219h-48.718V56.272z"
/>
<path fill="#384745" d="M565.493,56.272h29.637c14.072,0,23.56,6.823,23.56,20.041c0,10.768-7.357,17.272-14.499,19.51
c2.133,1.812,3.731,4.263,5.011,6.823c2.984,6.077,5.009,12.792,11.299,12.792c1.6,0,2.879-0.533,2.879-0.533l-1.386,12.686
c0,0-3.838,0.96-7.142,0.96c-8.528,0-13.432-3.305-18.443-14.713c-2.133-5.115-5.117-14.072-9.061-14.072h-4.052v28.464h-17.803
V56.272z M583.296,69.172v17.695h6.396c5.119,0,11.088-1.598,11.088-9.273c0-6.29-4.052-8.423-8.955-8.423H583.296z"/>
<path fill="#384745" d="M449.056,56.053h17.857v58.918h30.047v13.259h-47.904V56.053z"/>
<path fill="#384745" d="M242.545,56.053h17.857v27.266h21.921V56.053h17.857v72.177h-17.857V97.65h-21.921v30.58h-17.857V56.053z"/>
<path fill="#F17203" d="M183.245,172.234H29.368c-10.579,0-19.235-8.656-19.235-19.235V32.783c0-10.579,8.656-19.235,19.235-19.235
h153.877c10.579,0,19.235,8.656,19.235,19.235V153C202.48,163.579,193.825,172.234,183.245,172.234z"/>
<g>
<path fill="#FFFFFF" d="M173.305,72.915h1.284c-3.098,0-5.761-2.195-6.352-5.236l-0.947-4.868
c-1.21-6.224-6.662-10.718-13.003-10.718H135.67c-0.137,0-0.269,0.017-0.405,0.02v-1.472c0-9.632-7.808-17.441-17.441-17.441H48.81
c-9.632,0-17.441,7.808-17.441,17.441v29.131c0,0.141,0.018,0.278,0.021,0.418c-4.678,0.035-8.462,3.832-8.462,8.518
c0,4.708,3.816,8.524,8.524,8.524h17.325c0.066,0,0.127-0.018,0.193-0.019h14.038c12.104,0,22.953,7.542,27.143,18.897
l40.239,0.155c0.952,0.302,1.943,0.511,2.958,0.646c-1.542,2.529-2.681,5.329-3.279,8.328H99.797c-4.708,0-8.524,3.816-8.524,8.524
s3.816,8.524,8.524,8.524h32.743c4.327,8.208,12.936,13.824,22.842,13.824c14.235,0,25.816-11.581,25.816-25.816
c0-5.025-1.466-9.704-3.959-13.675c7.735-1.786,13.507-8.701,13.507-16.979v-9.287C190.745,80.723,182.937,72.915,173.305,72.915z
M135.67,69.142h15.483l0.349,1.791c2.062,10.604,11.122,18.412,21.804,18.995v0.035c0.216,0,0.392,0.176,0.392,0.391v9.287
c0,0.216-0.176,0.391-0.392,0.391H135.67c-0.194,0-0.339-0.15-0.369-0.336c-0.008-0.181-0.02-0.361-0.023-0.544v-29.62
C135.278,69.317,135.454,69.142,135.67,69.142z M100.187,99.099c-8.521-11.661-22.296-18.936-37.178-18.936H48.81
c-0.216,0-0.391-0.176-0.391-0.391V50.641c0-0.216,0.176-0.391,0.391-0.391h69.014c0.216,0,0.391,0.176,0.391,0.391v48.191
c0,0.112,0,0.224,0.001,0.336L100.187,99.099z M155.382,137.712c-4.089,0-7.416-3.327-7.416-7.416c0-4.089,3.327-7.416,7.416-7.416
c4.089,0,7.416,3.327,7.416,7.416C162.798,134.385,159.471,137.712,155.382,137.712z"/>
<path fill="#FFFFFF" d="M60.826,104.479c-14.235,0-25.816,11.581-25.816,25.816c0,14.235,11.581,25.816,25.816,25.816
s25.816-11.581,25.816-25.816C86.642,116.061,75.061,104.479,60.826,104.479z M60.826,137.712c-4.089,0-7.416-3.327-7.416-7.416
c0-4.089,3.327-7.416,7.416-7.416s7.416,3.327,7.416,7.416C68.242,134.385,64.915,137.712,60.826,137.712z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -1,23 +0,0 @@
---
apiVersion: collection.hauler.cattle.io/v1alpha1
kind: ThickCharts
metadata:
name: mythickchart
spec:
charts:
# charts are also fetched and served as OCI content (currently experimental in helm)
# HELM_EXPERIMENTAL_OCI=1 helm chart pull <hauler-registry>/loki:2.6.2
# - name: loki
# repoURL: https://grafana.github.io/helm-charts
# - name: longhorn
# repoURL: https://charts.longhorn.io
# - name: cert-manager
# repoURL: https://charts.jetstack.io
# version: v1.6.1
# extraImages:
# - ref: quay.io/jetstack/cert-manager-cainjector:v1.6.1
- name: podinfo
repoURL: https://stefanprodan.github.io/podinfo

View File

@@ -1,56 +0,0 @@
apiVersion: content.hauler.cattle.io/v1alpha1
kind: Files
metadata:
name: myfile
spec:
files:
# hauler can save/redistribute files on disk (be careful! paths are relative)
- path: testdata/contents.yaml
# when directories are specified, the directory contents will be archived and stored
- path: testdata/
# hauler can also fetch remote content, and will "smartly" identify filenames _when possible_
# filename below = "k3s-images.txt"
- path: "https://github.com/k3s-io/k3s/releases/download/v1.22.2%2Bk3s2/k3s-images.txt"
# when discovered filenames are not desired, a file name can be specified
- path: https://get.k3s.io
name: k3s-init.sh
---
apiVersion: content.hauler.cattle.io/v1alpha1
kind: Images
metadata:
name: myimage
spec:
images:
# images can be referenced shorthanded without a tag
- name: hello-world
# or namespaced with a tag
- name: rancher/cowsay:latest
# or by their digest:
- name: registry@sha256:42043edfae481178f07aa077fa872fcc242e276d302f4ac2026d9d2eb65b955f
# or fully qualified from any OCI compliant registry registry
- name: ghcr.io/fluxcd/flux-cli:v0.22.0
---
apiVersion: content.hauler.cattle.io/v1alpha1
kind: Charts
metadata:
name: mychart
spec:
charts:
# charts are also fetched and served as OCI content (currently experimental in helm)
# HELM_EXPERIMENTAL_OCI=1 helm chart pull <hauler-registry>/loki:2.6.2
- name: loki
repoURL: https://grafana.github.io/helm-charts
# version: latest # the latest version will be used when version is empty
# specific versions can also be used
- name: rancher
repoURL: https://releases.rancher.com/server-charts/latest
version: 2.6.2

BIN
testdata/haul.tar.zst vendored Normal file

Binary file not shown.

26
testdata/hauler-manifest.yaml vendored Normal file
View File

@@ -0,0 +1,26 @@
apiVersion: content.hauler.cattle.io/v1alpha1
kind: Images
metadata:
name: hauler-content-images-example
spec:
images:
- name: busybox:latest
---
apiVersion: content.hauler.cattle.io/v1alpha1
kind: Charts
metadata:
name: hauler-content-charts-example
spec:
charts:
- name: rancher
repoURL: https://releases.rancher.com/server-charts/stable
version: 2.8.2
---
apiVersion: content.hauler.cattle.io/v1alpha1
kind: Files
metadata:
name: hauler-content-files-example
spec:
files:
- path: https://get.rke2.io
name: install.sh

View File

@@ -1,13 +0,0 @@
---
apiVersion: collection.hauler.cattle.io/v1alpha1
kind: K3s
metadata:
name: myk3s
spec:
# version can be exact (as listed on https://github.com/k3s-io/k3s/releases)
version: v1.22.2+k3s2
# or can point to a channel, in which case the latest version in the channel is used: https://update.k3s.io/v1-release/channels
# version: stable
# version: latest
# version: v1.22

Binary file not shown.

Binary file not shown.

View File

@@ -1,25 +0,0 @@
#!/bin/sh
set -x
if [ "$#" -ne 1 ] || ( [ "$1" != "internet" ] && [ "$1" != "airgap" ] ); then
echo \
"Enable or disable internet access in hauler's CentOS Vagrant machine.
Usage: $0 internet
$0 airgap" >&2
exit 1
fi
if [ "$1" = "internet" ]; then
# internet: set default gateway to NAT network interface
default_iface="eth0"
gw_ip="10.0.2.2"
else
# airgap: set default gateway to private network interface
default_iface="eth1"
gw_ip=$(ip -f inet a show "${default_iface}" | awk 'match($0, /inet ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})/, arr) { print arr[1] }')
fi
ip r delete default
ip r add default via ${gw_ip} dev ${default_iface} proto dhcp metric 100

View File

@@ -1,41 +0,0 @@
#!/bin/sh
################################################################################
# RUN IN VAGRANT MACHINE
# Install a default, bare k3s cluster into the Vagrant machine
################################################################################
if [ -f "/usr/local/bin/k3s-uninstall.sh" ]; then
/usr/local/bin/k3s-uninstall.sh
else
echo "k3s is not installed"
fi
if pgrep -x "firewalld" >/dev/null
then
echo "[FATAL] disable firewalld first"
fi
SELINUXSTATUS=$(getenforce)
if [ "$SELINUXSTATUS" == "Permissive" ]; then
echo "[FATAL] disable selinux"
exit 1
else
echo "SELINUX disabled. continuing"
fi
LOCAL_IMAGES_FILEPATH=/var/lib/rancher/k3s/agent/images
ARTIFACT_DIR=/opt/hauler/local-artifacts/k3s
mkdir -p ${LOCAL_IMAGES_FILEPATH}
cp ${ARTIFACT_DIR}/images/* ${LOCAL_IMAGES_FILEPATH}
cp ${ARTIFACT_DIR}/bin/k3s /usr/local/bin/k3s
chmod +x /usr/local/bin/k3s
yum install -y ${ARTIFACT_DIR}/rpm/*
INSTALL_K3S_SKIP_DOWNLOAD=true ${ARTIFACT_DIR}/bin/k3s-install.sh
chmod +r /etc/rancher/k3s/k3s.yaml

View File

@@ -1,50 +0,0 @@
#!/bin/sh
################################################################################
# RUN IN VAGRANT MACHINE
# Download all required dependencies for an air-gapped k3s install, saving them
# to the folder shared with the host machine.
################################################################################
BASE_SHARED_DIR="/opt/hauler"
VAGRANT_SCRIPTS_DIR="${BASE_SHARED_DIR}/vagrant-scripts"
ARTIFACTS_DIR="${BASE_SHARED_DIR}/local-artifacts/k3s"
K3S_VERSION='v1.18.8+k3s1'
K3S_VERSION_URL='v1.18.8%2Bk3s1'
LOCAL_IMAGES="${ARTIFACTS_DIR}/images"
LOCAL_BIN="${ARTIFACTS_DIR}/bin"
LOCAL_RPM="${ARTIFACTS_DIR}/rpm"
mkdir -p ${LOCAL_IMAGES}
mkdir -p ${LOCAL_BIN}
mkdir -p ${LOCAL_RPM}
# temporarily allow internet access
${VAGRANT_SCRIPTS_DIR}/airgap.sh internet
pushd ${LOCAL_IMAGES}
curl -LO https://github.com/rancher/k3s/releases/download/${K3S_VERSION_URL}/k3s-airgap-images-amd64.tar
popd
pushd ${LOCAL_BIN}
curl -LO https://github.com/rancher/k3s/releases/download/${K3S_VERSION_URL}/k3s
curl -L https://raw.githubusercontent.com/rancher/k3s/${K3S_VERSION_URL}/install.sh -o k3s-install.sh
chmod +x ./*
popd
pushd ${LOCAL_RPM}
curl -LO https://rpm.rancher.io/k3s-selinux-0.1.1-rc1.el7.noarch.rpm
yum install -y yum-utils
yumdownloader --destdir=. --resolve container-selinux selinux-policy-base
popd
# restore air-gap configuration
${VAGRANT_SCRIPTS_DIR}/airgap.sh airgap

View File

@@ -1,12 +0,0 @@
#!/bin/sh
BASE_SHARED_DIR="/opt/hauler"
VAGRANT_SCRIPTS_DIR="${BASE_SHARED_DIR}/vagrant-scripts"
for script in ${VAGRANT_SCRIPTS_DIR}/*-prep.sh ; do
echo "---"
echo "Running ${script} ..."
echo "---"
sh "${script}"
done

View File

@@ -1,73 +0,0 @@
#!/bin/sh
################################################################################
# RUN IN VAGRANT MACHINE
# Install a default, bare rke2 cluster into the Vagrant machine
################################################################################
BASE_SHARED_DIR="/opt/hauler"
VAGRANT_SCRIPTS_DIR="${BASE_SHARED_DIR}/vagrant-scripts"
RKE2_VERSION_DOCKER='v1.18.4-beta16-rke2'
if pgrep -x "firewalld" >/dev/null
then
echo "[FATAL] disable firewalld first"
fi
mkdir -p /etc/rancher/rke2/
# TODO - allow using selinux
SELINUXSTATUS="$(getenforce)"
if [ "$SELINUXSTATUS" = "Permissive" ] || [ "$SELINUXSTATUS" = "Enforcing" ]
then
echo "selinux: true" | sudo tee -a /etc/rancher/rke2/config.yaml > /dev/null
else
echo "SELINUX disabled. continuing"
fi
LOCAL_IMAGES_FILEPATH=/var/lib/rancher/rke2/agent/images
ARTIFACT_DIR="${BASE_SHARED_DIR}/local-artifacts/rke2"
mkdir -p ${LOCAL_IMAGES_FILEPATH}
cp ${ARTIFACT_DIR}/images/* ${LOCAL_IMAGES_FILEPATH}
# TODO - add ability to use local binary with yum install
# ----------------------------------------------------------
# uncomment to use a specific local binary for the install
# ----------------------------------------------------------
# LOCAL_RKE2_BIN='rke2-beta13-dev'
#if [ -n "${LOCAL_RKE2_BIN}" ] && [ -f "${ARTIFACT_DIR}/bin/${LOCAL_RKE2_BIN}" ] ; then
# echo "Use "${ARTIFACT_DIR}/bin/${LOCAL_RKE2_BIN}" for rke2 binary"
#
# INSTALL_RKE2_SKIP_START=true \
# RKE2_RUNTIME_IMAGE="rancher/rke2-runtime:${RKE2_VERSION_DOCKER}" \
# ${ARTIFACT_DIR}/bin/rke2-installer.run
#
# rm -f /usr/local/bin/rke2
#
# cp "${ARTIFACT_DIR}/bin/${LOCAL_RKE2_BIN}" /usr/local/bin/rke2
#
# systemctl start rke2
#else
# ${ARTIFACT_DIR}/bin/rke2-installer.run
#fi
yum install -y ${ARTIFACT_DIR}/rpm/*
systemctl enable rke2-server && systemctl start rke2-server
while [ -f "/etc/rancher/rke2/rke2.yaml" ] ; do
echo "Waiting for /etc/rancher/rke2/rke2.yaml to exist..."
sleep 10
done
chmod +r /etc/rancher/rke2/rke2.yaml
echo "RKE2 cluster is wrapping up installation, run the following commands to allow kubectl access:
export KUBECONFIG=/etc/rancher/rke2/rke2.yaml
export PATH=/var/lib/rancher/rke2/bin/:\${PATH}"

View File

@@ -1,72 +0,0 @@
#!/bin/sh
################################################################################
# RUN IN VAGRANT MACHINE
# Download all required dependencies for an air-gapped rke2 install, saving them
# to the folder shared with the host machine.
################################################################################
BASE_SHARED_DIR="/opt/hauler"
VAGRANT_SCRIPTS_DIR="${BASE_SHARED_DIR}/vagrant-scripts"
ARTIFACTS_DIR="${BASE_SHARED_DIR}/local-artifacts/rke2"
RKE2_VERSION='v1.18.13+rke2r1'
RKE2_VERSION_URL='v1.18.13%2Brke2r1'
RKE2_VERSION_DOCKER='v1.18.13-rke2r1'
LOCAL_IMAGES="${ARTIFACTS_DIR}/images"
LOCAL_BIN="${ARTIFACTS_DIR}/bin"
LOCAL_RPM="${ARTIFACTS_DIR}/rpm"
mkdir -p ${LOCAL_IMAGES}
mkdir -p ${LOCAL_BIN}
mkdir -p ${LOCAL_RPM}
# temporarily allow internet access
${VAGRANT_SCRIPTS_DIR}/airgap.sh internet
pushd ${LOCAL_IMAGES}
curl -LO https://github.com/rancher/rke2/releases/download/${RKE2_VERSION_URL}/rke2-images.linux-amd64.tar.gz
gunzip rke2-images.linux-amd64.tar.gz
popd
#pushd ${LOCAL_BIN}
#
#curl -L https://github.com/rancher/rke2/releases/download/${RKE2_VERSION_URL}/rke2-installer.linux-amd64.run -o rke2-installer.run
#chmod +x ./*
#
#popd
pushd ${LOCAL_RPM}
yum install -y yum-plugin-downloadonly
rke2_rpm_channel='stable'
rpm_site='rpm.rancher.io'
maj_ver='7'
rke2_majmin=$(echo "${RKE2_VERSION}" | sed -E -e "s/^v([0-9]+\.[0-9]+).*/\1/")
cat <<-EOF >"/etc/yum.repos.d/rancher-rke2.repo"
[rancher-rke2-common-${rke2_rpm_channel}]
name=Rancher RKE2 Common (${RKE2_VERSION})
baseurl=https://${rpm_site}/rke2/${rke2_rpm_channel}/common/centos/${maj_ver}/noarch
enabled=1
gpgcheck=1
gpgkey=https://${rpm_site}/public.key
[rancher-rke2-${rke2_majmin}-${rke2_rpm_channel}]
name=Rancher RKE2 ${rke2_majmin} (${RKE2_VERSION})
baseurl=https://${rpm_site}/rke2/${rke2_rpm_channel}/${rke2_majmin}/centos/${maj_ver}/x86_64
enabled=1
gpgcheck=1
gpgkey=https://${rpm_site}/public.key
EOF
yum install --downloadonly --downloaddir=./ rke2-server
popd
# restore air-gap configuration
${VAGRANT_SCRIPTS_DIR}/airgap.sh airgap