func (rrn RelativeResourceNamerKeyRing) ProjectRRN() string {
	return fmt.Sprintf("projects/%s", rrn.projectName)
}
ProjectRRN yields the relative resource name for a GCP project
package kms
import (
	"context"
	"fmt"
	"time"
	kmsv1 "google.golang.org/api/cloudkms/v1"
	"k8s.io/client-go/util/workqueue"
	ctrl "sigs.k8s.io/controller-runtime"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/controller"
	xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
	"github.com/crossplane/crossplane-runtime/pkg/errors"
	"github.com/crossplane/crossplane-runtime/pkg/event"
	"github.com/crossplane/crossplane-runtime/pkg/logging"
	"github.com/crossplane/crossplane-runtime/pkg/meta"
	"github.com/crossplane/crossplane-runtime/pkg/ratelimiter"
	"github.com/crossplane/crossplane-runtime/pkg/reconciler/managed"
	"github.com/crossplane/crossplane-runtime/pkg/resource"
	"github.com/crossplane/provider-gcp/apis/kms/v1alpha1"
	gcp "github.com/crossplane/provider-gcp/pkg/clients"
	"github.com/crossplane/provider-gcp/pkg/clients/keyring"
)
const (
	errNewClient  = "cannot create new GCP KMS API client"
	errNotKeyRing = "managed resource is not a GCP KeyRing"
	errGet        = "cannot get GCP object via KMS API"
	errCreate     = "cannot create GCP object via KMS API"
	errUpdate     = "cannot update GCP object via KMS API"
)
func SetupKeyRing(mgr ctrl.Manager, l logging.Logger, rl workqueue.RateLimiter, poll time.Duration) error {
	name := managed.ControllerName(v1alpha1.KeyRingGroupKind)
	return ctrl.NewControllerManagedBy(mgr).
		Named(name).
		WithOptions(controller.Options{
			RateLimiter: ratelimiter.NewDefaultManagedRateLimiter(rl),
		}).
		For(&v1alpha1.KeyRing{}).
		Complete(managed.NewReconciler(mgr,
			resource.ManagedKind(v1alpha1.KeyRingGroupVersionKind),
			managed.WithExternalConnecter(&keyRingConnecter{client: mgr.GetClient()}),
			managed.WithPollInterval(poll),
			managed.WithLogger(l.WithValues("controller", name)),
			managed.WithRecorder(event.NewAPIRecorder(mgr.GetEventRecorderFor(name)))))
}
type keyRingConnecter struct {
	client client.Client
}
func (c *keyRingConnecter) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) {
	cr, ok := mg.(*v1alpha1.KeyRing)
	if !ok {
		return nil, errors.New(errNotKeyRing)
	}
	projectID, opts, err := gcp.GetAuthInfo(ctx, c.client, mg)
	if err != nil {
		return nil, err
	}
	s, err := kmsv1.NewService(ctx, opts)
	if err != nil {
		return nil, errors.Wrap(err, errNewClient)
	}
	rrn := NewRelativeResourceNamerKeyRing(projectID, cr.Spec.ForProvider.Location)
	return &keyRingExternal{keyrings: kmsv1.NewProjectsLocationsKeyRingsService(s), rrn: rrn}, nil
}
type keyRingExternal struct {
	keyrings keyring.Client
	rrn      RelativeResourceNamerKeyRing
}
func (e *keyRingExternal) Observe(ctx context.Context, mg resource.Managed) (managed.ExternalObservation, error) {
	cr, ok := mg.(*v1alpha1.KeyRing)
	if !ok {
		return managed.ExternalObservation{}, errors.New(errNotKeyRing)
	}
	if meta.WasDeleted(cr) {
		return managed.ExternalObservation{}, nil
	}
	call := e.keyrings.Get(e.rrn.ResourceName(cr))
	instance, err := call.Context(ctx).Do()
	if gcp.IsErrorNotFound(err) {
		return managed.ExternalObservation{ResourceExists: false}, nil
	}
	if err != nil {
		return managed.ExternalObservation{}, errors.Wrap(err, errGet)
	}
	cr.Status.SetConditions(xpv1.Available())
	cr.Status.AtProvider = keyring.GenerateObservation(*instance)
	return managed.ExternalObservation{
		ResourceExists:    true,
		ResourceUpToDate:  true,
		ConnectionDetails: managed.ConnectionDetails{},
	}, nil
}
func (e *keyRingExternal) Create(ctx context.Context, mg resource.Managed) (managed.ExternalCreation, error) {
	cr, ok := mg.(*v1alpha1.KeyRing)
	if !ok {
		return managed.ExternalCreation{}, errors.New(errNotKeyRing)
	}
	cr.SetConditions(xpv1.Creating())
	instance := &kmsv1.KeyRing{}
	if _, err := e.keyrings.Create(e.rrn.LocationRRN(), instance).
		KeyRingId(meta.GetExternalName(cr)).Context(ctx).Do(); err != nil {
		return managed.ExternalCreation{}, errors.Wrap(err, errCreate)
	}
	return managed.ExternalCreation{}, nil
}
func (e *keyRingExternal) Update(ctx context.Context, mg resource.Managed) (managed.ExternalUpdate, error) {
	return managed.ExternalUpdate{}, nil
}
func (e *keyRingExternal) Delete(ctx context.Context, mg resource.Managed) error {
	return nil
}
func NewRelativeResourceNamerKeyRing(projectName, location string) RelativeResourceNamerKeyRing {
	return RelativeResourceNamerKeyRing{projectName: projectName, location: location}
}
type RelativeResourceNamerKeyRing struct {
	projectName string
	location    string
}