diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 95d1a9082..5ca53e889 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -182,7 +182,7 @@ jobs: needs: - build_fn - run_e2e_tests - if: github.ref == 'refs/heads/main' + # if: github.ref == 'refs/heads/main' #TODO: revert comment once tested on private branch strategy: matrix: os: [ubuntu-20.04] @@ -223,20 +223,41 @@ jobs: - name: Prepare workspace run: | - /tmp/ns prepare eks --env=staging --cluster=${{ secrets.EKS_STAGING_CLUSTER }} --aws_profile=ns-staging + /tmp/ns prepare eks --env=staging --cluster=${{ secrets.EKS_STAGING_CLUSTER }} --aws_profile=ns-staging --use_head_orchestrator - /tmp/ns prepare new-build-cluster --env=staging + /tmp/ns prepare new-build-cluster --env=staging --use_head_orchestrator - - name: Deploy staging + - name: Upload staging deploy-plan to registry run: | - /tmp/ns deploy --env=staging \ + DEPLOY_PLAN_URI=$(/tmp/ns deploy --env=staging \ internal/testdata/server/gogrpc \ internal/testdata/integrations/dockerfile/complex \ internal/testdata/integrations/golang \ internal/testdata/integrations/nodejs/yarn \ --use_prebuilts=true \ --golang_use_buildkit=true \ - --run_codegen=false + --run_codegen=false \ + --upload_plan_to=staging-deploy-plan \ + --upload_to_registry | grep -F "Pushed plan to" | cut -f4 -d ' ') + echo "DEPLOY_PLAN_URI=$DEPLOY_PLAN_URI" >> $GITHUB_ENV + + - name: Checkout ArgoCD manifests repo + uses: actions/checkout@v3 + with: + repository: namespacelabs/argocd-staging-manifests + token: ${{ secrets.GH_MANIFESTS_REPO_PAT }} + path: argocd-staging-manifests + + - name: Push new Revision to manifests repo + run: | + cd argocd-staging-manifests + echo 'image: ${{ env.DEPLOY_PLAN_URI }}' > values.yaml + git config --global user.name "github-actions" + git config --global user.email "github-actions@github.com" + git add . + git commit -m "Foundation ${{ github.sha }}" + git push + - uses: k0kubun/action-slack@v2.0.0 with: diff --git a/internal/testdata/integrations/golang/main.go b/internal/testdata/integrations/golang/main.go index dffe203cd..9e743239c 100644 --- a/internal/testdata/integrations/golang/main.go +++ b/internal/testdata/integrations/golang/main.go @@ -21,7 +21,7 @@ func main() { port := config.Current.Port[0].Port http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { - w.Write([]byte("Hello, world! From Go")) + w.Write([]byte("Hello, world! From Giulio's Go!")) }) log.Printf("Listening on port: %d", port) diff --git a/orchestration/controllers/crds/revision/api.go b/orchestration/controllers/crds/revision/api.go new file mode 100644 index 000000000..06e76f5e4 --- /dev/null +++ b/orchestration/controllers/crds/revision/api.go @@ -0,0 +1,128 @@ +// Copyright 2022 Namespace Labs Inc; All rights reserved. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. + +package revision + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +type RevisionSpec struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // TODO: add comment + Image string `json:"image,omitempty"` +} + +// DeepCopyInto, DeepCopy, and DeepCopyObject are generated typically with +// https://github.com/kubernetes/code-generator and are necessary to fulfil the API contract +// for custom resources. +func (in *RevisionSpec) DeepCopyInto(out *RevisionSpec) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Image = in.Image +} + +func (in *RevisionSpec) DeepCopy() *RevisionSpec { + if in == nil { + return nil + } + out := new(RevisionSpec) + in.DeepCopyInto(out) + return out +} + +func (in *RevisionSpec) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +type RevisionStatus struct { + // TODO: add status properties? +} + +func (in *RevisionStatus) DeepCopyInto(out *RevisionStatus) { + *out = *in +} + +func (in *RevisionStatus) DeepCopy() *RevisionStatus { + if in == nil { + return nil + } + out := new(RevisionStatus) + in.DeepCopyInto(out) + return out +} + +type Revision struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec RevisionSpec `json:"spec,omitempty"` + Status RevisionStatus `json:"status,omitempty"` +} + +func (in *Revision) DeepCopyInto(out *Revision) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +func (in *Revision) DeepCopy() *Revision { + if in == nil { + return nil + } + out := new(Revision) + in.DeepCopyInto(out) + return out +} + +func (in *Revision) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +type RevisionList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Revision `json:"items"` +} + +func (in *RevisionList) DeepCopyInto(out *RevisionList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Revision, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +func (in *RevisionList) DeepCopy() *RevisionList { + if in == nil { + return nil + } + out := new(RevisionList) + in.DeepCopyInto(out) + return out +} + +func (in *RevisionList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} diff --git a/orchestration/controllers/crds/revision/configure/binary.cue b/orchestration/controllers/crds/revision/configure/binary.cue new file mode 100644 index 000000000..69c23bbe4 --- /dev/null +++ b/orchestration/controllers/crds/revision/configure/binary.cue @@ -0,0 +1,4 @@ +binary: { + name: "configure-revision-controller" + from: go_package: "." +} diff --git a/orchestration/controllers/crds/revision/configure/main.go b/orchestration/controllers/crds/revision/configure/main.go new file mode 100644 index 000000000..483d2c11a --- /dev/null +++ b/orchestration/controllers/crds/revision/configure/main.go @@ -0,0 +1,82 @@ +// Copyright 2022 Namespace Labs Inc; All rights reserved. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. + +package main + +import ( + "context" + _ "embed" + "fmt" + + rbacv1 "k8s.io/client-go/applyconfigurations/rbac/v1" + "namespacelabs.dev/foundation/framework/kubernetes/kubeblueprint" + "namespacelabs.dev/foundation/framework/kubernetes/kubedef" + "namespacelabs.dev/foundation/framework/kubernetes/kubeparser" + "namespacelabs.dev/foundation/framework/provisioning" + "namespacelabs.dev/foundation/internal/fnerrors" + "namespacelabs.dev/foundation/internal/runtime" + "namespacelabs.dev/foundation/schema" +) + +//go:embed revisioncrd.yaml +var revisionCrd string + +func main() { + h := provisioning.NewHandlers() + henv := h.MatchEnv(&schema.Environment{Runtime: "kubernetes"}) + henv.HandleStack(configuration{}) + provisioning.Handle(h) +} + +type configuration struct{} + +func (configuration) Apply(ctx context.Context, req provisioning.StackRequest, out *provisioning.ApplyOutput) error { + serviceAccount := makeServiceAccount(req.Focus.Server) + + apply, err := kubeparser.Single([]byte(revisionCrd)) + if err != nil { + return fnerrors.InternalError("failed to parse the HTTP gRPC Transcoder CRD: %w", err) + } + + out.Invocations = append(out.Invocations, kubedef.Create{ + Description: "Revision CustomResourceDefinition", + Resource: "customresourcedefinitions", + Body: apply.Resource, + UpdateIfExisting: true, + }) + + grant := kubeblueprint.GrantKubeACLs{ + DescriptionBase: "Revision", + ServiceAccount: serviceAccount, + } + + grant.Rules = append(grant.Rules, rbacv1.PolicyRule(). + WithAPIGroups("k8s.namespacelabs.dev"). + WithResources("revisions", "revisions/status"). + WithVerbs("get", "list", "watch", "create", "update", "delete", "patch")) + + // We leverage `record.EventRecorder` from "k8s.io/client-go/tools/record" which + // creates `Event` objects with the API group "". This rule ensures that + // the event objects created by the controller are accepted by the k8s API server. + grant.Rules = append(grant.Rules, rbacv1.PolicyRule(). + WithAPIGroups(""). + WithResources("events"). + WithVerbs("create")) + + if err := grant.Compile(req, kubeblueprint.NamespaceScope, out); err != nil { + return err + } + + return nil +} + +func (configuration) Delete(context.Context, provisioning.StackRequest, *provisioning.DeleteOutput) error { + // XXX unimplemented + return nil +} + +// TODO: duplicate from orchestration/server/tool/main.go +func makeServiceAccount(srv runtime.Deployable) string { + return fmt.Sprintf("admin-%s", kubedef.MakeDeploymentId(srv)) +} diff --git a/orchestration/controllers/crds/revision/configure/revisioncrd.yaml b/orchestration/controllers/crds/revision/configure/revisioncrd.yaml new file mode 100644 index 000000000..886365a4f --- /dev/null +++ b/orchestration/controllers/crds/revision/configure/revisioncrd.yaml @@ -0,0 +1,36 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + # name must match the spec fields below, and be in the form: . + name: revisions.k8s.namespacelabs.dev +spec: + # group name to use for REST API: /apis// + group: k8s.namespacelabs.dev + # list of versions supported by this CustomResourceDefinition + versions: + - name: v1alpha1 + # Each version can be enabled/disabled by Served flag. + served: true + # One and only one version must be marked as the storage version. + storage: true + schema: + openAPIV3Schema: + type: object + properties: + spec: + type: object + properties: + image: + type: string + # either Namespaced or Cluster + scope: Namespaced + names: + # plural name to be used in the URL: /apis/// + plural: revisions + # singular name to be used as an alias on the CLI and for display + singular: revision + # kind is normally the CamelCased singular type. Your resource manifests use this. + kind: Revision + # shortNames allow shorter string to match your resource on the CLI + shortNames: + - rev \ No newline at end of file diff --git a/orchestration/controllers/crds/revision/deps.fn.go b/orchestration/controllers/crds/revision/deps.fn.go new file mode 100644 index 000000000..507061cf3 --- /dev/null +++ b/orchestration/controllers/crds/revision/deps.fn.go @@ -0,0 +1,54 @@ +// This file was automatically generated by Namespace. +// DO NOT EDIT. To update, re-run `ns generate`. + +package revision + +import ( + "context" + "google.golang.org/grpc" + "namespacelabs.dev/foundation/orchestration/proto" + fncore "namespacelabs.dev/foundation/std/core" + "namespacelabs.dev/foundation/std/go/core" + "namespacelabs.dev/foundation/std/go/server" + fngrpc "namespacelabs.dev/foundation/std/grpc" +) + +// Dependencies that are instantiated once for the lifetime of the service. +type ServiceDeps struct { + Orchestrator proto.OrchestrationServiceClient + Ready core.Check + OrchestratorConn *grpc.ClientConn +} + +// Verify that WireService is present and has the appropriate type. +type checkWireService func(context.Context, server.Registrar, ServiceDeps) + +var _ checkWireService = WireService + +var ( + Package__qjpb7o = &core.Package{ + PackageName: "namespacelabs.dev/foundation/orchestration/controllers/crds/revision", + } + + Provider__qjpb7o = core.Provider{ + Package: Package__qjpb7o, + Instantiate: makeDeps__qjpb7o, + } +) + +func makeDeps__qjpb7o(ctx context.Context, di core.Dependencies) (_ interface{}, err error) { + var deps ServiceDeps + + if deps.Ready, err = fncore.ProvideReadinessCheck(ctx, nil); err != nil { + return nil, err + } + + // package_name: "namespacelabs.dev/foundation/orchestration/service" + if deps.OrchestratorConn, err = fngrpc.ProvideConn(ctx, core.MustUnwrapProto("CjJuYW1lc3BhY2VsYWJzLmRldi9mb3VuZGF0aW9uL29yY2hlc3RyYXRpb24vc2VydmljZQ==", &fngrpc.Backend{}).(*fngrpc.Backend)); err != nil { + return nil, err + } + + deps.Orchestrator = proto.NewOrchestrationServiceClient(deps.OrchestratorConn) + + return deps, nil +} diff --git a/orchestration/controllers/crds/revision/reconcile.go b/orchestration/controllers/crds/revision/reconcile.go new file mode 100644 index 000000000..228769d2a --- /dev/null +++ b/orchestration/controllers/crds/revision/reconcile.go @@ -0,0 +1,156 @@ +// Copyright 2022 Namespace Labs Inc; All rights reserved. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. + +package revision + +import ( + "context" + "io" + "io/fs" + + "github.com/google/go-containerregistry/pkg/v1/mutate" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/anypb" + "k8s.io/client-go/tools/record" + orchproto "namespacelabs.dev/foundation/orchestration/proto" + "namespacelabs.dev/foundation/std/tasks" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + "namespacelabs.dev/foundation/internal/artifacts/oci" + "namespacelabs.dev/foundation/internal/compute" + "namespacelabs.dev/foundation/internal/fnerrors" + "namespacelabs.dev/foundation/internal/fnfs/tarfs" + "namespacelabs.dev/foundation/internal/providers/aws/ecr" + "namespacelabs.dev/foundation/schema" +) + +const ( + revisionFinalizerKey = "revisions.k8s.namespacelabs.dev/finalizer" +) + +type RevisionReconciler struct { + clt client.Client + recorder record.EventRecorder + orchClt orchproto.OrchestrationServiceClient +} + +func (r *RevisionReconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) { + log := log.FromContext(ctx) + log.Info("Reconciling", "name", req.NamespacedName) + + rev := &Revision{} + err := r.clt.Get(ctx, req.NamespacedName, rev) + if err != nil { + return reconcile.Result{}, client.IgnoreNotFound(err) + } + + if rev.ObjectMeta.DeletionTimestamp.IsZero() { + // Revision is *not* under deletion - i.e. create or update + if !controllerutil.ContainsFinalizer(rev, revisionFinalizerKey) { + // Let's add the finalizer key if object does not have it + controllerutil.AddFinalizer(rev, revisionFinalizerKey) + if err := r.clt.Update(ctx, rev); err != nil { + return reconcile.Result{}, err + } + } + if err := r.handleCreateUpdate(ctx, rev); err != nil { + // if failed, return with error so that it can be retried + return reconcile.Result{}, err + } + } else { + // Revision is under deletion + if controllerutil.ContainsFinalizer(rev, revisionFinalizerKey) { + // our finalizer is present, so let's process the deletion + if err := r.handleDelete(ctx, rev); err != nil { + // if failed, return with error so that it can be retried + return reconcile.Result{}, err + } + + // remove our finalizer from the list and update it - so API server can delete the object + controllerutil.RemoveFinalizer(rev, revisionFinalizerKey) + if err := r.clt.Update(ctx, rev); err != nil { + return reconcile.Result{}, err + } + } + } + + return reconcile.Result{}, nil +} + +func (r *RevisionReconciler) handleCreateUpdate(ctx context.Context, rev *Revision) error { + log := log.FromContext(ctx) + plan, err := loadPlan(ctx, rev.Spec.Image) + if err != nil { + log.Error(err, "failed to load plan") + return err + } + + resp, err := r.orchClt.Deploy(ctx, &orchproto.DeployRequest{ + Plan: plan, + }) + if err != nil { + return err + } + + log.Info("deployed plan", "deploy ID", resp.Id) + return nil +} + +func (r *RevisionReconciler) handleDelete(ctx context.Context, rev *Revision) error { + log := log.FromContext(ctx) + + //TODO: handle undeploy use-case + + log.Info("delete case") + return nil +} + +func loadPlan(ctx context.Context, path string) (*schema.DeployPlan, error) { + raw, err := loadPlanContents(ctx, path) + if err != nil { + return nil, fnerrors.New("failed to load %q: %w", path, err) + } + + any := &anypb.Any{} + if err := proto.Unmarshal(raw, any); err != nil { + return nil, fnerrors.New("failed to unmarshal %q: %w", path, err) + } + + plan := &schema.DeployPlan{} + if err := any.UnmarshalTo(plan); err != nil { + return nil, fnerrors.New("failed to unmarshal %q: %w", path, err) + } + + return plan, nil +} + +func loadPlanContents(ctx context.Context, path string) ([]byte, error) { + imageID, err := oci.ParseImageID(path) + if err != nil { + return nil, err + } + + var img oci.Image + ctx = tasks.WithSink(ctx, tasks.NullSink()) + err = compute.Do(ctx, func(ctx context.Context) error { + img, err = compute.GetValue(ctx, oci.ImageP(imageID.ImageRef(), nil, oci.ResolveOpts{ + PublicImage: false, + RegistryAccess: oci.RegistryAccess{ + InsecureRegistry: false, + Keychain: ecr.DefaultKeychain, //TODO: hard-coded ECR authenticator? What about other registries? + }, + })) + return err + }) + if err != nil { + return nil, err + } + + fsys := tarfs.FS{TarStream: func() (io.ReadCloser, error) { return mutate.Extract(img), nil }} + + return fs.ReadFile(fsys, "deployplan.binarypb") +} diff --git a/orchestration/controllers/crds/revision/service.cue b/orchestration/controllers/crds/revision/service.cue new file mode 100644 index 000000000..11be21fc1 --- /dev/null +++ b/orchestration/controllers/crds/revision/service.cue @@ -0,0 +1,22 @@ +import ( + "namespacelabs.dev/foundation/std/fn" + "namespacelabs.dev/foundation/std/core" + "namespacelabs.dev/foundation/std/grpc" +) + +service: fn.#Service & { + framework: "GO" + + // We don't really need it, but https://github.com/namespacelabs/foundation/issues/717 + instantiate: { + ready: core.#Exports.ReadinessCheck + + orchestrator: grpc.#Exports.Backend & { + packageName: "namespacelabs.dev/foundation/orchestration/service" + } + } +} + +configure: fn.#Configure & { + with: binary: "namespacelabs.dev/foundation/orchestration/controllers/crds/revision/configure" +} diff --git a/orchestration/controllers/crds/revision/wire.go b/orchestration/controllers/crds/revision/wire.go new file mode 100644 index 000000000..1249cca98 --- /dev/null +++ b/orchestration/controllers/crds/revision/wire.go @@ -0,0 +1,92 @@ +// Copyright 2022 Namespace Labs Inc; All rights reserved. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. + +package revision + +import ( + "context" + "flag" + "fmt" + "log" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + "namespacelabs.dev/foundation/orchestration/proto" + "namespacelabs.dev/foundation/std/go/server" + ctrlruntime "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/healthz" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + runtimescheme "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // Kubernetes controller settings. + controllerPort = flag.Int("revision_controller_port", 10443, "Port that the Kubernetes controller binds to.") + + metricsAddress = flag.String("revision_controller_metrics_address", "0.0.0.0:19080", + "Address port pair that the Kubernetes controller metrics endpoint binds to.") + + probeAddress = flag.String("revision_controller_health_probe_bind_address", "0.0.0.0:19081", + "Address port pair that the Kubernetes controller health probe endpoint binds to.") +) + +func WireService(ctx context.Context, srv server.Registrar, deps ServiceDeps) { + if err := setupControllers(deps.Orchestrator); err != nil { + log.Fatal(err) + } +} + +func setupControllers(orchClt proto.OrchestrationServiceClient) error { + groupVersion := schema.GroupVersion{Group: "k8s.namespacelabs.dev", Version: "v1alpha1"} + schemeBuilder := &runtimescheme.Builder{GroupVersion: groupVersion} + schemeBuilder.Register(&Revision{}, &RevisionList{}) + + scheme := runtime.NewScheme() + utilruntime.Must(clientgoscheme.AddToScheme(scheme)) + utilruntime.Must(schemeBuilder.AddToScheme(scheme)) + + zapopts := zap.Options{} + ctrlruntime.SetLogger(zap.New(zap.UseFlagOptions(&zapopts))) + + mgr, err := ctrlruntime.NewManager(ctrlruntime.GetConfigOrDie(), ctrlruntime.Options{ + Scheme: scheme, + MetricsBindAddress: *metricsAddress, + Port: *controllerPort, + HealthProbeBindAddress: *probeAddress, + // No leader election until we figure out our HA requirements and design. + }) + if err != nil { + return fmt.Errorf("failed to start the controller manager: %+v", err) + } + + if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { + return fmt.Errorf("failed to set up healthz: %+v", err) + } + + if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { + return fmt.Errorf("failed to set up readyz: %+v", err) + } + + if err := ctrlruntime.NewControllerManagedBy(mgr). + For(&Revision{}). + Complete(&RevisionReconciler{ + clt: mgr.GetClient(), + recorder: mgr.GetEventRecorderFor("revision"), + orchClt: orchClt, + }); err != nil { + return err + } + + go func() { + // XXX we don't have a good way to model background work. + // Do not use the received context, as that has a timeout built-in. + if err := mgr.Start(context.Background()); err != nil { + log.Fatal(err) + } + }() + + return nil +} diff --git a/orchestration/controllers/deps.fn.go b/orchestration/controllers/runtimeconfig/deps.fn.go similarity index 77% rename from orchestration/controllers/deps.fn.go rename to orchestration/controllers/runtimeconfig/deps.fn.go index c17cc568e..c1aeeafd8 100644 --- a/orchestration/controllers/deps.fn.go +++ b/orchestration/controllers/runtimeconfig/deps.fn.go @@ -1,7 +1,7 @@ // This file was automatically generated by Namespace. // DO NOT EDIT. To update, re-run `ns generate`. -package controllers +package runtimeconfig import ( "context" @@ -21,17 +21,17 @@ type checkWireService func(context.Context, server.Registrar, ServiceDeps) var _ checkWireService = WireService var ( - Package__6f40u5 = &core.Package{ - PackageName: "namespacelabs.dev/foundation/orchestration/controllers", + Package__8ict6m = &core.Package{ + PackageName: "namespacelabs.dev/foundation/orchestration/controllers/runtimeconfig", } - Provider__6f40u5 = core.Provider{ - Package: Package__6f40u5, - Instantiate: makeDeps__6f40u5, + Provider__8ict6m = core.Provider{ + Package: Package__8ict6m, + Instantiate: makeDeps__8ict6m, } ) -func makeDeps__6f40u5(ctx context.Context, di core.Dependencies) (_ interface{}, err error) { +func makeDeps__8ict6m(ctx context.Context, di core.Dependencies) (_ interface{}, err error) { var deps ServiceDeps if deps.Ready, err = fncore.ProvideReadinessCheck(ctx, nil); err != nil { diff --git a/orchestration/controllers/runtimeconfig.go b/orchestration/controllers/runtimeconfig/runtimeconfig.go similarity index 99% rename from orchestration/controllers/runtimeconfig.go rename to orchestration/controllers/runtimeconfig/runtimeconfig.go index a6c6255d6..b83989878 100644 --- a/orchestration/controllers/runtimeconfig.go +++ b/orchestration/controllers/runtimeconfig/runtimeconfig.go @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. -package controllers +package runtimeconfig import ( "context" diff --git a/orchestration/controllers/service.cue b/orchestration/controllers/runtimeconfig/service.cue similarity index 100% rename from orchestration/controllers/service.cue rename to orchestration/controllers/runtimeconfig/service.cue diff --git a/orchestration/controllers/wire.go b/orchestration/controllers/runtimeconfig/wire.go similarity index 99% rename from orchestration/controllers/wire.go rename to orchestration/controllers/runtimeconfig/wire.go index c9407e04c..d8361e3b5 100644 --- a/orchestration/controllers/wire.go +++ b/orchestration/controllers/runtimeconfig/wire.go @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. -package controllers +package runtimeconfig import ( "context" @@ -47,6 +47,9 @@ func setupControllers() error { LeaderElection: *enableLeaderElection, LeaderElectionID: "64367099.k8s.namespacelabs.dev", }) + if err != nil { + return fmt.Errorf("failed to start the controller manager: %+v", err) + } if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { return fmt.Errorf("failed to set up healthz: %+v", err) @@ -56,10 +59,6 @@ func setupControllers() error { return fmt.Errorf("failed to set up readyz: %+v", err) } - if err != nil { - return fmt.Errorf("failed to start the controller manager: %+v", err) - } - if err := controllerruntime.NewControllerManagedBy(mgr). For(&corev1.Pod{}). Owns(&corev1.ConfigMap{}). diff --git a/orchestration/server/deps.fn.go b/orchestration/server/deps.fn.go index 415b297f0..7463d0671 100644 --- a/orchestration/server/deps.fn.go +++ b/orchestration/server/deps.fn.go @@ -5,7 +5,8 @@ package main import ( "context" - "namespacelabs.dev/foundation/orchestration/controllers" + "namespacelabs.dev/foundation/orchestration/controllers/crds/revision" + "namespacelabs.dev/foundation/orchestration/controllers/runtimeconfig" "namespacelabs.dev/foundation/orchestration/legacycontroller" "namespacelabs.dev/foundation/orchestration/service" "namespacelabs.dev/foundation/std/go/core" @@ -23,8 +24,15 @@ func RegisterInitializers(di *core.DependencyGraph) { func WireServices(ctx context.Context, srv server.Server, depgraph core.Dependencies) []error { var errs []error - if err := depgraph.Instantiate(ctx, controllers.Provider__6f40u5, func(ctx context.Context, v interface{}) error { - controllers.WireService(ctx, srv.Scope(controllers.Package__6f40u5), v.(controllers.ServiceDeps)) + if err := depgraph.Instantiate(ctx, revision.Provider__qjpb7o, func(ctx context.Context, v interface{}) error { + revision.WireService(ctx, srv.Scope(revision.Package__qjpb7o), v.(revision.ServiceDeps)) + return nil + }); err != nil { + errs = append(errs, err) + } + + if err := depgraph.Instantiate(ctx, runtimeconfig.Provider__8ict6m, func(ctx context.Context, v interface{}) error { + runtimeconfig.WireService(ctx, srv.Scope(runtimeconfig.Package__8ict6m), v.(runtimeconfig.ServiceDeps)) return nil }); err != nil { errs = append(errs, err) diff --git a/orchestration/server/server.cue b/orchestration/server/server.cue index 4aa6c3af4..2ce81ff68 100644 --- a/orchestration/server/server.cue +++ b/orchestration/server/server.cue @@ -8,7 +8,8 @@ server: fn.#Server & { framework: "GO" import: [ - "namespacelabs.dev/foundation/orchestration/controllers", + "namespacelabs.dev/foundation/orchestration/controllers/crds/revision", + "namespacelabs.dev/foundation/orchestration/controllers/runtimeconfig", "namespacelabs.dev/foundation/orchestration/service", "namespacelabs.dev/foundation/orchestration/legacycontroller", // TODO remove "namespacelabs.dev/foundation/std/grpc/logging",