generated from hashicorp/terraform-provider-scaffolding-framework
-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Provider-defined functions are new in Terraform 1.8+ (and opentofu 1.7+) This is expected to be a replacement for the `oci_string` and `oci_ref` datasources, which perform the same logic, but have their results persisted in state, which adds to slowness. Usage ``` output "parsed" { value = provider::oci::parse("cgr.dev/chainguard/static@sha256:abc...").digest # sha256:abcdef... } locals { parsed = provider::oci::parse("cgr.dev/chainguard/static@sha256:abc...").digest # sha256:abcdef... gotten = provider::oci::get("cgr.dev/chainguard/static").digest # sha256:... } ``` Docs https://developer.hashicorp.com/terraform/plugin/framework/functions/concepts https://developer.hashicorp.com/terraform/plugin/framework/functions/returns/object https://developer.hashicorp.com/terraform/plugin/framework/functions/testing --------- Signed-off-by: Jason Hall <jason@chainguard.dev>
- Loading branch information
Showing
12 changed files
with
627 additions
and
79 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--- | ||
# generated by https://github.com/hashicorp/terraform-plugin-docs | ||
page_title: "get function - terraform-provider-oci" | ||
subcategory: "" | ||
description: |- | ||
Parses a pinned OCI string into its constituent parts. | ||
--- | ||
|
||
# function: get | ||
|
||
|
||
|
||
|
||
|
||
## Signature | ||
|
||
<!-- signature generated by tfplugindocs --> | ||
```text | ||
get(input string) object | ||
``` | ||
|
||
## Arguments | ||
|
||
<!-- arguments generated by tfplugindocs --> | ||
1. `input` (String) The OCI reference string to get. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--- | ||
# generated by https://github.com/hashicorp/terraform-plugin-docs | ||
page_title: "parse function - terraform-provider-oci" | ||
subcategory: "" | ||
description: |- | ||
Parses a pinned OCI string into its constituent parts. | ||
--- | ||
|
||
# function: parse | ||
|
||
|
||
|
||
|
||
|
||
## Signature | ||
|
||
<!-- signature generated by tfplugindocs --> | ||
```text | ||
parse(input string) object | ||
``` | ||
|
||
## Arguments | ||
|
||
<!-- arguments generated by tfplugindocs --> | ||
1. `input` (String) The OCI reference string to parse. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
package provider | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/google/go-containerregistry/pkg/authn" | ||
"github.com/google/go-containerregistry/pkg/name" | ||
"github.com/google/go-containerregistry/pkg/v1/remote" | ||
"github.com/hashicorp/terraform-plugin-framework/attr" | ||
"github.com/hashicorp/terraform-plugin-framework/function" | ||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes" | ||
) | ||
|
||
// Ensure provider defined types fully satisfy framework interfaces. | ||
var _ function.Function = &GetFunction{} | ||
|
||
func NewGetFunction() function.Function { | ||
return &GetFunction{} | ||
} | ||
|
||
// GetFunction defines the function implementation. | ||
type GetFunction struct{} | ||
|
||
// Metadata should return the name of the function, such as parse_xyz. | ||
func (s *GetFunction) Metadata(_ context.Context, _ function.MetadataRequest, resp *function.MetadataResponse) { | ||
resp.Name = "get" | ||
} | ||
|
||
// Definition should return the definition for the function. | ||
func (s *GetFunction) Definition(_ context.Context, _ function.DefinitionRequest, resp *function.DefinitionResponse) { | ||
resp.Definition = function.Definition{ | ||
Summary: "Parses a pinned OCI string into its constituent parts.", | ||
Parameters: []function.Parameter{ | ||
function.StringParameter{ | ||
Name: "input", | ||
Description: "The OCI reference string to get.", | ||
}, | ||
}, | ||
Return: function.ObjectReturn{ | ||
AttributeTypes: map[string]attr.Type{ | ||
"full_ref": basetypes.StringType{}, | ||
"digest": basetypes.StringType{}, | ||
"tag": basetypes.StringType{}, | ||
"manifest": basetypes.ObjectType{AttrTypes: manifestAttribute.AttributeTypes}, | ||
"images": basetypes.MapType{ElemType: imageType}, | ||
"config": basetypes.ObjectType{AttrTypes: configAttribute.AttributeTypes}, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
// Run should return the result of the function logic. It is called when | ||
// Terraform reaches a function call in the configuration. Argument data | ||
// values should be read from the [RunRequest] and the result value set in | ||
// the [RunResponse]. | ||
func (s *GetFunction) Run(ctx context.Context, req function.RunRequest, resp *function.RunResponse) { | ||
var input string | ||
if ferr := req.Arguments.GetArgument(ctx, 0, &input); ferr != nil { | ||
resp.Error = ferr | ||
return | ||
} | ||
|
||
// Parse the input string into its constituent parts. | ||
ref, err := name.ParseReference(input) | ||
if err != nil { | ||
resp.Error = function.NewFuncError(fmt.Sprintf("Failed to parse OCI reference: %v", err)) | ||
return | ||
} | ||
|
||
result := struct { | ||
FullRef string `tfsdk:"full_ref"` | ||
Digest string `tfsdk:"digest"` | ||
Tag string `tfsdk:"tag"` | ||
Manifest *Manifest `tfsdk:"manifest"` | ||
Images map[string]Image `tfsdk:"images"` | ||
Config *Config `tfsdk:"config"` | ||
}{} | ||
|
||
if t, ok := ref.(name.Tag); ok { | ||
result.Tag = t.TagStr() | ||
} | ||
|
||
desc, err := remote.Get(ref, | ||
remote.WithAuthFromKeychain(authn.DefaultKeychain), | ||
remote.WithUserAgent("terraform-provider-oci"), | ||
remote.WithContext(ctx)) | ||
if err != nil { | ||
resp.Error = function.NewFuncError(fmt.Sprintf("Failed to get image: %v", err)) | ||
return | ||
} | ||
|
||
result.Digest = desc.Digest.String() | ||
result.FullRef = ref.Context().Digest(desc.Digest.String()).String() | ||
|
||
mf := &Manifest{} | ||
if err := mf.FromDescriptor(desc); err != nil { | ||
resp.Error = function.NewFuncError(fmt.Sprintf("Failed to parse manifest: %v", err)) | ||
return | ||
} | ||
result.Manifest = mf | ||
|
||
if desc.MediaType.IsIndex() { | ||
idx, err := desc.ImageIndex() | ||
if err != nil { | ||
resp.Error = function.NewFuncError(fmt.Sprintf("Failed to parse index: %v", err)) | ||
return | ||
} | ||
imf, err := idx.IndexManifest() | ||
if err != nil { | ||
resp.Error = function.NewFuncError(fmt.Sprintf("Failed to parse index manifest: %v", err)) | ||
return | ||
} | ||
result.Images = make(map[string]Image, len(imf.Manifests)) | ||
for _, m := range imf.Manifests { | ||
if m.Platform == nil { | ||
continue | ||
} | ||
result.Images[m.Platform.String()] = Image{ | ||
Digest: m.Digest.String(), | ||
ImageRef: ref.Context().Digest(m.Digest.String()).String(), | ||
} | ||
} | ||
} else if desc.MediaType.IsImage() { | ||
img, err := desc.Image() | ||
if err != nil { | ||
resp.Error = function.NewFuncError(fmt.Sprintf("Failed to parse image: %v", err)) | ||
return | ||
} | ||
cf, err := img.ConfigFile() | ||
if err != nil { | ||
resp.Error = function.NewFuncError(fmt.Sprintf("Failed to parse config: %v", err)) | ||
return | ||
} | ||
cfg := &Config{} | ||
cfg.FromConfigFile(cf) | ||
result.Config = cfg | ||
} | ||
|
||
resp.Error = function.ConcatFuncErrors(resp.Error, resp.Result.Set(ctx, &result)) | ||
} |
Oops, something went wrong.