diff --git a/pkg/plugins/golang/options.go b/pkg/plugins/golang/options.go index 65515fa8aec..e91b57260df 100644 --- a/pkg/plugins/golang/options.go +++ b/pkg/plugins/golang/options.go @@ -56,9 +56,13 @@ type Options struct { // Plural is the resource's kind plural form. Plural string - // ExternalAPIPath allows inform a path for APIs not defined in the project + // ExternalAPIPath allows to inform a path for APIs not defined in the project ExternalAPIPath string + // ExternalAPIPath allows to inform the resource domain to build the Qualified Group + // to generate the RBAC markers + ExternalAPIDomain string + // Namespaced is true if the resource should be namespaced. Namespaced bool @@ -123,6 +127,7 @@ func (opts Options) UpdateResource(res *resource.Resource, c config.Config) { if !alreadyHasAPI { if res.External { res.Path = opts.ExternalAPIPath + res.Domain = opts.ExternalAPIDomain } else { // Handle core types if domain, found := coreGroups[res.Group]; found { diff --git a/pkg/plugins/golang/v4/api.go b/pkg/plugins/golang/v4/api.go index 7a4ed098afd..60a749b344f 100644 --- a/pkg/plugins/golang/v4/api.go +++ b/pkg/plugins/golang/v4/api.go @@ -110,7 +110,13 @@ func (p *createAPISubcommand) BindFlags(fs *pflag.FlagSet) { p.controllerFlag = fs.Lookup("controller") fs.StringVar(&p.options.ExternalAPIPath, "external-api-path", "", - "Specify the Go package path for external APIs to scaffold controllers for resources not defined in this project.") + "Specify the Go package import path for the external API. This is used to scaffold controllers for resources "+ + "defined outside this project (e.g., github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1).") + + fs.StringVar(&p.options.ExternalAPIDomain, "external-api-domain", "", + "Specify the domain name for the external API. This domain is used to generate accurate RBAC markers and permissions "+ + "for the external resources (e.g., cert-manager.io).") + } func (p *createAPISubcommand) InjectConfig(c config.Config) error { @@ -131,12 +137,25 @@ func (p *createAPISubcommand) InjectResource(res *resource.Resource) error { p.options.DoController = util.YesNo(reader) } - if len(p.options.ExternalAPIPath) != 0 && p.options.DoAPI { - return errors.New("Cannot create an API and specify an external API path at the same time. " + - "Use '--resource=true' to create an API or '--external-api-path' to reference an external type, " + - "but not both.") + // Ensure that external API options cannot be used when creating an API in the project. + if p.options.DoAPI { + if len(p.options.ExternalAPIPath) != 0 || len(p.options.ExternalAPIDomain) != 0 { + return errors.New("Cannot use '--external-api-path' or '--external-api-domain' " + + "when creating an API in the project with '--resource=true'. " + + "Use '--resource=false' when referencing an external API.") + } + } + + // Ensure that if any external API flag is set, both must be provided. + if len(p.options.ExternalAPIPath) != 0 || len(p.options.ExternalAPIDomain) != 0 { + if len(p.options.ExternalAPIPath) == 0 || len(p.options.ExternalAPIDomain) == 0 { + return errors.New("Both '--external-api-path' and '--external-api-domain' must be " + + "specified together when referencing an external API.") + } } + // add check to ensure that if resource is true externapi and exytermal api domain cannot be set + // if one of those is filled then both should be informed p.options.UpdateResource(p.resource, p.config) if err := p.resource.Validate(); err != nil { diff --git a/test/testdata/generate.sh b/test/testdata/generate.sh index 1e0892a1daf..b9888de408d 100755 --- a/test/testdata/generate.sh +++ b/test/testdata/generate.sh @@ -46,7 +46,7 @@ function scaffold_test_project { $kb create api --group crew --version v1 --kind Admiral --plural=admirales --controller=true --resource=true --namespaced=false --make=false $kb create webhook --group crew --version v1 --kind Admiral --plural=admirales --defaulting # Controller for External types - $kb create api --group certmanager --version v1 --kind Certificate --controller=true --resource=false --make=false --external-api-path=github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1 + $kb create api --group certmanager --version v1 --kind Certificate --controller=true --resource=false --make=false --external-api-path=github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1 --external-api-domain=cert-manager.io fi if [[ $project =~ multigroup ]]; then @@ -72,7 +72,7 @@ function scaffold_test_project { $kb create api --group foo --version v1 --kind Bar --controller=true --resource=true --make=false $kb create api --group fiz --version v1 --kind Bar --controller=true --resource=true --make=false # Controller for External types - $kb create api --group certmanager --version v1 --kind Certificate --controller=true --resource=false --make=false --external-api-path=github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1 + $kb create api --group certmanager --version v1 --kind Certificate --controller=true --resource=false --make=false --external-api-path=github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1 --external-api-domain=cert-manager.io fi if [[ $project =~ multigroup ]] || [[ $project =~ with-plugins ]] ; then diff --git a/testdata/project-v4-multigroup/PROJECT b/testdata/project-v4-multigroup/PROJECT index 6eb91fe16c6..8d854bab7a5 100644 --- a/testdata/project-v4-multigroup/PROJECT +++ b/testdata/project-v4-multigroup/PROJECT @@ -126,7 +126,7 @@ resources: path: sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/fiz/v1 version: v1 - controller: true - domain: testproject.org + domain: cert-manager.io external: true group: certmanager kind: Certificate diff --git a/testdata/project-v4-multigroup/config/rbac/role.yaml b/testdata/project-v4-multigroup/config/rbac/role.yaml index 0bf2d893cc2..598a1c592a7 100644 --- a/testdata/project-v4-multigroup/config/rbac/role.yaml +++ b/testdata/project-v4-multigroup/config/rbac/role.yaml @@ -31,7 +31,7 @@ rules: - patch - update - apiGroups: - - certmanager.testproject.org + - certmanager.cert-manager.io resources: - certificates verbs: @@ -43,13 +43,13 @@ rules: - update - watch - apiGroups: - - certmanager.testproject.org + - certmanager.cert-manager.io resources: - certificates/finalizers verbs: - update - apiGroups: - - certmanager.testproject.org + - certmanager.cert-manager.io resources: - certificates/status verbs: diff --git a/testdata/project-v4-multigroup/dist/install.yaml b/testdata/project-v4-multigroup/dist/install.yaml index 1dd8dc4f2c2..d755f2547d2 100644 --- a/testdata/project-v4-multigroup/dist/install.yaml +++ b/testdata/project-v4-multigroup/dist/install.yaml @@ -1162,7 +1162,7 @@ rules: - patch - update - apiGroups: - - certmanager.testproject.org + - certmanager.cert-manager.io resources: - certificates verbs: @@ -1174,13 +1174,13 @@ rules: - update - watch - apiGroups: - - certmanager.testproject.org + - certmanager.cert-manager.io resources: - certificates/finalizers verbs: - update - apiGroups: - - certmanager.testproject.org + - certmanager.cert-manager.io resources: - certificates/status verbs: diff --git a/testdata/project-v4-multigroup/internal/controller/certmanager/certificate_controller.go b/testdata/project-v4-multigroup/internal/controller/certmanager/certificate_controller.go index 399964fed03..71fe01ee254 100644 --- a/testdata/project-v4-multigroup/internal/controller/certmanager/certificate_controller.go +++ b/testdata/project-v4-multigroup/internal/controller/certmanager/certificate_controller.go @@ -32,9 +32,9 @@ type CertificateReconciler struct { Scheme *runtime.Scheme } -// +kubebuilder:rbac:groups=certmanager.testproject.org,resources=certificates,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=certmanager.testproject.org,resources=certificates/status,verbs=get;update;patch -// +kubebuilder:rbac:groups=certmanager.testproject.org,resources=certificates/finalizers,verbs=update +// +kubebuilder:rbac:groups=certmanager.cert-manager.io,resources=certificates,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=certmanager.cert-manager.io,resources=certificates/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=certmanager.cert-manager.io,resources=certificates/finalizers,verbs=update // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. diff --git a/testdata/project-v4/PROJECT b/testdata/project-v4/PROJECT index 1cd544a12ab..e65c3db0df4 100644 --- a/testdata/project-v4/PROJECT +++ b/testdata/project-v4/PROJECT @@ -46,7 +46,7 @@ resources: defaulting: true webhookVersion: v1 - controller: true - domain: testproject.org + domain: cert-manager.io external: true group: certmanager kind: Certificate diff --git a/testdata/project-v4/config/rbac/role.yaml b/testdata/project-v4/config/rbac/role.yaml index 1e465f1d9c3..b7de1698cfb 100644 --- a/testdata/project-v4/config/rbac/role.yaml +++ b/testdata/project-v4/config/rbac/role.yaml @@ -5,7 +5,7 @@ metadata: name: manager-role rules: - apiGroups: - - certmanager.testproject.org + - certmanager.cert-manager.io resources: - certificates verbs: @@ -17,13 +17,13 @@ rules: - update - watch - apiGroups: - - certmanager.testproject.org + - certmanager.cert-manager.io resources: - certificates/finalizers verbs: - update - apiGroups: - - certmanager.testproject.org + - certmanager.cert-manager.io resources: - certificates/status verbs: diff --git a/testdata/project-v4/dist/install.yaml b/testdata/project-v4/dist/install.yaml index e109918da69..bc03981dc80 100644 --- a/testdata/project-v4/dist/install.yaml +++ b/testdata/project-v4/dist/install.yaml @@ -405,7 +405,7 @@ metadata: name: project-v4-manager-role rules: - apiGroups: - - certmanager.testproject.org + - certmanager.cert-manager.io resources: - certificates verbs: @@ -417,13 +417,13 @@ rules: - update - watch - apiGroups: - - certmanager.testproject.org + - certmanager.cert-manager.io resources: - certificates/finalizers verbs: - update - apiGroups: - - certmanager.testproject.org + - certmanager.cert-manager.io resources: - certificates/status verbs: diff --git a/testdata/project-v4/internal/controller/certificate_controller.go b/testdata/project-v4/internal/controller/certificate_controller.go index dc1f8845f4c..13e02a06098 100644 --- a/testdata/project-v4/internal/controller/certificate_controller.go +++ b/testdata/project-v4/internal/controller/certificate_controller.go @@ -32,9 +32,9 @@ type CertificateReconciler struct { Scheme *runtime.Scheme } -// +kubebuilder:rbac:groups=certmanager.testproject.org,resources=certificates,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=certmanager.testproject.org,resources=certificates/status,verbs=get;update;patch -// +kubebuilder:rbac:groups=certmanager.testproject.org,resources=certificates/finalizers,verbs=update +// +kubebuilder:rbac:groups=certmanager.cert-manager.io,resources=certificates,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=certmanager.cert-manager.io,resources=certificates/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=certmanager.cert-manager.io,resources=certificates/finalizers,verbs=update // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state.