diff --git a/ingressctl/cmd/common.go b/ingressctl/cmd/common.go new file mode 100644 index 000000000..1509f5f00 --- /dev/null +++ b/ingressctl/cmd/common.go @@ -0,0 +1,64 @@ +package cmd + +import ( + "fmt" + "os" + "strings" + "time" +) + +var DEBUG bool + +func init() { + DEBUG = false + debugENV := os.Getenv("MAGE_DEBUG") + if debugENV == "true" { + DEBUG = true + } +} + +// CheckArgs should be used to ensure the right command line arguments are +// passed before executing an example. +func CheckArgs(arg ...string) { + if len(os.Args) < len(arg)+1 { + ErrorF("Usage: %s %s", os.Args[0], strings.Join(arg, " ")) + os.Exit(1) + } +} + +// CheckIfError should be used to naively panics if an error is not nil. +func CheckIfError(err error, format string, args ...interface{}) { + if err == nil { + return + } + + fmt.Printf("\x1b[31;1m%s ERROR %s %s\x1b[0m\n", timeStamp(), fmt.Sprintf(format, args...), err) + os.Exit(1) +} + +// Info should be used to describe the example commands that are about to run. +func Info(format string, args ...interface{}) { + fmt.Printf("\x1b[34;1m%s INFO: %s\x1b[0m\n", timeStamp(), fmt.Sprintf(format, args...)) +} + +func timeStamp() string { + t := time.Now() + return t.Format(time.RFC3339) +} + +// Warning should be used to display a warning +func Warning(format string, args ...interface{}) { + fmt.Printf("\x1b[36;1m%s WARNING: %s\x1b[0m\n", timeStamp(), fmt.Sprintf(format, args...)) +} + +// Info should be used to describe the example commands that are about to run. +func Debug(format string, args ...interface{}) { + if DEBUG { + fmt.Printf("\x1b[34;1m%s DEBUG: %s\x1b[0m\n", timeStamp(), fmt.Sprintf(format, args...)) + } +} + +// Info should be used to describe the example commands that are about to run. +func ErrorF(format string, args ...interface{}) { + fmt.Printf("\x1b[31;1m%s ERROR: %s\x1b[0m\n", timeStamp(), fmt.Sprintf(format, args...)) +} diff --git a/ingressctl/cmd/docker.go b/ingressctl/cmd/docker.go index 287685aba..7bb70e7c5 100644 --- a/ingressctl/cmd/docker.go +++ b/ingressctl/cmd/docker.go @@ -3,7 +3,10 @@ package cmd import ( "context" "fmt" + "os" + "strings" + "github.com/codeskyblue/go-sh" "github.com/docker/docker/api/types" "github.com/docker/docker/client" "github.com/spf13/cobra" @@ -26,18 +29,33 @@ var dockerListCmd = &cobra.Command{ var dockerBuildCmd = &cobra.Command{ Use: "build", - Short: "build a docker container" - Long: "build a docker container for use with ingress-nginx" - Run: func(cmd *cobra.Command, args []string){ + + Long: "build a docker container for use with ingress-nginx", + Run: func(cmd *cobra.Command, args []string) { dockerBuild() }, - } + +var dco dockerBuildOpts + func init() { rootCmd.AddCommand(dockerCmd) dockerCmd.AddCommand(dockerListCmd) + dockerCmd.AddCommand(dockerBuildCmd) + dockerBuildCmd.Flags().StringVar(&dco.PlatformFlag, "platformflag", "", "Setting the Docker --platform build flag") + dockerBuildCmd.Flags().StringSliceVar(&dco.Platform, "platforms", PLATFORMS, "comma seperated list of platforms to build for container image") + dockerBuildCmd.Flags().StringVar(&dco.BuildArgs.BaseImage, "base", "", "base image to build container off of") + dockerBuildCmd.Flags().StringVar(&dco.Path, "path", "", "container build path") + dockerBuildCmd.Flags().StringVar(&dco.BuildArgs.Version, "version", "", "docker tag to build") + dockerBuildCmd.Flags().StringVar(&dco.BuildArgs.TargetArch, "targetarch", "", "target arch to build") + dockerBuildCmd.Flags().StringVar(&dco.BuildArgs.CommitSHA, "commitsha", "", "build arg commit sha to add to build") + dockerBuildCmd.Flags().StringVar(&dco.BuildArgs.BuildId, "build-id", "", "build id to add to container metadata") + dockerBuildCmd.Flags().StringVar(&dco.DockerFile, "dockerfile", "", "dockerfile of image to build") + dockerBuildCmd.Flags().StringVar(&dco.Image.Name, "name", "", "container image name registry/name:tag@digest") + dockerBuildCmd.Flags().StringVar(&dco.Image.Registry, "registry", Registry, "Registry to tag image and push container registry/name:tag@digest") + dockerBuildCmd.Flags().StringVar(&dco.Image.Tag, "tag", "", "container tag registry/name:tag@digest") + dockerBuildCmd.Flags().StringVar(&dco.Image.Digest, "digest", "", "digest of container image registry/name:tag@digest") } - func dockerList() { cli, err := client.NewClientWithOpts(client.FromEnv) if err != nil { @@ -54,35 +72,91 @@ func dockerList() { } } +var PLATFORMS = []string{"amd64", "arm", "arm64", "s390x"} +var BUILDX_PLATFORMS = "linux/amd64,linux/arm,linux/arm64,linux/s390x" +var Registry = "gcr.io/k8s-staging-ingress-nginx" +var PKG = "k8s.io/ingress-nginx" + +type dockerBuildOpts struct { + PlatformFlag string + Platform []string + BuildArgs BuildArgs + DockerFile string + Image Image + Path string +} + +type BuildArgs struct { + BaseImage string + Version string + TargetArch string + CommitSHA string + BuildId string +} + +// ControllerImage - struct with info about controllers +type Image struct { + Tag string + Digest string + Registry string + Name string +} + +func (i Image) print() string { + return fmt.Sprintf("%s/%s:%s@sha256:%s", i.Registry, i.Name, i.Tag, i.Digest) +} + func dockerBuild() error { -/* - docker build \ - ${PLATFORM_FLAG} ${PLATFORM} \ ---no-cache \ - --pull \ - --build-arg BASE_IMAGE="$(BASE_IMAGE)" \ - --build-arg VERSION="$(TAG)" \ - --build-arg TARGETARCH="$(ARCH)" \ - --build-arg COMMIT_SHA="$(COMMIT_SHA)" \ - --build-arg BUILD_ID="$(BUILD_ID)" \ - -t $(REGISTRY)/controller:$(TAG) rootfs -*/ + /* + docker build \ + ${PLATFORM_FLAG} ${PLATFORM} \ + --no-cache \ + --pull \ + --build-arg BASE_IMAGE="$(BASE_IMAGE)" \ + --build-arg VERSION="$(TAG)" \ + --build-arg TARGETARCH="$(ARCH)" \ + --build-arg COMMIT_SHA="$(COMMIT_SHA)" \ + --build-arg BUILD_ID="$(BUILD_ID)" \ + -t $(REGISTRY)/controller:$(TAG) rootfs + */ + session := sh.NewSession() + session.ShowCMD = true - cli, err := client.NewClientWithOpts(client.FromEnv) - if err != nil { - panic(err) - } + fmt.Printf("Container Build Path: %v\n", dco.Path) - builder := io.Reader{} + buildArgs := BuildArgs(dco.BuildArgs) - options := docker.ImageCreateOptions{ + fmt.Printf("Base image: %s\n", dco.BuildArgs.BaseImage) + fmt.Printf("Build Args: %s\n", buildArgs) - } - buildReponse, err := cli.ImageBuild(context.Background(), builder, options) - if err != nil{ - return err - } - return nil + session.Command("docker", "build", "--no-cache", "--pull", fmt.Sprintf("%v", buildArgs), fmt.Sprintf("%s", dco.Path)).Run() - } + return nil + +} + +func buildArgs(b *BuildArgs) string { + + if b.BaseImage == "" { + base, err := getIngressNginxBase() + CheckIfError(err, "Issue Retrieving base image") + fmt.Printf("Base Image set %s\n", base) + b.BaseImage = base + } + + buildArgString := "--build-arg BASE_IMAGE=" + b.BaseImage + + return buildArgString +} + +func getIngressNginxBase() (string, error) { + fmt.Print("GET INGRESS NGINX BASE") + dat, err := os.ReadFile("../NGINX_BASE") + CheckIfError(err, "Could not read NGINX_BASE file") + fmt.Printf("Get Ingress Dat: %v\n", dat) + datString := string(dat) + //remove newline + datString = strings.Replace(datString, "\n", "", -1) + return datString, nil +} diff --git a/ingressctl/cmd/tags.go b/ingressctl/cmd/tags.go new file mode 100644 index 000000000..d343f4208 --- /dev/null +++ b/ingressctl/cmd/tags.go @@ -0,0 +1,16 @@ +package cmd + +import ( + "os" + "strings" +) + +func getIngressNGINXVersion() (string, error) { + + dat, err := os.ReadFile("TAG") + CheckIfError(err, "Could not read TAG file") + datString := string(dat) + //remove newline + datString = strings.Replace(datString, "\n", "", -1) + return datString, nil +} diff --git a/ingressctl/go.mod b/ingressctl/go.mod index e90e10b83..75b17f159 100644 --- a/ingressctl/go.mod +++ b/ingressctl/go.mod @@ -3,12 +3,14 @@ module github.com/kubernetes/ingress-nginx/ingressctl go 1.20 require ( + github.com/codeskyblue/go-sh v0.0.0-20200712050446-30169cf553fe github.com/docker/docker v24.0.2+incompatible github.com/spf13/cobra v1.7.0 ) require ( github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect github.com/docker/distribution v2.8.2+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect diff --git a/ingressctl/go.sum b/ingressctl/go.sum index e945c6500..f7544022d 100644 --- a/ingressctl/go.sum +++ b/ingressctl/go.sum @@ -1,6 +1,10 @@ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q= +github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= +github.com/codeskyblue/go-sh v0.0.0-20200712050446-30169cf553fe h1:69JI97HlzP+PH5Mi1thcGlDoBr6PS2Oe+l3mNmAkbs4= +github.com/codeskyblue/go-sh v0.0.0-20200712050446-30169cf553fe/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= diff --git a/ingressctl/main.go b/ingressctl/main.go index c1d7f8adc..fc62a1942 100644 --- a/ingressctl/main.go +++ b/ingressctl/main.go @@ -4,4 +4,5 @@ import "github.com/kubernetes/ingress-nginx/ingressctl/cmd" func main() { cmd.Execute() + }