diff --git a/cmd/convert.go b/cmd/convert.go index 5ad5861..a998e1d 100644 --- a/cmd/convert.go +++ b/cmd/convert.go @@ -24,17 +24,18 @@ func NewConvertCmd() *cobra.Command { cmd.SilenceUsage = true cmd.SilenceErrors = true // Do not propagate errors down the line, we control them - // TODO: Check if this is really an existing dir (not a file) + // TODO: Convert these to named arguments rootfsDir := args[0] resultPath := args[1] imageName := args[2] + frameworkImage := args[3] logger := v1.NewLogger() runner := action.RealRunner{ Logger: logger, } - convertAction := action.NewConverterAction(rootfsDir, resultPath, imageName, runner) + convertAction := action.NewConverterAction(rootfsDir, resultPath, frameworkImage, imageName, runner) err := convertAction.Run() if err != nil { logger.Errorf(err.Error()) diff --git a/cmd/dockerfile.go b/cmd/dockerfile.go index fccb1e5..27d67ca 100644 --- a/cmd/dockerfile.go +++ b/cmd/dockerfile.go @@ -25,10 +25,22 @@ func NewDockerfileCmd() *cobra.Command { cmd.SilenceUsage = true cmd.SilenceErrors = true // Do not propagate errors down the line, we control them - rootfsDir, _ := cmd.Flags().GetString("rootfs-dir") - baseImageURI, _ := cmd.Flags().GetString("base-image-uri") + rootfsDir, err := cmd.Flags().GetString("rootfs-dir") + if err != nil { + return err + } - a := action.NewDockerfileAction(rootfsDir, baseImageURI) + baseImageURI, err := cmd.Flags().GetString("base-image-uri") + if err != nil { + return err + } + + frameworkImage, err := cmd.Flags().GetString("framework-image") + if err != nil { + return err + } + + a := action.NewDockerfileAction(rootfsDir, baseImageURI, frameworkImage) dockerfile, err := a.Run() if err != nil { return err @@ -48,4 +60,5 @@ func init() { rootCmd.AddCommand(c) c.Flags().StringP("rootfs-dir", "r", "", "the directory containing the extracted base image rootfs") c.Flags().StringP("base-image-uri", "i", "", "the URI of the base image") + c.Flags().StringP("framework-image", "i", "", "the URI of the base image") } diff --git a/pkg/action/converter.go b/pkg/action/converter.go index 3583858..5be4136 100644 --- a/pkg/action/converter.go +++ b/pkg/action/converter.go @@ -16,10 +16,11 @@ import ( // The "input" of this action is a directory where the rootfs is extracted. // [TBD] The output is the same directory updated to be a Kairos image type ConverterAction struct { - rootFSPath string - resultPath string - imageName string - Runner Runner + rootFSPath string + resultPath string + imageName string + frameworkImage string + Runner Runner } // A runner that can shell-out to other commands but also be mocked in tests. @@ -37,12 +38,13 @@ func (r RealRunner) Run(command string, args ...string) ([]byte, error) { return cmd.CombinedOutput() } -func NewConverterAction(rootfsPath, resultPath, imageName string, runner Runner) *ConverterAction { +func NewConverterAction(rootfsPath, resultPath, imageName, frameworkImage string, runner Runner) *ConverterAction { return &ConverterAction{ - rootFSPath: rootfsPath, - resultPath: resultPath, - imageName: imageName, - Runner: runner, + rootFSPath: rootfsPath, + frameworkImage: frameworkImage, + resultPath: resultPath, + imageName: imageName, + Runner: runner, } } @@ -55,7 +57,7 @@ func NewConverterAction(rootfsPath, resultPath, imageName string, runner Runner) // E.g. // CGO_ENABLED=0 go build -ldflags '-extldflags "-static"' -o build/enki && docker run -it -e PATH=/kaniko -v /tmp -v /home/dimitris/workspace/kairos/osbuilder/tmp/rootfs/:/context -v "$PWD/build/enki":/enki -v $PWD:/build --rm --entrypoint "/enki" gcr.io/kaniko-project/executor:latest convert /context func (ca *ConverterAction) Run() (err error) { - da := NewDockerfileAction(ca.rootFSPath, "") + da := NewDockerfileAction(ca.rootFSPath, "", ca.frameworkImage) dockerfile, err := da.Run() if err != nil { return err diff --git a/pkg/action/converter_test.go b/pkg/action/converter_test.go index ff8eb7f..4f195b6 100644 --- a/pkg/action/converter_test.go +++ b/pkg/action/converter_test.go @@ -23,7 +23,7 @@ var _ = Describe("ConverterAction", func() { Expect(err).ToNot(HaveOccurred()) imageName = newImageName(10) runner = v1mock.NewFakeRunner() - action = NewConverterAction(rootfsPath, path.Join(resultDir, "image.tar"), imageName, runner) + action = NewConverterAction(rootfsPath, path.Join(resultDir, "image.tar"), imageName, "quay.io/kairos/framework:master_ubuntu", runner) }) AfterEach(func() { diff --git a/pkg/action/dockerfile.go b/pkg/action/dockerfile.go index f960af9..43ae84f 100644 --- a/pkg/action/dockerfile.go +++ b/pkg/action/dockerfile.go @@ -5,21 +5,17 @@ import ( "fmt" ) -// ConverterAction is the action that converts a non-kairos image to a Kairos one. -// The conversion happens in a best-effort manner. It's not guaranteed that -// any distribution will successfully be converted to a Kairos flavor. See -// the Kairos releases for known-to-work flavors. -// The "input" of this action is a directory where the rootfs is extracted. -// [TBD] The output is the same directory updated to be a Kairos image type DockerfileAction struct { - rootFSPath string - baseImageURI string + rootFSPath string + baseImageURI string + frameworkImage string } -func NewDockerfileAction(rootfsPath, baseImageURI string) *DockerfileAction { +func NewDockerfileAction(rootfsPath, baseImageURI, frameworkImage string) *DockerfileAction { return &DockerfileAction{ - rootFSPath: rootfsPath, - baseImageURI: baseImageURI, + rootFSPath: rootfsPath, + baseImageURI: baseImageURI, + frameworkImage: frameworkImage, } } @@ -32,8 +28,8 @@ func (a *DockerfileAction) Run() (dockerfile string, err error) { dockerfile += a.baseImageSection() dockerfile += a.dnsSection() dockerfile += a.luetInstallSection("") - dockerfile += a.installFrameworkSection() dockerfile += a.switchRootSection() + dockerfile += a.installFrameworkSection() dockerfile += a.osSpecificSection() return dockerfile, nil @@ -84,10 +80,9 @@ COPY --from=builder /rootfs/ . // installFrameworkSection chooses the right framework image for the current // base image and upacks it to the /rootfs directory func (a *DockerfileAction) installFrameworkSection() string { - return ` -COPY --from=quay.io/kairos/enki /enki /enki -RUN /bin/bash -c 'luet util unpack quay.io/kairos/framework:$(/enki find-matching-framework) /' -` + return fmt.Sprintf(` +COPY --from=%s . / +`, a.frameworkImage) } func (a *DockerfileAction) osSpecificSection() string { @@ -103,5 +98,9 @@ func (a *DockerfileAction) Validate() error { return errors.New("exactly one of 'rootfs-dir' and 'base-image-uri' should be defined") } + if a.frameworkImage == "" { + return errors.New("'framework-image' should be defined") + } + return nil } diff --git a/pkg/action/dockerfile_test.go b/pkg/action/dockerfile_test.go index 1b5f563..62d0774 100644 --- a/pkg/action/dockerfile_test.go +++ b/pkg/action/dockerfile_test.go @@ -13,7 +13,7 @@ var _ = Describe("DockerfileAction", func() { When("both a rootfs dir and a base image URI are defined", func() { BeforeEach(func() { - action = NewDockerfileAction("somedir", "quay.io/kairos/someimage") + action = NewDockerfileAction("somedir", "quay.io/kairos/someimage", "quay.io/kairos/framework:master_ubuntu") }) It("returns an error", func() { @@ -28,7 +28,7 @@ var _ = Describe("DockerfileAction", func() { BeforeEach(func() { rootfsPath = prepareEmptyRootfs() - action = NewDockerfileAction(rootfsPath, "") + action = NewDockerfileAction(rootfsPath, "", "quay.io/kairos/framework:master_ubuntu") }) AfterEach(func() { @@ -45,7 +45,7 @@ var _ = Describe("DockerfileAction", func() { When("a base image uri is defined", func() { BeforeEach(func() { - action = NewDockerfileAction("", "ubuntu:latest") + action = NewDockerfileAction("", "ubuntu:latest", "quay.io/kairos/framework:master_ubuntu") }) It("starts with the provided base image", func() { @@ -63,7 +63,7 @@ var _ = Describe("DockerfileAction", func() { BeforeEach(func() { rootfsPath = prepareRootfsFromImage("ubuntu:latest") - action = NewDockerfileAction(rootfsPath, "") + action = NewDockerfileAction(rootfsPath, "", "quay.io/kairos/framework:master_ubuntu") }) AfterEach(func() { @@ -77,7 +77,7 @@ var _ = Describe("DockerfileAction", func() { When("base image URI is defined", func() { BeforeEach(func() { - action = NewDockerfileAction("", "ubuntu:latest") + action = NewDockerfileAction("", "ubuntu:latest", "quay.io/kairos/framework:master_ubuntu") }) It("adds Kairos bits", func() { @@ -102,5 +102,5 @@ func dockerfileMustHaveLuet(d string) { func dockerfileMustInstallFramework(d string) { By("checking installation of framework bits") - Expect(d).To(MatchRegexp("luet util unpack quay.io/kairos/framework")) + Expect(d).To(MatchRegexp("COPY --from=quay.io/kairos/framework")) }