feat: sidecar role and rolebinding (#23)

Signed-off-by: Leonardo Cecchi <leonardo.cecchi@enterprisedb.com>
This commit is contained in:
Leonardo Cecchi 2024-10-02 15:03:07 +02:00 committed by GitHub
parent ea6ee30d2e
commit 2f62d539c9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 501 additions and 112 deletions

View File

@ -45,7 +45,7 @@ help: ## Display this help.
.PHONY: manifests
manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
$(CONTROLLER_GEN) rbac:roleName=plugin-barman-cloud crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
.PHONY: generate
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.

View File

@ -29,7 +29,7 @@ func (in *ObjectStore) DeepCopyInto(out *ObjectStore) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
out.Spec = in.Spec
in.Spec.DeepCopyInto(&out.Spec)
out.Status = in.Status
}
@ -86,6 +86,7 @@ func (in *ObjectStoreList) DeepCopyObject() runtime.Object {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ObjectStoreSpec) DeepCopyInto(out *ObjectStoreSpec) {
*out = *in
in.Configuration.DeepCopyInto(&out.Configuration)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectStoreSpec.

View File

@ -2,17 +2,14 @@
package main
import (
"context"
"fmt"
"os"
"github.com/cloudnative-pg/machinery/pkg/log"
"github.com/sourcegraph/conc/pool"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/operator/manager"
)
func main() {
@ -20,7 +17,15 @@ func main() {
logFlags := &log.Flags{}
rootCmd := &cobra.Command{
Use: "plugin-barman-cloud",
Use: "plugin-barman-cloud",
Short: "Starts the BarmanObjectStore reconciler and the Barman Cloud CNPG-i plugin",
RunE: func(cmd *cobra.Command, _ []string) error {
if len(viper.GetString("sidecar-image")) == 0 {
return fmt.Errorf("missing required SIDECAR_IMAGE environment variable")
}
return operator.Start(cmd.Context())
},
PersistentPreRunE: func(_ *cobra.Command, _ []string) error {
logFlags.ConfigureLogging()
return nil
@ -28,61 +33,66 @@ func main() {
}
logFlags.AddFlags(rootCmd.PersistentFlags())
rootCmd.AddCommand(newOperatorCommand())
rootCmd.Flags().String("metrics-bind-address", "0", "The address the metrics endpoint binds to. "+
"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.")
_ = viper.BindPFlag("metrics-bind-address", rootCmd.Flags().Lookup("metrics-bind-address"))
rootCmd.Flags().String("health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
_ = viper.BindPFlag("health-probe-bind-address", rootCmd.Flags().Lookup("health-probe-bind-address"))
rootCmd.Flags().Bool("leader-elect", false,
"Enable leader election for controller manager. "+
"Enabling this will ensure there is only one active controller manager.")
_ = viper.BindPFlag("leader-elect", rootCmd.Flags().Lookup("leader-elect"))
rootCmd.Flags().Bool("metrics-secure", true,
"If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.")
_ = viper.BindPFlag("metrics-secure", rootCmd.Flags().Lookup("metrics-secure"))
rootCmd.Flags().Bool("enable-http2", false,
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
_ = viper.BindPFlag("enable-http2", rootCmd.Flags().Lookup("enable-http2"))
rootCmd.Flags().String(
"plugin-path",
"",
"The plugins socket path",
)
_ = viper.BindPFlag("plugin-path", rootCmd.Flags().Lookup("plugin-path"))
rootCmd.Flags().String(
"server-cert",
"",
"The public key to be used for the server process",
)
_ = viper.BindPFlag("server-cert", rootCmd.Flags().Lookup("server-cert"))
rootCmd.Flags().String(
"server-key",
"",
"The key to be used for the server process",
)
_ = viper.BindPFlag("server-key", rootCmd.Flags().Lookup("server-key"))
rootCmd.Flags().String(
"client-cert",
"",
"The client public key to verify the connection",
)
_ = viper.BindPFlag("client-cert", rootCmd.Flags().Lookup("client-cert"))
rootCmd.Flags().String(
"server-address",
"",
"The address where to listen (i.e. 0:9090)",
)
_ = viper.BindPFlag("server-address", rootCmd.Flags().Lookup("server-address"))
_ = viper.BindEnv("sidecar-image", "SIDECAR_IMAGE")
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func newOperatorCommand() *cobra.Command {
cmd := operator.NewCommand()
cmd.Use = "operator"
cmd.Short = "Starts the BarmanObjectStore reconciler and the Barman Cloud CNPG-i plugin"
grpcServer := cmd.RunE
cmd.RunE = func(cmd *cobra.Command, args []string) error {
operatorPool := pool.
New().
WithContext(cmd.Context()).
WithCancelOnError().
WithFirstError()
operatorPool.Go(func(ctx context.Context) error {
cmd.SetContext(ctx)
if len(viper.GetString("sidecar-image")) == 0 {
return fmt.Errorf("missing required SIDECAR_IMAGE environment variable")
}
err := grpcServer(cmd, args)
return err
})
operatorPool.Go(manager.Start)
return operatorPool.Wait()
}
cmd.Flags().String("metrics-bind-address", "0", "The address the metrics endpoint binds to. "+
"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.")
_ = viper.BindPFlag("metrics-bind-address", cmd.Flags().Lookup("metrics-bind-address"))
cmd.Flags().String("health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
_ = viper.BindPFlag("health-probe-bind-address", cmd.Flags().Lookup("health-probe-bind-address"))
cmd.Flags().Bool("leader-elect", false,
"Enable leader election for controller manager. "+
"Enabling this will ensure there is only one active controller manager.")
_ = viper.BindPFlag("leader-elect", cmd.Flags().Lookup("leader-elect"))
cmd.Flags().Bool("metrics-secure", true,
"If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.")
_ = viper.BindPFlag("metrics-secure", cmd.Flags().Lookup("metrics-secure"))
cmd.Flags().Bool("enable-http2", false,
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
_ = viper.BindPFlag("enable-http2", cmd.Flags().Lookup("enable-http2"))
_ = viper.BindEnv("sidecar-image", "SIDECAR_IMAGE")
return cmd
}

View File

@ -17,7 +17,7 @@ spec:
- name: v1
schema:
openAPIV3Schema:
description: ObjectStore is the Schema for the objectstores API
description: ObjectStore is the Schema for the objectstores API.
properties:
apiVersion:
description: |-
@ -37,7 +37,7 @@ spec:
metadata:
type: object
spec:
description: ObjectStoreSpec defines the desired state of ObjectStore
description: ObjectStoreSpec defines the desired state of ObjectStore.
properties:
configuration:
description: |-
@ -382,7 +382,7 @@ spec:
- configuration
type: object
status:
description: ObjectStoreStatus defines the observed state of ObjectStore
description: ObjectStoreStatus defines the observed state of ObjectStore.
type: object
type: object
served: true

View File

@ -2,7 +2,7 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: manager-role
name: plugin-barman-cloud
rules:
- apiGroups:
- barmancloud.cnpg.io
@ -30,3 +30,15 @@ rules:
- get
- patch
- update
- apiGroups:
- rbac.authorization.k8s.io
resources:
- rolebindings
- roles
verbs:
- create
- get
- list
- patch
- update
- watch

View File

@ -4,11 +4,11 @@ metadata:
labels:
app.kubernetes.io/name: plugin-barman-cloud
app.kubernetes.io/managed-by: kustomize
name: manager-rolebinding
name: plugin-barman-cloud-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: manager-role
name: plugin-barman-cloud
subjects:
- kind: ServiceAccount
name: plugin-barman-cloud

View File

@ -1,9 +0,0 @@
apiVersion: barmancloud.cnpg.io/v1
kind: ObjectStore
metadata:
labels:
app.kubernetes.io/name: plugin-barman-cloud
app.kubernetes.io/managed-by: kustomize
name: objectstore-sample
spec:
# TODO(user): Add fields here

View File

@ -8,7 +8,7 @@ spec:
plugins:
- name: barman-cloud.cloudnative-pg.io
parameters:
barmanObjectStore: minio-store
barmanObjectName: minio-store
storage:
size: 1Gi

View File

@ -0,0 +1,23 @@
apiVersion: barmancloud.cnpg.io/v1
kind: ObjectStore
metadata:
name: minio-store
spec:
configuration:
destinationPath: s3://backups/
endpointURL: http://minio:9000
s3Credentials:
accessKeyId:
name: minio
key: ACCESS_KEY_ID
secretAccessKey:
name: minio
key: ACCESS_SECRET_KEY
wal:
compression: gzip
data:
additionalCommandArgs:
- "--min-chunk-size=5MB"
- "--read-timeout=60"
- "-vv"

View File

@ -0,0 +1,20 @@
apiVersion: v1
kind: Pod
metadata:
labels:
run: mc
name: mc
spec:
containers:
- env:
- name: MC_HOST_minio
value: http://chooJeiroroo2noquomei2uuceisheth:ongeiqueitohL0queeLohkiur2quaing@minio:9000
image: minio/mc
name: mc
resources: {}
# Keep the pod up to exec stuff on it
command:
- sleep
- "3600"
dnsPolicy: ClusterFirst
restartPolicy: Always

View File

@ -0,0 +1 @@
kubectl exec -ti mc -- mc rm -r --force minio/backups

View File

@ -0,0 +1,42 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: minio
labels:
app: minio
spec:
replicas: 1
selector:
matchLabels:
app: minio
template:
metadata:
labels:
app: minio
spec:
containers:
- name: minio
image: minio/minio
ports:
- containerPort: 9000
volumeMounts:
- mountPath: /data
name: data
args:
- server
- /data
env:
- name: MINIO_ACCESS_KEY
valueFrom:
secretKeyRef:
name: minio
key: ACCESS_KEY_ID
- name: MINIO_SECRET_KEY
valueFrom:
secretKeyRef:
name: minio
key: ACCESS_SECRET_KEY
volumes:
- name: data
persistentVolumeClaim:
claimName: minio

11
docs/minio/minio-pvc.yaml Normal file
View File

@ -0,0 +1,11 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: minio
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 1Gi

View File

@ -0,0 +1,7 @@
apiVersion: v1
data:
ACCESS_KEY_ID: Y2hvb0plaXJvcm9vMm5vcXVvbWVpMnV1Y2Vpc2hldGg=
ACCESS_SECRET_KEY: b25nZWlxdWVpdG9oTDBxdWVlTG9oa2l1cjJxdWFpbmc=
kind: Secret
metadata:
name: minio

View File

@ -0,0 +1,11 @@
apiVersion: v1
kind: Service
metadata:
name: minio
spec:
selector:
app: minio
ports:
- protocol: TCP
port: 9000
targetPort: 9000

2
go.mod
View File

@ -10,7 +10,6 @@ require (
github.com/cloudnative-pg/machinery v0.0.0-20241001075747-34c8797af80f
github.com/onsi/ginkgo/v2 v2.20.2
github.com/onsi/gomega v1.34.2
github.com/sourcegraph/conc v0.3.0
github.com/spf13/cobra v1.8.1
github.com/spf13/viper v1.19.0
google.golang.org/grpc v1.67.1
@ -80,6 +79,7 @@ require (
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/snorwin/jsonpatch v1.5.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect

View File

@ -0,0 +1,71 @@
package config
import (
"strings"
cnpgv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1"
"github.com/cloudnative-pg/cnpg-i-machinery/pkg/pluginhelper/common"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/metadata"
)
// ConfigurationError represents a mistake in the plugin configuration
type ConfigurationError struct {
messages []string
}
// Error implements the error interface
func (e *ConfigurationError) Error() string {
return strings.Join(e.messages, ",")
}
// NewConfigurationError creates a new empty configuration error
func NewConfigurationError() *ConfigurationError {
return &ConfigurationError{}
}
// WithMessage adds a new error message to a potentially empty
// ConfigurationError
func (e *ConfigurationError) WithMessage(msg string) *ConfigurationError {
if e == nil {
return &ConfigurationError{
messages: []string{msg},
}
}
return &ConfigurationError{
messages: append(e.messages, msg),
}
}
// IsEmpty returns true if there's no error messages
func (e *ConfigurationError) IsEmpty() bool {
return len(e.messages) == 0
}
// PluginConfiguration is the configuration of the plugin
type PluginConfiguration struct {
BarmanObjectName string
}
// NewFromCluster extracts the configuration from the cluster
func NewFromCluster(cluster *cnpgv1.Cluster) (*PluginConfiguration, error) {
helper := common.NewPlugin(
*cluster,
metadata.PluginName,
)
result := &PluginConfiguration{
BarmanObjectName: helper.Parameters["barmanObjectName"],
}
err := NewConfigurationError()
if len(result.BarmanObjectName) == 0 {
err = err.WithMessage("Missing barmanObjectName parameter")
}
if err.IsEmpty() {
return result, nil
}
return result, err
}

View File

@ -0,0 +1,2 @@
// Package config contains the functions to parse the plugin configuration
package config

View File

@ -4,7 +4,6 @@ import (
"context"
"errors"
"github.com/cloudnative-pg/cnpg-i-machinery/pkg/pluginhelper/common"
"github.com/cloudnative-pg/cnpg-i-machinery/pkg/pluginhelper/decoder"
"github.com/cloudnative-pg/cnpg-i-machinery/pkg/pluginhelper/object"
"github.com/cloudnative-pg/cnpg-i/pkg/lifecycle"
@ -12,7 +11,7 @@ import (
"github.com/spf13/viper"
corev1 "k8s.io/api/core/v1"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/metadata"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator/config"
)
// LifecycleImplementation is the implementation of the lifecycle handler
@ -65,12 +64,10 @@ func (impl LifecycleImplementation) LifecycleHook(
return nil, err
}
helper := common.NewPlugin(
*cluster,
metadata.PluginName,
)
// TODO: Validation of the plugin configuration
pluginConfiguration, err := config.NewFromCluster(cluster)
if err != nil {
return nil, err
}
mutatedPod := pod.DeepCopy()
err = object.InjectPluginSidecar(mutatedPod, &corev1.Container{
@ -79,7 +76,7 @@ func (impl LifecycleImplementation) LifecycleHook(
Env: []corev1.EnvVar{
{
Name: "BARMAN_OBJECT_NAME",
Value: helper.Parameters["barmanObjectStore"],
Value: pluginConfiguration.BarmanObjectName,
},
{
// TODO: should we really use this one?

View File

@ -14,15 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Package manager contains the implementation of the ObjectStore controller manager
package manager
package operator
import (
"context"
"crypto/tls"
"flag"
// +kubebuilder:scaffold:imports
cnpgv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1"
"github.com/cloudnative-pg/machinery/pkg/log"
"github.com/spf13/viper"
"k8s.io/apimachinery/pkg/runtime"
@ -30,13 +29,12 @@ import (
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
"sigs.k8s.io/controller-runtime/pkg/metrics/filters"
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
"sigs.k8s.io/controller-runtime/pkg/webhook"
barmancloudv1 "github.com/cloudnative-pg/plugin-barman-cloud/api/v1"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/operator/controller"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/controller"
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
// to ensure that exec-entrypoint and run can make use of them.
@ -47,8 +45,8 @@ var scheme = runtime.NewScheme()
func init() {
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
utilruntime.Must(barmancloudv1.AddToScheme(scheme))
utilruntime.Must(cnpgv1.AddToScheme(scheme))
// +kubebuilder:scaffold:scheme
}
@ -58,14 +56,6 @@ func Start(ctx context.Context) error {
var tlsOpts []func(*tls.Config)
opts := zap.Options{
Development: true,
}
opts.BindFlags(flag.CommandLine)
flag.Parse()
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
// if the enable-http2 flag is false (the default), http/2 should be disabled
// due to its vulnerabilities. More specifically, disabling http/2 will
// prevent from being vulnerable to the HTTP/2 Stream Cancellation and
@ -151,6 +141,18 @@ func Start(ctx context.Context) error {
return err
}
if err := mgr.Add(&CNPGI{
Client: mgr.GetClient(),
PluginPath: viper.GetString("plugin-path"),
ServerCertPath: viper.GetString("server-cert"),
ServerKeyPath: viper.GetString("server-key"),
ClientCertPath: viper.GetString("client-cert"),
ServerAddress: viper.GetString("server-address"),
}); err != nil {
setupLog.Error(err, "unable to create CNPGI runnable")
return err
}
setupLog.Info("starting manager")
if err := mgr.Start(ctx); err != nil {
setupLog.Error(err, "problem running manager")

View File

@ -2,12 +2,24 @@ package operator
import (
"context"
"fmt"
cnpgv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1"
"github.com/cloudnative-pg/cnpg-i-machinery/pkg/pluginhelper/decoder"
"github.com/cloudnative-pg/cnpg-i-machinery/pkg/pluginhelper/object"
"github.com/cloudnative-pg/cnpg-i/pkg/reconciler"
rbacv1 "k8s.io/api/rbac/v1"
apierrs "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator/config"
)
// ReconcilerImplementation implements the Reconciler capability
type ReconcilerImplementation struct {
Client client.Client
reconciler.UnimplementedReconcilerHooksServer
}
@ -30,9 +42,37 @@ func (r ReconcilerImplementation) GetCapabilities(
// Pre implements the reconciler interface
func (r ReconcilerImplementation) Pre(
_ context.Context,
_ *reconciler.ReconcilerHooksRequest,
ctx context.Context,
request *reconciler.ReconcilerHooksRequest,
) (*reconciler.ReconcilerHooksResult, error) {
reconciledKind, err := object.GetKind(request.GetResourceDefinition())
if err != nil {
return nil, err
}
if reconciledKind != "Cluster" {
return &reconciler.ReconcilerHooksResult{
Behavior: reconciler.ReconcilerHooksResult_BEHAVIOR_CONTINUE,
}, nil
}
cluster, err := decoder.DecodeClusterJSON(request.GetResourceDefinition())
if err != nil {
return nil, err
}
pluginConfiguration, err := config.NewFromCluster(cluster)
if err != nil {
return nil, err
}
if err := r.ensureRole(ctx, cluster, pluginConfiguration.BarmanObjectName); err != nil {
return nil, err
}
if err := r.ensureRoleBinding(ctx, cluster); err != nil {
return nil, err
}
return &reconciler.ReconcilerHooksResult{
Behavior: reconciler.ReconcilerHooksResult_BEHAVIOR_CONTINUE,
}, nil
@ -47,3 +87,126 @@ func (r ReconcilerImplementation) Post(
Behavior: reconciler.ReconcilerHooksResult_BEHAVIOR_CONTINUE,
}, nil
}
func (r ReconcilerImplementation) ensureRole(
ctx context.Context,
cluster *cnpgv1.Cluster,
barmanObjectName string,
) error {
var role rbacv1.Role
if err := r.Client.Get(ctx, client.ObjectKey{
Namespace: cluster.Namespace,
Name: getRBACName(cluster.Name),
}, &role); err != nil {
if apierrs.IsNotFound(err) {
return r.createRole(ctx, cluster, barmanObjectName)
}
return err
}
// TODO: patch existing role
return nil
}
func (r ReconcilerImplementation) ensureRoleBinding(
ctx context.Context,
cluster *cnpgv1.Cluster,
) error {
var role rbacv1.RoleBinding
if err := r.Client.Get(ctx, client.ObjectKey{
Namespace: cluster.Namespace,
Name: getRBACName(cluster.Name),
}, &role); err != nil {
if apierrs.IsNotFound(err) {
return r.createRoleBinding(ctx, cluster)
}
return err
}
// TODO: patch existing role binding
return nil
}
func (r ReconcilerImplementation) createRole(
ctx context.Context,
cluster *cnpgv1.Cluster,
barmanObjectName string,
) error {
role := buildRole(cluster, barmanObjectName)
if err := ctrl.SetControllerReference(cluster, role, r.Client.Scheme()); err != nil {
return err
}
return r.Client.Create(ctx, role)
}
func (r ReconcilerImplementation) createRoleBinding(
ctx context.Context,
cluster *cnpgv1.Cluster,
) error {
roleBinding := buildRoleBinding(cluster)
if err := ctrl.SetControllerReference(cluster, roleBinding, r.Client.Scheme()); err != nil {
return err
}
return r.Client.Create(ctx, roleBinding)
}
func buildRole(
cluster *cnpgv1.Cluster,
barmanObjectName string,
) *rbacv1.Role {
return &rbacv1.Role{
ObjectMeta: metav1.ObjectMeta{
Namespace: cluster.Namespace,
Name: getRBACName(cluster.Name),
},
Rules: []rbacv1.PolicyRule{
{
APIGroups: []string{
"barmancloud.cnpg.io",
},
Verbs: []string{
"get",
"watch",
"list",
},
Resources: []string{
"objectstores",
},
ResourceNames: []string{
barmanObjectName,
},
},
},
}
}
func buildRoleBinding(
cluster *cnpgv1.Cluster,
) *rbacv1.RoleBinding {
return &rbacv1.RoleBinding{
ObjectMeta: metav1.ObjectMeta{
Namespace: cluster.Namespace,
Name: getRBACName(cluster.Name),
},
Subjects: []rbacv1.Subject{
{
Kind: "ServiceAccount",
APIGroup: "",
Name: cluster.Name,
Namespace: cluster.Namespace,
},
},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
Kind: "Role",
Name: getRBACName(cluster.Name),
},
}
}
// getRBACName returns the name of the RBAC entities for the
// barman cloud plugin
func getRBACName(clusterName string) string {
return fmt.Sprintf("%s-barman", clusterName)
}

View File

@ -1,21 +1,45 @@
package operator
import (
"context"
"github.com/cloudnative-pg/cnpg-i-machinery/pkg/pluginhelper/http"
"github.com/cloudnative-pg/cnpg-i/pkg/lifecycle"
"github.com/cloudnative-pg/cnpg-i/pkg/reconciler"
"github.com/spf13/cobra"
"google.golang.org/grpc"
"sigs.k8s.io/controller-runtime/pkg/client"
)
// NewCommand creates the command to start the GRPC server
// CNPGI is the implementation of the CNPG-i server
type CNPGI struct {
Client client.Client
PluginPath string
ServerCertPath string
ServerKeyPath string
ClientCertPath string
ServerAddress string
}
// Start starts the GRPC server
// of the operator plugin
func NewCommand() *cobra.Command {
cmd := http.CreateMainCmd(IdentityImplementation{}, func(server *grpc.Server) error {
reconciler.RegisterReconcilerHooksServer(server, ReconcilerImplementation{})
func (c *CNPGI) Start(ctx context.Context) error {
enrich := func(server *grpc.Server) error {
reconciler.RegisterReconcilerHooksServer(server, ReconcilerImplementation{
Client: c.Client,
})
lifecycle.RegisterOperatorLifecycleServer(server, LifecycleImplementation{})
return nil
})
cmd.Use = "plugin"
return cmd
}
srv := http.Server{
IdentityImpl: IdentityImplementation{},
Enrichers: []http.ServerEnricher{enrich},
PluginPath: c.PluginPath,
ServerCertPath: c.ServerCertPath,
ServerKeyPath: c.ServerKeyPath,
ClientCertPath: c.ClientCertPath,
ServerAddress: c.ServerAddress,
}
return srv.Start(ctx)
}

View File

@ -34,6 +34,8 @@ type ObjectStoreReconciler struct {
Scheme *runtime.Scheme
}
// +kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=rolebindings,verbs=create;patch;update;get;list;watch
// +kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=roles,verbs=create;patch;update;get;list;watch
// +kubebuilder:rbac:groups=barmancloud.cnpg.io,resources=objectstores,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=barmancloud.cnpg.io,resources=objectstores/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=barmancloud.cnpg.io,resources=objectstores/finalizers,verbs=update

View File

@ -61,7 +61,7 @@ var _ = BeforeSuite(func() {
By("bootstrapping test environment")
testEnv = &envtest.Environment{
CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crd", "bases")},
CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")},
ErrorIfCRDPathMissing: true,
// The BinaryAssetsDirectory is only required if you want to run the tests directly

View File

@ -29,7 +29,6 @@ spec:
key: SIDECAR_IMAGE
name: plugin-barman-cloud
args:
- operator
- --server-cert=/server/tls.crt
- --server-key=/server/tls.key
- --client-cert=/client/tls.crt

View File

@ -12,8 +12,8 @@ resources:
images:
- name: plugin-barman-cloud
newName: kind.local/github.com/cloudnative-pg/plugin-barman-cloud/cmd/operator
newTag: 634ab82d4f8b68ffada6033b7dff817bbed61a2fec8e05f9ebf74f5bedafb0dd
newTag: 7e901b38eaf33b047dcf2eb044c9c8ca85535d8041a3144d25f7e1a4690ea071
secretGenerator:
- literals:
- SIDECAR_IMAGE=kind.local/github.com/cloudnative-pg/plugin-barman-cloud/cmd/instance:7173a2dcf3ce74e982ca3d35053de40fcec67b31d607a0d12547b4f9d09c535c
- SIDECAR_IMAGE=kind.local/github.com/cloudnative-pg/plugin-barman-cloud/cmd/instance:ca1fd58413940a247bc52cdb44f4a6909192d781b1767dc7ee9625368ee9d7e2
name: plugin-barman-cloud