resolve feedback

Signed-off-by: Tim Ramlot <42113979+inteon@users.noreply.github.com>
This commit is contained in:
Tim Ramlot 2023-04-28 13:50:26 +02:00
parent 29e22e3900
commit 349aaf666b
No known key found for this signature in database
GPG Key ID: 47428728E0C2878D
11 changed files with 124 additions and 39 deletions

View File

@ -10,7 +10,6 @@ require (
github.com/spf13/pflag v1.0.5
golang.org/x/sync v0.1.0
k8s.io/apimachinery v0.26.3
k8s.io/apiserver v0.26.3
k8s.io/client-go v0.26.3
k8s.io/utils v0.0.0-20230313181309-38a27ef9d749
)
@ -142,6 +141,7 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.26.3 // indirect
k8s.io/apiextensions-apiserver v0.26.3 // indirect
k8s.io/apiserver v0.26.3 // indirect
k8s.io/component-base v0.26.3 // indirect
k8s.io/klog/v2 v2.90.1 // indirect
k8s.io/kube-aggregator v0.26.3 // indirect

View File

@ -30,16 +30,21 @@ import (
var cfg = framework.DefaultConfig
var isPrimary = false
// isGinkgoProcessNumberOne is true if this is the first ginkgo process to run.
// Only the first ginkgo process will run the global addon Setup, Provision &
// Deprovision code.
// All other ginkgo processes will only run the global addon Setup code using
// the data transferred from the Setup function on the first ginkgo process.
var isGinkgoProcessNumberOne = false
var _ = ginkgo.SynchronizedBeforeSuite(func() []byte {
addon.InitGlobals(cfg)
isPrimary = true
isGinkgoProcessNumberOne = true
// We first setup the global addons, but do not provision them yet.
// This is because we need to transfer the data from the primary
// node to the other nodes.
// This is because we need to transfer the data from ginkgo process #1
// to the other ginkgo processes.
toBeTransferred, err := addon.SetupGlobalsPrimary(cfg)
if err != nil {
framework.Failf("Error provisioning global addons: %v", err)
@ -52,22 +57,22 @@ var _ = ginkgo.SynchronizedBeforeSuite(func() []byte {
return encodedData
}, func(encodedData []byte) {
transferredData := []interface{}{}
transferredData := []addon.AddonTransferableData{}
err := json.Unmarshal(encodedData, &transferredData)
if err != nil {
framework.Failf("Error decoding global addon data: %v", err)
}
if isPrimary {
// For the primary node, we need to run ProvisionGlobals to
if isGinkgoProcessNumberOne {
// For ginkgo process #1, we need to run ProvisionGlobals to
// actually provision the global addons.
err = addon.ProvisionGlobals(cfg)
if err != nil {
framework.Failf("Error configuring global addons: %v", err)
}
} else {
// For non-primary nodes, we need to run Setup with the data
// transferred from the primary node.
// For gingko process #2 and above, we need to run Setup with
// the Setup data returned by ginkgo process #1.
addon.InitGlobals(cfg)
err := addon.SetupGlobalsNonPrimary(cfg, transferredData)
@ -78,8 +83,8 @@ var _ = ginkgo.SynchronizedBeforeSuite(func() []byte {
})
var _ = ginkgo.SynchronizedAfterSuite(func() {
// Reset the isPrimary flag to false for the next run (when --repeat flag is used)
isPrimary = false
// Reset the isGinkgoProcessNumberOne flag to false for the next run (when --repeat flag is used)
isGinkgoProcessNumberOne = false
}, func() {
ginkgo.By("Retrieving logs for global addons")
globalLogs, err := addon.GlobalLogs()

View File

@ -22,6 +22,7 @@ import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"github.com/cert-manager/cert-manager/e2e-tests/framework/addon/internal"
"github.com/cert-manager/cert-manager/e2e-tests/framework/config"
"github.com/cert-manager/cert-manager/e2e-tests/framework/helper"
"github.com/cert-manager/cert-manager/e2e-tests/framework/util"
@ -34,6 +35,8 @@ type Base struct {
details *Details
}
var _ internal.Addon = &Base{}
// Details return the details about the certmanager instance deployed
type Details struct {
// Config is exposed here to make it easier for upstream consumers to access
@ -53,7 +56,7 @@ func (d *Details) Helper() *helper.Helper {
}
}
func (b *Base) Setup(c *config.Config, _ ...interface{}) (interface{}, error) {
func (b *Base) Setup(c *config.Config, _ ...internal.AddonTransferableData) (internal.AddonTransferableData, error) {
kubeConfig, err := util.LoadConfig(c.KubeConfig, c.KubeContext)
if err != nil {
return nil, err

View File

@ -29,6 +29,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/cert-manager/cert-manager/e2e-tests/framework/addon/base"
"github.com/cert-manager/cert-manager/e2e-tests/framework/addon/internal"
"github.com/cert-manager/cert-manager/e2e-tests/framework/config"
)
@ -74,6 +75,8 @@ type Chart struct {
Repo Repo
}
var _ internal.Addon = &Chart{}
type Repo struct {
// name of the repository
Name string
@ -97,7 +100,7 @@ type Details struct {
Namespace string
}
func (c *Chart) Setup(cfg *config.Config, _ ...interface{}) (interface{}, error) {
func (c *Chart) Setup(cfg *config.Config, _ ...internal.AddonTransferableData) (internal.AddonTransferableData, error) {
var err error
c.config = cfg

View File

@ -22,17 +22,14 @@ import (
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"github.com/cert-manager/cert-manager/e2e-tests/framework/addon/base"
"github.com/cert-manager/cert-manager/e2e-tests/framework/addon/internal"
"github.com/cert-manager/cert-manager/e2e-tests/framework/addon/vault"
"github.com/cert-manager/cert-manager/e2e-tests/framework/config"
"github.com/cert-manager/cert-manager/e2e-tests/framework/log"
)
type Addon interface {
Setup(*config.Config, ...interface{}) (interface{}, error)
Provision() error
Deprovision() error
SupportsGlobal() bool
}
type Addon = internal.Addon
type AddonTransferableData = internal.AddonTransferableData
// This file is used to define global shared addon instances for the e2e suite.
// We have to define these somewhere that can be imported by the framework and
@ -75,11 +72,14 @@ func InitGlobals(cfg *config.Config) {
}
// SetupGlobals setups all of the global addons.
// This should be called by the test suite entrypoint in a SynchronizedBeforeSuite
// block to ensure it is run once per suite (only on ginkgo process #1).
func SetupGlobalsPrimary(cfg *config.Config) ([]interface{}, error) {
toBeTransferred := make([]interface{}, len(allAddons))
for idx, g := range allAddons {
// The primary ginkgo process is the process with index 1.
// This function should be called by the test suite entrypoint in a SynchronizedBeforeSuite
// block to ensure it is run only on ginkgo process #1. It has to be run before
// any other ginkgo processes are started, because the return value of this function
// has to be transferred to the other ginkgo processes.
func SetupGlobalsPrimary(cfg *config.Config) ([]AddonTransferableData, error) {
toBeTransferred := make([]AddonTransferableData, len(allAddons))
for addonIdx, g := range allAddons {
data, err := g.Setup(cfg)
if err != nil {
return nil, err
@ -87,14 +87,22 @@ func SetupGlobalsPrimary(cfg *config.Config) ([]interface{}, error) {
if !g.SupportsGlobal() {
return nil, fmt.Errorf("requested global plugin does not support shared mode with current configuration")
}
toBeTransferred[idx] = data
toBeTransferred[addonIdx] = data
}
return toBeTransferred, nil
}
func SetupGlobalsNonPrimary(cfg *config.Config, transferred []interface{}) error {
for idx, g := range allAddons {
_, err := g.Setup(cfg, transferred[idx])
// SetupGlobalsNonPrimary setups all of the global addons.
// A non-primary ginkgo process is one that is not process #1 (process #2 and above).
// This function should be called by the test suite entrypoint in a SynchronizedBeforeSuite
// block on all ginkgo processes except #1. It has to be run after the primary process has
// run SetupGlobalsPrimary, so that the data returned by SetupGlobalsPrimary on process #1
// can be passed into this function. This function calls Setup on all of the non-primary
// processes (processes #2 and above) and passes in the AddonTransferableData data returned
// by the primary process.
func SetupGlobalsNonPrimary(cfg *config.Config, transferred []AddonTransferableData) error {
for addonIdx, g := range allAddons {
_, err := g.Setup(cfg, transferred[addonIdx])
if err != nil {
return err
}
@ -105,10 +113,14 @@ func SetupGlobalsNonPrimary(cfg *config.Config, transferred []interface{}) error
return nil
}
// SetupGlobals will call Setup on all of the global addons, but not provision.
// This should be called by the test suite entrypoint in a BeforeSuite block
// on all ginkgo nodes to ensure global instances are configured for each test
// runner.
// ProvisionGlobals calls Provision on all of the global addons.
// This should be called by the test suite in a SynchronizedBeforeSuite block
// after the Setup data has been transferred to all ginkgo processes, so that
// not all processes have to wait for the addons to be provisioned. Instead,
// the individual test has to check that the addon is provisioned (eg. by querying
// the API server for a resource that the addon creates or by checking that an
// HTTP endpoint is available)
// This function should be run only on ginkgo process #1.
func ProvisionGlobals(cfg *config.Config) error {
for _, g := range allAddons {
provisioned = append(provisioned, g)
@ -148,7 +160,8 @@ func GlobalLogs() (map[string]string, error) {
// DeprovisionGlobals deprovisions all of the global addons.
// This should be called by the test suite in a SynchronizedAfterSuite to ensure
// all global addons are cleaned up after a run.
// all global addons are cleaned up after a run. This should be run only on ginkgo
// process #1.
func DeprovisionGlobals(cfg *config.Config) error {
if !cfg.Cleanup {
log.Logf("Skipping deprovisioning as cleanup set to false.")

View File

@ -0,0 +1,50 @@
/*
Copyright 2020 The cert-manager 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 internal
import (
"github.com/cert-manager/cert-manager/e2e-tests/framework/config"
)
// Addon is an interface that defines a e2e addon.
type Addon interface {
// For non-global addons, this function is called on all ginkgo processes without
// any arguments. For global addons, this function is called on ginkgo process #1
// without any arguments, but the returned data is passed to the Setup function
// on all other ginkgo processes.
Setup(*config.Config, ...AddonTransferableData) (AddonTransferableData, error)
// For non-global addons, this function is called on all ginkgo processes. For global
// addons, this function is called only on ginkgo process #1.
Provision() error
// For non-global addons, this function is called on all ginkgo processes. For global
// addons, this function is called only on ginkgo process #1.
Deprovision() error
SupportsGlobal() bool
}
// TransferableData is data generated by a global addons' Setup function running on ginigo
// process #1 that should be copied to all other ginkgo processes. This is used to setup these
// processes with the same data as ginkgo process #1. The data has to be json serializable.
//
// eg. The process #1 Setup function generates a private key and certificate and transfers
// it to all other ginkgo processes. Process #1 then starts a shared server that trusts the
// certificate. All other ginkgo processes can authenticate to this server using the private
// key and certificate that was transferred to them.
type AddonTransferableData interface{}

View File

@ -39,6 +39,7 @@ import (
"github.com/cert-manager/cert-manager/e2e-tests/framework/addon/base"
"github.com/cert-manager/cert-manager/e2e-tests/framework/addon/chart"
"github.com/cert-manager/cert-manager/e2e-tests/framework/addon/internal"
"github.com/cert-manager/cert-manager/e2e-tests/framework/config"
)
@ -72,6 +73,8 @@ type Vault struct {
details Details
}
var _ internal.Addon = &Vault{}
type Details struct {
// URL is the url that can be used to connect to Vault inside the cluster
URL string
@ -98,7 +101,7 @@ func convertInterfaceToDetails(unmarshalled interface{}) (Details, error) {
return details, nil
}
func (v *Vault) Setup(cfg *config.Config, leaderData ...interface{}) (interface{}, error) {
func (v *Vault) Setup(cfg *config.Config, leaderData ...internal.AddonTransferableData) (internal.AddonTransferableData, error) {
if v.Name == "" {
return nil, fmt.Errorf("'Name' field must be set on Vault addon")
}

View File

@ -24,6 +24,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/cert-manager/cert-manager/e2e-tests/framework/addon/base"
"github.com/cert-manager/cert-manager/e2e-tests/framework/addon/internal"
"github.com/cert-manager/cert-manager/e2e-tests/framework/config"
"github.com/cert-manager/cert-manager/e2e-tests/framework/util/errors"
cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
@ -42,11 +43,13 @@ type VenafiCloud struct {
createdSecret *corev1.Secret
}
var _ internal.Addon = &VenafiCloud{}
type CloudDetails struct {
issuerTemplate cmapi.VenafiIssuer
}
func (v *VenafiCloud) Setup(cfg *config.Config, _ ...interface{}) (interface{}, error) {
func (v *VenafiCloud) Setup(cfg *config.Config, _ ...internal.AddonTransferableData) (internal.AddonTransferableData, error) {
v.config = cfg
if v.Base == nil {

View File

@ -24,6 +24,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/cert-manager/cert-manager/e2e-tests/framework/addon/base"
"github.com/cert-manager/cert-manager/e2e-tests/framework/addon/internal"
"github.com/cert-manager/cert-manager/e2e-tests/framework/config"
"github.com/cert-manager/cert-manager/e2e-tests/framework/util/errors"
cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
@ -42,11 +43,13 @@ type VenafiTPP struct {
createdSecret *corev1.Secret
}
var _ internal.Addon = &VenafiTPP{}
type TPPDetails struct {
issuerTemplate cmapi.VenafiIssuer
}
func (v *VenafiTPP) Setup(cfg *config.Config, _ ...interface{}) (interface{}, error) {
func (v *VenafiTPP) Setup(cfg *config.Config, _ ...internal.AddonTransferableData) (internal.AddonTransferableData, error) {
v.config = cfg
if v.Base == nil {

View File

@ -22,6 +22,7 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/cert-manager/cert-manager/e2e-tests/framework/addon"
"github.com/cert-manager/cert-manager/e2e-tests/framework/addon/base"
"github.com/cert-manager/cert-manager/e2e-tests/framework/config"
"github.com/cert-manager/cert-manager/e2e-tests/framework/util/errors"
@ -44,7 +45,7 @@ type Cloudflare struct {
createdSecret *corev1.Secret
}
func (b *Cloudflare) Setup(c *config.Config, _ ...interface{}) (interface{}, error) {
func (b *Cloudflare) Setup(c *config.Config, _ ...addon.AddonTransferableData) (addon.AddonTransferableData, error) {
if c.Suite.ACME.Cloudflare.APIKey == "" ||
c.Suite.ACME.Cloudflare.Domain == "" ||
c.Suite.ACME.Cloudflare.Email == "" {

View File

@ -17,6 +17,7 @@ limitations under the License.
package dnsproviders
import (
"github.com/cert-manager/cert-manager/e2e-tests/framework/addon"
"github.com/cert-manager/cert-manager/e2e-tests/framework/config"
cmacme "github.com/cert-manager/cert-manager/pkg/apis/acme/v1"
)
@ -26,7 +27,7 @@ type RFC2136 struct {
nameserver string
}
func (b *RFC2136) Setup(c *config.Config, _ ...interface{}) (interface{}, error) {
func (b *RFC2136) Setup(c *config.Config, _ ...addon.AddonTransferableData) (addon.AddonTransferableData, error) {
b.nameserver = c.Addons.ACMEServer.DNSServer
return nil, nil
}