Skip to content

Commit

Permalink
Support --pull for build/publish commands
Browse files Browse the repository at this point in the history
The --pull flag is supported by Docker and forces a pull
attempt to be made for base images for the case that there
is a newer version available.

The main use-case for this is when teams are publishing
production or internal images directly from their own machines
which accumulate older images.

This is not needed in CI pipelines which start with an empty
library, so always pull the base images fresh from source.

Signed-off-by: Alex Ellis (OpenFaaS Ltd) <[email protected]>
  • Loading branch information
alexellis committed Aug 8, 2024
1 parent 7264f71 commit f509dd3
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 7 deletions.
14 changes: 11 additions & 3 deletions builder/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const AdditionalPackageBuildArg = "ADDITIONAL_PACKAGE"

// BuildImage construct Docker image from function parameters
// TODO: refactor signature to a struct to simplify the length of the method header
func BuildImage(image string, handler string, functionName string, language string, nocache bool, squash bool, shrinkwrap bool, buildArgMap map[string]string, buildOptions []string, tagFormat schema.BuildFormat, buildLabelMap map[string]string, quietBuild bool, copyExtraPaths []string, remoteBuilder, payloadSecretPath string) error {
func BuildImage(image string, handler string, functionName string, language string, nocache bool, squash bool, shrinkwrap bool, buildArgMap map[string]string, buildOptions []string, tagFormat schema.BuildFormat, buildLabelMap map[string]string, quietBuild bool, copyExtraPaths []string, remoteBuilder, payloadSecretPath string, forcePull bool) error {

if stack.IsValidTemplate(language) {
pathToTemplateYAML := fmt.Sprintf("./template/%s/template.yml", language)
Expand Down Expand Up @@ -127,6 +127,7 @@ func BuildImage(image string, handler string, functionName string, language stri
BuildArgMap: buildArgMap,
BuildOptPackages: buildOptPackages,
BuildLabelMap: buildLabelMap,
ForcePull: forcePull,
}

command, args := getDockerBuildCommand(dockerBuildVal)
Expand All @@ -135,6 +136,7 @@ func BuildImage(image string, handler string, functionName string, language stri
if mountSSH {
envs = append(envs, "DOCKER_BUILDKIT=1")
}
log.Printf("Build flags: %+v\n", args)

task := v2execute.ExecTask{
Cwd: tempPath,
Expand Down Expand Up @@ -260,7 +262,7 @@ func hashFolder(contextPath string) (string, error) {
}

func getDockerBuildCommand(build dockerBuild) (string, []string) {
flagSlice := buildFlagSlice(build.NoCache, build.Squash, build.HTTPProxy, build.HTTPSProxy, build.BuildArgMap, build.BuildOptPackages, build.BuildLabelMap)
flagSlice := buildFlagSlice(build.NoCache, build.Squash, build.HTTPProxy, build.HTTPSProxy, build.BuildArgMap, build.BuildOptPackages, build.BuildLabelMap, build.ForcePull)
args := []string{"build"}
args = append(args, flagSlice...)

Expand All @@ -287,6 +289,8 @@ type dockerBuild struct {

// ExtraTags for published images like :latest
ExtraTags []string

ForcePull bool
}

var defaultDirPermissions os.FileMode = 0700
Expand Down Expand Up @@ -409,7 +413,7 @@ func pathInScope(path string, scope string) (string, error) {
return "", fmt.Errorf("forbidden path appears to be outside of the build context: %s (%s)", path, abs)
}

func buildFlagSlice(nocache bool, squash bool, httpProxy string, httpsProxy string, buildArgMap map[string]string, buildOptionPackages []string, buildLabelMap map[string]string) []string {
func buildFlagSlice(nocache bool, squash bool, httpProxy string, httpsProxy string, buildArgMap map[string]string, buildOptionPackages []string, buildLabelMap map[string]string, forcePull bool) []string {

var spaceSafeBuildFlags []string

Expand Down Expand Up @@ -445,6 +449,10 @@ func buildFlagSlice(nocache bool, squash bool, httpProxy string, httpsProxy stri
spaceSafeBuildFlags = append(spaceSafeBuildFlags, "--label", fmt.Sprintf("%s=%s", k, v))
}

if forcePull {
spaceSafeBuildFlags = append(spaceSafeBuildFlags, "--pull")
}

return spaceSafeBuildFlags
}

Expand Down
3 changes: 2 additions & 1 deletion builder/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,8 @@ func Test_buildFlagSlice(t *testing.T) {

t.Run(test.title, func(t *testing.T) {

flagSlice := buildFlagSlice(test.nocache, test.squash, test.httpProxy, test.httpsProxy, test.buildArgMap, test.buildPackages, test.buildLabelMap)
forcePull := false
flagSlice := buildFlagSlice(test.nocache, test.squash, test.httpProxy, test.httpsProxy, test.buildArgMap, test.buildPackages, test.buildLabelMap, forcePull)
fmt.Println(flagSlice)
if len(flagSlice) != len(test.expectedSlice) {
t.Errorf("Slices differ in size - wanted: %d, found %d", len(test.expectedSlice), len(flagSlice))
Expand Down
10 changes: 8 additions & 2 deletions builder/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const BuilderConfigFilename = "com.openfaas.docker.config"
// PublishImage will publish images as multi-arch
// TODO: refactor signature to a struct to simplify the length of the method header
func PublishImage(image string, handler string, functionName string, language string, nocache bool, squash bool, shrinkwrap bool, buildArgMap map[string]string,
buildOptions []string, tagMode schema.BuildFormat, buildLabelMap map[string]string, quietBuild bool, copyExtraPaths []string, platforms string, extraTags []string, remoteBuilder, payloadSecretPath string) error {
buildOptions []string, tagMode schema.BuildFormat, buildLabelMap map[string]string, quietBuild bool, copyExtraPaths []string, platforms string, extraTags []string, remoteBuilder, payloadSecretPath string, forcePull bool) error {

if stack.IsValidTemplate(language) {
pathToTemplateYAML := fmt.Sprintf("./template/%s/template.yml", language)
Expand Down Expand Up @@ -81,6 +81,11 @@ func PublishImage(image string, handler string, functionName string, language st
fmt.Printf("Building: %s with %s template. Please wait..\n", imageName, language)

if remoteBuilder != "" {

if forcePull {
return fmt.Errorf("--pull is not supported with --remote-builder")
}

tempDir, err := os.MkdirTemp(os.TempDir(), "builder-*")
if err != nil {
return fmt.Errorf("failed to create temporary directory for %s, error: %w", functionName, err)
Expand Down Expand Up @@ -139,6 +144,7 @@ func PublishImage(image string, handler string, functionName string, language st
BuildLabelMap: buildLabelMap,
Platforms: platforms,
ExtraTags: extraTags,
ForcePull: forcePull,
}

command, args := getDockerBuildxCommand(dockerBuildVal)
Expand Down Expand Up @@ -173,7 +179,7 @@ func PublishImage(image string, handler string, functionName string, language st

func getDockerBuildxCommand(build dockerBuild) (string, []string) {
flagSlice := buildFlagSlice(build.NoCache, build.Squash, build.HTTPProxy, build.HTTPSProxy, build.BuildArgMap,
build.BuildOptPackages, build.BuildLabelMap)
build.BuildOptPackages, build.BuildLabelMap, build.ForcePull)

// pushOnly defined at https://github.com/docker/buildx
const pushOnly = "--output=type=registry,push=true"
Expand Down
7 changes: 6 additions & 1 deletion commands/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ var (
envsubst bool
quietBuild bool
disableStackPull bool
forcePull bool
)

func init() {
Expand All @@ -59,6 +60,7 @@ func init() {
buildCmd.Flags().BoolVar(&envsubst, "envsubst", true, "Substitute environment variables in stack.yml file")
buildCmd.Flags().BoolVar(&quietBuild, "quiet", false, "Perform a quiet build, without showing output from Docker")
buildCmd.Flags().BoolVar(&disableStackPull, "disable-stack-pull", false, "Disables the template configuration in the stack.yml")
buildCmd.Flags().BoolVar(&forcePull, "pull", false, "Force a re-pull of base images in template during build, useful for publishing images")

// Set bash-completion.
_ = buildCmd.Flags().SetAnnotation("handler", cobra.BashCompSubdirsInDir, []string{})
Expand All @@ -80,7 +82,8 @@ var buildCmd = &cobra.Command{
[--build-arg KEY=VALUE]
[--build-option VALUE]
[--copy-extra PATH]
[--tag <sha|branch|describe>]`,
[--tag <sha|branch|describe>]
[--forcePull]`,
Short: "Builds OpenFaaS function containers",
Long: `Builds OpenFaaS function containers either via the supplied YAML config using
the "--yaml" flag (which may contain multiple function definitions), or directly
Expand Down Expand Up @@ -207,6 +210,7 @@ func runBuild(cmd *cobra.Command, args []string) error {
copyExtra,
remoteBuilder,
payloadSecretPath,
forcePull,
); err != nil {
return err
}
Expand Down Expand Up @@ -263,6 +267,7 @@ func build(services *stack.Services, queueDepth int, shrinkwrap, quietBuild bool
combinedExtraPaths,
remoteBuilder,
payloadSecretPath,
forcePull,
)

if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions commands/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ func init() {
publishCmd.Flags().BoolVar(&resetQemu, "reset-qemu", false, "Runs \"docker run multiarch/qemu-user-static --reset -p yes\" to enable multi-arch builds. Compatible with AMD64 machines only.")
publishCmd.Flags().StringVar(&remoteBuilder, "remote-builder", "", "URL to the builder")
publishCmd.Flags().StringVar(&payloadSecretPath, "payload-secret", "", "Path to payload secret file")
publishCmd.Flags().BoolVar(&forcePull, "pull", false, "Force a re-pull of base images in template during build, useful for publishing images")

// Set bash-completion.
_ = publishCmd.Flags().SetAnnotation("handler", cobra.BashCompSubdirsInDir, []string{})
Expand Down Expand Up @@ -257,6 +258,7 @@ func publish(services *stack.Services, queueDepth int, shrinkwrap, quietBuild, m
extraTags,
remoteBuilder,
payloadSecretPath,
forcePull,
)

if err != nil {
Expand Down

0 comments on commit f509dd3

Please sign in to comment.