Skip to content

Commit

Permalink
Merge pull request #338 from ulucinar/rename-to-pluginsdk
Browse files Browse the repository at this point in the history
Replace NoFork Terminology with TerraformPluginSDK
  • Loading branch information
ulucinar authored Feb 1, 2024
2 parents 3c2fda9 + ca6672d commit 602c7d4
Show file tree
Hide file tree
Showing 14 changed files with 198 additions and 182 deletions.
2 changes: 1 addition & 1 deletion pkg/config/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func TestDefaultResource(t *testing.T) {
cmpopts.IgnoreFields(Sensitive{}, "fieldPaths", "AdditionalConnectionDetailsFn"),
cmpopts.IgnoreFields(LateInitializer{}, "ignoredCanonicalFieldPaths"),
cmpopts.IgnoreFields(ExternalName{}, "SetIdentifierArgumentFn", "GetExternalNameFn", "GetIDFn"),
cmpopts.IgnoreFields(Resource{}, "useNoForkClient"),
cmpopts.IgnoreFields(Resource{}, "useTerraformPluginSDKClient"),
cmpopts.IgnoreFields(Resource{}, "useTerraformPluginFrameworkClient"),
}

Expand Down
24 changes: 14 additions & 10 deletions pkg/config/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,14 @@ type Provider struct {
// Defaults to []string{".+"} which would include all resources.
IncludeList []string

// NoForkIncludeList is a list of regex for the Terraform resources
// TerraformPluginSDKIncludeList is a list of regex for the Terraform resources
// implemented with Terraform Plugin SDKv2 to be included and reconciled
// in the no-fork architecture (without the Terraform CLI).
// For example, to include "aws_shield_protection_group" into
// the generated resources, one can add "aws_shield_protection_group$".
// To include whole aws waf group, one can add "aws_waf.*" to the list.
// Defaults to []string{".+"} which would include all resources.
NoForkIncludeList []string
TerraformPluginSDKIncludeList []string

// TerraformPluginFrameworkIncludeList is a list of regex for the Terraform
// resources implemented with Terraform Plugin Framework to be included and
Expand Down Expand Up @@ -187,11 +187,11 @@ func WithIncludeList(l []string) ProviderOption {
}
}

// WithNoForkIncludeList configures the NoForkIncludeList for this Provider,
// WithTerraformPluginSDKIncludeList configures the TerraformPluginSDKIncludeList for this Provider,
// with the given Terraform Plugin SDKv2-based resource name list
func WithNoForkIncludeList(l []string) ProviderOption {
func WithTerraformPluginSDKIncludeList(l []string) ProviderOption {
return func(p *Provider) {
p.NoForkIncludeList = l
p.TerraformPluginSDKIncludeList = l
}
}

Expand Down Expand Up @@ -311,15 +311,19 @@ func NewProvider(schema []byte, prefix string, modulePath string, metadata []byt
fmt.Printf("Skipping resource %s because it has no schema\n", name)
}
// if in both of the include lists, the new behavior prevails
isNoFork := matches(name, p.NoForkIncludeList)
isTerraformPluginSDK := matches(name, p.TerraformPluginSDKIncludeList)
isPluginFrameworkResource := matches(name, p.TerraformPluginFrameworkIncludeList)
if len(terraformResource.Schema) == 0 || matches(name, p.SkipList) || (!matches(name, p.IncludeList) && !isNoFork && !isPluginFrameworkResource) {
isCLIResource := matches(name, p.IncludeList)
if (isTerraformPluginSDK && isPluginFrameworkResource) || (isTerraformPluginSDK && isCLIResource) || (isPluginFrameworkResource && isCLIResource) {
panic(errors.Errorf(`resource %q is specified in more than one include list. It should appear in at most one of the lists "IncludeList", "TerraformPluginSDKIncludeList" or "TerraformPluginFrameworkIncludeList"`, name))
}
if len(terraformResource.Schema) == 0 || matches(name, p.SkipList) || (!matches(name, p.IncludeList) && !isTerraformPluginSDK && !isPluginFrameworkResource) {
p.skippedResourceNames = append(p.skippedResourceNames, name)
continue
}
if isNoFork {
if isTerraformPluginSDK {
if p.TerraformProvider == nil || p.TerraformProvider.ResourcesMap[name] == nil {
panic(errors.Errorf("resource %q is configured to be reconciled without the Terraform CLI"+
panic(errors.Errorf("resource %q is configured to be reconciled with Terraform Plugin SDK"+
"but either config.Provider.TerraformProvider is not configured or the Go schema does not exist for the resource", name))
}
terraformResource = p.TerraformProvider.ResourcesMap[name]
Expand All @@ -345,7 +349,7 @@ func NewProvider(schema []byte, prefix string, modulePath string, metadata []byt
}

p.Resources[name] = DefaultResource(name, terraformResource, terraformPluginFrameworkResource, providerMetadata.Resources[name], p.DefaultResourceOptions...)
p.Resources[name].useNoForkClient = isNoFork
p.Resources[name].useTerraformPluginSDKClient = isTerraformPluginSDK
p.Resources[name].useTerraformPluginFrameworkClient = isPluginFrameworkResource
}
for i, refInjector := range p.refInjectors {
Expand Down
16 changes: 7 additions & 9 deletions pkg/config/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -455,9 +455,9 @@ type Resource struct {

Conversions []conversion.Conversion

// useNoForkClient indicates that a no-fork external client should
// useTerraformPluginSDKClient indicates that a plugin SDK external client should
// be generated instead of the Terraform CLI-forking client.
useNoForkClient bool
useTerraformPluginSDKClient bool

// useTerraformPluginFrameworkClient indicates that a Terraform
// Plugin Framework external client should be generated instead of
Expand Down Expand Up @@ -491,16 +491,14 @@ type Resource struct {
OverrideFieldNames map[string]string
}

// ShouldUseNoForkClient returns whether to generate a SDKv2-based no-fork
// external client for this Resource, instead of the Terraform CLI-forking
// external client
func (r *Resource) ShouldUseNoForkClient() bool {
return r.useNoForkClient
// ShouldUseTerraformPluginSDKClient returns whether to generate an SDKv2-based
// external client for this Resource.
func (r *Resource) ShouldUseTerraformPluginSDKClient() bool {
return r.useTerraformPluginSDKClient
}

// ShouldUseTerraformPluginFrameworkClient returns whether to generate a
// Terraform Plugin Framework-based no-fork external client for this Resource
// instead of a Terraform Plugin SDKv2-based external client
// Terraform Plugin Framework-based external client for this Resource.
func (r *Resource) ShouldUseTerraformPluginFrameworkClient() bool {
return r.useTerraformPluginFrameworkClient
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,17 @@ import (
tferrors "github.com/crossplane/upjet/pkg/terraform/errors"
)

// TerraformPluginFrameworkAsyncConnector is a managed reconciler Connecter
// implementation for reconciling Terraform plugin framework based
// resources.
type TerraformPluginFrameworkAsyncConnector struct {
*TerraformPluginFrameworkConnector
callback CallbackProvider
eventHandler *handler.EventHandler
}

// TerraformPluginFrameworkAsyncOption represents a configuration option for
// a TerraformPluginFrameworkAsyncConnector object.
type TerraformPluginFrameworkAsyncOption func(connector *TerraformPluginFrameworkAsyncConnector)

func NewTerraformPluginFrameworkAsyncConnector(kube client.Client,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,86 +25,95 @@ import (

var defaultAsyncTimeout = 1 * time.Hour

type NoForkAsyncConnector struct {
*NoForkConnector
// TerraformPluginSDKAsyncConnector is a managed reconciler Connecter
// implementation for reconciling Terraform plugin SDK v2 based
// resources.
type TerraformPluginSDKAsyncConnector struct {
*TerraformPluginSDKConnector
callback CallbackProvider
eventHandler *handler.EventHandler
}

type NoForkAsyncOption func(connector *NoForkAsyncConnector)
// TerraformPluginSDKAsyncOption represents a configuration option for
// a TerraformPluginSDKAsyncConnector object.
type TerraformPluginSDKAsyncOption func(connector *TerraformPluginSDKAsyncConnector)

func NewNoForkAsyncConnector(kube client.Client, ots *OperationTrackerStore, sf terraform.SetupFn, cfg *config.Resource, opts ...NoForkAsyncOption) *NoForkAsyncConnector {
nfac := &NoForkAsyncConnector{
NoForkConnector: NewNoForkConnector(kube, sf, cfg, ots),
// NewTerraformPluginSDKAsyncConnector initializes a new
// TerraformPluginSDKAsyncConnector.
func NewTerraformPluginSDKAsyncConnector(kube client.Client, ots *OperationTrackerStore, sf terraform.SetupFn, cfg *config.Resource, opts ...TerraformPluginSDKAsyncOption) *TerraformPluginSDKAsyncConnector {
nfac := &TerraformPluginSDKAsyncConnector{
TerraformPluginSDKConnector: NewTerraformPluginSDKConnector(kube, sf, cfg, ots),
}
for _, f := range opts {
f(nfac)
}
return nfac
}

func (c *NoForkAsyncConnector) Connect(ctx context.Context, mg xpresource.Managed) (managed.ExternalClient, error) {
ec, err := c.NoForkConnector.Connect(ctx, mg)
func (c *TerraformPluginSDKAsyncConnector) Connect(ctx context.Context, mg xpresource.Managed) (managed.ExternalClient, error) {
ec, err := c.TerraformPluginSDKConnector.Connect(ctx, mg)
if err != nil {
return nil, errors.Wrap(err, "cannot initialize the no-fork async external client")
return nil, errors.Wrap(err, "cannot initialize the Terraform plugin SDK async external client")
}

return &noForkAsyncExternal{
noForkExternal: ec.(*noForkExternal),
callback: c.callback,
eventHandler: c.eventHandler,
return &terraformPluginSDKAsyncExternal{
terraformPluginSDKExternal: ec.(*terraformPluginSDKExternal),
callback: c.callback,
eventHandler: c.eventHandler,
}, nil
}

// WithNoForkAsyncConnectorEventHandler configures the EventHandler so that
// the no-fork external clients can requeue reconciliation requests.
func WithNoForkAsyncConnectorEventHandler(e *handler.EventHandler) NoForkAsyncOption {
return func(c *NoForkAsyncConnector) {
// WithTerraformPluginSDKAsyncConnectorEventHandler configures the
// EventHandler so that the Terraform plugin SDK external clients can requeue
// reconciliation requests.
func WithTerraformPluginSDKAsyncConnectorEventHandler(e *handler.EventHandler) TerraformPluginSDKAsyncOption {
return func(c *TerraformPluginSDKAsyncConnector) {
c.eventHandler = e
}
}

// WithNoForkAsyncCallbackProvider configures the controller to use async variant of the functions
// of the Terraform client and run given callbacks once those operations are
// completed.
func WithNoForkAsyncCallbackProvider(ac CallbackProvider) NoForkAsyncOption {
return func(c *NoForkAsyncConnector) {
// WithTerraformPluginSDKAsyncCallbackProvider configures the controller to use
// async variant of the functions of the Terraform client and run given
// callbacks once those operations are completed.
func WithTerraformPluginSDKAsyncCallbackProvider(ac CallbackProvider) TerraformPluginSDKAsyncOption {
return func(c *TerraformPluginSDKAsyncConnector) {
c.callback = ac
}
}

// WithNoForkAsyncLogger configures a logger for the NoForkAsyncConnector.
func WithNoForkAsyncLogger(l logging.Logger) NoForkAsyncOption {
return func(c *NoForkAsyncConnector) {
// WithTerraformPluginSDKAsyncLogger configures a logger for the
// TerraformPluginSDKAsyncConnector.
func WithTerraformPluginSDKAsyncLogger(l logging.Logger) TerraformPluginSDKAsyncOption {
return func(c *TerraformPluginSDKAsyncConnector) {
c.logger = l
}
}

// WithNoForkAsyncMetricRecorder configures a metrics.MetricRecorder for the
// NoForkAsyncConnector.
func WithNoForkAsyncMetricRecorder(r *metrics.MetricRecorder) NoForkAsyncOption {
return func(c *NoForkAsyncConnector) {
// WithTerraformPluginSDKAsyncMetricRecorder configures a
// metrics.MetricRecorder for the TerraformPluginSDKAsyncConnector.
func WithTerraformPluginSDKAsyncMetricRecorder(r *metrics.MetricRecorder) TerraformPluginSDKAsyncOption {
return func(c *TerraformPluginSDKAsyncConnector) {
c.metricRecorder = r
}
}

// WithNoForkAsyncManagementPolicies configures whether the client should
// handle management policies.
func WithNoForkAsyncManagementPolicies(isManagementPoliciesEnabled bool) NoForkAsyncOption {
return func(c *NoForkAsyncConnector) {
// WithTerraformPluginSDKAsyncManagementPolicies configures whether the client
// should handle management policies.
func WithTerraformPluginSDKAsyncManagementPolicies(isManagementPoliciesEnabled bool) TerraformPluginSDKAsyncOption {
return func(c *TerraformPluginSDKAsyncConnector) {
c.isManagementPoliciesEnabled = isManagementPoliciesEnabled
}
}

type noForkAsyncExternal struct {
*noForkExternal
type terraformPluginSDKAsyncExternal struct {
*terraformPluginSDKExternal
callback CallbackProvider
eventHandler *handler.EventHandler
}

type CallbackFn func(error, context.Context) error

func (n *noForkAsyncExternal) Observe(ctx context.Context, mg xpresource.Managed) (managed.ExternalObservation, error) {
func (n *terraformPluginSDKAsyncExternal) Observe(ctx context.Context, mg xpresource.Managed) (managed.ExternalObservation, error) {
if n.opTracker.LastOperation.IsRunning() {
n.logger.WithValues("opType", n.opTracker.LastOperation.Type).Debug("ongoing async operation")
return managed.ExternalObservation{
Expand All @@ -114,7 +123,7 @@ func (n *noForkAsyncExternal) Observe(ctx context.Context, mg xpresource.Managed
}
n.opTracker.LastOperation.Flush()

o, err := n.noForkExternal.Observe(ctx, mg)
o, err := n.terraformPluginSDKExternal.Observe(ctx, mg)
// clear any previously reported LastAsyncOperation error condition here,
// because there are no pending updates on the existing resource and it's
// not scheduled to be deleted.
Expand All @@ -124,7 +133,7 @@ func (n *noForkAsyncExternal) Observe(ctx context.Context, mg xpresource.Managed
return o, err
}

func (n *noForkAsyncExternal) Create(_ context.Context, mg xpresource.Managed) (managed.ExternalCreation, error) {
func (n *terraformPluginSDKAsyncExternal) Create(_ context.Context, mg xpresource.Managed) (managed.ExternalCreation, error) {
if !n.opTracker.LastOperation.MarkStart("create") {
return managed.ExternalCreation{}, errors.Errorf("%s operation that started at %s is still running", n.opTracker.LastOperation.Type, n.opTracker.LastOperation.StartTime().String())
}
Expand All @@ -134,7 +143,7 @@ func (n *noForkAsyncExternal) Create(_ context.Context, mg xpresource.Managed) (
defer cancel()

n.opTracker.logger.Debug("Async create starting...", "tfID", n.opTracker.GetTfID())
_, err := n.noForkExternal.Create(ctx, mg)
_, err := n.terraformPluginSDKExternal.Create(ctx, mg)
err = tferrors.NewAsyncCreateFailed(err)
n.opTracker.LastOperation.SetError(err)
n.opTracker.logger.Debug("Async create ended.", "error", err, "tfID", n.opTracker.GetTfID())
Expand All @@ -148,7 +157,7 @@ func (n *noForkAsyncExternal) Create(_ context.Context, mg xpresource.Managed) (
return managed.ExternalCreation{}, nil
}

func (n *noForkAsyncExternal) Update(_ context.Context, mg xpresource.Managed) (managed.ExternalUpdate, error) {
func (n *terraformPluginSDKAsyncExternal) Update(_ context.Context, mg xpresource.Managed) (managed.ExternalUpdate, error) {
if !n.opTracker.LastOperation.MarkStart("update") {
return managed.ExternalUpdate{}, errors.Errorf("%s operation that started at %s is still running", n.opTracker.LastOperation.Type, n.opTracker.LastOperation.StartTime().String())
}
Expand All @@ -158,7 +167,7 @@ func (n *noForkAsyncExternal) Update(_ context.Context, mg xpresource.Managed) (
defer cancel()

n.opTracker.logger.Debug("Async update starting...", "tfID", n.opTracker.GetTfID())
_, err := n.noForkExternal.Update(ctx, mg)
_, err := n.terraformPluginSDKExternal.Update(ctx, mg)
err = tferrors.NewAsyncUpdateFailed(err)
n.opTracker.LastOperation.SetError(err)
n.opTracker.logger.Debug("Async update ended.", "error", err, "tfID", n.opTracker.GetTfID())
Expand All @@ -172,7 +181,7 @@ func (n *noForkAsyncExternal) Update(_ context.Context, mg xpresource.Managed) (
return managed.ExternalUpdate{}, nil
}

func (n *noForkAsyncExternal) Delete(_ context.Context, mg xpresource.Managed) error {
func (n *terraformPluginSDKAsyncExternal) Delete(_ context.Context, mg xpresource.Managed) error {
switch {
case n.opTracker.LastOperation.Type == "delete":
n.opTracker.logger.Debug("The previous delete operation is still ongoing", "tfID", n.opTracker.GetTfID())
Expand All @@ -186,7 +195,7 @@ func (n *noForkAsyncExternal) Delete(_ context.Context, mg xpresource.Managed) e
defer cancel()

n.opTracker.logger.Debug("Async delete starting...", "tfID", n.opTracker.GetTfID())
err := tferrors.NewAsyncDeleteFailed(n.noForkExternal.Delete(ctx, mg))
err := tferrors.NewAsyncDeleteFailed(n.terraformPluginSDKExternal.Delete(ctx, mg))
n.opTracker.LastOperation.SetError(err)
n.opTracker.logger.Debug("Async delete ended.", "error", err, "tfID", n.opTracker.GetTfID())

Expand Down
Loading

0 comments on commit 602c7d4

Please sign in to comment.