Merge pull request #17 from BenTheElder/prebuilt

prebuilt images
This commit is contained in:
k8s-ci-robot
2018-09-20 10:25:22 -07:00
committed by GitHub
10 changed files with 258 additions and 36 deletions

View File

@@ -26,6 +26,7 @@ import (
type flags struct {
Source string
Image string
Tag string
}
// NewCommand returns a new cobra.Command for building the base image
@@ -41,14 +42,24 @@ func NewCommand() *cobra.Command {
},
}
cmd.Flags().StringVar(&flags.Source, "source", "", "path to the base image sources")
cmd.Flags().StringVar(&flags.Image, "image", "kind-base", "name of the resulting image to be built")
cmd.Flags().StringVar(
&flags.Image, "image",
base.DefaultImageName,
"name of the resulting image to be built",
)
cmd.Flags().StringVar(
&flags.Tag, "tag",
base.DefaultImageTag,
"tag of the resulting image to be built",
)
return cmd
}
func run(flags *flags, cmd *cobra.Command, args []string) {
// TODO(bentheelder): make this more configurable
ctx := base.NewBuildContext(
base.WithImageTag(flags.Image),
base.WithImageName(flags.Image),
base.WithImageTag(flags.Tag),
base.WithSourceDir(flags.Source),
)
err := ctx.Build()

View File

@@ -27,7 +27,9 @@ type flags struct {
Source string
BuildType string
ImageName string
ImageTag string
BaseImageName string
BaseImageTag string
}
// NewCommand returns a new cobra.Command for building the node image
@@ -42,9 +44,30 @@ func NewCommand() *cobra.Command {
run(flags, cmd, args)
},
}
cmd.Flags().StringVar(&flags.BuildType, "type", "docker", "build type, one of [bazel, docker, apt]")
cmd.Flags().StringVar(&flags.ImageName, "image", "kind-node", "name of the resulting image to be built")
cmd.Flags().StringVar(&flags.BaseImageName, "base-image", "kind-base", "name of the base image to use for the build")
cmd.Flags().StringVar(
&flags.BuildType, "type",
"docker", "build type, one of [bazel, docker, apt]",
)
cmd.Flags().StringVar(
&flags.ImageName, "image",
node.DefaultImageName,
"name of the resulting image to be built",
)
cmd.Flags().StringVar(
&flags.ImageTag, "tag",
node.DefaultImageTag,
"tag of the resulting image to be built",
)
cmd.Flags().StringVar(
&flags.BaseImageName, "base-image",
node.DefaultBaseImageName,
"name of the base image to use for the build",
)
cmd.Flags().StringVar(
&flags.BaseImageTag, "base-tag",
node.DefaultBaseImageTag,
"tag of the base image to use for the build",
)
return cmd
}
@@ -52,8 +75,10 @@ func run(flags *flags, cmd *cobra.Command, args []string) {
// TODO(bentheelder): make this more configurable
ctx, err := node.NewBuildContext(
node.WithMode(flags.BuildType),
node.WithImageTag(flags.ImageName),
node.WithBaseImage(flags.BaseImageName),
node.WithImageName(flags.ImageName),
node.WithImageTag(flags.ImageTag),
node.WithBaseImageName(flags.BaseImageName),
node.WithBaseImageTag(flags.BaseImageTag),
)
if err != nil {
log.Fatalf("Error creating build context: %v", err)

View File

@@ -44,9 +44,9 @@ func NewCommand() *cobra.Command {
run(flags, cmd, args)
},
}
cmd.Flags().StringVar(&flags.Name, "name", "1", "the cluster name")
cmd.Flags().StringVar(&flags.Config, "config", "", "path to create config file")
cmd.Flags().StringVar(&flags.ImageName, "image", "", "name of the image to use for booting the cluster. If this is non-empty, it will override the value specified in the --config file.")
cmd.Flags().StringVar(&flags.Name, "name", "1", "the cluster context name")
cmd.Flags().StringVar(&flags.Config, "config", "", "path to a kind config file")
cmd.Flags().StringVar(&flags.ImageName, "image", "", "node docker image to use for booting the cluster")
return cmd
}

46
hack/build/push-base.sh Executable file
View File

@@ -0,0 +1,46 @@
#!/usr/bin/env bash
# Copyright 2018 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -o errexit
set -o nounset
set -o pipefail
# cd to the repo root
REPO_ROOT=$(git rev-parse --show-toplevel)
cd "${REPO_ROOT}"
# place to stick temp binaries
BINDIR="${REPO_ROOT}/_output/bin"
# install kind from the repo into $BINDIR
get_kind() {
# build kind from the repo and use that ...
GOBIN="${BINDIR}" go install .
echo "${BINDIR}/kind"
}
# select kind binary to use
KIND="${KIND:-$(get_kind)}"
# generate tag
DATE="$(date +v%Y%m%d)"
TAG="${DATE}-$(git describe --tags --always --dirty)"
# build
(set -x; "${KIND}" build base --tag="${TAG}")
# push
docker push kindest/base:"${TAG}"

53
hack/build/push-node.sh Executable file
View File

@@ -0,0 +1,53 @@
#!/usr/bin/env bash
# Copyright 2018 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -o errexit
set -o nounset
set -o pipefail
# cd to the repo root
REPO_ROOT=$(git rev-parse --show-toplevel)
cd "${REPO_ROOT}"
# place to stick temp binaries
BINDIR="${REPO_ROOT}/_output/bin"
# install kind from the repo into $BINDIR
get_kind() {
# build kind from the repo and use that ...
GOBIN="${BINDIR}" go install .
echo "${BINDIR}/kind"
}
# select kind binary to use
KIND="${KIND:-$(get_kind)}"
# generate tag
DATE="$(date +v%Y%m%d)"
TAG="${DATE}-$(git describe --tags --always --dirty)"
# build
set -x
"${KIND}" build node --tag="${TAG}" --base-tag="${TAG}"
# re-tag with kubernetes version
IMG="kindest/node:${TAG}"
KUBE_VERSION="$(docker run --rm --entrypoint=cat "${IMG}" /kind/version)"
docker tag "${IMG}" "kindest/node:${KUBE_VERSION}"
# push
docker push kindest/node:"${KUBE_VERSION}"

View File

@@ -24,20 +24,28 @@ import (
log "github.com/sirupsen/logrus"
"sigs.k8s.io/kind/pkg/build/base/sources"
"sigs.k8s.io/kind/pkg/docker"
"sigs.k8s.io/kind/pkg/exec"
"sigs.k8s.io/kind/pkg/fs"
)
// DefaultImageName is the default name of the built base image
const DefaultImageName = "kind-base"
const DefaultImageName = "kindest/base"
// DefaultImageTag is the default tag of the built base image
const DefaultImageTag = "latest"
// BuildContext is used to build the kind node base image, and contains
// build configuration
type BuildContext struct {
// option fields
sourceDir string
imageName string
imageTag string
goCmd string
arch string
// non option fields
image string
goCmd string // TODO(bentheelder): should be an option possibly
arch string // TODO(bentheelder): should be an option
}
// Option is BuildContext configuration option supplied to NewBuildContext
@@ -50,6 +58,13 @@ func WithSourceDir(sourceDir string) Option {
}
}
// WithImageName configures a NewBuildContext to tag the built image with `name`
func WithImageName(name string) Option {
return func(b *BuildContext) {
b.imageName = name
}
}
// WithImageTag configures a NewBuildContext to tag the built image with `tag`
func WithImageTag(tag string) Option {
return func(b *BuildContext) {
@@ -61,13 +76,16 @@ func WithImageTag(tag string) Option {
// default configuration
func NewBuildContext(options ...Option) *BuildContext {
ctx := &BuildContext{
imageTag: DefaultImageName,
goCmd: "go",
arch: "amd64",
imageName: DefaultImageName,
imageTag: DefaultImageTag,
goCmd: "go",
arch: "amd64",
}
for _, option := range options {
option(ctx)
}
// normalize name and tag into an image reference
ctx.image = docker.JoinNameAndTag(ctx.imageName, ctx.imageTag)
return ctx
}
@@ -135,7 +153,7 @@ func (c *BuildContext) buildEntrypoint(dir string) error {
func (c *BuildContext) buildImage(dir string) error {
// build the image, tagged as tagImageAs, using the our tempdir as the context
cmd := exec.Command("docker", "build", "-t", c.imageTag, dir)
cmd := exec.Command("docker", "build", "-t", c.image, dir)
cmd.Debug = true
cmd.InheritOutput = true

View File

@@ -27,15 +27,24 @@ import (
log "github.com/sirupsen/logrus"
"sigs.k8s.io/kind/pkg/build/kube"
"sigs.k8s.io/kind/pkg/docker"
"sigs.k8s.io/kind/pkg/exec"
"sigs.k8s.io/kind/pkg/fs"
)
// DefaultTag is the default tag for the built image
const DefaultTag = "kind-node"
// DefaultImageName is the default name for the built image
const DefaultImageName = "kindest/node"
// DefaultBaseImage is the default base image used
const DefaultBaseImage = "kind-base"
// DefaultImageTag is the default tag for the built image
const DefaultImageTag = "latest"
// DefaultBaseImageName is the default base image name used
const DefaultBaseImageName = "kindest/base"
// DefaultBaseImageTag is the default base image tag used
// TODO(bentheelder): add tooling to automanage this,
// and document using --base-tag=latest for local builds
const DefaultBaseImageTag = "v20180920-afa27a7"
// DefaultMode is the default kubernetes build mode for the built image
// see pkg/build/kube.Bits
@@ -44,6 +53,13 @@ const DefaultMode = "docker"
// Option is BuildContext configuration option supplied to NewBuildContext
type Option func(*BuildContext)
// WithImageName configures a NewBuildContext to tag the built image with `name`
func WithImageName(name string) Option {
return func(b *BuildContext) {
b.imageName = name
}
}
// WithImageTag configures a NewBuildContext to tag the built image with `tag`
func WithImageTag(tag string) Option {
return func(b *BuildContext) {
@@ -51,10 +67,17 @@ func WithImageTag(tag string) Option {
}
}
// WithBaseImage configures a NewBuildContext to use `image` as the base image
func WithBaseImage(image string) Option {
// WithBaseImageName configures a NewBuildContext to use `image` as the base image name
func WithBaseImageName(image string) Option {
return func(b *BuildContext) {
b.baseImage = image
b.baseImageName = image
}
}
// WithBaseImageTag configures a NewBuildContext to use `tag` as the base image tag
func WithBaseImageTag(tag string) Option {
return func(b *BuildContext) {
b.baseImageTag = tag
}
}
@@ -69,13 +92,17 @@ func WithMode(mode string) Option {
// build configuration
type BuildContext struct {
// option fields
mode string
imageTag string
arch string
baseImage string
mode string
imageName string
imageTag string
baseImageName string
baseImageTag string
// non-option fields
kubeRoot string
bits kube.Bits
arch string // TODO(bentheelder): this should be an option
image string
baseImage string
kubeRoot string
bits kube.Bits
}
// NewBuildContext creates a new BuildContext with default configuration,
@@ -83,15 +110,20 @@ type BuildContext struct {
func NewBuildContext(options ...Option) (ctx *BuildContext, err error) {
// default options
ctx = &BuildContext{
mode: DefaultMode,
imageTag: DefaultTag,
arch: "amd64",
baseImage: DefaultBaseImage,
mode: DefaultMode,
imageName: DefaultImageName,
imageTag: DefaultImageTag,
arch: "amd64",
baseImageName: DefaultBaseImageName,
baseImageTag: DefaultBaseImageTag,
}
// apply user options
for _, option := range options {
option(ctx)
}
// normalize name and tag into an image reference
ctx.image = docker.JoinNameAndTag(ctx.imageName, ctx.imageTag)
ctx.baseImage = docker.JoinNameAndTag(ctx.baseImageName, ctx.baseImageTag)
// lookup kuberoot unless mode == "apt",
// apt should not fail on finding kube root as it does not use it
kubeRoot := ""
@@ -249,7 +281,7 @@ func (c *BuildContext) buildImage(dir string) error {
}
// Save the image changes to a new image
cmd := exec.Command("docker", "commit", containerID, c.imageTag)
cmd := exec.Command("docker", "commit", containerID, c.image)
cmd.Debug = true
cmd.InheritOutput = true
if err = cmd.Run(); err != nil {

View File

@@ -26,7 +26,8 @@ func New() *Config {
// ApplyDefaults replaces unset fields with defaults
func (c *Config) ApplyDefaults() {
if c.Image == "" {
c.Image = "kind-node"
// TODO(bentheelder): move this to a constant
c.Image = "kindest/node:v1.11.3"
}
if c.NumNodes == 0 {
c.NumNodes = 1

View File

@@ -24,6 +24,7 @@ package config
// Other API versions can be converted to this struct with Convert()
type Config struct {
// Image is the node image to use when running the cluster
// TODO(bentheelder): split this into image and tag?
Image string `json:"image,omitempty"`
// NumNodes is the number of nodes to create (currently only one is supported)
NumNodes int `json:"numNodes,omitempty"`

35
pkg/docker/docker.go Normal file
View File

@@ -0,0 +1,35 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package docker contains helpers for working with docker
package docker
import (
"strings"
)
// JoinNameAndTag combines a docker image name and tag
// The tag may be empty, a tag as in name:tag, or a a sha as in `@sha256:asdf`
func JoinNameAndTag(name, tag string) string {
// Join the name and tag with a colon IFF the tag is not any of:
// - empty, in which case we can just the name
// - starts with @, this is either a digest, or an invalid value
// - starts with :, we can gracefully not double up the :
if tag != "" && !strings.HasPrefix(tag, "@") && !strings.HasPrefix(tag, ":") {
return name + ":" + tag
}
return name + tag
}