mirror of
https://github.com/hauler-dev/hauler.git
synced 2026-02-19 20:40:18 +00:00
Compare commits
103 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0674e0ab30 | ||
|
|
d645c52135 | ||
|
|
44baab3213 | ||
|
|
1a317b0172 | ||
|
|
128cb3b252 | ||
|
|
91ff998634 | ||
|
|
8ac1ecaf29 | ||
|
|
7447aad20a | ||
|
|
003456d8ab | ||
|
|
f44b8b93af | ||
|
|
e405840642 | ||
|
|
8c9aa909b0 | ||
|
|
8670489520 | ||
|
|
f20d4052a4 | ||
|
|
c84bca43d2 | ||
|
|
6863d91f69 | ||
|
|
16eea6ac2a | ||
|
|
f6f227567c | ||
|
|
eb810c16f5 | ||
|
|
b18f55ea60 | ||
|
|
4bbe622073 | ||
|
|
ea5bcb36ae | ||
|
|
5c7daddfef | ||
|
|
7083f3a4f3 | ||
|
|
8541d73a0d | ||
|
|
49d705d14c | ||
|
|
722851d809 | ||
|
|
82aedc867a | ||
|
|
e8fb37c6ed | ||
|
|
545b3f8acd | ||
|
|
3ae92fe20a | ||
|
|
35538bf45a | ||
|
|
b6701bbfbc | ||
|
|
14738c3cd6 | ||
|
|
0657fd80fe | ||
|
|
d132e8b8e0 | ||
|
|
29367c152e | ||
|
|
185ae6bd74 | ||
|
|
b6c78d3925 | ||
|
|
e718d40744 | ||
|
|
1505bfb3af | ||
|
|
e27b5b3cd1 | ||
|
|
0472c8fc65 | ||
|
|
70a48f2efe | ||
|
|
bb2a8bfbec | ||
|
|
2779c649c2 | ||
|
|
8120537af2 | ||
|
|
9cdab516f0 | ||
|
|
d136d1bfd2 | ||
|
|
003560c3b3 | ||
|
|
1b9d057f7a | ||
|
|
2764e2d3ea | ||
|
|
360049fe19 | ||
|
|
79b240d17f | ||
|
|
214704bcfb | ||
|
|
ef73fff01a | ||
|
|
0c6fdc86da | ||
|
|
7fb537a31a | ||
|
|
6ca7fb6255 | ||
|
|
d70a867283 | ||
|
|
46ea8b5df9 | ||
|
|
5592ec0f88 | ||
|
|
e8254371c0 | ||
|
|
8d2a84d27c | ||
|
|
72734ecc76 | ||
|
|
4759879a5d | ||
|
|
dbcfe13fb6 | ||
|
|
cd8d4f6e46 | ||
|
|
e15c8d54fa | ||
|
|
ccd529ab48 | ||
|
|
3cf4afe6d1 | ||
|
|
0c55d00d49 | ||
|
|
6c2b97042e | ||
|
|
be22e56f27 | ||
|
|
c8ea279c0d | ||
|
|
59ff02b52b | ||
|
|
8b3398018a | ||
|
|
ae80b482e4 | ||
|
|
1ae496fb8b | ||
|
|
7919dccffc | ||
|
|
fc7a19c755 | ||
|
|
ade0feccf0 | ||
|
|
f78fdf5e3d | ||
|
|
85d6bc0233 | ||
|
|
d1499b7738 | ||
|
|
27acb239e4 | ||
|
|
e8d084847d | ||
|
|
e70379870f | ||
|
|
a05d21c052 | ||
|
|
8256aa55ce | ||
|
|
0e6c3690b1 | ||
|
|
a977cec50c | ||
|
|
5edc96d152 | ||
|
|
fbafa60da5 | ||
|
|
cc917af0f2 | ||
|
|
f76160d8be | ||
|
|
b24b25d557 | ||
|
|
d9e298b725 | ||
|
|
e14453f730 | ||
|
|
990ade9cd0 | ||
|
|
aecd37d192 | ||
|
|
02f4946ead | ||
|
|
978dc659f8 |
8
.dockerignore
Normal file
8
.dockerignore
Normal file
@@ -0,0 +1,8 @@
|
||||
*
|
||||
!cmd
|
||||
!go.mod
|
||||
!go.sum
|
||||
!internal
|
||||
!Makefile
|
||||
!pkg
|
||||
!static
|
||||
50
.github/ISSUE_TEMPLATE/bug_report.md
vendored
50
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -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 -->
|
||||
|
||||
-
|
||||
|
||||
34
.github/ISSUE_TEMPLATE/feature_request.md
vendored
34
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -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 -->
|
||||
|
||||
-
|
||||
|
||||
42
.github/PULL_REQUEST_TEMPLATE.md
vendored
42
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -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... -->
|
||||
|
||||
-
|
||||
|
||||
52
.github/workflows/release.yaml
vendored
52
.github/workflows/release.yaml
vendored
@@ -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 }}
|
||||
|
||||
40
.github/workflows/unittest.yaml
vendored
40
.github/workflows/unittest.yaml
vendored
@@ -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
7
.gitignore
vendored
@@ -18,13 +18,10 @@ artifacts
|
||||
local-artifacts
|
||||
airgap-scp.sh
|
||||
|
||||
# test artifacts
|
||||
*.tar*
|
||||
*.out
|
||||
|
||||
# generated
|
||||
dist/
|
||||
tmp/
|
||||
bin/
|
||||
/store/
|
||||
/registry/
|
||||
/registry/
|
||||
cmd/hauler/binaries
|
||||
|
||||
@@ -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
25
Dockerfile
Normal 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
177
LICENSE
Normal 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
|
||||
14
Makefile
14
Makefile
@@ -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)
|
||||
|
||||
38
README.md
38
README.md
@@ -1,32 +1,36 @@
|
||||
# Rancher Government Hauler
|
||||
|
||||

|
||||
|
||||
## 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)
|
||||
|
||||
50
ROADMAP.md
50
ROADMAP.md
@@ -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
|
||||
49
VAGRANT.md
49
VAGRANT.md
@@ -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
65
Vagrantfile
vendored
@@ -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
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
75
cmd/hauler/cli/login.go
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
21
deploy/kubernetes/helm/charts/hauler/.helmignore
Normal file
21
deploy/kubernetes/helm/charts/hauler/.helmignore
Normal 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/
|
||||
7
deploy/kubernetes/helm/charts/hauler/Chart.yaml
Normal file
7
deploy/kubernetes/helm/charts/hauler/Chart.yaml
Normal 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
|
||||
33
deploy/kubernetes/helm/charts/hauler/README.md
Normal file
33
deploy/kubernetes/helm/charts/hauler/README.md
Normal 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
|
||||
```
|
||||
33
deploy/kubernetes/helm/charts/hauler/app-readme.md
Normal file
33
deploy/kubernetes/helm/charts/hauler/app-readme.md
Normal 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
|
||||
```
|
||||
62
deploy/kubernetes/helm/charts/hauler/templates/_helpers.tpl
Normal file
62
deploy/kubernetes/helm/charts/hauler/templates/_helpers.tpl
Normal 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 }}
|
||||
@@ -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 }}
|
||||
@@ -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 }}
|
||||
@@ -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 }}
|
||||
@@ -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 }}
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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 }}
|
||||
@@ -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 }}
|
||||
@@ -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 }}
|
||||
@@ -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 }}
|
||||
94
deploy/kubernetes/helm/charts/hauler/values.yaml
Normal file
94
deploy/kubernetes/helm/charts/hauler/values.yaml
Normal 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
83
go.mod
@@ -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
183
go.sum
@@ -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=
|
||||
|
||||
106
install.sh
106
install.sh
@@ -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"
|
||||
|
||||
@@ -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 = "."
|
||||
}
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
BIN
static/rgs-hauler-logo-icon.png
Normal file
BIN
static/rgs-hauler-logo-icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
38
static/rgs-hauler-logo-icon.svg
Normal file
38
static/rgs-hauler-logo-icon.svg
Normal 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 |
BIN
static/rgs-hauler-logo-stacked.png
Normal file
BIN
static/rgs-hauler-logo-stacked.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 59 KiB |
52
static/rgs-hauler-logo-stacked.svg
Normal file
52
static/rgs-hauler-logo-stacked.svg
Normal 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
BIN
static/rgs-hauler-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
51
static/rgs-hauler-logo.svg
Normal file
51
static/rgs-hauler-logo.svg
Normal 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 |
23
testdata/chart-collection.yaml
vendored
23
testdata/chart-collection.yaml
vendored
@@ -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
|
||||
56
testdata/contents.yaml
vendored
56
testdata/contents.yaml
vendored
@@ -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
BIN
testdata/haul.tar.zst
vendored
Normal file
Binary file not shown.
26
testdata/hauler-manifest.yaml
vendored
Normal file
26
testdata/hauler-manifest.yaml
vendored
Normal 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
|
||||
13
testdata/k3s-collection.yaml
vendored
13
testdata/k3s-collection.yaml
vendored
@@ -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
|
||||
BIN
testdata/podinfo-6.0.3.tgz
vendored
BIN
testdata/podinfo-6.0.3.tgz
vendored
Binary file not shown.
BIN
testdata/rancher-cluster-templates-0.4.4.tgz
vendored
Normal file
BIN
testdata/rancher-cluster-templates-0.4.4.tgz
vendored
Normal file
Binary file not shown.
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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}"
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user