mirror of
https://github.com/kairos-io/osbuilder.git
synced 2025-08-21 17:23:20 +00:00
[WIP] Run kaniko
Signed-off-by: Dimitris Karakasilis <dimitris@karakasilis.me>
This commit is contained in:
parent
d74178362f
commit
427ccc341b
@ -3,6 +3,16 @@ VERSION 0.7
|
|||||||
# renovate: datasource=docker depName=golang
|
# renovate: datasource=docker depName=golang
|
||||||
ARG --global GO_VERSION=1.20-alpine3.18
|
ARG --global GO_VERSION=1.20-alpine3.18
|
||||||
|
|
||||||
|
build:
|
||||||
|
FROM golang:$GO_VERSION
|
||||||
|
WORKDIR /build
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
ENV CGO_ENABLED=0
|
||||||
|
RUN go build -ldflags '-extldflags "-static"'
|
||||||
|
|
||||||
|
SAVE ARTIFACT enki AS LOCAL build/enki
|
||||||
|
|
||||||
test:
|
test:
|
||||||
FROM golang:$GO_VERSION
|
FROM golang:$GO_VERSION
|
||||||
RUN apk add rsync gcc musl-dev docker jq
|
RUN apk add rsync gcc musl-dev docker jq
|
||||||
|
51
tools-image/enki/cmd/convert.go
Normal file
51
tools-image/enki/cmd/convert.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/kairos-io/enki/pkg/action"
|
||||||
|
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewBuildISOCmd returns a new instance of the build-iso subcommand and appends it to
|
||||||
|
// the root command.
|
||||||
|
func NewConvertCmd() *cobra.Command {
|
||||||
|
c := &cobra.Command{
|
||||||
|
Use: "convert rootfs",
|
||||||
|
Short: "Convert a base image to a Kairos image",
|
||||||
|
Long: "Convert a base image to a Kairos image\n\n" +
|
||||||
|
"This is best effort. Enki will try to detect the distribution and add\n" +
|
||||||
|
"the necessary bits to convert it to a Kairos image",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
return CheckRoot() // TODO: Do we need root?
|
||||||
|
},
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
// Set this after parsing of the flags, so it fails on parsing and prints usage properly
|
||||||
|
cmd.SilenceUsage = true
|
||||||
|
cmd.SilenceErrors = true // Do not propagate errors down the line, we control them
|
||||||
|
|
||||||
|
rootfsDir := args[0]
|
||||||
|
// TODO: Check if this is really an existing dir (not a file)
|
||||||
|
fmt.Printf("rootfsDir = %+v\n", rootfsDir)
|
||||||
|
|
||||||
|
logger := v1.NewLogger()
|
||||||
|
|
||||||
|
convertAction := action.NewConverterAction(rootfsDir)
|
||||||
|
err := convertAction.Run()
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf(err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rootCmd.AddCommand(NewConvertCmd())
|
||||||
|
}
|
@ -1,13 +1,108 @@
|
|||||||
package action
|
package action
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
)
|
||||||
|
|
||||||
// ConverterAction is the action that converts a non-kairos image to a Kairos one.
|
// 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
|
// The conversion happens in a best-effort manner. It's not guaranteed that
|
||||||
// any distribution will successfully be converted to a Kairos flavor. See
|
// any distribution will successfully be converted to a Kairos flavor. See
|
||||||
// the Kairos releases for known-to-work flavors.
|
// 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 ConverterAction struct {
|
type ConverterAction struct {
|
||||||
rootFSPath string
|
rootFSPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConverterAction() *ConverterAction {
|
func NewConverterAction(rootfsPath string) *ConverterAction {
|
||||||
return &ConverterAction{}
|
return &ConverterAction{
|
||||||
|
rootFSPath: rootfsPath,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/GoogleContainerTools/kaniko/issues/1007
|
||||||
|
// docker run -it -v $PWD:/work:rw --rm gcr.io/kaniko-project/executor:latest --dockerfile /work/Dockerfile --context dir:///work/rootfs --destination whatever --tar-path /work/image.tar --no-push
|
||||||
|
|
||||||
|
// Run assumes the `kaniko` executable is in PATH as it shells out to it.
|
||||||
|
// The best way to do that is to spin up a container with the upstream
|
||||||
|
// image (gcr.io/kaniko-project/executor:latest) and mount enki in it.
|
||||||
|
// E.g.
|
||||||
|
// docker run -it -v "$PWD/enki":/enki --rm --entrypoint "/enki" gcr.io/kaniko-project/executor:latest
|
||||||
|
func (ca *ConverterAction) Run() (err error) {
|
||||||
|
dockerfile, err := ca.createDockerfile()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer os.Remove(dockerfile)
|
||||||
|
|
||||||
|
err = ca.addDockerIgnore()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer ca.removeDockerIgnore()
|
||||||
|
|
||||||
|
out, err := ca.BuildWithKaniko(dockerfile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%w: %s", err, out)
|
||||||
|
}
|
||||||
|
fmt.Printf("out = %+v\n", out)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ca *ConverterAction) createDockerfile() (string, error) {
|
||||||
|
f, err := os.CreateTemp("", "")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
// write data to the temporary file
|
||||||
|
data := []byte(`
|
||||||
|
FROM scratch as rootfs
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
FROM rootfs
|
||||||
|
|
||||||
|
# TODO: Do more clever things
|
||||||
|
RUN apt-get install -y curl
|
||||||
|
`)
|
||||||
|
|
||||||
|
if _, err := f.Write(data); err != nil {
|
||||||
|
os.Remove(f.Name())
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return f.Name(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/GoogleContainerTools/kaniko/issues/1007
|
||||||
|
// Create a .dockerignore in the rootfs directory to skip these:
|
||||||
|
// https://github.com/GoogleContainerTools/kaniko/pull/1724/files#diff-1e90758e2fb0f26bdbfe7a40aafc4b4796cbf808842703e52e16c1f36b8da7dcR89
|
||||||
|
func (ca *ConverterAction) addDockerIgnore() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ca *ConverterAction) removeDockerIgnore() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ca *ConverterAction) BuildWithKaniko(dockerfile string) (string, error) {
|
||||||
|
fmt.Printf("ca.rootFSPath = %+v\n", ca.rootFSPath)
|
||||||
|
cmd := exec.Command("executor",
|
||||||
|
"--dockerfile", dockerfile,
|
||||||
|
"--context", ca.rootFSPath,
|
||||||
|
"--destination", "whatever",
|
||||||
|
"--tar-path", "image.tar", // TODO: Where do we write? Do we want this extracted to the rootFSPath?
|
||||||
|
"--no-push",
|
||||||
|
)
|
||||||
|
|
||||||
|
d, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("%w: %s", err, string(d))
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(d), err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user