mirror of https://github.com/knative/func.git
139 lines
5.2 KiB
Go
139 lines
5.2 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/ory/viper"
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/boson-project/faas"
|
|
"github.com/boson-project/faas/buildpacks"
|
|
"github.com/boson-project/faas/prompt"
|
|
)
|
|
|
|
func init() {
|
|
root.AddCommand(buildCmd)
|
|
buildCmd.Flags().StringP("builder", "b", "default", "Buildpacks builder")
|
|
buildCmd.Flags().BoolP("confirm", "c", false, "Prompt to confirm all configuration options - $FAAS_CONFIRM")
|
|
buildCmd.Flags().StringP("image", "i", "", "Optional full image name, in form [registry]/[namespace]/[name]:[tag] for example quay.io/myrepo/project.name:latest (overrides --repository) - $FAAS_IMAGE")
|
|
buildCmd.Flags().StringP("path", "p", cwd(), "Path to the Function project directory - $FAAS_PATH")
|
|
buildCmd.Flags().StringP("repository", "r", "", "Repository for built images, ex 'docker.io/myuser' or just 'myuser'. Optional if --image provided. - $FAAS_REPOSITORY")
|
|
|
|
err := buildCmd.RegisterFlagCompletionFunc("builder", CompleteBuilderList)
|
|
if err != nil {
|
|
fmt.Println("Error while calling RegisterFlagCompletionFunc: ", err)
|
|
}
|
|
}
|
|
|
|
var buildCmd = &cobra.Command{
|
|
Use: "build",
|
|
Short: "Build an existing Function project as an OCI image",
|
|
Long: `Build an existing Function project as an OCI image
|
|
|
|
Builds the Function project in the current directory or in the directory
|
|
specified by the --path flag. The faas.yaml file is read to determine the
|
|
image name and repository. If both of these values are unset in the
|
|
configuration file the --repository or -r flag should be provided and an image
|
|
name will be derived from the project name.
|
|
|
|
Any value provided for --image or --repository will be persisted in the
|
|
faas.yaml configuration file. On subsequent invocations of the "build" command
|
|
these values will be read from the configuration file.
|
|
|
|
It's possible to use a custom Buildpack builder with the --builder flag.
|
|
The value may be image name e.g. "cnbs/sample-builder:bionic",
|
|
or reference to builderMaps in the config file e.g. "default".
|
|
`,
|
|
SuggestFor: []string{"biuld", "buidl", "built"},
|
|
PreRunE: bindEnv("image", "path", "builder", "repository", "confirm"),
|
|
RunE: runBuild,
|
|
}
|
|
|
|
func runBuild(cmd *cobra.Command, _ []string) (err error) {
|
|
config := newBuildConfig()
|
|
function, err := functionWithOverrides(config.Path, functionOverrides{Builder: config.Builder, Image: config.Image})
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// If the Function does not yet have an image name, and one was not provided
|
|
// on the command line AND a --repository was not provided, then we need to
|
|
// prompt for a repository from which we can derive an image name.
|
|
if function.Image == "" && config.Repository == "" {
|
|
fmt.Print("A repository for Function images is required. For example, 'docker.io/tigerteam'.\n\n")
|
|
config.Repository = prompt.ForString("Repository for Function images", "")
|
|
if config.Repository == "" {
|
|
return fmt.Errorf("Unable to determine Function image name")
|
|
}
|
|
}
|
|
|
|
builder := buildpacks.NewBuilder()
|
|
builder.Verbose = config.Verbose
|
|
|
|
client := faas.New(
|
|
faas.WithVerbose(config.Verbose),
|
|
faas.WithRepository(config.Repository), // for deriving image name when --image not provided explicitly.
|
|
faas.WithBuilder(builder))
|
|
|
|
config.Prompt()
|
|
|
|
return client.Build(config.Path)
|
|
}
|
|
|
|
type buildConfig struct {
|
|
// Image name in full, including registry, repo and tag (overrides
|
|
// image name derivation based on Repository and Function Name)
|
|
Image string
|
|
|
|
// Path of the Function implementation on local disk. Defaults to current
|
|
// working directory of the process.
|
|
Path string
|
|
|
|
// Push the resultnat image to the repository after building.
|
|
Push bool
|
|
|
|
// Repository at which interstitial build artifacts should be kept.
|
|
// Registry is optional and is defaulted to faas.DefaultRegistry.
|
|
// ex: "quay.io/myrepo" or "myrepo"
|
|
// This setting is ignored if Image is specified, which includes the full
|
|
Repository string
|
|
|
|
// Verbose logging.
|
|
Verbose bool
|
|
|
|
// Confirm: confirm values arrived upon from environment plus flags plus defaults,
|
|
// with interactive prompting (only applicable when attached to a TTY).
|
|
Confirm bool
|
|
Builder string
|
|
}
|
|
|
|
func newBuildConfig() buildConfig {
|
|
return buildConfig{
|
|
Image: viper.GetString("image"),
|
|
Path: viper.GetString("path"),
|
|
Repository: viper.GetString("repository"),
|
|
Verbose: viper.GetBool("verbose"), // defined on root
|
|
Confirm: viper.GetBool("confirm"),
|
|
Builder: viper.GetString("builder"),
|
|
}
|
|
}
|
|
|
|
// Prompt the user with value of config members, allowing for interaractive changes.
|
|
// Skipped if not in an interactive terminal (non-TTY), or if --confirm false (agree to
|
|
// all prompts) was set (default).
|
|
func (c buildConfig) Prompt() buildConfig {
|
|
imageName := deriveImage(c.Image, c.Repository, c.Path)
|
|
if !interactiveTerminal() || !c.Confirm {
|
|
// If --confirm false or non-interactive, just print the image name
|
|
fmt.Printf("Building image: %v\n", imageName)
|
|
return c
|
|
}
|
|
return buildConfig{
|
|
Path: prompt.ForString("Path to project directory", c.Path),
|
|
Image: prompt.ForString("Image name", imageName, prompt.WithRequired(true)),
|
|
Verbose: c.Verbose,
|
|
// Repository not prompted for as it would be confusing when combined with explicit image. Instead it is
|
|
// inferred by the derived default for Image, which uses Repository for derivation.
|
|
}
|
|
}
|