diff --git a/go.mod b/go.mod index 146089460..f2297bd26 100644 --- a/go.mod +++ b/go.mod @@ -253,7 +253,7 @@ require ( k8s.io/kubectl v0.26.0 // indirect k8s.io/utils v0.0.0-20240102154912-e7106e64919e // indirect oras.land/oras-go v1.2.2 // indirect - sigs.k8s.io/controller-runtime v0.16.3 // indirect + sigs.k8s.io/controller-runtime v0.16.3 sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/kustomize/api v0.15.0 // indirect sigs.k8s.io/kustomize/kyaml v0.15.0 // indirect diff --git a/pkg/kubernetes/client.go b/pkg/kubernetes/client.go index 115bc07be..a153033cb 100644 --- a/pkg/kubernetes/client.go +++ b/pkg/kubernetes/client.go @@ -14,12 +14,15 @@ limitations under the License. package kubernetes import ( + "errors" "flag" "sync" + "k8s.io/apimachinery/pkg/runtime" k8s "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" + "sigs.k8s.io/controller-runtime/pkg/client" scheme "github.com/dapr/dapr/pkg/client/clientset/versioned" @@ -31,6 +34,14 @@ import ( // oidc auth _ "k8s.io/client-go/plugin/pkg/client/auth/oidc" + + componentsapi "github.com/dapr/dapr/pkg/apis/components/v1alpha1" + configurationapi "github.com/dapr/dapr/pkg/apis/configuration/v1alpha1" + httpendpointsapi "github.com/dapr/dapr/pkg/apis/httpEndpoint/v1alpha1" + resiliencyapi "github.com/dapr/dapr/pkg/apis/resiliency/v1alpha1" + subscriptionsapiV1alpha1 "github.com/dapr/dapr/pkg/apis/subscriptions/v1alpha1" + subapi "github.com/dapr/dapr/pkg/apis/subscriptions/v2alpha1" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" ) var ( @@ -96,3 +107,41 @@ func DaprClient() (scheme.Interface, error) { } return scheme.NewForConfig(config) } + +// buildScheme builds the scheme for the controller-runtime client +// from https://github.com/dapr/dapr/blob/eb49e564fbd704ceb1379498fc8e94ad7110840f/pkg/operator/operator.go#L444-L466 +func buildScheme() (*runtime.Scheme, error) { + builders := []func(*runtime.Scheme) error{ + clientgoscheme.AddToScheme, + componentsapi.AddToScheme, + configurationapi.AddToScheme, + resiliencyapi.AddToScheme, + httpendpointsapi.AddToScheme, + subscriptionsapiV1alpha1.AddToScheme, + subapi.AddToScheme, + } + + errs := make([]error, len(builders)) + scheme := runtime.NewScheme() + for i, builder := range builders { + errs[i] = builder(scheme) + } + + return scheme, errors.Join(errs...) +} + +// CtrlClient returns a new Controller-Runtime Client (https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client) - no caching +// with the scheme built with the Dapr API groups. +func CtrlClient() (client.Client, error) { + config, err := getConfig() + if err != nil { + return nil, err + } + + scheme, err := buildScheme() + if err != nil { + return nil, err + } + + return client.New(config, client.Options{Scheme: scheme}) +} diff --git a/pkg/kubernetes/run.go b/pkg/kubernetes/run.go index b8869916e..0eb7f33cb 100644 --- a/pkg/kubernetes/run.go +++ b/pkg/kubernetes/run.go @@ -119,6 +119,23 @@ func Run(runFilePath string, config runfileconfig.RunFileConfig) (bool, error) { runStates := []runState{} print.InfoStatusEvent(os.Stdout, "This is a preview feature and subject to change in future releases.") + ctrlClient, cErr := CtrlClient() + if cErr != nil { + // exit with error. + return true, fmt.Errorf("error getting controller-runtime k8s client: %w", cErr) + } + + resources, err := getResources(config.Common.ResourcesPath) + if err != nil { + print.FailureStatusEvent(os.Stderr, "Error getting resources from %q: %s", config.Common.ResourcesPath, err.Error()) + exitWithError = true + } + + if err := createOrUpdateResources(context.Background(), ctrlClient, resources, namespace); err != nil { + print.FailureStatusEvent(os.Stderr, "Error creating or updating resources: %s", err.Error()) + exitWithError = true + } + for _, app := range config.Apps { print.StatusEvent(os.Stdout, print.LogInfo, "Validating config and starting app %q", app.RunConfig.AppID) // Set defaults if zero value provided in config yaml. @@ -140,11 +157,7 @@ func Run(runFilePath string, config runfileconfig.RunFileConfig) (bool, error) { // create default deployment config. dep := createDeploymentConfig(daprClient, app) - if err != nil { - print.FailureStatusEvent(os.Stderr, "Error creating deployment file for app %q present in %s: %s", app.RunConfig.AppID, runFilePath, err.Error()) - exitWithError = true - break - } + // overwrite /.dapr/deploy/service.yaml. // overwrite /.dapr/deploy/deployment.yaml.