This commit is contained in:
Josh Wolf
2021-05-29 00:05:39 -06:00
parent 2c1e73fd5d
commit 751e0f6865
44 changed files with 504 additions and 1086 deletions
@@ -1 +0,0 @@
{"architecture":"amd64","config":{"Hostname":"","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"ExposedPorts":{"5000/tcp":{}},"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/etc/docker/registry/config.yml"],"Image":"sha256:16d08570c8f60bc500abc6aa8de40dc570f76849f4e09e92dfb73eccd616b9ac","Volumes":{"/var/lib/registry":{}},"WorkingDir":"","Entrypoint":["/entrypoint.sh"],"OnBuild":null,"Labels":null},"container":"2a7522517dbdc8460dafc3c829a1af17303b46f4efdb87319e7237fc22b5e809","container_config":{"Hostname":"2a7522517dbd","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"ExposedPorts":{"5000/tcp":{}},"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/sh","-c","#(nop) ","CMD [\"/etc/docker/registry/config.yml\"]"],"Image":"sha256:16d08570c8f60bc500abc6aa8de40dc570f76849f4e09e92dfb73eccd616b9ac","Volumes":{"/var/lib/registry":{}},"WorkingDir":"","Entrypoint":["/entrypoint.sh"],"OnBuild":null,"Labels":{}},"created":"2021-04-15T02:47:06.008149989Z","docker_version":"19.03.12","history":[{"created":"2021-04-14T19:19:56.19548415Z","created_by":"/bin/sh -c #(nop) ADD file:282b9d56236cae29600bf8b698cb0a865ab17db7beea0be6870f9de63e7d4f80 in / "},{"created":"2021-04-14T19:19:56.41508347Z","created_by":"/bin/sh -c #(nop) CMD [\"/bin/sh\"]","empty_layer":true},{"created":"2021-04-15T02:47:02.917510551Z","created_by":"/bin/sh -c set -ex \u0026\u0026 apk add --no-cache ca-certificates"},{"created":"2021-04-15T02:47:03.775592191Z","created_by":"/bin/sh -c #(nop) COPY file:21256ff7df5369f7ad2e19c6d020a644303aded200bdbec4d46648f38d55df78 in /bin/registry "},{"created":"2021-04-15T02:47:04.209181789Z","created_by":"/bin/sh -c #(nop) COPY file:4544cc1555469403b322faecc1cf1ca584667c43a6a60b17300f97840c04196e in /etc/docker/registry/config.yml "},{"created":"2021-04-15T02:47:04.475173565Z","created_by":"/bin/sh -c #(nop) VOLUME [/var/lib/registry]","empty_layer":true},{"created":"2021-04-15T02:47:04.891850515Z","created_by":"/bin/sh -c #(nop) EXPOSE 5000","empty_layer":true},{"created":"2021-04-15T02:47:05.327358635Z","created_by":"/bin/sh -c #(nop) COPY file:507caa54f88c1f3862e5876e09a108b2083630ba24c57ad124e356a2de861d62 in /entrypoint.sh "},{"created":"2021-04-15T02:47:05.670828729Z","created_by":"/bin/sh -c #(nop) ENTRYPOINT [\"/entrypoint.sh\"]","empty_layer":true},{"created":"2021-04-15T02:47:06.008149989Z","created_by":"/bin/sh -c #(nop) CMD [\"/etc/docker/registry/config.yml\"]","empty_layer":true}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:9a5d14f9f5503e55088666beef7e85a8d9625d4fa7418e2fe269e9c54bcb853c","sha256:de9819405bcf1beb534c0049077f51160af2cec312a812e8c2f091fba1f9c306","sha256:b4592cba0628522e3e5aeac4dd6733405d92e6e106dfde5acb266eefc41c8569","sha256:3764c3e89288ef5786f440a66a5981593ddceb8b273ec9465f45c1758d64ced3","sha256:7b9a3910f3c3cddca51015d4dc228a39660e5f1e1bf93a8aa9053b65a271297e"]}}
@@ -1,36 +0,0 @@
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"config": {
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": 3112,
"digest": "sha256:1fd8e1b0bb7ef6cc63e0094e2fb5a35259bdce7041ef5e7e4c99694ded1041d7"
},
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 2816246,
"digest": "sha256:ddad3d7c1e96adf9153f8921a7c9790f880a390163df453be1566e9ef0d546e0"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 299663,
"digest": "sha256:6eda6749503f60eb69077e148cba1015ec5808b0c1c2e6f027f7d1b960f6a3a9"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 6823927,
"digest": "sha256:363ab70c2143bc121f037ba432cede225b7053200abba2a7a4ca24c2915a3998"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 402,
"digest": "sha256:5b94580856e6fd27a74d55ab33fc3b53fd6f599f7147f38845a2482cc003cc19"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 213,
"digest": "sha256:12008541203a024dab3a30542c87421e5a27dbb601b9c6f029b3827af138ccb3"
}
]
}
@@ -1 +0,0 @@
{"architecture":"amd64","config":{"Hostname":"","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/sh"],"Image":"sha256:d3d4554f8b07cf59894bfb3551e10f89a559b24ee0992c4900c54175596b1389","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"container":"60a3cdd128a8b373b313ed3e1083ff45e6badaad5dca5187282b005c38d04712","container_config":{"Hostname":"60a3cdd128a8","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/sh","-c","#(nop) ","CMD [\"/bin/sh\"]"],"Image":"sha256:d3d4554f8b07cf59894bfb3551e10f89a559b24ee0992c4900c54175596b1389","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":{}},"created":"2021-04-14T19:19:39.643236135Z","docker_version":"19.03.12","history":[{"created":"2021-04-14T19:19:39.267885491Z","created_by":"/bin/sh -c #(nop) ADD file:8ec69d882e7f29f0652d537557160e638168550f738d0d49f90a7ef96bf31787 in / "},{"created":"2021-04-14T19:19:39.643236135Z","created_by":"/bin/sh -c #(nop) CMD [\"/bin/sh\"]","empty_layer":true}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:b2d5eeeaba3a22b9b8aa97261957974a6bd65274ebd43e1d81d0a7b8b752b116"]}}
@@ -1,16 +0,0 @@
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"config": {
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": 1472,
"digest": "sha256:6dbb9cc54074106d46d4ccb330f2a40a682d49dda5f4844962b7dce9fe44aaec"
},
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 2811969,
"digest": "sha256:540db60ca9383eac9e418f78490994d0af424aab7bf6d0e47ac8ed4e2e9bcbba"
}
]
}
-21
View File
@@ -1,21 +0,0 @@
{
"schemaVersion": 2,
"manifests": [
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 528,
"digest": "sha256:def822f9851ca422481ec6fee59a9966f12b351c62ccb9aca841526ffaa9f748",
"annotations": {
"org.opencontainers.image.ref.name": "index.docker.io/library/alpine:latest"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 1363,
"digest": "sha256:42043edfae481178f07aa077fa872fcc242e276d302f4ac2026d9d2eb65b955f",
"annotations": {
"org.opencontainers.image.ref.name": "index.docker.io/library/registry:2.7.1"
}
}
]
}
-3
View File
@@ -1,3 +0,0 @@
{
"imageLayoutVersion": "1.0.0"
}
+38 -5
View File
@@ -1,13 +1,18 @@
package app
import (
"fmt"
"context"
"github.com/mholt/archiver/v3"
"github.com/rancherfederal/hauler/pkg/apis/haul"
"github.com/rancherfederal/hauler/pkg/bootstrap"
"github.com/spf13/cobra"
"gopkg.in/yaml.v3"
"os"
"path/filepath"
)
type deployOpts struct {
haul string
haulerDir string
}
// NewBootstrapCommand create a new sub command of haulerctl that bootstraps a cluster
@@ -26,11 +31,39 @@ func NewBootstrapCommand() *cobra.Command {
},
}
f := cmd.Flags()
f.StringVarP(&opts.haulerDir, "hauler-dir", "", "/opt/hauler", "Directory to install hauler components in")
return cmd
}
// Run performs the operation.
func (o *deployOpts) Run(haul string) error {
fmt.Println("Bootstrap")
func (o *deployOpts) Run(haulPath string) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
z := archiver.NewTarZstd()
z.OverwriteExisting = true
z.MkdirAll = true
err := z.Unarchive(haulPath, o.haulerDir)
if err != nil {
return err
}
haulerCfgPath := filepath.Join(o.haulerDir, "hauler.yaml")
data, err := os.ReadFile(haulerCfgPath)
var h haul.Haul
if err := yaml.Unmarshal(data, &h); err != nil {
return err
}
bstrp := bootstrap.NewBootstrapper(h, o.haulerDir)
err = bstrp.Bootstrap(ctx)
if err != nil {
return err
}
return nil
}
+24 -16
View File
@@ -1,16 +1,17 @@
package app
import (
"bytes"
"context"
"github.com/rancherfederal/hauler/pkg/apis/bundle"
"github.com/imdario/mergo"
"github.com/rancherfederal/hauler/pkg/apis/driver"
"github.com/rancherfederal/hauler/pkg/apis/haul"
"github.com/rancherfederal/hauler/pkg/apis/hauler.cattle.io/v1alpha1"
"github.com/rancherfederal/hauler/pkg/packager"
"github.com/rancherfederal/hauler/pkg/create"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"k8s.io/apimachinery/pkg/util/json"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type createOpts struct {
@@ -26,7 +27,7 @@ func NewCreateCommand() *cobra.Command {
opts := &createOpts{}
cmd := &cobra.Command{
Use: "package",
Use: "create",
Short: "package all dependencies into a compressed archive",
Long: `package all dependencies into a compressed archive used by deploy.
@@ -74,20 +75,27 @@ func (o *createOpts) Run() error {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
cluster := v1alpha1.NewDefaultCluster(o.driver)
// Merge user defined config with default config
// TODO: This should be done with types... but we'll need mergo for more stuff so lazy approach here
if err := mergo.Merge(cluster, o.userClusterConfig, mergo.WithOverride); err != nil {
return err
d := driver.K3sDriver{
Version: "v1.21.1+k3s1",
Config: driver.K3sConfig{},
}
d, _ := json.Marshal(cluster)
buf := bytes.NewReader(d)
viper.ReadConfig(buf)
h := haul.Haul{
TypeMeta: metav1.TypeMeta{},
Metadata: metav1.ObjectMeta{
Name: "haul",
},
Spec: haul.HaulSpec{
Driver: d,
Bundles: []bundle.Bundle{
bundle.CreateDriverBundle(d),
{ Name: "test", Path: "testdata/bundle-a" },
},
},
}
pkg := packager.NewPackager(cluster)
if err := pkg.Package(ctx, o.outputFile); err != nil {
creator, _ := create.NewCreator()
if err := creator.Create(ctx, h); err != nil {
return err
}
+7 -4
View File
@@ -8,17 +8,20 @@ require (
github.com/go-git/go-git/v5 v5.4.0
github.com/google/go-cmp v0.5.5 // indirect
github.com/google/go-containerregistry v0.4.1
github.com/imdario/mergo v0.3.12
github.com/klauspost/compress v1.12.2 // indirect
github.com/mholt/archiver/v3 v3.5.0
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/pelletier/go-toml v1.8.1 // indirect
github.com/mitchellh/go-homedir v1.1.0
github.com/opencontainers/image-spec v1.0.1
github.com/oras-project/oras-go v0.1.0
github.com/pterm/pterm v0.12.18
github.com/rogpeppe/go-internal v1.3.0
github.com/rs/zerolog v1.22.0
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.1.3
github.com/spf13/viper v1.7.0
github.com/ulikunitz/xz v0.5.8 // indirect
go.uber.org/multierr v1.7.0 // indirect
go.uber.org/zap v1.16.0
go.uber.org/zap v1.16.0 // indirect
golang.org/x/net v0.0.0-20210521195947-fe42d452be8f
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20210521203332-0cec03c779c1 // indirect
+15 -5
View File
@@ -44,7 +44,6 @@ github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6L
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=
@@ -101,6 +100,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/atomicgo/cursor v0.0.1 h1:xdogsqa6YYlLfM+GyClC/Lchf7aiMerFiZQn7soTOoU=
github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk=
github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@@ -491,6 +492,8 @@ github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1a
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
github.com/googleapis/gnostic v0.5.1 h1:A8Yhf6EtqTv9RMsU6MQTyrtV1TjWlR6xU9BsZIwuTCM=
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
github.com/gookit/color v1.4.2 h1:tXy44JFSFkKnELV6WaMo/lLfu/meqITX3iAV52do7lk=
github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
@@ -609,6 +612,8 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.12 h1:Y41i/hVW3Pgwr8gV+J23B9YEY0zxjptBuCWEaxmAOow=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI=
@@ -760,7 +765,13 @@ github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/pterm/pterm v0.12.18 h1:lGPcpzyWQhPZS7N0NQWHLA5Q4GiZ5OBiQ3m/NiNOcJM=
github.com/pterm/pterm v0.12.18/go.mod h1:KJSTVufsT+4ByOegmntwkTvDGpDhNQQG7034Klkn9kc=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.22.0 h1:XrVUjV4K+izZpKXZHlPrYQiDtmdGiCylnT4i43AAWxg=
@@ -869,6 +880,8 @@ github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMx
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -953,7 +966,6 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
@@ -962,7 +974,6 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1101,6 +1112,7 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210521203332-0cec03c779c1 h1:lCnv+lfrU9FRPGf8NeRuWAAPjNnema5WtBinMgs1fD8=
@@ -1175,7 +1187,6 @@ golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a h1:CB3a9Nez8M13wwlr/E2YtwoU+qYHKfC+JrDa45RXXoQ=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1307,7 +1318,6 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78=
k8s.io/api v0.18.10/go.mod h1:xWtwPX1v47j5RTncmlMFGCx8b0avh+nP8OgZZ9hjo3M=
+132
View File
@@ -0,0 +1,132 @@
package bundle
import (
"github.com/rancherfederal/hauler/pkg/apis/driver"
"github.com/rancherfederal/hauler/pkg/util"
"github.com/sirupsen/logrus"
"io/fs"
"os"
"path/filepath"
"strings"
)
const (
AutodeployDirectory = "autodeploy"
StaticDirectory = "static"
ImagePreloadDirectory = "images"
)
type Bundle struct {
Name string `yaml:"name"`
Path string `yaml:"path"`
Images []string
}
func CreateDriverBundle(d driver.Driver) Bundle {
return Bundle{
Name: d.Name(),
Path: "",
Images: d.Images(),
}
}
func (b Bundle) CreateLayout(root string) *util.FSLayout {
l := util.NewLayout(root)
l.AddDir(AutodeployDirectory, os.ModePerm)
l.AddDir(StaticDirectory, os.ModePerm)
l.AddDir(ImagePreloadDirectory, os.ModePerm)
return l
}
//ResolveBundle will resolve all provided references
func (b *Bundle) ResolveBundleFromPath() error {
if b.Path == "" {
//Only need to resolve bundles that are sourced from a directory
return nil
}
if _, err := os.Stat(b.Path); os.IsNotExist(err) {
return err
}
manifestsPath := filepath.Join(b.Path, AutodeployDirectory)
err := filepath.WalkDir(manifestsPath, func(path string, d fs.DirEntry, err error) error {
if d.IsDir() { return nil }
ext := filepath.Ext(path)
if !(strings.HasSuffix(ext, "yaml") || strings.HasSuffix(ext, "yml")) { return nil }
//TODO: Identify Images from manifests
return nil
})
if err != nil {
return err
}
imagesPath := filepath.Join(b.Path, ImagePreloadDirectory)
err = filepath.WalkDir(imagesPath, func(path string, d fs.DirEntry, err error) error {
if d.IsDir() { return nil }
ext := filepath.Ext(path)
if strings.HasSuffix(ext, "txt") {
//Try reading as text line
f, err := os.Open(path)
if err != nil {
return err
}
imgs, err := util.LinesToSlice(f)
b.Images = append(b.Images, imgs...)
}
return nil
})
if err != nil {
return err
}
return nil
}
func (b Bundle) Setup(d driver.Driver, path string) error {
cwd, err := os.Getwd()
if err != nil {
return err
}
defer os.Chdir(cwd)
err = os.Chdir(path)
if err != nil {
return err
}
targetStatic := filepath.Join(d.VarPath(), d.AnonymousStaticPath(), b.Name)
if err := safeSymlink(StaticDirectory, targetStatic); err != nil {
return err
}
targetImages := filepath.Join(d.VarPath(), d.PreloadImagesPath(), b.Name)
if err := safeSymlink(ImagePreloadDirectory, targetImages); err != nil {
return err
}
targetManifests := filepath.Join(d.VarPath(), d.AutodeployManifestsPath(), b.Name)
if err := safeSymlink(AutodeployDirectory, targetManifests); err != nil {
return err
}
return nil
}
func safeSymlink(src, dst string) error {
logrus.Infof("symlinking %s to %s", src, dst)
if _, err := os.Stat(dst); err == nil {
if err := os.RemoveAll(dst); err != nil {
return err
}
}
return os.Symlink(src, dst)
}
+7 -23
View File
@@ -1,13 +1,9 @@
package driver
import (
"bufio"
"io"
)
const (
EtcPath = "/etc/rancher"
ExecutableBin = "hauler/bin"
VarBasePath = "/var/lib/rancher"
ExecutableBin = "bin"
)
type Driver interface {
@@ -18,24 +14,12 @@ type Driver interface {
AutodeployManifestsPath() string
PreloadImagesPath() string
AnonymousStaticPath() string
VarPath() string
}
type DriverConfig struct {
NodeName string `json:"node-name" yaml:"node-name"`
KubeConfigMode string `json:"write-kubeconfig-mode" yaml:"write-kubeconfig-mode"`
NodeLabels []string `json:"node-label" yaml:"node-label"`
}
func linesToSlice(r io.ReadCloser) ([]string, error) {
var lines []string
scanner := bufio.NewScanner(r)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if err := scanner.Err(); err != nil {
return nil, err
}
return lines, nil
NodeName string `yaml:"node-name"`
KubeConfigMode string `yaml:"write-kubeconfig-mode"`
NodeLabels []string `yaml:"node-label"`
}
+9 -7
View File
@@ -2,6 +2,7 @@ package driver
import (
"fmt"
"github.com/rancherfederal/hauler/pkg/util"
"net/http"
"path/filepath"
)
@@ -17,13 +18,13 @@ const (
)
type K3sDriver struct {
Version string `json:"version" yaml:"version"`
Version string `yaml:"version"`
Config K3sConfig `json:"config"`
Config K3sConfig
}
type K3sConfig struct {
DriverConfig
DriverConfig `yaml:"config,inline"`
}
func (k K3sDriver) Name() string { return k3sDriverName }
@@ -35,7 +36,7 @@ func (k K3sDriver) Images() []string {
}
defer resp.Body.Close()
images, err := linesToSlice(resp.Body)
images, err := util.LinesToSlice(resp.Body)
if err != nil {
panic("failed getting images")
}
@@ -44,6 +45,7 @@ func (k K3sDriver) Images() []string {
}
func (k K3sDriver) ReleaseArtifactsURL() string { return fmt.Sprintf("%s/%s", K3sDefaultReleasesURL, k.Version) }
func (k K3sDriver) PreloadImagesPath() string { return filepath.Join(k3sDriverName, "agent/images") }
func (k K3sDriver) AutodeployManifestsPath() string { return filepath.Join(k3sDriverName, "server/manifests") }
func (k K3sDriver) AnonymousStaticPath() string { return filepath.Join(k3sDriverName, "server/static") }
func (k K3sDriver) PreloadImagesPath() string { return "agent/images" }
func (k K3sDriver) AutodeployManifestsPath() string { return "server/manifests" }
func (k K3sDriver) AnonymousStaticPath() string { return "server/static" }
func (k K3sDriver) VarPath() string { return filepath.Join(VarBasePath, k.Name()) }
+21 -5
View File
@@ -1,19 +1,35 @@
package haul
import (
"github.com/rancherfederal/hauler/pkg/apis/bundle"
"github.com/rancherfederal/hauler/pkg/apis/driver"
"github.com/rancherfederal/hauler/pkg/util"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"os"
"path/filepath"
)
type Haul struct {
metav1.TypeMeta `json:",inline" yaml:",inline"`
Metadata metav1.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
metav1.TypeMeta `yaml:",inline"`
Metadata metav1.ObjectMeta `yaml:"metadata,omitempty"`
Spec HaulSpec `json:"spec" yaml:"spec"`
Spec HaulSpec `yaml:"spec"`
}
type HaulSpec struct {
Driver driver.Driver
Driver driver.K3sDriver `yaml:"driver"`
PreloadImages []string `json:"preloadedImages" yaml:"preloadedImages"`
Bundles []bundle.Bundle `yaml:"bundles"`
}
func (h Haul) CreateLayout(root string) *util.FSLayout {
l := util.NewLayout(root)
l.AddDir("bin", os.ModePerm)
for _, b := range h.Spec.Bundles {
bundlePath := filepath.Join("bundles", b.Name)
l.AddDir(bundlePath, os.ModePerm)
}
return l
}
-49
View File
@@ -1,49 +0,0 @@
package archive
import (
"fmt"
"github.com/mholt/archiver/v3"
"os"
"path/filepath"
)
type Archiver interface {
// TODO: This isn't the greatest interface...
Archive([]string, string) error
String() string
}
type zstdArchiver archiver.TarZstd
func NewArchiver() *archiver.TarZstd {
z := &archiver.TarZstd{
Tar: &archiver.Tar{
OverwriteExisting: true,
MkdirAll: true,
ImplicitTopLevelFolder: false,
StripComponents: 0,
ContinueOnError: false,
},
}
return z
}
func CompressAndArchive(a Archiver, source string, dest string) error {
cwd, err := os.Getwd()
if err != nil {
return err
}
err = os.Chdir(source)
if err != nil {
return err
}
defer os.Chdir(cwd)
archivePath := filepath.Join(cwd, fmt.Sprintf("%s.%s", dest, a.String()))
if err := a.Archive([]string{"."}, archivePath); err != nil {
return err
}
return nil
}
+82 -20
View File
@@ -2,46 +2,108 @@ package bootstrap
import (
"context"
"embed"
"fmt"
"github.com/rancherfederal/hauler/pkg/apis/driver"
"github.com/rancherfederal/hauler/pkg/apis/haul"
"github.com/rancherfederal/hauler/pkg/archive"
"github.com/rancherfederal/hauler/pkg/util"
"io/fs"
"os"
"os/exec"
"path/filepath"
"strings"
)
//go:embed bin/*
var e embed.FS
type bootstrapper struct {
haul haul.Haul
dir string
}
func NewBootstrapper(haulPath string) *bootstrapper {
tmpdir, err := os.MkdirTemp("", "hauler")
if err != nil {
return nil
}
defer os.Remove(tmpdir)
a := archive.NewArchiver()
err = a.Unarchive(haulPath, tmpdir)
var h haul.Haul
func NewBootstrapper(h haul.Haul, haulerDir string) *bootstrapper {
return &bootstrapper{
haul: h,
dir: haulerDir,
}
}
func (b bootstrapper) Bootstrap(ctx context.Context) error {
a := archive.NewArchiver()
_ = a
tmpdir, err := os.MkdirTemp("", "hauler")
if err != nil {
if err := b.renderEmbeddedDriverInit(); err != nil {
return err
}
defer os.Remove(tmpdir)
err = a.Unarchive(".", tmpdir)
if err := b.createLayout(); err != nil {
return err
}
for _, bndl := range b.haul.Spec.Bundles {
bundleBasePath := filepath.Join(b.dir, "bundles", bndl.Name)
err := bndl.Setup(b.haul.Spec.Driver, bundleBasePath)
if err != nil {
return err
}
}
err := StartDriver(b.haul.Spec.Driver)
if err != nil {
return err
}
return nil
}
func (b bootstrapper) renderEmbeddedDriverInit() error {
err := fs.WalkDir(e, "bin", func(path string, d fs.DirEntry, err error) error {
if d.IsDir() {
return nil
}
if strings.Contains(path, b.haul.Spec.Driver.Name()) {
data, err := fs.ReadFile(e, path)
if err != nil {
return err
}
renderedFile := filepath.Join(b.dir, path)
err = os.WriteFile(renderedFile, data, 0755)
if err != nil {
return err
}
}
return nil
})
if err != nil {
return err
}
return nil
}
func (b bootstrapper) createLayout() error {
l := util.NewLayout(b.haul.Spec.Driver.VarPath())
l.AddDir("server/static", 0700)
l.AddDir("server/manifests", 0755)
l.AddDir("agent/images", 0755)
return l.Create()
}
func StartDriver(d driver.Driver) error {
cmd := exec.Command("/bin/sh", "/opt/hauler/bin/k3s-init.sh")
cmd.Env = append(os.Environ(), []string{
"INSTALL_K3S_SKIP_DOWNLOAD=true",
"INSTALL_K3S_SELINUX_WARN=true",
"INSTALL_K3S_SKIP_SELINUX_RPM=true",
"INSTALL_K3S_BIN_DIR=/opt/hauler/bin",
"INSTALL_K3S_SKIP_START=true",
}...)
out, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("with driver: %s\n%v", out, err)
}
fmt.Println(string(out))
return nil
}
-145
View File
@@ -1,145 +0,0 @@
package bundle
import (
"context"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/empty"
"github.com/google/go-containerregistry/pkg/v1/layout"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/sirupsen/logrus"
"os"
)
const refNameAnnotation = "org.opencontainers.image.ref.name"
type LayoutStore struct {
Dir string
layout layout.Path
logger *logrus.Entry
client *Client
}
type Client struct {
}
func NewLayoutStore(path string) *LayoutStore {
lp, err := createLayoutIfNotExists(path)
if err != nil {
return nil
}
return &LayoutStore{
Dir: path,
layout: lp,
logger: logrus.WithFields(logrus.Fields{
"store": "hauler",
}),
}
}
func createLayoutIfNotExists(path string) (layout.Path, error) {
if _, err := os.Stat(path); err != nil {
if !os.IsNotExist(err) {
return "", err
}
if err := os.MkdirAll(path, 0755); err != nil {
return "", err
}
}
lp, err := layout.Write(path, empty.Index)
if err != nil {
return "", err
}
return lp, nil
}
func (l *LayoutStore) Add(ctx context.Context, imageName string) error {
ref, err := name.ParseReference(imageName)
if err != nil {
return err
}
img, err := remote.Image(ref, remote.WithAuthFromKeychain(authn.DefaultKeychain))
if err != nil {
return err
}
if err := l.appendImage(img, ref); err != nil {
return err
}
return nil
}
func (l *LayoutStore) Find(ctx context.Context, imageName string) error {
//ii, err := l.layout.ImageIndex()
//if err != nil {
// return err
//}
//
//im, err := ii.IndexManifest()
//if err != nil {
// return err
//}
//
//for _, m := range im.Manifests {
// if ref, ok := m.Annotations[refNameAnnotation]; ok {
// r, err := l.layout.Image(m.Digest)
// if err != nil {
// return err
// }
// if r == imageName {
// return
// }
// }
//}
return nil
}
func (l *LayoutStore) appendImage(img v1.Image, ref name.Reference, options ...layout.Option) error {
if err := l.layout.WriteImage(img); err != nil {
return err
}
mt, err := img.MediaType()
if err != nil {
return err
}
d, err := img.Digest()
if err != nil {
return err
}
manifest, err := img.RawManifest()
if err != nil {
return err
}
annotations := map[string]string{
refNameAnnotation: ref.Name(),
}
desc := v1.Descriptor{
MediaType: mt,
Size: int64(len(manifest)),
Digest: d,
URLs: nil,
Annotations: annotations,
Platform: nil,
}
for _, opt := range options {
if err := opt(&desc); err != nil {
return err
}
}
return l.layout.AppendDescriptor(desc)
}
+5 -5
View File
@@ -28,7 +28,7 @@ func NewCopier(path string, media string) *Copier {
return &Copier{
Dir: path,
fileStore: fs,
fileStore: *fs,
mediaType: media,
logger: logrus.WithFields(logrus.Fields{
"store": "hauler",
@@ -36,13 +36,13 @@ func NewCopier(path string, media string) *Copier {
}
}
func createFileStoreIfNotExists(path string) (content.FileStore, error) {
func createFileStoreIfNotExists(path string) (*content.FileStore, error) {
if _, err := os.Stat(path); err != nil {
if !os.IsNotExist(err) {
return "", err
return nil, err
}
if err := os.MkdirAll(path, 0755); err != nil {
return "", err
return nil, err
}
}
@@ -62,7 +62,7 @@ func (c Copier) Get(ctx context.Context, src string) error {
// Pull file(s) from registry and save to disk
fmt.Printf("Pulling from %s and saving to %s...\n", src, c.Dir)
allowedMediaTypes := []string{(c.mediaType)}
desc, _, err := oras.Pull(ctx, resolver, src, c.fileStore, oras.WithAllowedMediaTypes(allowedMediaTypes))
desc, _, err := oras.Pull(ctx, resolver, src, &c.fileStore, oras.WithAllowedMediaTypes(allowedMediaTypes))
if err != nil {
return err
+8
View File
@@ -0,0 +1,8 @@
package create
import "github.com/rancherfederal/hauler/pkg/apis/bundle"
func ResolveBundle(b bundle.Bundle) error {
return nil
}
+53 -74
View File
@@ -3,25 +3,22 @@ package create
import (
"context"
"fmt"
"github.com/rancherfederal/hauler/pkg/apis/driver"
"github.com/rancherfederal/hauler/pkg/apis/haul"
"github.com/rancherfederal/hauler/pkg/archive"
"github.com/rancherfederal/hauler/pkg/fetcher"
"github.com/rancherfederal/hauler/pkg/log"
"github.com/rs/zerolog"
"k8s.io/apimachinery/pkg/util/json"
"github.com/mholt/archiver/v3"
"github.com/rancherfederal/hauler/pkg/apis/bundle"
"github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
"os"
"path/filepath"
"github.com/rancherfederal/hauler/pkg/apis/driver"
"github.com/rancherfederal/hauler/pkg/apis/haul"
"github.com/rancherfederal/hauler/pkg/fetcher"
)
type Creator struct {
logger zerolog.Logger
}
type Creator struct{}
func NewCreator(logger zerolog.Logger) (*Creator, error) {
return &Creator{
logger: logger,
}, nil
func NewCreator() (*Creator, error) {
return &Creator{}, nil
}
func (c Creator) Create(ctx context.Context, h haul.Haul) error {
@@ -31,27 +28,50 @@ func (c Creator) Create(ctx context.Context, h haul.Haul) error {
}
defer os.Remove(tmpdir)
if err := c.buildHaulLayout(h.Spec.Driver, tmpdir); err != nil {
layout := h.CreateLayout(tmpdir)
if err := layout.Create(); err != nil {
return err
}
if err := c.stamp(h.Spec.Driver, tmpdir); err != nil {
return err
}
err = saveDriverExecutable(ctx, h.Spec.Driver, tmpdir, &c.logger)
err = saveDriverExecutable(ctx, h.Spec.Driver, tmpdir)
if err != nil {
return err
}
archivePath := filepath.Join(tmpdir, h.Spec.Driver.PreloadImagesPath(), fmt.Sprintf("%s.tar", h.Metadata.Name))
err = SavePreloadImages(ctx, h, archivePath, &c.logger)
if err != nil {
return err
for _, b := range h.Spec.Bundles {
logrus.Infof("Packaging bundle %s", b.Name)
err = b.ResolveBundleFromPath()
if err != nil {
return err
}
bundlePath := filepath.Join(tmpdir, "bundles", b.Name)
bl := b.CreateLayout(bundlePath)
if err := bl.Create(); err != nil {
return err
}
imagesPath := filepath.Join(bundlePath, bundle.ImagePreloadDirectory, fmt.Sprintf("%s.tar", b.Name))
err = SavePreloadImages(ctx, b.Images, imagesPath)
if err != nil {
return err
}
}
a := archive.NewArchiver()
err = archive.CompressAndArchive(a, tmpdir, h.Metadata.Name)
if data, err := yaml.Marshal(h); err != nil {
return err
} else {
haulerConfigPath := filepath.Join(tmpdir, "hauler.yaml")
err = os.WriteFile(haulerConfigPath, data, os.ModePerm)
if err != nil {
return err
}
}
zstd := archiver.NewTarZstd()
zstd.OverwriteExisting = true
err = layout.Archive(zstd, h.Metadata.Name)
if err != nil {
return err
}
@@ -59,54 +79,8 @@ func (c Creator) Create(ctx context.Context, h haul.Haul) error {
return nil
}
func (c Creator) stamp(d driver.Driver, dir string) error {
data, err := json.Marshal(d)
if err != nil {
return err
}
haulerCfgFile := filepath.Join(dir, "hauler.json")
err = os.WriteFile(haulerCfgFile, data, 0644)
if err != nil {
return err
}
return nil
}
func (c Creator) buildHaulLayout(d driver.Driver, dir string) error {
c.logger.Info().Msgf("building package layout in %s", dir)
preloadImagesPath := filepath.Join(dir, d.PreloadImagesPath())
c.logger.Debug().Msgf("Creating directory for preloaded images: %s", preloadImagesPath)
if err := os.MkdirAll(preloadImagesPath, 0755); err != nil {
return err
}
autodeployManifestsPath := filepath.Join(dir, d.AutodeployManifestsPath())
c.logger.Debug().Msgf("Creating directory for autodeployed resources: %s", autodeployManifestsPath)
if err := os.MkdirAll(autodeployManifestsPath, 0700); err != nil {
return err
}
anonymousStaticPath := filepath.Join(dir, d.AnonymousStaticPath())
c.logger.Debug().Msgf("Creating directory for content to host anonymously: %s", anonymousStaticPath)
if err := os.MkdirAll(anonymousStaticPath, 0700); err != nil {
return err
}
driverExecutablePath := filepath.Join(dir, driver.ExecutableBin)
c.logger.Debug().Msgf("Creating directory for driver executable: %s", driverExecutablePath)
if err := os.MkdirAll(driverExecutablePath, 0755); err != nil {
return err
}
return nil
}
func saveDriverExecutable(ctx context.Context, d driver.Driver, dir string, logger log.Logger) error {
logger.Info().Msgf("Fetching %s executable", d.Name())
rawUrl := fmt.Sprintf("%s/%s", d.ReleaseArtifactsURL(), driver.K3sExecutable)
func saveDriverExecutable(ctx context.Context, d driver.Driver, dir string) error {
rawUrl := fmt.Sprintf("%s/%s", d.ReleaseArtifactsURL(), d.Name())
f := fetcher.FileFetcher{}
dst := filepath.Join(dir, driver.ExecutableBin, driver.K3sExecutable)
@@ -116,5 +90,10 @@ func saveDriverExecutable(ctx context.Context, d driver.Driver, dir string, logg
return err
}
err = os.Chmod(dst, 0755)
if err != nil {
return err
}
return nil
}
+5 -13
View File
@@ -7,13 +7,10 @@ import (
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/google/go-containerregistry/pkg/v1/tarball"
"github.com/rancherfederal/hauler/pkg/apis/haul"
"github.com/rancherfederal/hauler/pkg/log"
)
func SavePreloadImages(ctx context.Context, h haul.Haul, archivePath string, logger log.Logger) error {
func SavePreloadImages(ctx context.Context, images []string, archivePath string) error {
imageRefs := make(map[name.Reference]v1.Image)
images := listImages(h)
for _, image := range images {
ref, err := name.ParseReference(image)
@@ -21,7 +18,6 @@ func SavePreloadImages(ctx context.Context, h haul.Haul, archivePath string, log
return err
}
logger.Info().Msgf("identified %s", ref.Name())
img, err := remote.Image(ref, remote.WithAuthFromKeychain(authn.DefaultKeychain))
if err != nil {
return err
@@ -30,16 +26,12 @@ func SavePreloadImages(ctx context.Context, h haul.Haul, archivePath string, log
imageRefs[ref] = img
}
logger.Info().Msgf("saving %d images to preload as %s", len(images), archivePath)
if len(images) == 0 {
return nil
}
if err := tarball.MultiRefWriteToFile(archivePath, imageRefs); err != nil {
return err
}
return nil
}
func listImages(h haul.Haul) []string {
images := h.Spec.Driver.Images()
images = append(images, h.Spec.PreloadImages...)
return images
}
-148
View File
@@ -1,148 +0,0 @@
package deployer
import (
"context"
"github.com/mholt/archiver/v3"
"github.com/rancherfederal/hauler/pkg/apis/hauler.cattle.io/v1alpha1"
"github.com/rancherfederal/hauler/pkg/embed"
"github.com/sirupsen/logrus"
"io/fs"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"os"
"os/exec"
"path/filepath"
)
type Deployer struct {
Cluster *v1alpha1.Cluster
logger *logrus.Entry
za *archiver.TarZstd
}
func NewDeployer() *Deployer {
return &Deployer{
// TODO: Load this from config file
Cluster: &v1alpha1.Cluster{
TypeMeta: metav1.TypeMeta{},
Metadata: metav1.ObjectMeta{},
Driver: v1alpha1.K3SDriver{
Version: "",
ReleaseURL: "",
},
Arch: "amd64",
PreloadImages: nil,
AutodeployManifests: nil,
},
logger: logrus.WithFields(logrus.Fields{
"cluster": "",
"driver": "",
"stage:": "deployer",
}),
za: &archiver.TarZstd{
Tar: &archiver.Tar{
OverwriteExisting: true,
MkdirAll: true,
},
},
}
}
func (d *Deployer) Deploy(ctx context.Context, pkg string) error {
d.logger.Infof("deploying cluster from %s", pkg)
if err := d.explode(pkg); err != nil {
return err
}
d.logger.Infof("configuring %s", d.Cluster.Driver.String())
if err := d.config(); err != nil {
return err
}
d.logger.Infof("starting %s", d.Cluster.Driver.String())
if err := d.start(); err != nil {
return err
}
return nil
}
func (d *Deployer) explode(pkg string) error {
d.logger.Infof("extracting %s to %s", d.Cluster.Driver.String(), v1alpha1.DriverVarPath)
if err := d.za.Extract(pkg, d.Cluster.Driver.String(), v1alpha1.DriverVarPath); err != nil {
return err
}
// TODO: This walks through the compressed archive twice, loss in speed is minimal but it's still not optimal
d.logger.Infof("extracting %s to %s", v1alpha1.HaulerBin, "/opt/hauler")
if err := d.za.Extract(pkg, v1alpha1.HaulerBin, "/opt/hauler"); err != nil {
return err
}
d.logger.Infof("rendering embedded files")
if err := embed.RenderEmbedded(d.Cluster.Driver); err != nil {
return err
}
d.logger.Debugf("ensuring everything in %s is executable", "/opt/hauler/bin")
err := filepath.WalkDir("/opt/hauler/bin", func(path string, d fs.DirEntry, err error) error {
if d.IsDir() {
return err
}
err = os.Chmod(path, 0755)
if err != nil {
return err
}
return nil
})
if err != nil {
return err
}
return nil
}
// config will create a driver config if not exists, and merge if one exists
func (d *Deployer) config() error {
cfgFilePath := filepath.Join(v1alpha1.DriverEtcPath, d.Cluster.Driver.String(), "config.yaml")
err := os.MkdirAll(filepath.Dir(cfgFilePath), 0755)
if err != nil {
return err
}
if _, err := os.ReadFile(cfgFilePath); os.IsNotExist(err) {
data, _ := d.Cluster.Driver.MarshalConfig()
err := os.WriteFile(cfgFilePath, data, 0666)
if err != nil {
return err
}
} else {
// TODO: Merge configs
}
return nil
}
func (d *Deployer) start() error {
cmd := exec.Command("/bin/sh", "/opt/hauler/bin/k3s-init.sh")
cmd.Env = append(os.Environ(), []string{
"INSTALL_K3S_EXEC=--write-kubeconfig-mode '0644'",
"INSTALL_K3S_SKIP_DOWNLOAD=true",
"INSTALL_K3S_SELINUX_WARN=true",
"INSTALL_K3S_SKIP_SELINUX_RPM=true",
"INSTALL_K3S_BIN_DIR=/opt/hauler/bin",
}...)
_, err := cmd.CombinedOutput()
if err != nil {
return err
}
// TODO: Do this? or leave it up to user and print message
//path := os.Getenv("PATH")
//d.logger.Infof("adding /opt/hauler/bin to $PATH")
//err = os.Setenv("PATH", fmt.Sprintf("%s:/opt/hauler/bin", path))
//if err != nil {
// return err
//}
return nil
}
-128
View File
@@ -1,128 +0,0 @@
package embed
import (
"embed"
"fmt"
"github.com/rancherfederal/hauler/pkg/apis/hauler.cattle.io/v1alpha1"
"github.com/sirupsen/logrus"
"io/fs"
"os"
"path/filepath"
)
const embedRootDir = "embedded"
//go:embed embedded/*
var e embed.FS
type embedded struct {
fs fs.FS
embedMap []embedMap
}
type embedMap struct {
src string
dst string
mode os.FileMode
}
func RenderEmbedded(d v1alpha1.Driver) error {
efsys, err := fs.Sub(e, embedRootDir)
if err != nil {
logrus.Fatalf("failed to load embedded filesystem: %v", err)
}
e := &embedded{
fs: efsys,
embedMap: []embedMap{
{
src: "manifests",
dst: filepath.Join(v1alpha1.DriverVarPath, d.String(), "server"),
mode: 0600,
},
{
src: "static",
dst: filepath.Join(v1alpha1.DriverVarPath, d.String(), "server"),
mode: 0600,
},
{
src: "bin/k3s-init.sh",
dst: filepath.Join("/opt", v1alpha1.HaulerBin, "k3s-init.sh"),
mode: 0755,
},
},
}
if err := e.render(); err != nil {
return err
}
return nil
}
func (e *embedded) render() error {
for _, em := range e.embedMap {
f, err := fs.Stat(e.fs, em.src)
if err != nil {
return err
}
if f.IsDir() {
err := e.WalkDir(em.src, em.dst, em.mode)
if err != nil {
return err
}
} else {
err := e.WriteTo(em.src, em.dst, em.mode)
if err != nil {
return err
}
}
}
return nil
}
func (e *embedded) WriteTo(src string, dest string, mode os.FileMode) error {
logrus.Infof("creating file from embedded store: %s", src)
data, err := fs.ReadFile(e.fs, src)
if err != nil {
return fmt.Errorf("failed to read file %s from embedded store: %v", src, err)
}
err = os.WriteFile(dest, data, mode)
if err != nil {
return fmt.Errorf("failed to write %s to %s from embedded store: %v", src, dest, err)
}
return nil
}
func (e *embedded) WalkDir(src string, dest string, mode os.FileMode) error {
err := fs.WalkDir(e.fs, src, func(path string, d fs.DirEntry, err error) error {
p := filepath.Join(dest, path)
if d.IsDir() {
logrus.Infof("creating directory: %s", p)
err := os.Mkdir(filepath.Join(dest, path), mode)
//TODO: lol
if err == fs.ErrExist {
return fmt.Errorf("failed to create directory: %v", err)
}
} else {
err := e.WriteTo(path, p, mode)
if err != nil {
return err
}
}
return nil
})
if err != nil {
return err
}
return nil
}
+4 -2
View File
@@ -3,7 +3,7 @@ package fetcher
import (
"context"
"fmt"
"github.com/sirupsen/logrus"
"github.com/pterm/pterm"
"io"
"net/http"
"net/url"
@@ -22,7 +22,7 @@ func (f FileFetcher) Get(ctx context.Context, src string, dst string) error {
}
defer out.Close()
logrus.Infof("Getting %s from %s", dst, src)
spinner, _ := pterm.DefaultSpinner.Start("Fetching ", src, " and saving to ", dst)
resp, err := http.Get(src)
if err != nil {
return fmt.Errorf("getting file: %w", err)
@@ -30,6 +30,8 @@ func (f FileFetcher) Get(ctx context.Context, src string, dst string) error {
defer resp.Body.Close()
_, err = io.Copy(out, resp.Body)
spinner.Success("Finished fetching ", src)
return err
}
-48
View File
@@ -1,48 +0,0 @@
package kube
import (
"github.com/rancherfederal/hauler/pkg/apis/hauler.cattle.io/v1alpha1"
corev1 "k8s.io/api/core/v1"
apiruntime "k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"path/filepath"
"sigs.k8s.io/controller-runtime/pkg/client"
)
func NewKubeClient() (client.Client, error) {
cfg, err := NewKubeClientConfig()
if err != nil {
return nil, err
}
scheme := apiruntime.NewScheme()
_ = corev1.AddToScheme(scheme)
kubeClient, err := client.New(cfg, client.Options{
Scheme: scheme,
})
if err != nil {
return nil, err
}
return kubeClient, nil
}
func NewKubeClientConfig() (*rest.Config, error) {
loadingRules := loadingRules()
configOverrides := &clientcmd.ConfigOverrides{}
kubeConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, configOverrides)
cfg, err := kubeConfig.ClientConfig()
return cfg, err
}
func loadingRules() *clientcmd.ClientConfigLoadingRules {
return &clientcmd.ClientConfigLoadingRules{
Precedence: []string{
filepath.Join(v1alpha1.DriverEtcPath, v1alpha1.DriverK3S, "k3s.yaml"),
filepath.Join(v1alpha1.DriverEtcPath, v1alpha1.DriverRKE2, "rke2.yaml"),
},
WarnIfAllMissing: true,
}
}
-94
View File
@@ -1,94 +0,0 @@
package kube
import (
"context"
"fmt"
"github.com/sirupsen/logrus"
"k8s.io/client-go/rest"
"sigs.k8s.io/cli-utils/pkg/kstatus/polling"
"sigs.k8s.io/cli-utils/pkg/kstatus/polling/aggregator"
"sigs.k8s.io/cli-utils/pkg/kstatus/polling/collector"
"sigs.k8s.io/cli-utils/pkg/kstatus/polling/event"
"sigs.k8s.io/cli-utils/pkg/kstatus/status"
"sigs.k8s.io/cli-utils/pkg/object"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
"strings"
"time"
)
type StatusChecker struct {
poller *polling.StatusPoller
client client.Client
logger *logrus.Entry
interval time.Duration
timeout time.Duration
}
func NewStatusChecker(kubeConfig *rest.Config, interval time.Duration, timeout time.Duration) (*StatusChecker, error) {
restMapper, err := apiutil.NewDynamicRESTMapper(kubeConfig)
if err != nil {
return nil, err
}
c, err := client.New(kubeConfig, client.Options{Mapper: restMapper})
if err != nil {
return nil, err
}
return &StatusChecker{
poller: polling.NewStatusPoller(c, restMapper),
client: c,
logger: logrus.WithFields(logrus.Fields{}),
interval: interval,
timeout: timeout,
}, nil
}
func (sc *StatusChecker) WaitForCondition(objs ...object.ObjMetadata) error {
ctx, cancel := context.WithTimeout(context.Background(), sc.timeout)
defer cancel()
eventsChan := sc.poller.Poll(ctx, objs, polling.Options{
PollInterval: sc.interval,
UseCache: true,
})
coll := collector.NewResourceStatusCollector(objs)
done := coll.ListenWithObserver(eventsChan, desiredStatusNotifierFunc(cancel, status.CurrentStatus))
<-done
for _, rs := range coll.ResourceStatuses {
switch rs.Status {
case status.CurrentStatus:
fmt.Printf("%s: %s ready\n", rs.Identifier.Name, strings.ToLower(rs.Identifier.GroupKind.Kind))
case status.NotFoundStatus:
fmt.Println(fmt.Errorf("%s: %s not found", rs.Identifier.Name, strings.ToLower(rs.Identifier.GroupKind.Kind)))
default:
fmt.Println(fmt.Errorf("%s: %s not ready", rs.Identifier.Name, strings.ToLower(rs.Identifier.GroupKind.Kind)))
}
}
if coll.Error != nil || ctx.Err() == context.DeadlineExceeded {
return fmt.Errorf("timed out waiting for condition")
}
return nil
}
// desiredStatusNotifierFunc returns an Observer function for the
// ResourceStatusCollector that will cancel the context (using the cancelFunc)
// when all resources have reached the desired status.
func desiredStatusNotifierFunc(cancelFunc context.CancelFunc, desired status.Status) collector.ObserverFunc {
return func(rsc *collector.ResourceStatusCollector, _ event.Event) {
var rss []*event.ResourceStatus
for _, rs := range rsc.ResourceStatuses {
rss = append(rss, rs)
}
aggStatus := aggregator.AggregateStatus(rss, desired)
if aggStatus == desired {
cancelFunc()
}
}
}
-21
View File
@@ -1,21 +0,0 @@
package log
import (
"github.com/rs/zerolog"
"os"
)
type Logger interface {
Info() *zerolog.Event
Debug() *zerolog.Event
Error() *zerolog.Event
}
func NewPrettyLogger() zerolog.Logger {
output := zerolog.ConsoleWriter{
Out: os.Stdout,
}
logger := zerolog.New(output).With().Timestamp().Logger()
return logger
}
-196
View File
@@ -1,196 +0,0 @@
package packager
import (
"context"
"fmt"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/google/go-containerregistry/pkg/v1/tarball"
"github.com/mholt/archiver/v3"
"github.com/rancherfederal/hauler/pkg/apis/hauler.cattle.io/v1alpha1"
"github.com/rancherfederal/hauler/pkg/fetcher"
"github.com/sirupsen/logrus"
"os"
"path/filepath"
"time"
)
type Packager struct {
Cluster *v1alpha1.Cluster
logger *logrus.Entry
za *archiver.TarZstd
}
func NewPackager(cluster *v1alpha1.Cluster) *Packager {
return &Packager{
Cluster: cluster,
logger: logrus.WithFields(logrus.Fields{
"cluster": cluster.Metadata.Name,
"driver": cluster.Driver.String(),
}),
za: &archiver.TarZstd{
Tar: &archiver.Tar{
OverwriteExisting: true,
MkdirAll: true,
},
},
}
}
func (p *Packager) Package(ctx context.Context, outFile string) error {
ctx, cancel := context.WithTimeout(ctx, 2*time.Minute)
defer cancel()
tmpdir, err := os.MkdirTemp("", "hauler")
if err != nil {
return err
}
defer os.RemoveAll(tmpdir)
logrus.Debugf("Using temporary packaging directory: %s", tmpdir)
if err := p.prepFS(tmpdir); err != nil {
return err
}
// TODO: Build api space for providing git repos to package, below is just an example of it "working"
//var reposToGet []string
//reposToGet = append(reposToGet, []string{"https://github.com/hashicorp/go-getter.git", "https://github.com/open-policy-agent/conftest.git"}...)
//
//gitReposPath := filepath.Join(tmpdir, "repos")
//if err := p.pkgGitRepos(ctx, gitReposPath, reposToGet); err != nil {
// return err
//}
var urlsToGet []string
urlsToGet = append(urlsToGet, buildDriverURLs(p.Cluster.Driver)...)
// TODO: User defined gets
filesPath := filepath.Join(tmpdir, v1alpha1.HaulerBin)
if err := p.pkgFiles(ctx, filesPath, urlsToGet); err != nil {
return err
}
var imgs []string
imgs = append(imgs, p.Cluster.Driver.Images()...)
imgs = append(imgs, p.Cluster.PreloadImages...)
// TODO: User defined preloaded images
preloadImagesPath := filepath.Join(tmpdir, v1alpha1.ImagePreloadPath(p.Cluster.Driver), "hauler.tar")
if err := p.pkgPreloadImages(ctx, preloadImagesPath, imgs); err != nil {
return err
}
err = p.archive(ctx, tmpdir, outFile)
if err != nil {
return err
}
return nil
}
func (p *Packager) pkgFiles(ctx context.Context, dir string, rawUrls []string) error {
logrus.Infof("Packaging %s driver artifacts...", p.Cluster.Driver.String())
f := fetcher.FileFetcher{}
for _, rawUrl := range rawUrls {
dst := filepath.Join(dir, fetcher.GetFileNameFromURL(rawUrl))
err := f.Get(ctx, rawUrl, dst)
if err != nil {
return err
}
}
return nil
}
func buildDriverURLs(driver v1alpha1.Driver) []string {
urls := make([]string, 0)
urls = append(urls, driver.ExecutableURL())
return urls
}
func (p *Packager) pkgPreloadImages(ctx context.Context, dir string, images []string) error {
logrus.Infof("Packaging %d images to preload...", len(images))
ctx, cancel := context.WithCancel(ctx)
defer cancel()
imageRefs := make(map[name.Reference]v1.Image)
for _, i := range images {
ref, err := name.ParseReference(i)
if err != nil {
return err
}
p.logger.Debugf("adding %s to preload image archive", ref.Name())
img, err := remote.Image(ref, remote.WithAuthFromKeychain(authn.DefaultKeychain))
if err != nil {
return err
}
imageRefs[ref] = img
}
// Get preload images and save to a single compressed tarball
if err := tarball.MultiRefWriteToFile(dir, imageRefs); err != nil {
return err
}
return nil
}
func (p *Packager) pkgGitRepos(ctx context.Context, dir string, repos []string) error {
logrus.Infof("Packaging %d repos to prepopulate...", len(repos))
f := fetcher.GitFetcher{ Bare: true }
for _, repo := range repos {
dst := filepath.Join(dir, fetcher.GetFileNameFromURL(repo))
err := f.Get(ctx, repo, dst)
if err != nil {
return err
}
}
return nil
}
// archive will archive a folder using Packager's archiver while preserving the root folder structure
func (p *Packager) archive(ctx context.Context, dir string, outFile string) error {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
cwd, err := os.Getwd()
if err != nil {
return err
}
err = os.Chdir(dir)
if err != nil {
return err
}
defer os.Chdir(cwd)
archivePath := filepath.Join(cwd, outFile)
p.logger.Infof("Archiving contents of %s to %s", dir, archivePath)
if err := p.za.Archive([]string{"."}, archivePath); err != nil {
return err
}
return nil
}
func (p *Packager) prepFS(dir string) error {
for _, fs := range v1alpha1.FS(p.Cluster.Driver) {
path := filepath.Join(dir, fs)
p.logger.Debugf("creating directory: %s", path)
err := os.MkdirAll(path, 0755)
if err != nil {
return fmt.Errorf("to create directory: %s, %w", path, err)
}
}
return nil
}
+92
View File
@@ -0,0 +1,92 @@
package util
import (
"bufio"
"fmt"
"github.com/mholt/archiver/v3"
"io"
"os"
"path/filepath"
)
type dir struct {
Path string
Permission os.FileMode
}
type FSLayout struct {
Root string
dirs []dir
}
type Layout interface {
Create() error
AddDir()
Archive(archiver2 archiver.Archiver) error
Remove() error
}
func NewLayout(root string) *FSLayout {
absRoot, _ := filepath.Abs(root)
return &FSLayout{
Root: absRoot,
dirs: nil,
}
}
//Create will create the FSLayout at the FSLayout.Root
func (l FSLayout) Create() error {
for _, dir := range l.dirs {
fullPath := filepath.Join(l.Root, dir.Path)
if err := os.MkdirAll(fullPath, dir.Permission); err != nil {
return err
}
}
return nil
}
//AddDir will add a folder to the FSLayout
func (l *FSLayout) AddDir(relPath string, perm os.FileMode) {
l.dirs = append(l.dirs, dir{
Path: relPath,
Permission: perm,
})
}
func (l FSLayout) Remove() error {
return os.RemoveAll(l.Root)
}
func (l FSLayout) Archive(a *archiver.TarZstd, name string) error {
cwd, err := os.Getwd()
if err != nil {
return err
}
err = os.Chdir(l.Root)
if err != nil {
return err
}
defer os.Chdir(cwd)
archiveFile := filepath.Join(cwd, fmt.Sprintf("%s.%s", name, a.String()))
if err := a.Archive([]string{"."}, archiveFile); err != nil {
return err
}
return nil
}
func LinesToSlice(r io.ReadCloser) ([]string, error) {
var lines []string
scanner := bufio.NewScanner(r)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if err := scanner.Err(); err != nil {
return nil, err
}
return lines, nil
}
+2
View File
@@ -0,0 +1,2 @@
registry:2.7.1
gitea/gitea:1.14.1-rootless