Skip to content

Commit

Permalink
test
Browse files Browse the repository at this point in the history
  • Loading branch information
camilamacedo86 committed Sep 14, 2024
1 parent ec4fee8 commit ae337f6
Show file tree
Hide file tree
Showing 8 changed files with 485 additions and 270 deletions.
116 changes: 116 additions & 0 deletions test/e2e/common/kustomize.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
Copyright 2024 The Kubernetes Authors.
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 common

//nolint:lll
const CertManagerTarget = `#replacements:
# - source: # Add cert-manager annotation to ValidatingWebhookConfiguration, MutatingWebhookConfiguration and CRDs
# kind: Certificate
# group: cert-manager.io
# version: v1
# name: serving-cert # this name should match the one in certificate.yaml
# fieldPath: .metadata.namespace # namespace of the certificate CR
# targets:
# - select:
# kind: ValidatingWebhookConfiguration
# fieldPaths:
# - .metadata.annotations.[cert-manager.io/inject-ca-from]
# options:
# delimiter: '/'
# index: 0
# create: true
# - select:
# kind: MutatingWebhookConfiguration
# fieldPaths:
# - .metadata.annotations.[cert-manager.io/inject-ca-from]
# options:
# delimiter: '/'
# index: 0
# create: true
# - select:
# kind: CustomResourceDefinition
# fieldPaths:
# - .metadata.annotations.[cert-manager.io/inject-ca-from]
# options:
# delimiter: '/'
# index: 0
# create: true
# - source:
# kind: Certificate
# group: cert-manager.io
# version: v1
# name: serving-cert # this name should match the one in certificate.yaml
# fieldPath: .metadata.name
# targets:
# - select:
# kind: ValidatingWebhookConfiguration
# fieldPaths:
# - .metadata.annotations.[cert-manager.io/inject-ca-from]
# options:
# delimiter: '/'
# index: 1
# create: true
# - select:
# kind: MutatingWebhookConfiguration
# fieldPaths:
# - .metadata.annotations.[cert-manager.io/inject-ca-from]
# options:
# delimiter: '/'
# index: 1
# create: true
# - select:
# kind: CustomResourceDefinition
# fieldPaths:
# - .metadata.annotations.[cert-manager.io/inject-ca-from]
# options:
# delimiter: '/'
# index: 1
# create: true
# - source: # Add cert-manager annotation to the webhook Service
# kind: Service
# version: v1
# name: webhook-service
# fieldPath: .metadata.name # namespace of the service
# targets:
# - select:
# kind: Certificate
# group: cert-manager.io
# version: v1
# fieldPaths:
# - .spec.dnsNames.0
# - .spec.dnsNames.1
# options:
# delimiter: '.'
# index: 0
# create: true
# - source:
# kind: Service
# version: v1
# name: webhook-service
# fieldPath: .metadata.namespace # namespace of the service
# targets:
# - select:
# kind: Certificate
# group: cert-manager.io
# version: v1
# fieldPaths:
# - .spec.dnsNames.0
# - .spec.dnsNames.1
# options:
# delimiter: '.'
# index: 1
# create: true`
170 changes: 170 additions & 0 deletions test/e2e/common/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*
Copyright 2024 The Kubernetes Authors.
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 common

import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"time"

"sigs.k8s.io/kubebuilder/v4/test/e2e/utils"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

const (
tokenRequestRawString = `{"apiVersion": "authentication.k8s.io/v1", "kind": "TokenRequest"}`
)

// tokenRequest is a trimmed down version of the authentication.k8s.io/v1/TokenRequest Type
// that we want to use for extracting the token.
type tokenRequest struct {
Status struct {
Token string `json:"token"`
} `json:"status"`
}

// ServiceAccountToken provides a helper function that can provide you with a service account
// token that you can use to interact with the service. This function leverages the k8s'
// TokenRequest API in raw format in order to make it generic for all version of the k8s that
// is currently being supported in kubebuilder test infra.
// TokenRequest API returns the token in raw JWT format itself. There is no conversion required.
func ServiceAccountToken(kbc *utils.TestContext) (out string, err error) {
secretName := fmt.Sprintf("%s-token-request", kbc.Kubectl.ServiceAccount)
tokenRequestFile := filepath.Join(kbc.Dir, secretName)
err = os.WriteFile(tokenRequestFile, []byte(tokenRequestRawString), os.FileMode(0o755))
if err != nil {
return out, err
}
var rawJson string
Eventually(func() error {
// Output of this is already a valid JWT token. No need to covert this from base64 to string format
rawJson, err = kbc.Kubectl.Command(
"create",
"--raw", fmt.Sprintf(
"/api/v1/namespaces/%s/serviceaccounts/%s/token",
kbc.Kubectl.Namespace,
kbc.Kubectl.ServiceAccount,
),
"-f", tokenRequestFile,
)
if err != nil {
return err
}
var token tokenRequest
err = json.Unmarshal([]byte(rawJson), &token)
if err != nil {
return err
}
out = token.Status.Token
return nil
}, time.Minute, time.Second).Should(Succeed())

return out, err
}

func EnableMetricsCreateCurlPod(kbc *utils.TestContext) {
_, err := kbc.Kubectl.Command(
"create", "clusterrolebinding", fmt.Sprintf("metrics-%s", kbc.TestSuffix),
fmt.Sprintf("--clusterrole=e2e-%s-metrics-reader", kbc.TestSuffix),
fmt.Sprintf("--serviceaccount=%s:%s", kbc.Kubectl.Namespace, kbc.Kubectl.ServiceAccount))
ExpectWithOffset(1, err).NotTo(HaveOccurred())

token, err := ServiceAccountToken(kbc)
ExpectWithOffset(2, err).NotTo(HaveOccurred())
ExpectWithOffset(2, token).NotTo(BeEmpty())

By("validating that the controller-manager service is available")
_, err = kbc.Kubectl.Get(
true,
"service", fmt.Sprintf("e2e-%s-controller-manager-metrics-service", kbc.TestSuffix),
)
ExpectWithOffset(2, err).NotTo(HaveOccurred(), "Controller-manager service should exist")

By("ensuring the service endpoint is ready")
eventuallyCheckServiceEndpoint := func() error {
output, err := kbc.Kubectl.Get(
true,
"endpoints", fmt.Sprintf("e2e-%s-controller-manager-metrics-service", kbc.TestSuffix),
"-o", "jsonpath={.subsets[*].addresses[*].ip}",
)
if err != nil {
return err
}
if output == "" {
return fmt.Errorf("no endpoints found")
}
return nil
}
EventuallyWithOffset(2, eventuallyCheckServiceEndpoint, 2*time.Minute, time.Second).Should(Succeed(),
"Service endpoint should be ready")

By("creating a curl pod to access the metrics endpoint")
cmdOpts := CmdOptsToCreateCurlPod(kbc, token)
_, err = kbc.Kubectl.CommandInNamespace(cmdOpts...)
ExpectWithOffset(2, err).NotTo(HaveOccurred())

By("validating that the curl pod is running as expected")
verifyCurlUp := func() error {
status, err := kbc.Kubectl.Get(
true,
"pods", "curl", "-o", "jsonpath={.status.phase}")
ExpectWithOffset(3, err).NotTo(HaveOccurred())
if status != "Succeeded" {
return fmt.Errorf("curl pod in %s status", status)
}
return nil
}
EventuallyWithOffset(2, verifyCurlUp, 240*time.Second, time.Second).Should(Succeed())
}

// GetMetricsOutput return the metrics output from curl pod
func GetMetricsOutput(kbc *utils.TestContext) string {
By("getting logs from curl")
var metricsOutput string
getCurlLogs := func() string {
metricsOutput, err := kbc.Kubectl.Logs("curl")
ExpectWithOffset(3, err).NotTo(HaveOccurred())
return metricsOutput
}
EventuallyWithOffset(2, getCurlLogs, 10*time.Second, time.Second).Should(ContainSubstring("< HTTP/1.1 200 OK"))
return metricsOutput
}

// RemoveCurlPod created to collect the metrics
func RemoveCurlPod(kbc *utils.TestContext) {
By("cleaning up the curl pod")
_, err := kbc.Kubectl.Delete(true, "pods/curl")
ExpectWithOffset(3, err).NotTo(HaveOccurred())
}

// CmdOptsToCreateCurlPod return the options to create curl Pod
func CmdOptsToCreateCurlPod(kbc *utils.TestContext, token string) []string {
// nolint:lll
cmdOpts := []string{
"run", "curl",
"--restart=Never",
"--namespace", kbc.Kubectl.Namespace,
"--image=curlimages/curl:7.78.0",
"--",
"/bin/sh", "-c", fmt.Sprintf("curl -v -k -H 'Authorization: Bearer %s' https://e2e-%s-controller-manager-metrics-service.%s.svc.cluster.local:8443/metrics",
token, kbc.TestSuffix, kbc.Kubectl.Namespace),
}
return cmdOpts
}
14 changes: 7 additions & 7 deletions test/e2e/utils/webhooks.go → test/e2e/common/webhooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package utils
package common

import (
"fmt"
Expand Down Expand Up @@ -43,8 +43,8 @@ func ImplementWebhooks(filename, lowerKind string) error {
}

// implement defaulting webhook logic
replace := fmt.Sprintf(`if %s.Spec.Count == 0 {
%s.Spec.Count = 5
replace := fmt.Sprintf(`if %s.Spec.Size == 0 {
%s.Spec.Size = 5
}`, lowerKind, lowerKind)
str, err = util.EnsureExistAndReplace(
str,
Expand All @@ -59,17 +59,17 @@ func ImplementWebhooks(filename, lowerKind string) error {
str, err = util.EnsureExistAndReplace(
str,
"// TODO(user): fill in your validation logic upon object creation.",
fmt.Sprintf(`if %s.Spec.Count < 0 {
return nil, errors.New(".spec.count must >= 0")
fmt.Sprintf(`if %s.Spec.Size < 0 {
return nil, errors.New(".spec.size must >= 0")
}`, lowerKind))
if err != nil {
return err
}
str, err = util.EnsureExistAndReplace(
str,
"// TODO(user): fill in your validation logic upon object update.",
fmt.Sprintf(`if %s.Spec.Count < 0 {
return nil, errors.New(".spec.count must >= 0")
fmt.Sprintf(`if %s.Spec.Size < 0 {
return nil, errors.New(".spec.size must >= 0")
}`, lowerKind))
if err != nil {
return err
Expand Down
31 changes: 31 additions & 0 deletions test/e2e/deployimage/e2e_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ package deployimage

import (
"fmt"
"sigs.k8s.io/kubebuilder/v4/pkg/plugin/util"
"sigs.k8s.io/kubebuilder/v4/test/e2e/utils"
"testing"

. "github.com/onsi/ginkgo/v2"
Expand All @@ -30,3 +32,32 @@ func TestE2E(t *testing.T) {
_, _ = fmt.Fprintf(GinkgoWriter, "Starting kubebuilder suite\n")
RunSpecs(t, "Kubebuilder e2e suite")
}

// BeforeSuite run before any specs are run to perform the required actions for all e2e Go tests.
var _ = BeforeSuite(func() {
var err error

kbc, err := utils.NewTestContext(util.KubebuilderBinName, "GO111MODULE=on")
Expect(err).NotTo(HaveOccurred())
Expect(kbc.Prepare()).To(Succeed())

By("installing the cert-manager bundle")
Expect(kbc.InstallCertManager()).To(Succeed())

By("installing the Prometheus operator")
Expect(kbc.InstallPrometheusOperManager()).To(Succeed())
})

// AfterSuite run after all the specs have run, regardless of whether any tests have failed to ensures that
// all be cleaned up
var _ = AfterSuite(func() {
kbc, err := utils.NewTestContext(util.KubebuilderBinName, "GO111MODULE=on")
Expect(err).NotTo(HaveOccurred())
Expect(kbc.Prepare()).To(Succeed())

By("uninstalling the Prometheus manager bundle")
kbc.UninstallPrometheusOperManager()

By("uninstalling the cert-manager bundle")
kbc.UninstallCertManager()
})
Loading

0 comments on commit ae337f6

Please sign in to comment.