Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 53 additions & 1 deletion cluster/local/integration_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -110,24 +110,49 @@ setup_crossplane() {
echo_info "using crossplane version ${chart_version}"
echo

# Disable the default ManagedResourceActivationPolicy that activates all resources,
# so we can test safe-start with selective activation policies.
"${HELM}" install crossplane --namespace crossplane-system --create-namespace \
crossplane-channel/crossplane \
--version "${chart_version}" --wait
--version "${chart_version}" --wait --set 'provider.defaultActivations={}'
}

setup_provider() {
echo_sub_step "applying ManagedResourceActivationPolicy to disable cluster-wide MSSQL"
"${KUBECTL}" apply -f "${projectdir}/examples/activation-policy-no-cluster-mssql.yaml"

echo_step "deploying provider via local.xpkg.deploy"
make -C "${projectdir}" local.xpkg.deploy.provider.${PACKAGE_NAME} KIND_CLUSTER_NAME="${K8S_CLUSTER}"

echo_step "waiting for provider to be installed"
"${KUBECTL}" wait "provider.pkg.crossplane.io/${PACKAGE_NAME}" --for=condition=healthy --timeout=60s

echo_step "verifying cluster-wide MSSQL CRDs are NOT installed"
if "${KUBECTL}" get crd databases.mssql.sql.crossplane.io 2>/dev/null; then
echo_error "cluster-wide MSSQL Database CRD should not be installed"
fi
if "${KUBECTL}" get crd grants.mssql.sql.crossplane.io 2>/dev/null; then
echo_error "cluster-wide MSSQL Grant CRD should not be installed"
fi
if "${KUBECTL}" get crd users.mssql.sql.crossplane.io 2>/dev/null; then
echo_error "cluster-wide MSSQL User CRD should not be installed"
fi
echo_step_completed

echo_step "verifying namespaced MSSQL CRDs ARE installed"
"${KUBECTL}" get crd databases.mssql.sql.m.crossplane.io || echo_error "namespaced MSSQL Database CRD should be installed"
"${KUBECTL}" get crd grants.mssql.sql.m.crossplane.io || echo_error "namespaced MSSQL Grant CRD should be installed"
"${KUBECTL}" get crd users.mssql.sql.m.crossplane.io || echo_error "namespaced MSSQL User CRD should be installed"
echo_step_completed
}

cleanup_provider() {
echo_step "uninstalling provider"

"${KUBECTL}" delete provider.pkg.crossplane.io "${PACKAGE_NAME}"
"${KUBECTL}" delete deploymentruntimeconfig.pkg.crossplane.io runtimeconfig-${PACKAGE_NAME}
"${KUBECTL}" delete managedresourceactivationpolicy.apiextensions.crossplane.io disable-cluster-mssql --ignore-not-found=true
"${KUBECTL}" delete managedresourceactivationpolicy.apiextensions.crossplane.io enable-cluster-mssql --ignore-not-found=true

echo_step "waiting for provider pods to be deleted"
timeout=60
Expand Down Expand Up @@ -458,6 +483,33 @@ TLS=false API_TYPE="cluster" run_test integration_tests_postgres
TLS=false API_TYPE="namespaced" run_test integration_tests_postgres

# no TLS=false variant - MSSQL uses built-in encryption
# Enable cluster-wide MSSQL CRDs before running cluster MSSQL tests.
# The initial activation policy excludes them to test safe-start.
echo_step "creating activation policy to enable cluster-wide MSSQL"
"${KUBECTL}" apply -f - <<EOF
apiVersion: apiextensions.crossplane.io/v1alpha1
kind: ManagedResourceActivationPolicy
metadata:
name: enable-cluster-mssql
spec:
activate:
- "*.mssql.sql.crossplane.io"
EOF

echo_step "waiting for cluster-wide MSSQL CRDs to be installed"
timeout=60
current=0
step=3
while ! "${KUBECTL}" get crd databases.mssql.sql.crossplane.io 2>/dev/null; do
echo "waiting another $step seconds for MSSQL CRDs..."
current=$((current + step))
if [[ $current -ge $timeout ]]; then
echo_error "timeout of ${timeout}s waiting for MSSQL CRDs"
fi
sleep $step
done
echo_step_completed

TLS=true API_TYPE="cluster" run_test integration_tests_mssql
TLS=true API_TYPE="namespaced" run_test integration_tests_mssql

Expand Down
7 changes: 7 additions & 0 deletions cmd/provider/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,13 @@ import (

xpcontroller "github.com/crossplane/crossplane-runtime/v2/pkg/controller"
"github.com/crossplane/crossplane-runtime/v2/pkg/feature"
"github.com/crossplane/crossplane-runtime/v2/pkg/gate"
"github.com/crossplane/crossplane-runtime/v2/pkg/logging"
"github.com/crossplane/crossplane-runtime/v2/pkg/ratelimiter"
"github.com/crossplane/crossplane-runtime/v2/pkg/reconciler/customresourcesgate"
"github.com/crossplane/crossplane-runtime/v2/pkg/statemetrics"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/runtime/schema"

"github.com/crossplane-contrib/provider-sql/apis"
"github.com/crossplane-contrib/provider-sql/pkg/controller"
Expand Down Expand Up @@ -81,6 +85,7 @@ func main() {
})
kingpin.FatalIfError(err, "Cannot create controller manager")
kingpin.FatalIfError(apis.AddToScheme(mgr.GetScheme()), "Cannot add SQL APIs to scheme")
kingpin.FatalIfError(apiextensionsv1.AddToScheme(mgr.GetScheme()), "Cannot add CustomResourceDefinition to scheme")

mrStateMetrics := statemetrics.NewMRStateMetrics()
metrics.Registry.MustRegister(mrStateMetrics)
Expand All @@ -96,13 +101,15 @@ func main() {
PollInterval: *pollInterval,
GlobalRateLimiter: ratelimiter.NewGlobal(*maxReconcileRate),
Features: &feature.Flags{},
Gate: new(gate.Gate[schema.GroupVersionKind]),
MetricOptions: &mo,
}
if *enableManagementPolicies {
o.Features.Enable(feature.EnableBetaManagementPolicies)
log.Info("Beta feature enabled", "flag", feature.EnableBetaManagementPolicies)
}

kingpin.FatalIfError(customresourcesgate.Setup(mgr, o), "Cannot setup CRD gate controller")
kingpin.FatalIfError(controller.Setup(mgr, o), "Cannot setup SQL controllers")
kingpin.FatalIfError(mgr.Start(ctrl.SetupSignalHandler()), "Cannot start controller manager")
}
14 changes: 14 additions & 0 deletions examples/activation-policy-no-cluster-mssql.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: apiextensions.crossplane.io/v1alpha1
kind: ManagedResourceActivationPolicy
metadata:
name: disable-cluster-mssql
spec:
activate:
# Activate all MySQL resources (both cluster and namespaced)
- "*.mysql.sql.crossplane.io"
- "*.mysql.sql.m.crossplane.io"
# Activate all PostgreSQL resources (both cluster and namespaced)
- "*.postgresql.sql.crossplane.io"
- "*.postgresql.sql.m.crossplane.io"
# Activate only namespaced MSSQL resources (cluster-wide MSSQL is excluded)
- "*.mssql.sql.m.crossplane.io"
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ require (
github.com/microsoft/go-mssqldb v1.10.0
github.com/pkg/errors v0.9.1
k8s.io/api v0.35.0
k8s.io/apiextensions-apiserver v0.35.0
k8s.io/apimachinery v0.35.0
k8s.io/utils v0.0.0-20260108192941-914a6e750570
sigs.k8s.io/controller-runtime v0.23.1
Expand Down Expand Up @@ -110,7 +111,6 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apiextensions-apiserver v0.35.0 // indirect
k8s.io/client-go v0.35.0 // indirect
k8s.io/code-generator v0.35.0 // indirect
k8s.io/component-base v0.35.0 // indirect
Expand Down
3 changes: 3 additions & 0 deletions package/crossplane.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@ metadata:
friendly-kind-name.meta.crossplane.io/role.postgresql.sql.crossplane.io: Role
friendly-kind-name.meta.crossplane.io/user.mysql.sql.crossplane.io: User
friendly-kind-name.meta.crossplane.io/defaultprivileges.postgresql.sql.crossplane.io: DefaultPrivileges
spec:
capabilities:
- safe-start
46 changes: 11 additions & 35 deletions pkg/controller/cluster/mssql/database/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,22 @@ package database
import (
"context"

"github.com/crossplane/crossplane-runtime/v2/pkg/statemetrics"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
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/v2/apis/common/v1"
xpcontroller "github.com/crossplane/crossplane-runtime/v2/pkg/controller"
"github.com/crossplane/crossplane-runtime/v2/pkg/event"
"github.com/crossplane/crossplane-runtime/v2/pkg/feature"
"github.com/crossplane/crossplane-runtime/v2/pkg/meta"
"github.com/crossplane/crossplane-runtime/v2/pkg/reconciler/managed"
"github.com/crossplane/crossplane-runtime/v2/pkg/resource"

clusterv1alpha1 "github.com/crossplane-contrib/provider-sql/apis/cluster/mssql/v1alpha1"
"github.com/crossplane-contrib/provider-sql/pkg/clients/mssql"
"github.com/crossplane-contrib/provider-sql/pkg/clients/xsql"
"github.com/crossplane-contrib/provider-sql/pkg/controller/setup"
)

const (
Expand All @@ -52,42 +49,21 @@ const (
errSelectDB = "cannot select database"
errCreateDB = "cannot create database"
errDropDB = "cannot drop database"

maxConcurrency = 5
)

// Setup adds a controller that reconciles Database managed resources.
func Setup(mgr ctrl.Manager, o xpcontroller.Options) error {
name := managed.ControllerName(clusterv1alpha1.DatabaseGroupKind)

t := resource.NewLegacyProviderConfigUsageTracker(mgr.GetClient(), &clusterv1alpha1.ProviderConfigUsage{})

reconcilerOptions := []managed.ReconcilerOption{
managed.WithTypedExternalConnector(&connector{kube: mgr.GetClient(), track: t.Track, newClient: mssql.New}),
managed.WithLogger(o.Logger.WithValues("controller", name)),
managed.WithPollInterval(o.PollInterval),
managed.WithRecorder(event.NewAPIRecorder(mgr.GetEventRecorderFor(name))),
}
if o.Features.Enabled(feature.EnableBetaManagementPolicies) {
reconcilerOptions = append(reconcilerOptions, managed.WithManagementPolicies())
}
r := managed.NewReconciler(mgr,
resource.ManagedKind(clusterv1alpha1.DatabaseGroupVersionKind),
reconcilerOptions...,
)
if err := mgr.Add(statemetrics.NewMRStateRecorder(
mgr.GetClient(), o.Logger, o.MetricOptions.MRStateMetrics,
&clusterv1alpha1.DatabaseList{}, o.MetricOptions.PollStateMetricInterval,
)); err != nil {
return err
}
return ctrl.NewControllerManagedBy(mgr).
Named(name).
For(&clusterv1alpha1.Database{}).
WithOptions(controller.Options{
MaxConcurrentReconciles: maxConcurrency,
}).
Complete(r)
return setup.Setup(mgr, o, setup.ControllerConfig{
GVK: clusterv1alpha1.DatabaseGroupVersionKind,
Resource: &clusterv1alpha1.Database{},
List: &clusterv1alpha1.DatabaseList{},
Connector: managed.WithTypedExternalConnector(&connector{
kube: mgr.GetClient(),
track: t.Track,
newClient: mssql.New,
}),
})
}

type connector struct {
Expand Down
50 changes: 14 additions & 36 deletions pkg/controller/cluster/mssql/grant/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,22 @@ import (
"sort"
"strings"

"github.com/crossplane/crossplane-runtime/v2/pkg/statemetrics"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/utils/ptr"
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/v2/apis/common/v1"
xpcontroller "github.com/crossplane/crossplane-runtime/v2/pkg/controller"
"github.com/crossplane/crossplane-runtime/v2/pkg/event"
"github.com/crossplane/crossplane-runtime/v2/pkg/feature"
"github.com/crossplane/crossplane-runtime/v2/pkg/reconciler/managed"
"github.com/crossplane/crossplane-runtime/v2/pkg/resource"

"github.com/crossplane-contrib/provider-sql/apis/cluster/mssql/v1alpha1"
"github.com/crossplane-contrib/provider-sql/pkg/clients/mssql"
"github.com/crossplane-contrib/provider-sql/pkg/clients/xsql"
"github.com/crossplane-contrib/provider-sql/pkg/controller/setup"
)

const (
Expand All @@ -52,43 +49,24 @@ const (
errGrant = "cannot grant"
errRevoke = "cannot revoke"
errCannotGetGrants = "cannot get current grants"

maxConcurrency = 5
)

// Setup adds a controller that reconciles Grant managed resources.
func Setup(mgr ctrl.Manager, o xpcontroller.Options) error {
name := managed.ControllerName(v1alpha1.GrantGroupKind)

t := resource.NewLegacyProviderConfigUsageTracker(mgr.GetClient(), &v1alpha1.ProviderConfigUsage{})

reconcilerOptions := []managed.ReconcilerOption{
managed.WithTypedExternalConnector(&connector{kube: mgr.GetClient(), track: t.Track, newClient: mssql.New}),
managed.WithReferenceResolver(managed.NewAPISimpleReferenceResolver(mgr.GetClient())),
managed.WithLogger(o.Logger.WithValues("controller", name)),
managed.WithPollInterval(o.PollInterval),
managed.WithRecorder(event.NewAPIRecorder(mgr.GetEventRecorderFor(name))),
}
if o.Features.Enabled(feature.EnableBetaManagementPolicies) {
reconcilerOptions = append(reconcilerOptions, managed.WithManagementPolicies())
}
r := managed.NewReconciler(mgr,
resource.ManagedKind(v1alpha1.GrantGroupVersionKind),
reconcilerOptions...,
)
if err := mgr.Add(statemetrics.NewMRStateRecorder(
mgr.GetClient(), o.Logger, o.MetricOptions.MRStateMetrics,
&v1alpha1.GrantList{}, o.MetricOptions.PollStateMetricInterval,
)); err != nil {
return err
}
return ctrl.NewControllerManagedBy(mgr).
Named(name).
For(&v1alpha1.Grant{}).
WithOptions(controller.Options{
MaxConcurrentReconciles: maxConcurrency,
}).
Complete(r)
return setup.Setup(mgr, o, setup.ControllerConfig{
GVK: v1alpha1.GrantGroupVersionKind,
Resource: &v1alpha1.Grant{},
List: &v1alpha1.GrantList{},
Connector: managed.WithTypedExternalConnector(&connector{
kube: mgr.GetClient(),
track: t.Track,
newClient: mssql.New,
}),
ExtraOpts: []managed.ReconcilerOption{
managed.WithReferenceResolver(managed.NewAPISimpleReferenceResolver(mgr.GetClient())),
},
})
Comment thread
fernandezcuesta marked this conversation as resolved.
}

type connector struct {
Expand Down
Loading
Loading