Skip to content

Commit

Permalink
Add github integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
nitisht committed Oct 6, 2023
1 parent 168960c commit aaf1b7f
Show file tree
Hide file tree
Showing 5 changed files with 385 additions and 0 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ require (
)

require (
github.com/MakeNowJust/heredoc v1.0.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
github.com/pkg/errors v0.9.1 // indirect
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
Expand Down
125 changes: 125 additions & 0 deletions internal/test/helpers/webhook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
Copyright 2023 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 helpers

import (
"fmt"
"net"
"os"
"path"
"path/filepath"
goruntime "runtime"
"strconv"
"time"

v1 "k8s.io/api/admissionregistration/v1"
"k8s.io/klog/v2"
utilyaml "sigs.k8s.io/cluster-api/util/yaml"
"sigs.k8s.io/controller-runtime/pkg/envtest"
)

const (
mutatingWebhookKind = "MutatingWebhookConfiguration"
validatingWebhookKind = "ValidatingWebhookConfiguration"
mutatingwebhook = "mutating-webhook-configuration"
validatingwebhook = "validating-webhook-configuration"
)

// Mutate the name of each webhook, because kubebuilder generates the same name for all controllers.
// In normal usage, kustomize will prefix the controller name, which we have to do manually here.
func appendWebhookConfiguration(configyamlFile []byte, tag string) ([]*v1.MutatingWebhookConfiguration, []*v1.ValidatingWebhookConfiguration, error) {
var mutatingWebhooks []*v1.MutatingWebhookConfiguration
var validatingWebhooks []*v1.ValidatingWebhookConfiguration
objs, err := utilyaml.ToUnstructured(configyamlFile)
if err != nil {
klog.Fatalf("failed to parse yaml")
}
// look for resources of kind MutatingWebhookConfiguration
for i := range objs {
o := objs[i]
if o.GetKind() == mutatingWebhookKind {
// update the name in metadata
if o.GetName() == mutatingwebhook {
var m v1.MutatingWebhookConfiguration
o.SetName(mutatingwebhook + "-" + tag)
if err := scheme.Convert(&o, &m, nil); err != nil {
return nil, nil, fmt.Errorf("failed to convert scheme: %w", err)
}
mutatingWebhooks = append(mutatingWebhooks, &m)
}
}
if o.GetKind() == validatingWebhookKind {
// update the name in metadata
if o.GetName() == validatingwebhook {
var v v1.ValidatingWebhookConfiguration
o.SetName(validatingwebhook + "-" + tag)
if err := scheme.Convert(&o, &v, nil); err != nil {
return nil, nil, fmt.Errorf("failed to convert scheme: %w", err)
}
validatingWebhooks = append(validatingWebhooks, &v)
}
}
}
return mutatingWebhooks, validatingWebhooks, nil
}

func initializeWebhookInEnvironment() {
// Get the root of the current file to use in CRD paths.
_, filename, _, _ := goruntime.Caller(0)
root := path.Join(path.Dir(filename), "..", "..", "..")
corepath := filepath.Join(root, "config", "webhook", "manifests.yaml")
configyamlFile, err := os.ReadFile(corepath) //#nosec
if err != nil {
klog.Fatalf("Failed to read core webhook configuration file: %v", err)
}
if err != nil {
klog.Fatalf("failed to parse yaml")
}
// append the webhook with suffix to avoid clashing webhooks. repeated for every webhook
mutatingWebhooks, validatingWebhooks, err := appendWebhookConfiguration(configyamlFile, "config")
if err != nil {
klog.Fatalf("Failed to append core controller webhook config: %v", err)
}

env.WebhookInstallOptions = envtest.WebhookInstallOptions{
MaxTime: 20 * time.Second,
PollInterval: time.Second,
ValidatingWebhooks: validatingWebhooks,
MutatingWebhooks: mutatingWebhooks,
}
}

// WaitForWebhooks waits for webhook port to be ready.
func (*TestEnvironment) WaitForWebhooks() {
port := env.WebhookInstallOptions.LocalServingPort

klog.V(2).Infof("Waiting for webhook port %d to be open prior to running tests", port)
timeout := 1 * time.Second
for {
time.Sleep(1 * time.Second)
conn, err := net.DialTimeout("tcp", net.JoinHostPort("127.0.0.1", strconv.Itoa(port)), timeout)
if err != nil {
klog.V(2).Infof("Webhook port is not ready, will retry in %v: %s", timeout, err)
continue
}
if err := conn.Close(); err != nil {
klog.Fatalf("failed to close connection: %s", err)
}
klog.V(2).Info("Webhook port is now open. Continuing with tests...")
return
}
}
72 changes: 72 additions & 0 deletions internal/test/integration/github/integration_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
Copyright 2023 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 github

import (
"testing"
"time"

"github.com/SovereignCloudStack/cluster-stack-operator/internal/controller"
"github.com/SovereignCloudStack/cluster-stack-operator/internal/test/helpers"
githubclient "github.com/SovereignCloudStack/cluster-stack-operator/pkg/github/client"
"github.com/SovereignCloudStack/cluster-stack-operator/pkg/kube"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
ctrl "sigs.k8s.io/controller-runtime"
controllerruntimecontroller "sigs.k8s.io/controller-runtime/pkg/controller"
)

const (
timeout = time.Second * 10
interval = 1000 * time.Millisecond
)

func TestControllers(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Controller Suite")
}

var (
ctx = ctrl.SetupSignalHandler()
testEnv *helpers.TestEnvironment
)

var _ = BeforeSuite(func() {
testEnv = helpers.NewTestEnvironment()
Expect((&controller.ClusterStackReconciler{
Client: testEnv.Manager.GetClient(),
GitHubClientFactory: githubclient.NewFactory(),
ReleaseDirectory: "/tmp/downloads",
}).SetupWithManager(ctx, testEnv.Manager, controllerruntimecontroller.Options{})).To(Succeed())
Expect((&controller.ClusterStackReleaseReconciler{
Client: testEnv.Manager.GetClient(),
RESTConfig: testEnv.Manager.GetConfig(),
KubeClientFactory: kube.NewFactory(),
GitHubClientFactory: githubclient.NewFactory(),
ReleaseDirectory: "/tmp/downloads",
}).SetupWithManager(ctx, testEnv.Manager, controllerruntimecontroller.Options{})).To(Succeed())

go func() {
defer GinkgoRecover()
Expect(testEnv.StartManager(ctx)).To(Succeed())
}()
<-testEnv.Manager.Elected()
// wait for webhook port to be open prior to running tests
testEnv.WaitForWebhooks()
})

var _ = AfterSuite(func() {
Expect(testEnv.Stop()).To(Succeed())
})
Loading

0 comments on commit aaf1b7f

Please sign in to comment.