diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 1ca30102..afd8ca82 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -17,15 +17,14 @@ TF_ACC=1 go test ./internal/provider/... This relies on https://www.terraform.io/cli/config/config-file#implied-local-mirror-directories ``` -KO_DOCKER_REPO=gcr.io/jason-chainguard rm .terraform.lock.hcl && \ go build -o ~/.terraform.d/plugins/registry.terraform.io/chainguard-dev/ko/0.0.100/darwin_arm64/terraform-provider-ko && \ terraform init && \ - terraform apply -var project=jason-chainguard + terraform apply ``` Also update `version = "0.0.0"` in the .tf file. -This builds the provider code into the correct local mirror location, installs the provider using that location, +This builds the provider code into the correct local mirror location, installs the provider using that location, Don't forget to delete the provider from the local mirror if you want to use the released provider later. diff --git a/docs/index.md b/docs/index.md index 45347e39..e8edf72e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -23,4 +23,5 @@ provider "ko" { ### Optional -- `docker_repo` (String) Container repositor to publish images to. Defaults to `KO_DOCKER_REPO` env var +- `docker_repo` (String) [DEPRECATED: use `repo`] Container repository to publish images to. Defaults to `KO_DOCKER_REPO` env var +- `repo` (String) Container repository to publish images to. Defaults to `KO_DOCKER_REPO` env var diff --git a/docs/resources/image.md b/docs/resources/image.md index 92d4c5b6..4912b65e 100644 --- a/docs/resources/image.md +++ b/docs/resources/image.md @@ -29,6 +29,7 @@ resource "ko_image" "example" { - `base_image` (String) base image to use - `platforms` (List of String) Which platform to use when pulling a multi-platform base. Format: all | [/[/]][,platform]* +- `repo` (String) Container repository to publish images to. If set, this overrides the provider's docker_repo, and the image name will be exactly the specified `repo`, without the importpath appended. - `sbom` (String) The SBOM media type to use (none will disable SBOM synthesis and upload, also supports: spdx, cyclonedx, go.version-m). - `working_dir` (String) working directory for the build diff --git a/internal/provider/const.go b/internal/provider/const.go index 3a3238ad..248a17f7 100644 --- a/internal/provider/const.go +++ b/internal/provider/const.go @@ -17,20 +17,22 @@ const ( BaseImageKey = "base_image" // TagsKey is used for common "tags" resource attribute TagsKey = "tags" - // TagOnlyKey used for common "tag_only" resource attribute + // TagOnlyKey is used for common "tag_only" resource attribute TagOnlyKey = "tag_only" - // PushKey used for common "push" resource attribute + // PushKey is used for common "push" resource attribute PushKey = "push" - // FilenamesKey used for common "filenames" resource attribute + // FilenamesKey is used for common "filenames" resource attribute FilenamesKey = "filenames" - // RecursiveKey used for common "recursive" resource attribute + // RecursiveKey is used for common "recursive" resource attribute RecursiveKey = "recursive" - // SelectorKey used for common "selector" resource attribute + // SelectorKey is used for common "selector" resource attribute SelectorKey = "selector" - // ImageRefKey used for common "image_ref" resource attribute + // ImageRefKey is used for common "image_ref" resource attribute ImageRefKey = "image_ref" - // ManifestsKey used for common "manifests" resource attribute + // ManifestsKey is used for common "manifests" resource attribute ManifestsKey = "manifests" + // RepoKey is used for common "repo" resource attribute + RepoKey = "repo" ) func StringSlice(in []interface{}) []string { diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 0878cfd6..c6309fd9 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -32,7 +32,13 @@ func New(version string) func() *schema.Provider { p := &schema.Provider{ Schema: map[string]*schema.Schema{ "docker_repo": { - Description: "Container repositor to publish images to. Defaults to `KO_DOCKER_REPO` env var", + Description: "[DEPRECATED: use `repo`] Container repository to publish images to. Defaults to `KO_DOCKER_REPO` env var", + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KO_DOCKER_REPO", ""), + Type: schema.TypeString, + }, + "repo": { + Description: "Container repository to publish images to. Defaults to `KO_DOCKER_REPO` env var", Optional: true, DefaultFunc: schema.EnvDefaultFunc("KO_DOCKER_REPO", ""), Type: schema.TypeString, @@ -53,18 +59,21 @@ func New(version string) func() *schema.Provider { // configure initializes the global provider with sensible defaults (that mimic what ko does with cli/cobra defaults) func configure(version string, p *schema.Provider) func(context.Context, *schema.ResourceData) (interface{}, diag.Diagnostics) { return func(ctx context.Context, s *schema.ResourceData) (interface{}, diag.Diagnostics) { - repo, ok := s.Get("docker_repo").(string) + koDockerRepo, ok := s.Get("repo").(string) if !ok { - return nil, diag.Errorf("expected docker_repo to be string") + return nil, diag.Errorf("expected repo to be string") } - if repo == "" { - return nil, diag.Errorf("docker_repo attribute or KO_DOCKER_REPO environment variable must be set") + if koDockerRepo == "" { + koDockerRepo, ok = s.Get("docker_repo").(string) + if !ok { + return nil, diag.Errorf("expected docker_repo to be string") + } } return &providerOpts{ bo: &options.BuildOptions{}, po: &options.PublishOptions{ - DockerRepo: repo, + DockerRepo: koDockerRepo, }, }, nil } diff --git a/internal/provider/resource_ko_image.go b/internal/provider/resource_ko_image.go index c587faa0..a539479f 100644 --- a/internal/provider/resource_ko_image.go +++ b/internal/provider/resource_ko_image.go @@ -2,6 +2,7 @@ package provider import ( "context" + "errors" "fmt" "log" "sync" @@ -85,6 +86,13 @@ func resourceImage() *schema.Resource { return nil }, }, + RepoKey: { + Description: "Container repository to publish images to. If set, this overrides the provider's docker_repo, and the image name will be exactly the specified `repo`, without the importpath appended.", + Default: "", + Optional: true, + Type: schema.TypeString, + ForceNew: true, // Any time this changes, don't try to update in-place, just create it. + }, ImageRefKey: { Description: "built image reference by digest", Type: schema.TypeString, @@ -116,12 +124,13 @@ func (o *publishOpts) makePublisher() (publish.Interface, error) { } type buildOptions struct { - ip string - workingDir string - dockerRepo string - platforms []string - baseImage string - sbom string + ip string + workingDir string + koDockerRepo string // KO_DOCKER_REPO env var, or the provider's configured repo if set. + imageRepo string // The image's repo, if set. + platforms []string + baseImage string + sbom string } func (o *buildOptions) makeBuilder(ctx context.Context) (*build.Caching, error) { @@ -178,6 +187,23 @@ func (o *buildOptions) makeBuilder(ctx context.Context) (*build.Caching, error) var baseImages sync.Map // Cache of base image lookups. func doBuild(ctx context.Context, opts buildOptions) (string, error) { + if opts.koDockerRepo == "" && opts.imageRepo == "" { + return "", errors.New("one of KO_DOCKER_REPO env var, or provider `docker_repo` or `repo`, or image resource `repo` must be set") + } + po := []publish.Option{publish.WithAuthFromKeychain(authn.DefaultKeychain)} + var repo string + if opts.imageRepo != "" { + // image resource's `repo` takes precedence if set, and selects the + // `--bare` namer so the image is named exactly `repo`. + repo = opts.imageRepo + po = append(po, publish.WithNamer(options.MakeNamer(&options.PublishOptions{ + DockerRepo: opts.imageRepo, + Bare: true, + }))) + } else { + repo = opts.koDockerRepo + } + b, err := opts.makeBuilder(ctx) if err != nil { return "", fmt.Errorf("NewGo: %v", err) @@ -187,8 +213,7 @@ func doBuild(ctx context.Context, opts buildOptions) (string, error) { return "", fmt.Errorf("build: %v", err) } - p, err := publish.NewDefault(opts.dockerRepo, - publish.WithAuthFromKeychain(authn.DefaultKeychain)) + p, err := publish.NewDefault(repo, po...) if err != nil { return "", fmt.Errorf("NewDefault: %v", err) } @@ -199,14 +224,15 @@ func doBuild(ctx context.Context, opts buildOptions) (string, error) { return ref.String(), nil } -func fromData(d *schema.ResourceData, repo string) buildOptions { +func fromData(d *schema.ResourceData, providerRepo string) buildOptions { return buildOptions{ - ip: d.Get("importpath").(string), - workingDir: d.Get("working_dir").(string), - dockerRepo: repo, - platforms: toStringSlice(d.Get("platforms").([]interface{})), - baseImage: d.Get("base_image").(string), - sbom: d.Get("sbom").(string), + ip: d.Get("importpath").(string), + workingDir: d.Get("working_dir").(string), + koDockerRepo: providerRepo, + imageRepo: d.Get("repo").(string), + platforms: toStringSlice(d.Get("platforms").([]interface{})), + baseImage: d.Get("base_image").(string), + sbom: d.Get("sbom").(string), } }