diff --git a/api/core.oam.dev/v1alpha2/appdeploy_types.go b/api/core.oam.dev/v1alpha2/appdeploy_types.go new file mode 100644 index 000000000..6ad34e99c --- /dev/null +++ b/api/core.oam.dev/v1alpha2/appdeploy_types.go @@ -0,0 +1,59 @@ +/* + + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha2 + +import ( + runtimev1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// ApplicationDeploymentSpec defines the desired state of ApplicationDeployment +type ApplicationDeploymentSpec struct { + //TODO add spec here +} + +// ApplicationDeploymentStatus defines the observed state of ApplicationDeployment +type ApplicationDeploymentStatus struct { + //TODO add status field here + runtimev1alpha1.ConditionedStatus `json:",inline"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:resource:categories={oam} +// +kubebuilder:subresource:status +// ApplicationDeployment is the Schema for the ApplicationDeployment API +type ApplicationDeployment struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ApplicationDeploymentSpec `json:"spec,omitempty"` + Status ApplicationDeploymentStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true +// ApplicationDeploymentList contains a list of ApplicationDeployment +type ApplicationDeploymentList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ApplicationDeployment `json:"items"` +} + +func init() { + SchemeBuilder.Register(&ApplicationDeployment{}, &ApplicationDeploymentList{}) +} diff --git a/api/core.oam.dev/v1alpha2/groupversion_info.go b/api/core.oam.dev/v1alpha2/groupversion_info.go new file mode 100644 index 000000000..182b83e77 --- /dev/null +++ b/api/core.oam.dev/v1alpha2/groupversion_info.go @@ -0,0 +1,35 @@ +/* + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1alpha2 contains API Schema definitions for the core.oam.dev v1alpha2 API group +// +kubebuilder:object:generate=true +// +groupName=core.oam.dev +package v1alpha2 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = schema.GroupVersion{Group: "core.oam.dev", Version: "v1alpha2"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/api/core.oam.dev/v1alpha2/zz_generated.deepcopy.go b/api/core.oam.dev/v1alpha2/zz_generated.deepcopy.go new file mode 100644 index 000000000..7d50482f8 --- /dev/null +++ b/api/core.oam.dev/v1alpha2/zz_generated.deepcopy.go @@ -0,0 +1,115 @@ +// +build !ignore_autogenerated + +/* + + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationDeployment) DeepCopyInto(out *ApplicationDeployment) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationDeployment. +func (in *ApplicationDeployment) DeepCopy() *ApplicationDeployment { + if in == nil { + return nil + } + out := new(ApplicationDeployment) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ApplicationDeployment) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationDeploymentList) DeepCopyInto(out *ApplicationDeploymentList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ApplicationDeployment, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationDeploymentList. +func (in *ApplicationDeploymentList) DeepCopy() *ApplicationDeploymentList { + if in == nil { + return nil + } + out := new(ApplicationDeploymentList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ApplicationDeploymentList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationDeploymentSpec) DeepCopyInto(out *ApplicationDeploymentSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationDeploymentSpec. +func (in *ApplicationDeploymentSpec) DeepCopy() *ApplicationDeploymentSpec { + if in == nil { + return nil + } + out := new(ApplicationDeploymentSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationDeploymentStatus) DeepCopyInto(out *ApplicationDeploymentStatus) { + *out = *in + in.ConditionedStatus.DeepCopyInto(&out.ConditionedStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationDeploymentStatus. +func (in *ApplicationDeploymentStatus) DeepCopy() *ApplicationDeploymentStatus { + if in == nil { + return nil + } + out := new(ApplicationDeploymentStatus) + in.DeepCopyInto(out) + return out +} diff --git a/charts/vela-core/crds/core.oam.dev_applicationdeployments.yaml b/charts/vela-core/crds/core.oam.dev_applicationdeployments.yaml new file mode 100644 index 000000000..b81376935 --- /dev/null +++ b/charts/vela-core/crds/core.oam.dev_applicationdeployments.yaml @@ -0,0 +1,90 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.2.5 + creationTimestamp: null + name: applicationdeployments.core.oam.dev +spec: + group: core.oam.dev + names: + categories: + - oam + kind: ApplicationDeployment + listKind: ApplicationDeploymentList + plural: applicationdeployments + singular: applicationdeployment + scope: Namespaced + versions: + - name: v1alpha2 + schema: + openAPIV3Schema: + description: ApplicationDeployment is the Schema for the ApplicationDeployment + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ApplicationDeploymentSpec defines the desired state of ApplicationDeployment + type: object + status: + description: ApplicationDeploymentStatus defines the observed state of + ApplicationDeployment + properties: + conditions: + description: Conditions of the resource. + items: + description: A Condition that may apply to a resource. + properties: + lastTransitionTime: + description: LastTransitionTime is the last time this condition + transitioned from one status to another. + format: date-time + type: string + message: + description: A Message containing details about this condition's + last transition from one status to another, if any. + type: string + reason: + description: A Reason for this condition's last transition from + one status to another. + type: string + status: + description: Status of this condition; is it currently True, + False, or Unknown? + type: string + type: + description: Type of this condition. At most one of each condition + type may apply to a resource at any point in time. + type: string + required: + - lastTransitionTime + - reason + - status + - type + type: object + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/charts/vela-core/crds/standard.oam.dev_podspecworkloads.yaml b/charts/vela-core/crds/standard.oam.dev_podspecworkloads.yaml index ec3233cf7..1587ae485 100644 --- a/charts/vela-core/crds/standard.oam.dev_podspecworkloads.yaml +++ b/charts/vela-core/crds/standard.oam.dev_podspecworkloads.yaml @@ -3503,7 +3503,6 @@ spec: can be referred to by services. type: string protocol: - default: TCP description: Protocol for port. Must be UDP, TCP, or SCTP. Defaults to "TCP". type: string diff --git a/pkg/controller/core.oam.dev/applicationdeployment/applicationdeployment_controller.go b/pkg/controller/core.oam.dev/applicationdeployment/applicationdeployment_controller.go new file mode 100644 index 000000000..e7578deb6 --- /dev/null +++ b/pkg/controller/core.oam.dev/applicationdeployment/applicationdeployment_controller.go @@ -0,0 +1,64 @@ +package applicationdeployment + +import ( + "context" + + "github.com/crossplane/crossplane-runtime/pkg/event" + "github.com/go-logr/logr" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + corev1alpha2 "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2" + "github.com/oam-dev/kubevela/api/core.oam.dev/v1alpha2" +) + +// Reconciler reconciles a PodSpecWorkload object +type Reconciler struct { + client.Client + log logr.Logger + record event.Recorder + Scheme *runtime.Scheme +} + +// +kubebuilder:rbac:groups=core.oam.dev,resources=applicationdeployments,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=core.oam.dev,resources=applicationdeployments/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=core.oam.dev,resources=applicationconfigurations,verbs=get;list;watch;create;update;patch;delete +func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { + ctx := context.Background() + log := r.log.WithValues("applicationdeployments", req.NamespacedName) + log.Info("Reconcile applicationdeployment") + + var appdeploy v1alpha2.ApplicationDeployment + if err := r.Get(ctx, req.NamespacedName, &appdeploy); err != nil { + if apierrors.IsNotFound(err) { + log.Info("applicationdeployment is deleted") + } + return ctrl.Result{}, client.IgnoreNotFound(err) + } + log.Info("Get the applicationdeployment", "apiVersion", appdeploy.APIVersion, "kind", appdeploy.Kind) + + //TODO add reconcile logic here + + return ctrl.Result{}, nil +} + +func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error { + r.record = event.NewAPIRecorder(mgr.GetEventRecorderFor("ApplicationDeployment")). + WithAnnotations("controller", "ApplicationDeployment") + return ctrl.NewControllerManagedBy(mgr). + For(&v1alpha2.ApplicationDeployment{}). + Owns(&corev1alpha2.ApplicationConfiguration{}). + Complete(r) +} + +// Setup adds a controller that reconciles ApplicationDeployment. +func Setup(mgr ctrl.Manager) error { + reconciler := Reconciler{ + Client: mgr.GetClient(), + log: ctrl.Log.WithName("ApplicationDeployment"), + Scheme: mgr.GetScheme(), + } + return reconciler.SetupWithManager(mgr) +} diff --git a/pkg/controller/core.oam.dev/applicationdeployment/suite_test.go b/pkg/controller/core.oam.dev/applicationdeployment/suite_test.go new file mode 100644 index 000000000..c9a69c290 --- /dev/null +++ b/pkg/controller/core.oam.dev/applicationdeployment/suite_test.go @@ -0,0 +1,71 @@ +package applicationdeployment + +import ( + "path/filepath" + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + "sigs.k8s.io/controller-runtime/pkg/envtest/printer" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + + "github.com/oam-dev/kubevela/api/core.oam.dev/v1alpha2" + // +kubebuilder:scaffold:imports +) + +// These tests use Ginkgo (BDD-style Go testing framework). Refer to +// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. + +var cfg *rest.Config +var k8sClient client.Client +var testEnv *envtest.Environment + +func TestAPIs(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecsWithDefaultAndCustomReporters(t, + "Controller Suite", + []Reporter{printer.NewlineReporter{}}) +} + +var _ = BeforeSuite(func(done Done) { + logf.SetLogger(zap.LoggerTo(GinkgoWriter, true)) + + By("bootstrapping test environment") + useExistCluster := true + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{ + filepath.Join("../../../..", "charts/vela-core/crds"), // this has all the required CRDs, + filepath.Join("..", "config", "crd", "bases")}, + UseExistingCluster: &useExistCluster, + } + + var err error + cfg, err = testEnv.Start() + Expect(err).ToNot(HaveOccurred()) + Expect(cfg).ToNot(BeNil()) + + err = v1alpha2.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + + // +kubebuilder:scaffold:scheme + + k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) + Expect(err).ToNot(HaveOccurred()) + Expect(k8sClient).ToNot(BeNil()) + + //TODO write test here + + close(done) +}, 60) + +var _ = AfterSuite(func() { + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).ToNot(HaveOccurred()) +}) diff --git a/pkg/controller/setup.go b/pkg/controller/setup.go index 46f394141..ce4afe52f 100644 --- a/pkg/controller/setup.go +++ b/pkg/controller/setup.go @@ -19,6 +19,7 @@ package controller import ( ctrl "sigs.k8s.io/controller-runtime" + "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/applicationdeployment" "github.com/oam-dev/kubevela/pkg/controller/v1alpha1/metrics" "github.com/oam-dev/kubevela/pkg/controller/v1alpha1/podspecworkload" "github.com/oam-dev/kubevela/pkg/controller/v1alpha1/routes" @@ -27,7 +28,7 @@ import ( // Setup workload controllers. func Setup(mgr ctrl.Manager) error { for _, setup := range []func(ctrl.Manager) error{ - metrics.Setup, podspecworkload.Setup, routes.Setup, + metrics.Setup, podspecworkload.Setup, routes.Setup, applicationdeployment.Setup, } { if err := setup(mgr); err != nil { return err diff --git a/pkg/controller/v1alpha1/podspecworkload/podspecworkload_controller.go b/pkg/controller/v1alpha1/podspecworkload/podspecworkload_controller.go index 08a7bc355..05301fde5 100644 --- a/pkg/controller/v1alpha1/podspecworkload/podspecworkload_controller.go +++ b/pkg/controller/v1alpha1/podspecworkload/podspecworkload_controller.go @@ -70,7 +70,6 @@ type Reconciler struct { // +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=,resources=services,verbs=get;list;watch;create;update;patch;delete func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { - _ = context.Background() ctx := context.Background() log := r.log.WithValues("podspecworkload", req.NamespacedName) log.Info("Reconcile podspecworkload workload") @@ -280,7 +279,7 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error { Complete(r) } -// Setup adds a controller that reconciles MetricsTrait. +// Setup adds a controller that reconciles PodSpecWorkload. func Setup(mgr ctrl.Manager) error { reconciler := Reconciler{ Client: mgr.GetClient(),