Skip to content

Commit

Permalink
Merge branch 'master' into dependabot/github_actions/codecov/codecov-…
Browse files Browse the repository at this point in the history
…action-5
  • Loading branch information
fbm3307 authored Jan 2, 2025
2 parents 517f399 + 22cd84e commit 5c16316
Show file tree
Hide file tree
Showing 11 changed files with 387 additions and 74 deletions.
10 changes: 7 additions & 3 deletions OWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@
approvers:
- alexeykazakov
- MatousJobanek
- sbryzak
- xcoulon
- rajivnathan
- ranakan19
- mfrancisc
- fbm3307
- metlos
- rsoaresd

reviewers:
- alexeykazakov
- MatousJobanek
- sbryzak
- xcoulon
- rajivnathan
- ranakan19
- mfrancisc
- mfrancisc
- fbm3307
- metlos
- rsoaresd
6 changes: 3 additions & 3 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ image:https://goreportcard.com/badge/github.com/codeready-toolchain/member-opera
image:https://godoc.org/github.com/codeready-toolchain/member-operator?status.png[GoDoc,link="https://godoc.org/github.com/codeready-toolchain/member-operator"]
image:https://codecov.io/gh/codeready-toolchain/member-operator/branch/master/graph/badge.svg[Codecov.io,link="https://codecov.io/gh/codeready-toolchain/member-operator"]
image:https://github.com/codeready-toolchain/member-operator/actions/workflows/operator-cd.yml/badge.svg[Operator CD,link="https://github.com/codeready-toolchain/member-operator/actions/workflows/operator-cd.yml"]
image:https://quay.io/repository/codeready-toolchain/member-operator/status["Docker Repository on Quay", link="https://quay.io/repository/codeready-toolchain/member-operator"]
image:https://quay.io/repository/codeready-toolchain/member-operator/status["Image Repository on Quay", link="https://quay.io/repository/codeready-toolchain/member-operator"]

This is the CodeReady Toolchain Member Operator repository. It contains the OpenShift Operator that is deployed on the "member" cluster in the SaaS.

Expand Down Expand Up @@ -32,7 +32,7 @@ then the release has to be fixed manually. In such a case, please follow these s

1. Log in to quay.io using an account that has the write permissions in quay.io/codeready-toolchain/member-operator repo.
2. Checkout to the problematic (missing) commit that failed in the pipeline and that has to be manually released.
3. Run `make docker-push QUAY_NAMESPACE=codeready-toolchain`
3. Run `make podman-push QUAY_NAMESPACE=codeready-toolchain`
4. Run `make push-to-quay-staging QUAY_NAMESPACE=codeready-toolchain`


Expand Down Expand Up @@ -69,7 +69,7 @@ There are two Makefile targets that will execute the e2e tests:
* `make test-e2e-local` - this target doesn't clone anything, but it runs run e2e tests for both operators from the directory `../toolchain-e2e`. As deployment for `member-operator` it uses the current code that is in the local repository.

The tests executed within https://github.com/codeready-toolchain/toolchain-e2e[toolchain-e2e] repo will take care of creating all needed namespaces with random names (or see below for enforcing some specific namespace names).
It will also create all required CRDs, role and role bindings for the service accounts, build the Docker images for both operators and push them to the OpenShift container registry. Finally, it will deploy the operators and run the tests using the operator-sdk.
It will also create all required CRDs, role and role bindings for the service accounts, build the images for both operators and push them to the image registry. Finally, it will deploy the operators and run the tests.

NOTE: you can override the default namespace names where the end-to-end tests are going to be executed - eg.: `make test-e2e HOST_NS=my-host MEMBER_NS=my-member` file.

Expand Down
15 changes: 14 additions & 1 deletion cmd/webhook/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"crypto/tls"
"flag"
"fmt"
"net/http"
"os"
"os/signal"
Expand Down Expand Up @@ -106,28 +107,40 @@ func main() {
sspRequestValidator := &validatingwebhook.SSPRequestValidator{
Client: cl,
}
vmRequestValidator := &validatingwebhook.VMRequestValidator{
Client: cl,
}
mux := http.NewServeMux()

mux.HandleFunc("/mutate-users-pods", mutatingwebhook.HandleMutateUserPods)
mux.HandleFunc("/mutate-virtual-machines", mutatingwebhook.HandleMutateVirtualMachines)
mux.HandleFunc("/validate-users-rolebindings", rolebindingValidator.HandleValidate)
mux.HandleFunc("/validate-spacebindingrequests", spacebindingrequestValidator.HandleValidate)
mux.HandleFunc("/validate-ssprequests", sspRequestValidator.HandleValidate) // SSP is a CNV specific resource
mux.HandleFunc("/validate-vmrequests", vmRequestValidator.HandleValidate)

webhookServer := &http.Server{ //nolint:gosec //TODO: configure ReadHeaderTimeout (gosec G112)
Addr: ":8443",
Handler: mux,
TLSConfig: &tls.Config{
MinVersion: tls.VersionTLS12,
NextProtos: []string{"http/1.1"}, // disable HTTP/2 for now

GetCertificate: func(_ *tls.ClientHelloInfo) (*tls.Certificate, error) {
cert, err := tls.LoadX509KeyPair("/etc/webhook/certs/"+cert.ServerCert, "/etc/webhook/certs/"+cert.ServerKey)
if err != nil {
return nil, fmt.Errorf("could not load TLS certs: %w", err)
}
return &cert, err
},
},
}

setupLog.Info("Webhook server configured.")

go func() {
setupLog.Info("Listening...")
if err := webhookServer.ListenAndServeTLS("/etc/webhook/certs/"+cert.ServerCert, "/etc/webhook/certs/"+cert.ServerKey); err != nil {
if err := webhookServer.ListenAndServeTLS("", ""); err != nil {
setupLog.Error(err, "Listening and serving TLS failed")
os.Exit(1)
}
Expand Down
32 changes: 31 additions & 1 deletion deploy/webhook/member-operator-webhook.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ objects:
rules:
- operations: ["CREATE"]
apiGroups: ["kubevirt.io"]
apiVersions: ["v1"]
apiVersions: ["*"]
resources: ["virtualmachines"]
scope: "Namespaced"
sideEffects: None
Expand Down Expand Up @@ -251,6 +251,9 @@ objects:
namespaceSelector:
matchLabels:
toolchain.dev.openshift.com/provider: codeready-toolchain
# The users.virtualmachines.ssp.webhook.sandbox webhook validates SSP CRs,
# Specifically it blocks the creation/update of SSP resources by sandbox users because it should only be managed by the Virtualization operator
# The webhook code is available at member-operator/pkg/webhook/validatingwebhook/validate_ssp_request.go
- name: users.virtualmachines.ssp.webhook.sandbox
admissionReviewVersions:
- v1
Expand All @@ -275,6 +278,33 @@ objects:
namespaceSelector:
matchLabels:
toolchain.dev.openshift.com/provider: codeready-toolchain
# The users.virtualmachines.validating.webhook.sandbox webhook validates VirtualMachine CRs,
# Specifically it blocks the creation/update of VirtualMachine resources that have '.spec.RunStrategy' set because it interferes with the Idler.
# The webhook code is available at member-operator/pkg/webhook/validatingwebhook/validate_vm_request.go
- name: users.virtualmachines.validating.webhook.sandbox
admissionReviewVersions:
- v1
clientConfig:
caBundle: ${CA_BUNDLE}
service:
name: member-operator-webhook
namespace: ${NAMESPACE}
path: "/validate-vmrequests"
port: 443
matchPolicy: Equivalent
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["kubevirt.io"]
apiVersions: ["*"]
resources: ["virtualmachines"]
scope: "Namespaced"
sideEffects: None
timeoutSeconds: 5
reinvocationPolicy: Never
failurePolicy: Fail
namespaceSelector:
matchLabels:
toolchain.dev.openshift.com/provider: codeready-toolchain
parameters:
- name: NAMESPACE
value: 'toolchain-member-operator'
Expand Down
61 changes: 0 additions & 61 deletions make/docker.mk

This file was deleted.

27 changes: 27 additions & 0 deletions make/podman.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
QUAY_NAMESPACE ?= ${GO_PACKAGE_ORG_NAME}
TARGET_REGISTRY := quay.io
IMAGE_TAG ?= ${GIT_COMMIT_ID_SHORT}
IMAGE ?= ${TARGET_REGISTRY}/${QUAY_NAMESPACE}/${GO_PACKAGE_REPO_NAME}:${IMAGE_TAG}
QUAY_USERNAME ?= ${QUAY_NAMESPACE}
WEBHOOK_IMAGE ?= ${TARGET_REGISTRY}/${QUAY_NAMESPACE}/${GO_PACKAGE_REPO_NAME}-webhook:${IMAGE_TAG}
IMAGE_PLATFORM ?= linux/amd64

.PHONY: podman-image
## Build the binary image
podman-image: build
$(Q)podman build --platform ${IMAGE_PLATFORM} -f build/Dockerfile -t ${IMAGE} .
$(Q)podman build --platform ${IMAGE_PLATFORM} -f build/Dockerfile.webhook -t ${WEBHOOK_IMAGE} .

.PHONY: podman-push
## Push the binary image to quay.io registry
podman-push: check-namespace podman-image
$(Q)podman push ${IMAGE}
$(Q)podman push ${WEBHOOK_IMAGE}

.PHONY: check-namespace
check-namespace:
ifeq ($(QUAY_NAMESPACE),${GO_PACKAGE_ORG_NAME})
@echo "#################################################### WARNING ####################################################"
@echo you are going to push to $(QUAY_NAMESPACE) namespace, make sure you have set QUAY_NAMESPACE variable appropriately
@echo "#################################################################################################################"
endif
4 changes: 2 additions & 2 deletions pkg/webhook/deploy/deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,11 +223,11 @@ func deployment(namespace, sa string, image string) string {
}

func mutatingWebhookConfig(namespace, caBundle string) string {
return fmt.Sprintf(`{"apiVersion":"admissionregistration.k8s.io/v1","kind":"MutatingWebhookConfiguration","metadata":{"name":"member-operator-webhook-%[2]s","labels":{"app":"member-operator-webhook","toolchain.dev.openshift.com/provider":"codeready-toolchain"}},"webhooks":[{"name":"users.pods.webhook.sandbox","admissionReviewVersions":["v1"],"clientConfig":{"caBundle":"%[1]s","service":{"name":"member-operator-webhook","namespace":"%[2]s","path":"/mutate-users-pods","port":443}},"matchPolicy":"Equivalent","rules":[{"operations":["CREATE"],"apiGroups":[""],"apiVersions":["v1"],"resources":["pods"],"scope":"Namespaced"}],"sideEffects":"None","timeoutSeconds":5,"reinvocationPolicy":"Never","failurePolicy":"Ignore","namespaceSelector":{"matchLabels":{"toolchain.dev.openshift.com/provider":"codeready-toolchain"}}},{"name":"users.virtualmachines.webhook.sandbox","admissionReviewVersions":["v1"],"clientConfig":{"caBundle":"%[1]s","service":{"name":"member-operator-webhook","namespace":"%[2]s","path":"/mutate-virtual-machines","port":443}},"matchPolicy":"Equivalent","rules":[{"operations":["CREATE"],"apiGroups":["kubevirt.io"],"apiVersions":["v1"],"resources":["virtualmachines"],"scope":"Namespaced"}],"sideEffects":"None","timeoutSeconds":5,"reinvocationPolicy":"Never","failurePolicy":"Fail","namespaceSelector":{"matchLabels":{"toolchain.dev.openshift.com/provider":"codeready-toolchain"}}}]}`, caBundle, namespace)
return fmt.Sprintf(`{"apiVersion":"admissionregistration.k8s.io/v1","kind":"MutatingWebhookConfiguration","metadata":{"name":"member-operator-webhook-%[2]s","labels":{"app":"member-operator-webhook","toolchain.dev.openshift.com/provider":"codeready-toolchain"}},"webhooks":[{"name":"users.pods.webhook.sandbox","admissionReviewVersions":["v1"],"clientConfig":{"caBundle":"%[1]s","service":{"name":"member-operator-webhook","namespace":"%[2]s","path":"/mutate-users-pods","port":443}},"matchPolicy":"Equivalent","rules":[{"operations":["CREATE"],"apiGroups":[""],"apiVersions":["v1"],"resources":["pods"],"scope":"Namespaced"}],"sideEffects":"None","timeoutSeconds":5,"reinvocationPolicy":"Never","failurePolicy":"Ignore","namespaceSelector":{"matchLabels":{"toolchain.dev.openshift.com/provider":"codeready-toolchain"}}},{"name":"users.virtualmachines.webhook.sandbox","admissionReviewVersions":["v1"],"clientConfig":{"caBundle":"%[1]s","service":{"name":"member-operator-webhook","namespace":"%[2]s","path":"/mutate-virtual-machines","port":443}},"matchPolicy":"Equivalent","rules":[{"operations":["CREATE"],"apiGroups":["kubevirt.io"],"apiVersions":["*"],"resources":["virtualmachines"],"scope":"Namespaced"}],"sideEffects":"None","timeoutSeconds":5,"reinvocationPolicy":"Never","failurePolicy":"Fail","namespaceSelector":{"matchLabels":{"toolchain.dev.openshift.com/provider":"codeready-toolchain"}}}]}`, caBundle, namespace)
}

func validatingWebhookConfig(namespace, caBundle string) string {
return fmt.Sprintf(`{"apiVersion": "admissionregistration.k8s.io/v1","kind": "ValidatingWebhookConfiguration","metadata": {"labels": {"app": "member-operator-webhook","toolchain.dev.openshift.com/provider": "codeready-toolchain"},"name": "member-operator-validating-webhook-%[2]s"},"webhooks": [{"admissionReviewVersions": ["v1"],"clientConfig": {"caBundle": "%[1]s","service": {"name": "member-operator-webhook","namespace": "%[2]s","path": "/validate-users-rolebindings","port": 443}},"failurePolicy": "Ignore","matchPolicy": "Equivalent","name": "users.rolebindings.webhook.sandbox","namespaceSelector": {"matchLabels": {"toolchain.dev.openshift.com/provider": "codeready-toolchain"}},"reinvocationPolicy": "Never","rules": [{"apiGroups": ["rbac.authorization.k8s.io","authorization.openshift.io"],"apiVersions": ["v1"],"operations": ["CREATE","UPDATE"],"resources": ["rolebindings"],"scope": "Namespaced"}],"sideEffects": "None","timeoutSeconds": 5},{"admissionReviewVersions": ["v1"],"clientConfig": {"caBundle": "%[1]s","service": {"name": "member-operator-webhook","namespace": "%[2]s","path": "/validate-spacebindingrequests","port": 443}},"failurePolicy": "Fail","matchPolicy": "Equivalent","name": "users.spacebindingrequests.webhook.sandbox","namespaceSelector": {"matchLabels": {"toolchain.dev.openshift.com/provider": "codeready-toolchain"}},"reinvocationPolicy": "Never","rules": [{"apiGroups": ["toolchain.dev.openshift.com"],"apiVersions": ["v1alpha1"],"operations": ["CREATE","UPDATE"],"resources": ["spacebindingrequests"],"scope": "Namespaced"}],"sideEffects": "None","timeoutSeconds": 5},{"admissionReviewVersions": ["v1"],"clientConfig": {"caBundle": "%[1]s","service": {"name": "member-operator-webhook","namespace": "%[2]s","path": "/validate-ssprequests","port": 443}},"failurePolicy": "Fail","matchPolicy": "Equivalent","name": "users.virtualmachines.ssp.webhook.sandbox","namespaceSelector": {"matchLabels": {"toolchain.dev.openshift.com/provider": "codeready-toolchain"}},"reinvocationPolicy": "Never","rules": [{"apiGroups": ["ssp.kubevirt.io"],"apiVersions": ["*"],"operations": ["CREATE","UPDATE"],"resources": ["ssps"],"scope": "Namespaced"}],"sideEffects": "None","timeoutSeconds": 5}]}`, caBundle, namespace)
return fmt.Sprintf(`{"apiVersion": "admissionregistration.k8s.io/v1","kind": "ValidatingWebhookConfiguration","metadata": {"labels": {"app": "member-operator-webhook","toolchain.dev.openshift.com/provider": "codeready-toolchain"},"name": "member-operator-validating-webhook-%[2]s"},"webhooks": [{"admissionReviewVersions": ["v1"],"clientConfig": {"caBundle": "%[1]s","service": {"name": "member-operator-webhook","namespace": "%[2]s","path": "/validate-users-rolebindings","port": 443}},"failurePolicy": "Ignore","matchPolicy": "Equivalent","name": "users.rolebindings.webhook.sandbox","namespaceSelector": {"matchLabels": {"toolchain.dev.openshift.com/provider": "codeready-toolchain"}},"reinvocationPolicy": "Never","rules": [{"apiGroups": ["rbac.authorization.k8s.io","authorization.openshift.io"],"apiVersions": ["v1"],"operations": ["CREATE","UPDATE"],"resources": ["rolebindings"],"scope": "Namespaced"}],"sideEffects": "None","timeoutSeconds": 5},{"admissionReviewVersions": ["v1"],"clientConfig": {"caBundle": "%[1]s","service": {"name": "member-operator-webhook","namespace": "%[2]s","path": "/validate-spacebindingrequests","port": 443}},"failurePolicy": "Fail","matchPolicy": "Equivalent","name": "users.spacebindingrequests.webhook.sandbox","namespaceSelector": {"matchLabels": {"toolchain.dev.openshift.com/provider": "codeready-toolchain"}},"reinvocationPolicy": "Never","rules": [{"apiGroups": ["toolchain.dev.openshift.com"],"apiVersions": ["v1alpha1"],"operations": ["CREATE","UPDATE"],"resources": ["spacebindingrequests"],"scope": "Namespaced"}],"sideEffects": "None","timeoutSeconds": 5},{"admissionReviewVersions": ["v1"],"clientConfig": {"caBundle": "%[1]s","service": {"name": "member-operator-webhook","namespace": "%[2]s","path": "/validate-ssprequests","port": 443}},"failurePolicy": "Fail","matchPolicy": "Equivalent","name": "users.virtualmachines.ssp.webhook.sandbox","namespaceSelector": {"matchLabels": {"toolchain.dev.openshift.com/provider": "codeready-toolchain"}},"reinvocationPolicy": "Never","rules": [{"apiGroups": ["ssp.kubevirt.io"],"apiVersions": ["*"],"operations": ["CREATE","UPDATE"],"resources": ["ssps"],"scope": "Namespaced"}],"sideEffects": "None","timeoutSeconds": 5},{"admissionReviewVersions": ["v1"],"clientConfig": {"caBundle": "%[1]s","service": {"name": "member-operator-webhook","namespace": "%[2]s","path": "/validate-vmrequests","port": 443}},"failurePolicy": "Fail","matchPolicy": "Equivalent","name": "users.virtualmachines.validating.webhook.sandbox","namespaceSelector": {"matchLabels": {"toolchain.dev.openshift.com/provider": "codeready-toolchain"}},"reinvocationPolicy": "Never","rules": [{"apiGroups": ["kubevirt.io"],"apiVersions": ["*"],"operations": ["CREATE","UPDATE"],"resources": ["virtualmachines"],"scope": "Namespaced"}],"sideEffects": "None","timeoutSeconds": 5}]}`, caBundle, namespace)
}

func serviceAccount(namespace string) string {
Expand Down
4 changes: 2 additions & 2 deletions pkg/webhook/validatingwebhook/test/verify_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import (
func VerifyRequestBlocked(t *testing.T, response []byte, msg string, UID string) {
reviewResponse := toReviewResponse(t, response)
assert.False(t, reviewResponse.Allowed)
assert.NotEmpty(t, reviewResponse.Result)
assert.Contains(t, reviewResponse.Result.Message, msg)
assert.Equal(t, UID, string(reviewResponse.UID))
require.NotEmpty(t, reviewResponse.Result)
assert.Contains(t, reviewResponse.Result.Message, msg)
}

func VerifyRequestAllowed(t *testing.T, response []byte, UID string) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/webhook/validatingwebhook/validate_ssp_request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func TestValidateSSPAdmissionRequest(t *testing.T) {
t.Run("sandbox user trying to update a SSP resource is denied", func(t *testing.T) {
// given
v := newSSPRequestValidator(t, "johnsmith", true)
req := newCreateSSPAdmissionRequest(t, SSPAdmReviewTmplParams{"CREATE", "johnsmith"})
req := newCreateSSPAdmissionRequest(t, SSPAdmReviewTmplParams{"UPDATE", "johnsmith"})

// when
response := v.validate(context.TODO(), req)
Expand Down
Loading

0 comments on commit 5c16316

Please sign in to comment.