diff --git a/bundle/blobs/sha256/12008541203a024dab3a30542c87421e5a27dbb601b9c6f029b3827af138ccb3 b/bundle/blobs/sha256/12008541203a024dab3a30542c87421e5a27dbb601b9c6f029b3827af138ccb3 deleted file mode 100644 index 1ee038f..0000000 Binary files a/bundle/blobs/sha256/12008541203a024dab3a30542c87421e5a27dbb601b9c6f029b3827af138ccb3 and /dev/null differ diff --git a/bundle/blobs/sha256/1fd8e1b0bb7ef6cc63e0094e2fb5a35259bdce7041ef5e7e4c99694ded1041d7 b/bundle/blobs/sha256/1fd8e1b0bb7ef6cc63e0094e2fb5a35259bdce7041ef5e7e4c99694ded1041d7 deleted file mode 100644 index 49df596..0000000 --- a/bundle/blobs/sha256/1fd8e1b0bb7ef6cc63e0094e2fb5a35259bdce7041ef5e7e4c99694ded1041d7 +++ /dev/null @@ -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"]}} \ No newline at end of file diff --git a/bundle/blobs/sha256/363ab70c2143bc121f037ba432cede225b7053200abba2a7a4ca24c2915a3998 b/bundle/blobs/sha256/363ab70c2143bc121f037ba432cede225b7053200abba2a7a4ca24c2915a3998 deleted file mode 100644 index 79ccf12..0000000 Binary files a/bundle/blobs/sha256/363ab70c2143bc121f037ba432cede225b7053200abba2a7a4ca24c2915a3998 and /dev/null differ diff --git a/bundle/blobs/sha256/42043edfae481178f07aa077fa872fcc242e276d302f4ac2026d9d2eb65b955f b/bundle/blobs/sha256/42043edfae481178f07aa077fa872fcc242e276d302f4ac2026d9d2eb65b955f deleted file mode 100644 index b5d80fe..0000000 --- a/bundle/blobs/sha256/42043edfae481178f07aa077fa872fcc242e276d302f4ac2026d9d2eb65b955f +++ /dev/null @@ -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" - } - ] -} \ No newline at end of file diff --git a/bundle/blobs/sha256/540db60ca9383eac9e418f78490994d0af424aab7bf6d0e47ac8ed4e2e9bcbba b/bundle/blobs/sha256/540db60ca9383eac9e418f78490994d0af424aab7bf6d0e47ac8ed4e2e9bcbba deleted file mode 100644 index f301fc6..0000000 Binary files a/bundle/blobs/sha256/540db60ca9383eac9e418f78490994d0af424aab7bf6d0e47ac8ed4e2e9bcbba and /dev/null differ diff --git a/bundle/blobs/sha256/5b94580856e6fd27a74d55ab33fc3b53fd6f599f7147f38845a2482cc003cc19 b/bundle/blobs/sha256/5b94580856e6fd27a74d55ab33fc3b53fd6f599f7147f38845a2482cc003cc19 deleted file mode 100644 index 5094bb4..0000000 Binary files a/bundle/blobs/sha256/5b94580856e6fd27a74d55ab33fc3b53fd6f599f7147f38845a2482cc003cc19 and /dev/null differ diff --git a/bundle/blobs/sha256/6dbb9cc54074106d46d4ccb330f2a40a682d49dda5f4844962b7dce9fe44aaec b/bundle/blobs/sha256/6dbb9cc54074106d46d4ccb330f2a40a682d49dda5f4844962b7dce9fe44aaec deleted file mode 100644 index 21b9526..0000000 --- a/bundle/blobs/sha256/6dbb9cc54074106d46d4ccb330f2a40a682d49dda5f4844962b7dce9fe44aaec +++ /dev/null @@ -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"]}} \ No newline at end of file diff --git a/bundle/blobs/sha256/6eda6749503f60eb69077e148cba1015ec5808b0c1c2e6f027f7d1b960f6a3a9 b/bundle/blobs/sha256/6eda6749503f60eb69077e148cba1015ec5808b0c1c2e6f027f7d1b960f6a3a9 deleted file mode 100644 index f269c71..0000000 Binary files a/bundle/blobs/sha256/6eda6749503f60eb69077e148cba1015ec5808b0c1c2e6f027f7d1b960f6a3a9 and /dev/null differ diff --git a/bundle/blobs/sha256/ddad3d7c1e96adf9153f8921a7c9790f880a390163df453be1566e9ef0d546e0 b/bundle/blobs/sha256/ddad3d7c1e96adf9153f8921a7c9790f880a390163df453be1566e9ef0d546e0 deleted file mode 100644 index 8b57202..0000000 Binary files a/bundle/blobs/sha256/ddad3d7c1e96adf9153f8921a7c9790f880a390163df453be1566e9ef0d546e0 and /dev/null differ diff --git a/bundle/blobs/sha256/def822f9851ca422481ec6fee59a9966f12b351c62ccb9aca841526ffaa9f748 b/bundle/blobs/sha256/def822f9851ca422481ec6fee59a9966f12b351c62ccb9aca841526ffaa9f748 deleted file mode 100644 index ae5e2e2..0000000 --- a/bundle/blobs/sha256/def822f9851ca422481ec6fee59a9966f12b351c62ccb9aca841526ffaa9f748 +++ /dev/null @@ -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" - } - ] -} \ No newline at end of file diff --git a/bundle/index.json b/bundle/index.json deleted file mode 100755 index b7016c5..0000000 --- a/bundle/index.json +++ /dev/null @@ -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" - } - } - ] -} \ No newline at end of file diff --git a/bundle/oci-layout b/bundle/oci-layout deleted file mode 100755 index 224a869..0000000 --- a/bundle/oci-layout +++ /dev/null @@ -1,3 +0,0 @@ -{ - "imageLayoutVersion": "1.0.0" -} \ No newline at end of file diff --git a/cmd/haulerctl/app/bootstrap.go b/cmd/haulerctl/app/bootstrap.go index a52157c..1a611ec 100644 --- a/cmd/haulerctl/app/bootstrap.go +++ b/cmd/haulerctl/app/bootstrap.go @@ -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 } diff --git a/cmd/haulerctl/app/create.go b/cmd/haulerctl/app/create.go index d151fe9..4b70991 100644 --- a/cmd/haulerctl/app/create.go +++ b/cmd/haulerctl/app/create.go @@ -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 } diff --git a/go.mod b/go.mod index 499567c..be61244 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index 5cab837..cbe4b4a 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/pkg/apis/bundle/bundle.go b/pkg/apis/bundle/bundle.go new file mode 100644 index 0000000..0cff4e1 --- /dev/null +++ b/pkg/apis/bundle/bundle.go @@ -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) +} \ No newline at end of file diff --git a/pkg/apis/driver/driver.go b/pkg/apis/driver/driver.go index 44af917..186d79a 100644 --- a/pkg/apis/driver/driver.go +++ b/pkg/apis/driver/driver.go @@ -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"` } \ No newline at end of file diff --git a/pkg/apis/driver/k3s.go b/pkg/apis/driver/k3s.go index 28b1f9c..5c361d9 100644 --- a/pkg/apis/driver/k3s.go +++ b/pkg/apis/driver/k3s.go @@ -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") } \ No newline at end of file +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()) } \ No newline at end of file diff --git a/pkg/apis/haul/haul.go b/pkg/apis/haul/haul.go index 5de2822..fbd4576 100644 --- a/pkg/apis/haul/haul.go +++ b/pkg/apis/haul/haul.go @@ -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 +} \ No newline at end of file diff --git a/pkg/archive/archive.go b/pkg/archive/archive.go deleted file mode 100644 index 270dce1..0000000 --- a/pkg/archive/archive.go +++ /dev/null @@ -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 -} \ No newline at end of file diff --git a/pkg/embed/embedded/bin/k3s-init.sh b/pkg/bootstrap/bin/k3s-init.sh similarity index 100% rename from pkg/embed/embedded/bin/k3s-init.sh rename to pkg/bootstrap/bin/k3s-init.sh diff --git a/pkg/embed/embedded/bin/rke2-init.sh b/pkg/bootstrap/bin/rke2-init.sh similarity index 100% rename from pkg/embed/embedded/bin/rke2-init.sh rename to pkg/bootstrap/bin/rke2-init.sh diff --git a/pkg/bootstrap/bootstrap.go b/pkg/bootstrap/bootstrap.go index 565721c..4ad25a7 100644 --- a/pkg/bootstrap/bootstrap.go +++ b/pkg/bootstrap/bootstrap.go @@ -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 } \ No newline at end of file diff --git a/pkg/bundle/bundle.go b/pkg/bundle/bundle.go deleted file mode 100644 index 5f9556b..0000000 --- a/pkg/bundle/bundle.go +++ /dev/null @@ -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) -} \ No newline at end of file diff --git a/pkg/copy/copy.go b/pkg/copy/copy.go index 5ddb811..504a71d 100644 --- a/pkg/copy/copy.go +++ b/pkg/copy/copy.go @@ -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 diff --git a/pkg/create/bundle.go b/pkg/create/bundle.go new file mode 100644 index 0000000..8a28930 --- /dev/null +++ b/pkg/create/bundle.go @@ -0,0 +1,8 @@ +package create + +import "github.com/rancherfederal/hauler/pkg/apis/bundle" + +func ResolveBundle(b bundle.Bundle) error { + + return nil +} \ No newline at end of file diff --git a/pkg/create/create.go b/pkg/create/create.go index 561e0c0..a1c64f7 100644 --- a/pkg/create/create.go +++ b/pkg/create/create.go @@ -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 } diff --git a/pkg/create/preload.go b/pkg/create/preload.go index fd86db4..bbcdf13 100644 --- a/pkg/create/preload.go +++ b/pkg/create/preload.go @@ -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 -} \ No newline at end of file diff --git a/pkg/deployer/deploy.go b/pkg/deployer/deploy.go deleted file mode 100644 index bf0ce2c..0000000 --- a/pkg/deployer/deploy.go +++ /dev/null @@ -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 -} diff --git a/pkg/embed/embed.go b/pkg/embed/embed.go deleted file mode 100644 index ac317e0..0000000 --- a/pkg/embed/embed.go +++ /dev/null @@ -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 -} \ No newline at end of file diff --git a/pkg/fetcher/file.go b/pkg/fetcher/file.go index 37aa9e7..744acba 100644 --- a/pkg/fetcher/file.go +++ b/pkg/fetcher/file.go @@ -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 } diff --git a/pkg/kube/client.go b/pkg/kube/client.go deleted file mode 100644 index 90712f1..0000000 --- a/pkg/kube/client.go +++ /dev/null @@ -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, - } -} \ No newline at end of file diff --git a/pkg/kube/status.go b/pkg/kube/status.go deleted file mode 100644 index a93fdbd..0000000 --- a/pkg/kube/status.go +++ /dev/null @@ -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() - } - } -} diff --git a/pkg/log/log.go b/pkg/log/log.go deleted file mode 100644 index 7efb6fb..0000000 --- a/pkg/log/log.go +++ /dev/null @@ -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 -} \ No newline at end of file diff --git a/pkg/packager/package.go b/pkg/packager/package.go deleted file mode 100644 index e9e4142..0000000 --- a/pkg/packager/package.go +++ /dev/null @@ -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 -} diff --git a/pkg/util/files.go b/pkg/util/files.go new file mode 100644 index 0000000..a62987c --- /dev/null +++ b/pkg/util/files.go @@ -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 +} diff --git a/pkg/embed/embedded/manifests/gitea.yaml b/testdata/bundle-a/autodeploy/gitea.yaml similarity index 100% rename from pkg/embed/embedded/manifests/gitea.yaml rename to testdata/bundle-a/autodeploy/gitea.yaml diff --git a/pkg/embed/embedded/manifests/hauler.yaml b/testdata/bundle-a/autodeploy/hauler.yaml similarity index 100% rename from pkg/embed/embedded/manifests/hauler.yaml rename to testdata/bundle-a/autodeploy/hauler.yaml diff --git a/pkg/embed/embedded/manifests/registry.yaml b/testdata/bundle-a/autodeploy/registry.yaml similarity index 100% rename from pkg/embed/embedded/manifests/registry.yaml rename to testdata/bundle-a/autodeploy/registry.yaml diff --git a/pkg/embed/embedded/manifests/traefik-config.yaml b/testdata/bundle-a/autodeploy/traefik-config.yaml similarity index 100% rename from pkg/embed/embedded/manifests/traefik-config.yaml rename to testdata/bundle-a/autodeploy/traefik-config.yaml diff --git a/testdata/bundle-a/images/images.txt b/testdata/bundle-a/images/images.txt new file mode 100644 index 0000000..ac53233 --- /dev/null +++ b/testdata/bundle-a/images/images.txt @@ -0,0 +1,2 @@ +registry:2.7.1 +gitea/gitea:1.14.1-rootless \ No newline at end of file diff --git a/pkg/embed/embedded/static/charts/docker-registry-1.10.1.tgz b/testdata/bundle-a/static/docker-registry-1.10.1.tgz similarity index 100% rename from pkg/embed/embedded/static/charts/docker-registry-1.10.1.tgz rename to testdata/bundle-a/static/docker-registry-1.10.1.tgz diff --git a/pkg/embed/embedded/static/charts/gitea-3.0.0.tgz b/testdata/bundle-a/static/gitea-3.0.0.tgz similarity index 100% rename from pkg/embed/embedded/static/charts/gitea-3.0.0.tgz rename to testdata/bundle-a/static/gitea-3.0.0.tgz