fix: ensureNamespace uses Get-then-Create to avoid RBAC failures
The deployer was blindly calling Namespaces().Create() which triggered cluster-scope RBAC checks even when the namespace already existed. Now checks with Get() first and only creates if NotFound. Also adds namespace get/create and secrets create/update/patch permissions to the rdev-api-deployer ClusterRole. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
1adffbd50e
commit
043cc8c63b
@ -203,14 +203,18 @@ rules:
|
|||||||
- apiGroups: ["networking.k8s.io"]
|
- apiGroups: ["networking.k8s.io"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
|
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
|
||||||
|
# Namespace verification (check exists before creating)
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["namespaces"]
|
||||||
|
verbs: ["get", "create"]
|
||||||
# Pod logs for deployment status
|
# Pod logs for deployment status
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["pods", "pods/log"]
|
resources: ["pods", "pods/log"]
|
||||||
verbs: ["get", "list", "watch"]
|
verbs: ["get", "list", "watch"]
|
||||||
# Secrets for TLS certificates (read-only to reference existing)
|
# Secrets for env vars and TLS certificates
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["secrets"]
|
resources: ["secrets"]
|
||||||
verbs: ["get", "list"]
|
verbs: ["get", "list", "create", "update", "patch"]
|
||||||
---
|
---
|
||||||
# ClusterRoleBinding for rdev-api deployer
|
# ClusterRoleBinding for rdev-api deployer
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
|||||||
@ -15,15 +15,23 @@ import (
|
|||||||
"github.com/orchard9/rdev/internal/domain"
|
"github.com/orchard9/rdev/internal/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ensureNamespace creates the deployment namespace if it doesn't exist.
|
// ensureNamespace verifies the deployment namespace exists, creating it only if needed.
|
||||||
func (d *Deployer) ensureNamespace(ctx context.Context) error {
|
func (d *Deployer) ensureNamespace(ctx context.Context) error {
|
||||||
|
_, err := d.client.CoreV1().Namespaces().Get(ctx, d.config.Namespace, metav1.GetOptions{})
|
||||||
|
if err == nil {
|
||||||
|
return nil // namespace exists
|
||||||
|
}
|
||||||
|
if !errors.IsNotFound(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Namespace doesn't exist, try to create it
|
||||||
ns := &corev1.Namespace{
|
ns := &corev1.Namespace{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: d.config.Namespace,
|
Name: d.config.Namespace,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
_, err = d.client.CoreV1().Namespaces().Create(ctx, ns, metav1.CreateOptions{})
|
||||||
_, err := d.client.CoreV1().Namespaces().Create(ctx, ns, metav1.CreateOptions{})
|
|
||||||
if err != nil && !errors.IsAlreadyExists(err) {
|
if err != nil && !errors.IsAlreadyExists(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user