diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 432ab4bb585..7555c298360 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -49,7 +49,7 @@ jobs: needs: [get-version, publish-python-sdk] strategy: matrix: - component: [feature-server, feature-server-python-aws, feature-server-java, feature-transformation-server] + component: [feature-server, feature-server-python-aws, feature-server-java, feature-transformation-server, feast-operator] env: MAVEN_CACHE: gs://feast-templocation-kf-feast/.m2.2020-08-19.tar REGISTRY: feastdev diff --git a/Makefile b/Makefile index f42d5c1edaf..9031b392078 100644 --- a/Makefile +++ b/Makefile @@ -395,6 +395,18 @@ build-feature-server-java-docker: -t $(REGISTRY)/feature-server-java:$(VERSION) \ -f java/infra/docker/feature-server/Dockerfile --load . +push-feast-operator-docker: + cd infra/feast-operator && \ + IMAGE_TAG_BASE=$(REGISTRY)/feast-operator \ + VERSION=$(VERSION) \ + $(MAKE) docker-push + +build-feast-operator-docker: + cd infra/feast-operator && \ + IMAGE_TAG_BASE=$(REGISTRY)/feast-operator \ + VERSION=$(VERSION) \ + $(MAKE) docker-build + # Dev images build-feature-server-dev: diff --git a/infra/feast-operator/.gitignore b/infra/feast-operator/.gitignore new file mode 100644 index 00000000000..62fd3e3995f --- /dev/null +++ b/infra/feast-operator/.gitignore @@ -0,0 +1,14 @@ + +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib +bin + +# editor and IDE paraphernalia +.idea +*.swp +*.swo +*~ diff --git a/infra/feast-operator/Dockerfile b/infra/feast-operator/Dockerfile new file mode 100644 index 00000000000..0aad602c2d2 --- /dev/null +++ b/infra/feast-operator/Dockerfile @@ -0,0 +1,7 @@ +# Build the manager binary +FROM quay.io/operator-framework/helm-operator:v1.34.1 + +ENV HOME=/opt/helm +COPY watches.yaml ${HOME}/watches.yaml +COPY --from=helmcharts feast-feature-server ${HOME}/helm-charts/feast-feature-server +WORKDIR ${HOME} diff --git a/infra/feast-operator/Makefile b/infra/feast-operator/Makefile new file mode 100644 index 00000000000..b02b392465a --- /dev/null +++ b/infra/feast-operator/Makefile @@ -0,0 +1,227 @@ +# VERSION defines the project version for the bundle. +# Update this value when you upgrade the version of your project. +# To re-generate a bundle for another specific version without changing the standard setup, you can: +# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2) +# - use environment variables to overwrite this value (e.g export VERSION=0.0.2) +VERSION ?= 0.37.1 + +# CHANNELS define the bundle channels used in the bundle. +# Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable") +# To re-generate a bundle for other specific channels without changing the standard setup, you can: +# - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=candidate,fast,stable) +# - use environment variables to overwrite this value (e.g export CHANNELS="candidate,fast,stable") +ifneq ($(origin CHANNELS), undefined) +BUNDLE_CHANNELS := --channels=$(CHANNELS) +endif + +# DEFAULT_CHANNEL defines the default channel used in the bundle. +# Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = "stable") +# To re-generate a bundle for any other default channel without changing the default setup, you can: +# - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable) +# - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL="stable") +ifneq ($(origin DEFAULT_CHANNEL), undefined) +BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) +endif +BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) + +# IMAGE_TAG_BASE defines the docker.io namespace and part of the image name for remote images. +# This variable is used to construct full image tags for bundle and catalog images. +# +# For example, running 'make bundle-build bundle-push catalog-build catalog-push' will build and push both +# feastdev/feast-operator-bundle:$VERSION and feastdev/feast-operator-catalog:$VERSION. +IMAGE_TAG_BASE ?= feastdev/feast-operator + +# BUNDLE_IMG defines the image:tag used for the bundle. +# You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=/:) +BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION) + +# BUNDLE_GEN_FLAGS are the flags passed to the operator-sdk generate bundle command +BUNDLE_GEN_FLAGS ?= -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) + +# USE_IMAGE_DIGESTS defines if images are resolved via tags or digests +# You can enable this value if you would like to use SHA Based Digests +# To enable set flag to true +USE_IMAGE_DIGESTS ?= false +ifeq ($(USE_IMAGE_DIGESTS), true) + BUNDLE_GEN_FLAGS += --use-image-digests +endif + +# Set the Operator SDK version to use. By default, what is installed on the system is used. +# This is useful for CI or a project to utilize a specific version of the operator-sdk toolkit. +OPERATOR_SDK_VERSION ?= v1.34.1 + +# Image URL to use all building/pushing image targets +IMG ?= $(IMAGE_TAG_BASE):$(VERSION) + +.PHONY: all +all: docker-build + +##@ General + +# The help target prints out all targets with their descriptions organized +# beneath their categories. The categories are represented by '##@' and the +# target descriptions by '##'. The awk commands is responsible for reading the +# entire set of makefiles included in this invocation, looking for lines of the +# file as xyz: ## something, and then pretty-format the target and help. Then, +# if there's a line with ##@ something, that gets pretty-printed as a category. +# More info on the usage of ANSI control characters for terminal formatting: +# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters +# More info on the awk command: +# http://linuxcommand.org/lc3_adv_awk.php + +.PHONY: help +help: ## Display this help. + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + +##@ Build + +.PHONY: run +run: helm-operator ## Run against the configured Kubernetes cluster in ~/.kube/config + $(HELM_OPERATOR) run + +.PHONY: docker-build +docker-build: ## Build docker image with the manager. + docker build --build-context helmcharts=../charts/ -t ${IMG} . + +.PHONY: docker-push +docker-push: ## Push docker image with the manager. + docker push ${IMG} + +# PLATFORMS defines the target platforms for the manager image be build to provide support to multiple +# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to: +# - able to use docker buildx . More info: https://docs.docker.com/build/buildx/ +# - have enable BuildKit, More info: https://docs.docker.com/develop/develop-images/build_enhancements/ +# - be able to push the image for your registry (i.e. if you do not inform a valid value via IMG=> than the export will fail) +# To properly provided solutions that supports more than one platform you should use this option. +PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le +.PHONY: docker-buildx +docker-buildx: ## Build and push docker image for the manager for cross-platform support + - docker buildx create --name project-v3-builder + - docker buildx use project-v3-builder + - docker buildx build --push --platform=$(PLATFORMS) --build-context helmcharts=../charts/ --tag ${IMG} -f Dockerfile . + - docker buildx rm project-v3-builder + +##@ Deployment + +.PHONY: install +install: kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. + $(KUSTOMIZE) build config/crd | kubectl apply -f - + +.PHONY: uninstall +uninstall: kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. + $(KUSTOMIZE) build config/crd | kubectl delete -f - + +.PHONY: deploy +deploy: kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config. + cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} + $(KUSTOMIZE) build config/default | kubectl apply -f - + +.PHONY: undeploy +undeploy: kustomize ## Undeploy controller from the K8s cluster specified in ~/.kube/config. + $(KUSTOMIZE) build config/default | kubectl delete -f - + +OS := $(shell uname -s | tr '[:upper:]' '[:lower:]') +ARCH := $(shell uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/') + +.PHONY: kustomize +KUSTOMIZE = $(shell pwd)/bin/kustomize +kustomize: ## Download kustomize locally if necessary. +ifeq (,$(wildcard $(KUSTOMIZE))) +ifeq (,$(shell which kustomize 2>/dev/null)) + @{ \ + set -e ;\ + mkdir -p $(dir $(KUSTOMIZE)) ;\ + curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v5.2.1/kustomize_v5.2.1_$(OS)_$(ARCH).tar.gz | \ + tar xzf - -C bin/ ;\ + } +else +KUSTOMIZE = $(shell which kustomize) +endif +endif + +.PHONY: helm-operator +HELM_OPERATOR = $(shell pwd)/bin/helm-operator +helm-operator: ## Download helm-operator locally if necessary, preferring the $(pwd)/bin path over global if both exist. +ifeq (,$(wildcard $(HELM_OPERATOR))) +ifeq (,$(shell which helm-operator 2>/dev/null)) + @{ \ + set -e ;\ + mkdir -p $(dir $(HELM_OPERATOR)) ;\ + curl -sSLo $(HELM_OPERATOR) https://github.com/operator-framework/operator-sdk/releases/download/v1.34.1/helm-operator_$(OS)_$(ARCH) ;\ + chmod +x $(HELM_OPERATOR) ;\ + } +else +HELM_OPERATOR = $(shell which helm-operator) +endif +endif + +.PHONY: operator-sdk +OPERATOR_SDK ?= $(LOCALBIN)/operator-sdk +operator-sdk: ## Download operator-sdk locally if necessary. +ifeq (,$(wildcard $(OPERATOR_SDK))) +ifeq (, $(shell which operator-sdk 2>/dev/null)) + @{ \ + set -e ;\ + mkdir -p $(dir $(OPERATOR_SDK)) ;\ + curl -sSLo $(OPERATOR_SDK) https://github.com/operator-framework/operator-sdk/releases/download/$(OPERATOR_SDK_VERSION)/operator-sdk_$(OS)_$(ARCH) ;\ + chmod +x $(OPERATOR_SDK) ;\ + } +else +OPERATOR_SDK = $(shell which operator-sdk) +endif +endif + +.PHONY: bundle +bundle: kustomize operator-sdk ## Generate bundle manifests and metadata, then validate generated files. + $(OPERATOR_SDK) generate kustomize manifests -q + cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) + $(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK) generate bundle $(BUNDLE_GEN_FLAGS) + $(OPERATOR_SDK) bundle validate ./bundle + +.PHONY: bundle-build +bundle-build: ## Build the bundle image. + docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) . + +.PHONY: bundle-push +bundle-push: ## Push the bundle image. + $(MAKE) docker-push IMG=$(BUNDLE_IMG) + +.PHONY: opm +OPM = $(LOCALBIN)/opm +opm: ## Download opm locally if necessary. +ifeq (,$(wildcard $(OPM))) +ifeq (,$(shell which opm 2>/dev/null)) + @{ \ + set -e ;\ + mkdir -p $(dir $(OPM)) ;\ + curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.23.0/$(OS)-$(ARCH)-opm ;\ + chmod +x $(OPM) ;\ + } +else +OPM = $(shell which opm) +endif +endif + +# A comma-separated list of bundle images (e.g. make catalog-build BUNDLE_IMGS=example.com/operator-bundle:v0.1.0,example.com/operator-bundle:v0.2.0). +# These images MUST exist in a registry and be pull-able. +BUNDLE_IMGS ?= $(BUNDLE_IMG) + +# The image tag given to the resulting catalog image (e.g. make catalog-build CATALOG_IMG=example.com/operator-catalog:v0.2.0). +CATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:v$(VERSION) + +# Set CATALOG_BASE_IMG to an existing catalog image tag to add $BUNDLE_IMGS to that image. +ifneq ($(origin CATALOG_BASE_IMG), undefined) +FROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG) +endif + +# Build a catalog image by adding bundle images to an empty catalog using the operator package manager tool, 'opm'. +# This recipe invokes 'opm' in 'semver' bundle add mode. For more information on add modes, see: +# https://github.com/operator-framework/community-operators/blob/7f1438c/docs/packaging-operator.md#updating-your-existing-operator +.PHONY: catalog-build +catalog-build: opm ## Build a catalog image. + $(OPM) index add --container-tool docker --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT) + +# Push the catalog image. +.PHONY: catalog-push +catalog-push: ## Push a catalog image. + $(MAKE) docker-push IMG=$(CATALOG_IMG) diff --git a/infra/feast-operator/PROJECT b/infra/feast-operator/PROJECT new file mode 100644 index 00000000000..56b2532d859 --- /dev/null +++ b/infra/feast-operator/PROJECT @@ -0,0 +1,20 @@ +# Code generated by tool. DO NOT EDIT. +# This file is used to track the info used to scaffold your project +# and allow the plugins properly work. +# More info: https://book.kubebuilder.io/reference/project-config.html +domain: feast.dev +layout: +- helm.sdk.operatorframework.io/v1 +plugins: + manifests.sdk.operatorframework.io/v2: {} + scorecard.sdk.operatorframework.io/v2: {} +projectName: feast-operator +resources: +- api: + crdVersion: v1 + namespaced: true + domain: feast.dev + group: charts + kind: FeastFeatureServer + version: v1alpha1 +version: "3" diff --git a/infra/feast-operator/README.md b/infra/feast-operator/README.md new file mode 100644 index 00000000000..e058a97d5c6 --- /dev/null +++ b/infra/feast-operator/README.md @@ -0,0 +1,11 @@ +# Feast Feature Server Helm-based Operator + +Leverages [operator-sdk](https://github.com/operator-framework/operator-sdk) and the [feast-feature-server helm chart](/infra/charts/feast-feature-server). + +### To run against an OCP cluster - +```bash +$ make deploy + +# test the operator by deploying a feature server sample CR +$ oc apply -f config/samples/charts_v1alpha1_feastfeatureserver.yaml +``` diff --git a/infra/feast-operator/config/crd/bases/charts.feast.dev_feastfeatureservers.yaml b/infra/feast-operator/config/crd/bases/charts.feast.dev_feastfeatureservers.yaml new file mode 100644 index 00000000000..8c4c6a1eceb --- /dev/null +++ b/infra/feast-operator/config/crd/bases/charts.feast.dev_feastfeatureservers.yaml @@ -0,0 +1,44 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: feastfeatureservers.charts.feast.dev +spec: + group: charts.feast.dev + names: + kind: FeastFeatureServer + listKind: FeastFeatureServerList + plural: feastfeatureservers + singular: feastfeatureserver + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: FeastFeatureServer is the Schema for the feastfeatureservers 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: Spec defines the desired state of FeastFeatureServer + type: object + x-kubernetes-preserve-unknown-fields: true + status: + description: Status defines the observed state of FeastFeatureServer + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: true + storage: true + subresources: + status: {} diff --git a/infra/feast-operator/config/crd/kustomization.yaml b/infra/feast-operator/config/crd/kustomization.yaml new file mode 100644 index 00000000000..bba243307b9 --- /dev/null +++ b/infra/feast-operator/config/crd/kustomization.yaml @@ -0,0 +1,6 @@ +# This kustomization.yaml is not intended to be run by itself, +# since it depends on service name and namespace that are out of this kustomize package. +# It should be run by config/default +resources: +- bases/charts.feast.dev_feastfeatureservers.yaml +#+kubebuilder:scaffold:crdkustomizeresource diff --git a/infra/feast-operator/config/default/kustomization.yaml b/infra/feast-operator/config/default/kustomization.yaml new file mode 100644 index 00000000000..6cd524d5199 --- /dev/null +++ b/infra/feast-operator/config/default/kustomization.yaml @@ -0,0 +1,20 @@ +# Adds namespace to all resources. +namespace: feast-operator-system + +# Value of this field is prepended to the +# names of all resources, e.g. a deployment named +# "wordpress" becomes "alices-wordpress". +# Note that it should also match with the prefix (text before '-') of the namespace +# field above. +namePrefix: feast-operator- + +# Labels to add to all resources and selectors. +#labels: +#- includeSelectors: true +# pairs: +# someName: someValue + +resources: +- ../crd +- ../rbac +- ../manager diff --git a/infra/feast-operator/config/manager/kustomization.yaml b/infra/feast-operator/config/manager/kustomization.yaml new file mode 100644 index 00000000000..2da26f66524 --- /dev/null +++ b/infra/feast-operator/config/manager/kustomization.yaml @@ -0,0 +1,8 @@ +resources: +- manager.yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +images: +- name: controller + newName: docker.io/feastdev/feast-operator + newTag: 0.37.1 diff --git a/infra/feast-operator/config/manager/manager.yaml b/infra/feast-operator/config/manager/manager.yaml new file mode 100644 index 00000000000..d65e8a78902 --- /dev/null +++ b/infra/feast-operator/config/manager/manager.yaml @@ -0,0 +1,101 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + control-plane: controller-manager + app.kubernetes.io/name: namespace + app.kubernetes.io/instance: system + app.kubernetes.io/component: manager + app.kubernetes.io/created-by: feast-operator + app.kubernetes.io/part-of: feast-operator + app.kubernetes.io/managed-by: kustomize + name: system +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system + labels: + control-plane: controller-manager + app.kubernetes.io/name: deployment + app.kubernetes.io/instance: controller-manager + app.kubernetes.io/component: manager + app.kubernetes.io/created-by: feast-operator + app.kubernetes.io/part-of: feast-operator + app.kubernetes.io/managed-by: kustomize +spec: + selector: + matchLabels: + control-plane: controller-manager + replicas: 1 + template: + metadata: + annotations: + kubectl.kubernetes.io/default-container: manager + labels: + control-plane: controller-manager + spec: + # TODO(user): Uncomment the following code to configure the nodeAffinity expression + # according to the platforms which are supported by your solution. + # It is considered best practice to support multiple architectures. You can + # build your manager image using the makefile target docker-buildx. + # affinity: + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: kubernetes.io/arch + # operator: In + # values: + # - amd64 + # - arm64 + # - ppc64le + # - s390x + # - key: kubernetes.io/os + # operator: In + # values: + # - linux + securityContext: + runAsNonRoot: true + # TODO(user): For common cases that do not require escalating privileges + # it is recommended to ensure that all your Pods/Containers are restrictive. + # More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted + # Please uncomment the following code if your project does NOT have to work on old Kubernetes + # versions < 1.19 or on vendors versions which do NOT support this field by default (i.e. Openshift < 4.11 ). + # seccompProfile: + # type: RuntimeDefault + containers: + - args: + - --leader-elect + - --leader-election-id=feast-operator + image: controller:latest + name: manager + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - "ALL" + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + # TODO(user): Configure the resources accordingly based on the project requirements. + # More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + resources: + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 10m + memory: 64Mi + serviceAccountName: controller-manager + terminationGracePeriodSeconds: 10 diff --git a/infra/feast-operator/config/manifests/kustomization.yaml b/infra/feast-operator/config/manifests/kustomization.yaml new file mode 100644 index 00000000000..392c30f6b6f --- /dev/null +++ b/infra/feast-operator/config/manifests/kustomization.yaml @@ -0,0 +1,7 @@ +# These resources constitute the fully configured set of manifests +# used to generate the 'manifests/' directory in a bundle. +resources: +- bases/feast-operator.clusterserviceversion.yaml +- ../default +- ../samples +- ../scorecard diff --git a/infra/feast-operator/config/rbac/auth_proxy_client_clusterrole.yaml b/infra/feast-operator/config/rbac/auth_proxy_client_clusterrole.yaml new file mode 100644 index 00000000000..c9ec144e9e4 --- /dev/null +++ b/infra/feast-operator/config/rbac/auth_proxy_client_clusterrole.yaml @@ -0,0 +1,16 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: metrics-reader + app.kubernetes.io/component: kube-rbac-proxy + app.kubernetes.io/created-by: feast-operator + app.kubernetes.io/part-of: feast-operator + app.kubernetes.io/managed-by: kustomize + name: metrics-reader +rules: +- nonResourceURLs: + - "/metrics" + verbs: + - get diff --git a/infra/feast-operator/config/rbac/auth_proxy_role.yaml b/infra/feast-operator/config/rbac/auth_proxy_role.yaml new file mode 100644 index 00000000000..98fe4b2f847 --- /dev/null +++ b/infra/feast-operator/config/rbac/auth_proxy_role.yaml @@ -0,0 +1,24 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: proxy-role + app.kubernetes.io/component: kube-rbac-proxy + app.kubernetes.io/created-by: feast-operator + app.kubernetes.io/part-of: feast-operator + app.kubernetes.io/managed-by: kustomize + name: proxy-role +rules: +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create diff --git a/infra/feast-operator/config/rbac/auth_proxy_role_binding.yaml b/infra/feast-operator/config/rbac/auth_proxy_role_binding.yaml new file mode 100644 index 00000000000..d181fb9a718 --- /dev/null +++ b/infra/feast-operator/config/rbac/auth_proxy_role_binding.yaml @@ -0,0 +1,19 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/name: clusterrolebinding + app.kubernetes.io/instance: proxy-rolebinding + app.kubernetes.io/component: kube-rbac-proxy + app.kubernetes.io/created-by: feast-operator + app.kubernetes.io/part-of: feast-operator + app.kubernetes.io/managed-by: kustomize + name: proxy-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: proxy-role +subjects: +- kind: ServiceAccount + name: controller-manager + namespace: system diff --git a/infra/feast-operator/config/rbac/auth_proxy_service.yaml b/infra/feast-operator/config/rbac/auth_proxy_service.yaml new file mode 100644 index 00000000000..e52232ad9b7 --- /dev/null +++ b/infra/feast-operator/config/rbac/auth_proxy_service.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + control-plane: controller-manager + app.kubernetes.io/name: service + app.kubernetes.io/instance: controller-manager-metrics-service + app.kubernetes.io/component: kube-rbac-proxy + app.kubernetes.io/created-by: feast-operator + app.kubernetes.io/part-of: feast-operator + app.kubernetes.io/managed-by: kustomize + name: controller-manager-metrics-service + namespace: system +spec: + ports: + - name: https + port: 8443 + protocol: TCP + targetPort: https + selector: + control-plane: controller-manager diff --git a/infra/feast-operator/config/rbac/feastfeatureserver_editor_role.yaml b/infra/feast-operator/config/rbac/feastfeatureserver_editor_role.yaml new file mode 100644 index 00000000000..f03ac20fddc --- /dev/null +++ b/infra/feast-operator/config/rbac/feastfeatureserver_editor_role.yaml @@ -0,0 +1,39 @@ +# permissions for end users to edit feastfeatureservers. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: feastfeatureserver-editor-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: feast-operator + app.kubernetes.io/part-of: feast-operator + app.kubernetes.io/managed-by: kustomize + name: feastfeatureserver-editor-role +rules: +- apiGroups: + - charts.feast.dev + resources: + - feastfeatureservers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - charts.feast.dev + resources: + - feastfeatureservers/finalizers + verbs: + - update +- apiGroups: + - charts.feast.dev + resources: + - feastfeatureservers/status + verbs: + - get + - patch + - update diff --git a/infra/feast-operator/config/rbac/feastfeatureserver_editor_rolebinding.yaml b/infra/feast-operator/config/rbac/feastfeatureserver_editor_rolebinding.yaml new file mode 100644 index 00000000000..054eb5a1a20 --- /dev/null +++ b/infra/feast-operator/config/rbac/feastfeatureserver_editor_rolebinding.yaml @@ -0,0 +1,19 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: feastfeatureserver-editor-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: feast-operator + app.kubernetes.io/part-of: feast-operator + app.kubernetes.io/managed-by: kustomize + name: feastfeatureserver-editor-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: feastfeatureserver-editor-role +subjects: +- kind: ServiceAccount + name: controller-manager + namespace: system diff --git a/infra/feast-operator/config/rbac/kustomization.yaml b/infra/feast-operator/config/rbac/kustomization.yaml new file mode 100644 index 00000000000..61f45e26096 --- /dev/null +++ b/infra/feast-operator/config/rbac/kustomization.yaml @@ -0,0 +1,20 @@ +resources: +# All RBAC will be applied under this service account in +# the deployment namespace. You may comment out this resource +# if your manager will use a service account that exists at +# runtime. Be sure to update RoleBinding and ClusterRoleBinding +# subjects if changing service account names. +- service_account.yaml +- role.yaml +- role_binding.yaml +- leader_election_role.yaml +- leader_election_role_binding.yaml +- feastfeatureserver_editor_role.yaml +- feastfeatureserver_editor_rolebinding.yaml +# Comment the following 4 lines if you want to disable +# the auth proxy (https://github.com/brancz/kube-rbac-proxy) +# which protects your /metrics endpoint. +- auth_proxy_service.yaml +- auth_proxy_role.yaml +- auth_proxy_role_binding.yaml +- auth_proxy_client_clusterrole.yaml diff --git a/infra/feast-operator/config/rbac/leader_election_role.yaml b/infra/feast-operator/config/rbac/leader_election_role.yaml new file mode 100644 index 00000000000..0adc316dd39 --- /dev/null +++ b/infra/feast-operator/config/rbac/leader_election_role.yaml @@ -0,0 +1,44 @@ +# permissions to do leader election. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/name: role + app.kubernetes.io/instance: leader-election-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: feast-operator + app.kubernetes.io/part-of: feast-operator + app.kubernetes.io/managed-by: kustomize + name: leader-election-role +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch diff --git a/infra/feast-operator/config/rbac/leader_election_role_binding.yaml b/infra/feast-operator/config/rbac/leader_election_role_binding.yaml new file mode 100644 index 00000000000..f745675c0e7 --- /dev/null +++ b/infra/feast-operator/config/rbac/leader_election_role_binding.yaml @@ -0,0 +1,19 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/name: rolebinding + app.kubernetes.io/instance: leader-election-rolebinding + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: feast-operator + app.kubernetes.io/part-of: feast-operator + app.kubernetes.io/managed-by: kustomize + name: leader-election-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: leader-election-role +subjects: +- kind: ServiceAccount + name: controller-manager + namespace: system diff --git a/infra/feast-operator/config/rbac/role.yaml b/infra/feast-operator/config/rbac/role.yaml new file mode 100644 index 00000000000..2469689484e --- /dev/null +++ b/infra/feast-operator/config/rbac/role.yaml @@ -0,0 +1,30 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: manager-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: feast-operator + app.kubernetes.io/part-of: feast-operator + app.kubernetes.io/managed-by: kustomize + name: manager-role +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list", "watch"] +- apiGroups: + - "" + - apps + resources: + - deployments + - secrets + - services + verbs: + - create + - delete + - get + - list + - patch + - update + - watch diff --git a/infra/feast-operator/config/rbac/role_binding.yaml b/infra/feast-operator/config/rbac/role_binding.yaml new file mode 100644 index 00000000000..3359e911695 --- /dev/null +++ b/infra/feast-operator/config/rbac/role_binding.yaml @@ -0,0 +1,19 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/name: clusterrolebinding + app.kubernetes.io/instance: manager-rolebinding + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: feast-operator + app.kubernetes.io/part-of: feast-operator + app.kubernetes.io/managed-by: kustomize + name: manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: manager-role +subjects: +- kind: ServiceAccount + name: controller-manager + namespace: system diff --git a/infra/feast-operator/config/rbac/service_account.yaml b/infra/feast-operator/config/rbac/service_account.yaml new file mode 100644 index 00000000000..7ba6f27c603 --- /dev/null +++ b/infra/feast-operator/config/rbac/service_account.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/name: serviceaccount + app.kubernetes.io/instance: controller-manager-sa + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: feast-operator + app.kubernetes.io/part-of: feast-operator + app.kubernetes.io/managed-by: kustomize + name: controller-manager + namespace: system diff --git a/infra/feast-operator/config/samples/charts_v1alpha1_feastfeatureserver.yaml b/infra/feast-operator/config/samples/charts_v1alpha1_feastfeatureserver.yaml new file mode 100644 index 00000000000..44b8b61af56 --- /dev/null +++ b/infra/feast-operator/config/samples/charts_v1alpha1_feastfeatureserver.yaml @@ -0,0 +1,29 @@ +apiVersion: charts.feast.dev/v1alpha1 +kind: FeastFeatureServer +metadata: + name: feastfeatureserver-sample +spec: + # Default values copied from helm-charts/feast-feature-server/values.yaml + affinity: {} + # base64 encoding of `sdk/python/feast/templates/local/feature_repo/feature_store.yaml` + feature_store_yaml_base64: "cHJvamVjdDogbXlfcHJvamVjdAojIEJ5IGRlZmF1bHQsIHRoZSByZWdpc3RyeSBpcyBhIGZpbGUgKGJ1dCBjYW4gYmUgdHVybmVkIGludG8gYSBtb3JlIHNjYWxhYmxlIFNRTC1iYWNrZWQgcmVnaXN0cnkpCnJlZ2lzdHJ5OiBkYXRhL3JlZ2lzdHJ5LmRiCiMgVGhlIHByb3ZpZGVyIHByaW1hcmlseSBzcGVjaWZpZXMgZGVmYXVsdCBvZmZsaW5lIC8gb25saW5lIHN0b3JlcyAmIHN0b3JpbmcgdGhlIHJlZ2lzdHJ5IGluIGEgZ2l2ZW4gY2xvdWQKcHJvdmlkZXI6IGxvY2FsCm9ubGluZV9zdG9yZToKICAgIHR5cGU6IHNxbGl0ZQogICAgcGF0aDogZGF0YS9vbmxpbmVfc3RvcmUuZGIKZW50aXR5X2tleV9zZXJpYWxpemF0aW9uX3ZlcnNpb246IDIK" + fullnameOverride: "" + image: {} + imagePullSecrets: [] + livenessProbe: + initialDelaySeconds: 30 + periodSeconds: 30 + nameOverride: "" + nodeSelector: {} + podAnnotations: {} + podSecurityContext: {} + readinessProbe: + initialDelaySeconds: 20 + periodSeconds: 10 + replicaCount: 1 + resources: {} + securityContext: {} + service: + port: 80 + type: ClusterIP + tolerations: [] diff --git a/infra/feast-operator/config/samples/kustomization.yaml b/infra/feast-operator/config/samples/kustomization.yaml new file mode 100644 index 00000000000..8a8cf497ead --- /dev/null +++ b/infra/feast-operator/config/samples/kustomization.yaml @@ -0,0 +1,4 @@ +## Append samples of your project ## +resources: +- charts_v1alpha1_feastfeatureserver.yaml +#+kubebuilder:scaffold:manifestskustomizesamples diff --git a/infra/feast-operator/config/scorecard/bases/config.yaml b/infra/feast-operator/config/scorecard/bases/config.yaml new file mode 100644 index 00000000000..c77047841ed --- /dev/null +++ b/infra/feast-operator/config/scorecard/bases/config.yaml @@ -0,0 +1,7 @@ +apiVersion: scorecard.operatorframework.io/v1alpha3 +kind: Configuration +metadata: + name: config +stages: +- parallel: true + tests: [] diff --git a/infra/feast-operator/config/scorecard/kustomization.yaml b/infra/feast-operator/config/scorecard/kustomization.yaml new file mode 100644 index 00000000000..50cd2d084eb --- /dev/null +++ b/infra/feast-operator/config/scorecard/kustomization.yaml @@ -0,0 +1,16 @@ +resources: +- bases/config.yaml +patchesJson6902: +- path: patches/basic.config.yaml + target: + group: scorecard.operatorframework.io + version: v1alpha3 + kind: Configuration + name: config +- path: patches/olm.config.yaml + target: + group: scorecard.operatorframework.io + version: v1alpha3 + kind: Configuration + name: config +#+kubebuilder:scaffold:patchesJson6902 diff --git a/infra/feast-operator/config/scorecard/patches/basic.config.yaml b/infra/feast-operator/config/scorecard/patches/basic.config.yaml new file mode 100644 index 00000000000..78ad61a41bd --- /dev/null +++ b/infra/feast-operator/config/scorecard/patches/basic.config.yaml @@ -0,0 +1,10 @@ +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - basic-check-spec + image: quay.io/operator-framework/scorecard-test:v1.34.1 + labels: + suite: basic + test: basic-check-spec-test diff --git a/infra/feast-operator/config/scorecard/patches/olm.config.yaml b/infra/feast-operator/config/scorecard/patches/olm.config.yaml new file mode 100644 index 00000000000..69dda63f2eb --- /dev/null +++ b/infra/feast-operator/config/scorecard/patches/olm.config.yaml @@ -0,0 +1,50 @@ +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-bundle-validation + image: quay.io/operator-framework/scorecard-test:v1.34.1 + labels: + suite: olm + test: olm-bundle-validation-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-crds-have-validation + image: quay.io/operator-framework/scorecard-test:v1.34.1 + labels: + suite: olm + test: olm-crds-have-validation-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-crds-have-resources + image: quay.io/operator-framework/scorecard-test:v1.34.1 + labels: + suite: olm + test: olm-crds-have-resources-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-spec-descriptors + image: quay.io/operator-framework/scorecard-test:v1.34.1 + labels: + suite: olm + test: olm-spec-descriptors-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-status-descriptors + image: quay.io/operator-framework/scorecard-test:v1.34.1 + labels: + suite: olm + test: olm-status-descriptors-test diff --git a/infra/feast-operator/helm-charts/feast-feature-server b/infra/feast-operator/helm-charts/feast-feature-server new file mode 120000 index 00000000000..e432d2cba69 --- /dev/null +++ b/infra/feast-operator/helm-charts/feast-feature-server @@ -0,0 +1 @@ +../../charts/feast-feature-server \ No newline at end of file diff --git a/infra/feast-operator/watches.yaml b/infra/feast-operator/watches.yaml new file mode 100644 index 00000000000..bb400cb90d6 --- /dev/null +++ b/infra/feast-operator/watches.yaml @@ -0,0 +1,6 @@ +# Use the 'create api' subcommand to add watches to this file. +- group: charts.feast.dev + version: v1alpha1 + kind: FeastFeatureServer + chart: helm-charts/feast-feature-server +#+kubebuilder:scaffold:watch diff --git a/infra/scripts/release/files_to_bump.txt b/infra/scripts/release/files_to_bump.txt index 61a70ac6b3c..505ef87b243 100644 --- a/infra/scripts/release/files_to_bump.txt +++ b/infra/scripts/release/files_to_bump.txt @@ -10,5 +10,7 @@ infra/charts/feast/README.md 11 68 69 infra/charts/feast-feature-server/Chart.yaml 5 infra/charts/feast-feature-server/README.md 3 infra/charts/feast-feature-server/values.yaml 12 +infra/feast-operator/Makefile 6 +infra/feast-operator/config/manager/kustomization.yaml 8 java/pom.xml 38 ui/package.json 3