Compare commits
55 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 | ||
|
|
ef73fff01a | ||
|
|
0c6fdc86da |
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
@@ -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
@@ -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
@@ -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
@@ -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 -p 1
|
||||
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 }}
|
||||
|
||||
38
.github/workflows/unittest.yaml
vendored
@@ -1,41 +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
|
||||
|
||||
6
.gitignore
vendored
@@ -18,14 +18,10 @@ artifacts
|
||||
local-artifacts
|
||||
airgap-scp.sh
|
||||
|
||||
# test artifacts
|
||||
*.tar*
|
||||
*.out
|
||||
|
||||
# generated
|
||||
dist/
|
||||
tmp/
|
||||
bin/
|
||||
/store/
|
||||
/registry/
|
||||
cmd/hauler/binaries
|
||||
cmd/hauler/binaries
|
||||
|
||||
@@ -10,7 +10,7 @@ release:
|
||||
|
||||
env:
|
||||
- vpkg=github.com/rancherfederal/hauler/internal/version
|
||||
- cosign_version=v2.2.2+carbide.2
|
||||
- cosign_version=v2.2.3+carbide.1
|
||||
|
||||
builds:
|
||||
- main: cmd/hauler/main.go
|
||||
|
||||
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" ]
|
||||
2
Makefile
@@ -1,7 +1,7 @@
|
||||
SHELL:=/bin/bash
|
||||
GO_FILES=$(shell go list ./... | grep -v /vendor/)
|
||||
|
||||
COSIGN_VERSION=v2.2.2+carbide.2
|
||||
COSIGN_VERSION=v2.2.3+carbide.1
|
||||
|
||||
.SILENT:
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Rancher Government Hauler
|
||||
|
||||

|
||||

|
||||
|
||||
## Airgap Swiss Army Knife
|
||||
|
||||
|
||||
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
@@ -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
|
||||
@@ -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,12 +52,14 @@ 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
|
||||
}
|
||||
|
||||
@@ -93,18 +97,19 @@ func AddImageCmd(ctx context.Context, o *AddImageOpts, s *store.Layout, referenc
|
||||
|
||||
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(), 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
|
||||
}
|
||||
|
||||
@@ -141,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
|
||||
@@ -160,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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ func ServeRegistryCmd(ctx context.Context, o *ServeRegistryOpts, s *store.Layout
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
if err = r.ListenAndServe(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -79,8 +79,8 @@ func ServeRegistryCmd(ctx context.Context, o *ServeRegistryOpts, s *store.Layout
|
||||
type ServeFilesOpts struct {
|
||||
*RootOpts
|
||||
|
||||
Port int
|
||||
RootDir string
|
||||
Port int
|
||||
RootDir string
|
||||
|
||||
storedir string
|
||||
}
|
||||
@@ -89,7 +89,7 @@ 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", "store-files", "Directory to use for backend. Defaults to $PWD/store-files")
|
||||
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 {
|
||||
@@ -100,7 +100,7 @@ func ServeFilesCmd(ctx context.Context, o *ServeFilesOpts, s *store.Layout) erro
|
||||
if err := CopyCmd(ctx, opts, s, "dir://"+o.RootDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
cfg := server.FileConfig{
|
||||
Root: o.RootDir,
|
||||
Port: o.Port,
|
||||
@@ -110,7 +110,7 @@ func ServeFilesCmd(ctx context.Context, o *ServeFilesOpts, s *store.Layout) erro
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
l.Infof("starting file server on port [%d]", o.Port)
|
||||
if err := f.ListenAndServe(); err != nil {
|
||||
return err
|
||||
|
||||
@@ -31,6 +31,8 @@ type SyncOpts struct {
|
||||
Key string
|
||||
Products []string
|
||||
Platform string
|
||||
Registry string
|
||||
ProductRegistry string
|
||||
}
|
||||
|
||||
func (o *SyncOpts) AddFlags(cmd *cobra.Command) {
|
||||
@@ -40,6 +42,8 @@ func (o *SyncOpts) AddFlags(cmd *cobra.Command) {
|
||||
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 {
|
||||
@@ -50,7 +54,14 @@ 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,
|
||||
@@ -142,10 +153,20 @@ func processContent(ctx context.Context, fi *os.File, o *SyncOpts, s *store.Layo
|
||||
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] != "" {
|
||||
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,_ = reference.Relocate(i.Name, a[consts.ImageAnnotationRegistry])
|
||||
newRef,err = reference.Relocate(i.Name, newReg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
i.Name = newRef.Name()
|
||||
}
|
||||
@@ -156,10 +177,16 @@ func processContent(ctx context.Context, fi *os.File, o *SyncOpts, s *store.Layo
|
||||
// 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)
|
||||
|
||||
@@ -182,8 +209,7 @@ func processContent(ctx context.Context, fi *os.File, o *SyncOpts, s *store.Layo
|
||||
if i.Platform != "" {
|
||||
platform = i.Platform
|
||||
}
|
||||
l.Debugf("platform for image [%s]", platform)
|
||||
|
||||
|
||||
err = storeImage(ctx, s, i, platform)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -2,8 +2,8 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"embed"
|
||||
"os"
|
||||
|
||||
"github.com/rancherfederal/hauler/cmd/hauler/cli"
|
||||
"github.com/rancherfederal/hauler/pkg/cosign"
|
||||
@@ -23,9 +23,12 @@ func main() {
|
||||
// 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
6
go.mod
@@ -21,7 +21,7 @@ require (
|
||||
github.com/spf13/afero v1.10.0
|
||||
github.com/spf13/cobra v1.8.0
|
||||
golang.org/x/sync v0.6.0
|
||||
helm.sh/helm/v3 v3.14.1
|
||||
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
|
||||
@@ -54,7 +54,7 @@ require (
|
||||
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.1+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.5.0 // indirect
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
|
||||
@@ -154,7 +154,7 @@ require (
|
||||
google.golang.org/appengine v1.6.7 // 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.31.0 // 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
|
||||
|
||||
12
go.sum
@@ -129,8 +129,8 @@ github.com/docker/cli v25.0.1+incompatible h1:mFpqnrS6Hsm3v1k7Wa/BO23oz0k121MTbT
|
||||
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.1+incompatible h1:k5TYd5rIVQRSqcTwCID+cyVA0yRg86+Pcrz1ls0/frA=
|
||||
github.com/docker/docker v25.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
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.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
||||
@@ -888,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.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.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=
|
||||
@@ -910,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.14.1 h1:4AwRLx+wfzlPtvrsbDmWP5PUokGmf9/nAmEdk21vae8=
|
||||
helm.sh/helm/v3 v3.14.1/go.mod h1:2itvvDv2WSZXTllknfQo6j7u3VVgMAvm8POCDgYH424=
|
||||
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=
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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,21 +1,22 @@
|
||||
package cosign
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"embed"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"context"
|
||||
"time"
|
||||
"bufio"
|
||||
"embed"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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/pkg/store"
|
||||
"oras.land/oras-go/pkg/content"
|
||||
)
|
||||
|
||||
const maxRetries = 3
|
||||
@@ -24,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 := getCosignPath(ctx)
|
||||
cosignBinaryPath, err := getCosignPath()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -45,30 +46,62 @@ func VerifySignature(ctx context.Context, s *store.Layout, keyPath string, ref s
|
||||
func SaveImage(ctx context.Context, s *store.Layout, ref string, platform string) error {
|
||||
l := log.FromContext(ctx)
|
||||
operation := func() error {
|
||||
cosignBinaryPath, err := getCosignPath(ctx)
|
||||
cosignBinaryPath, err := getCosignPath()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check to see if the image is multi-arch
|
||||
isMultiArch, err := image.IsMultiArchImage(ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l.Debugf("multi-arch image: %v", isMultiArch)
|
||||
|
||||
cmd := exec.Command(cosignBinaryPath, "save", ref, "--dir", s.Root)
|
||||
// Conditionally add platform.
|
||||
if platform != "" {
|
||||
if platform != "" && isMultiArch {
|
||||
l.Debugf("platform for image [%s]", platform)
|
||||
cmd.Args = append(cmd.Args, "--platform", platform)
|
||||
}
|
||||
|
||||
output, err := cmd.CombinedOutput()
|
||||
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
if strings.Contains(string(output), "specified reference is not a multiarch image") {
|
||||
l.Debugf(fmt.Sprintf("specified image [%s] is not a multiarch image. (choosing default)", ref))
|
||||
// Rerun the command without the platform flag
|
||||
cmd = exec.Command(cosignBinaryPath, "save", ref, "--dir", s.Root)
|
||||
output, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error adding image to store: %v, output: %s", err, output)
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("error adding image to store: %v, output: %s", err, output)
|
||||
}
|
||||
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
|
||||
@@ -81,7 +114,7 @@ func SaveImage(ctx context.Context, s *store.Layout, ref string, platform string
|
||||
func LoadImages(ctx context.Context, s *store.Layout, registry string, ropts content.RegistryOptions) error {
|
||||
l := log.FromContext(ctx)
|
||||
|
||||
cosignBinaryPath, err := getCosignPath(ctx)
|
||||
cosignBinaryPath, err := getCosignPath()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -108,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() {
|
||||
@@ -141,7 +174,7 @@ 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 {
|
||||
log := log.FromContext(ctx)
|
||||
cosignBinaryPath, err := getCosignPath(ctx)
|
||||
cosignBinaryPath, err := getCosignPath()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -166,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 {
|
||||
@@ -178,14 +211,13 @@ func RetryOperation(ctx context.Context, operation func() error) error {
|
||||
return fmt.Errorf("operation failed after %d attempts", maxRetries)
|
||||
}
|
||||
|
||||
|
||||
func EnsureBinaryExists(ctx context.Context, bin embed.FS) (error) {
|
||||
func EnsureBinaryExists(ctx context.Context, bin embed.FS) error {
|
||||
// Set up a path for the binary to be copied.
|
||||
binaryPath, err := getCosignPath(ctx)
|
||||
binaryPath, err := getCosignPath()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error: %v\n", err)
|
||||
return fmt.Errorf("error: %v", err)
|
||||
}
|
||||
|
||||
|
||||
// Determine the architecture so that we pull the correct embedded binary.
|
||||
arch := runtime.GOARCH
|
||||
rOS := runtime.GOOS
|
||||
@@ -199,25 +231,24 @@ func EnsureBinaryExists(ctx context.Context, bin embed.FS) (error) {
|
||||
// retrieve the embedded binary
|
||||
f, err := bin.ReadFile(fmt.Sprintf("binaries/%s", binaryName))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error: %v\n", err)
|
||||
return fmt.Errorf("error: %v", err)
|
||||
}
|
||||
|
||||
// write the binary to the filesystem
|
||||
err = os.WriteFile(binaryPath, f, 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error: %v\n", err)
|
||||
return fmt.Errorf("error: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
// getCosignPath returns the binary path
|
||||
func getCosignPath(ctx context.Context) (string, error) {
|
||||
func getCosignPath() (string, error) {
|
||||
// Get the current user's information
|
||||
currentUser, err := user.Current()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error: %v\n", err)
|
||||
return "", fmt.Errorf("error: %v", err)
|
||||
}
|
||||
|
||||
// Get the user's home directory
|
||||
@@ -225,14 +256,14 @@ func getCosignPath(ctx context.Context) (string, error) {
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
@@ -242,7 +273,7 @@ func getCosignPath(ctx context.Context) (string, error) {
|
||||
}
|
||||
|
||||
// construct path to binary
|
||||
binaryPath := filepath.Join(haulerDir, binaryName)
|
||||
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
|
||||
|
||||
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 44 KiB |
BIN
static/rgs-hauler-logo-icon.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
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
|
After Width: | Height: | Size: 59 KiB |
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
|
After Width: | Height: | Size: 35 KiB |
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
@@ -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
@@ -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
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
@@ -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/rancher-cluster-templates-0.4.4.tgz
vendored
Normal file
@@ -1,25 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -x
|
||||
|
||||
if [ "$#" -ne 1 ] || ( [ "$1" != "internet" ] && [ "$1" != "airgap" ] ); then
|
||||
echo \
|
||||
"Enable or disable internet access in hauler's CentOS Vagrant machine.
|
||||
|
||||
Usage: $0 internet
|
||||
$0 airgap" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$1" = "internet" ]; then
|
||||
# internet: set default gateway to NAT network interface
|
||||
default_iface="eth0"
|
||||
gw_ip="10.0.2.2"
|
||||
else
|
||||
# airgap: set default gateway to private network interface
|
||||
default_iface="eth1"
|
||||
gw_ip=$(ip -f inet a show "${default_iface}" | awk 'match($0, /inet ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})/, arr) { print arr[1] }')
|
||||
fi
|
||||
|
||||
|
||||
ip r delete default
|
||||
ip r add default via ${gw_ip} dev ${default_iface} proto dhcp metric 100
|
||||
@@ -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
|
||||