Merge pull request #4184 from inteon/kubectl_certmanager_install_tests

Add basic tests to kubectl cert-manager x install
This commit is contained in:
jetstack-bot
2021-07-23 16:16:19 +01:00
committed by GitHub
5 changed files with 302 additions and 5 deletions
+8 -3
View File
@@ -228,9 +228,14 @@ func (o *InstallOptions) runInstall(ctx context.Context) (*release.Release, erro
}
// Install chart
o.client.DryRun = false // Apply DryRun cli flags
o.client.ClientOnly = false // Perform install against cluster
o.client.Atomic = true // If part of the install fails, also undo other installed resources
o.client.DryRun = false // Apply DryRun cli flags
o.client.ClientOnly = false // Perform install against cluster
// 'Atomic=True' means that if part of the install fails, all resource installs are reverted;
// Helm supports 3 diffent combinations of the (Atomic, Wait) boolean couple:
// (False, False), (False, True) or (True, True)
// For simplicity, we want do not support Waiting without the Atomic option (False, True),
// this allows this cli to use a single --wait=(True|False) flag
o.client.Atomic = o.client.Wait
chartValues[installCRDsFlagName] = false // Do not render CRDs, as this might cause problems when uninstalling using helm
return o.client.Run(chart, chartValues)
+18 -2
View File
@@ -1,4 +1,4 @@
load("@io_bazel_rules_go//go:def.bzl", "go_test")
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_test(
name = "go_default_test",
@@ -9,6 +9,7 @@ go_test(
"ctl_status_certificate_test.go",
],
data = glob(["testdata/**"]),
embed = [":go_default_library"],
deps = [
"//cmd/ctl/pkg/convert:go_default_library",
"//cmd/ctl/pkg/create/certificaterequest:go_default_library",
@@ -42,7 +43,22 @@ filegroup(
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
srcs = [
":package-srcs",
"//test/integration/ctl/install_framework:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_library(
name = "go_default_library",
srcs = ["ctl_install.go"],
importpath = "github.com/jetstack/cert-manager/test/integration/ctl",
visibility = ["//visibility:public"],
deps = [
"//cmd/ctl/cmd:go_default_library",
"//test/integration/ctl/install_framework:go_default_library",
"@com_github_sergi_go_diff//diffmatchpatch:go_default_library",
],
)
+140
View File
@@ -0,0 +1,140 @@
/*
Copyright 2021 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 ctl
import (
"bytes"
"context"
"fmt"
"regexp"
"strings"
"testing"
"time"
"github.com/sergi/go-diff/diffmatchpatch"
"github.com/jetstack/cert-manager/cmd/ctl/cmd"
"github.com/jetstack/cert-manager/test/integration/ctl/install_framework"
)
func TestCtlInstall(t *testing.T) {
tests := map[string]struct {
prerun bool
preInputArgs []string
preExpErr bool
preExpOutput string
inputArgs []string
expErr bool
expOutput string
}{
"install cert-manager": {
inputArgs: []string{},
expErr: false,
expOutput: `STATUS: deployed`,
},
"install cert-manager (already installed)": {
prerun: true,
preInputArgs: []string{},
preExpErr: false,
preExpOutput: `STATUS: deployed`,
inputArgs: []string{},
expErr: true,
expOutput: `^Found existing installed cert-manager CRDs! Cannot continue with installation.$`,
},
"install cert-manager (already installed, in other namespace)": {
prerun: true,
preInputArgs: []string{"--namespace=test"},
preExpErr: false,
preExpOutput: `STATUS: deployed`,
inputArgs: []string{},
expErr: true,
expOutput: `^Found existing installed cert-manager CRDs! Cannot continue with installation.$`,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
testApiServer, cleanup := install_framework.NewTestInstallApiServer(t)
defer cleanup()
ctx, cancel := context.WithTimeout(context.TODO(), time.Second*20)
defer cancel()
if test.prerun {
executeCommandAndCheckOutput(t, ctx, testApiServer.KubeConfig(), test.preInputArgs, test.preExpErr, test.preExpOutput)
}
executeCommandAndCheckOutput(t, ctx, testApiServer.KubeConfig(), test.inputArgs, test.expErr, test.expOutput)
})
}
}
func executeCommandAndCheckOutput(
t *testing.T,
ctx context.Context,
kubeConfig string,
inputArgs []string,
expErr bool,
expOutput string,
) {
// Options to run status command
stdin := bytes.NewBufferString("")
stdout := bytes.NewBufferString("")
cmd := cmd.NewCertManagerCtlCommand(ctx, stdin, stdout, stdout)
cmd.SetArgs(append([]string{
fmt.Sprintf("--kubeconfig=%s", kubeConfig),
"--wait=false",
"x",
"install",
}, inputArgs...))
err := cmd.Execute()
if err != nil {
fmt.Fprintf(stdout, "%s\n", err)
if !expErr {
t.Errorf("got unexpected error: %v", err)
} else {
t.Logf("got an error, which was expected, details: %v", err)
}
} else if expErr {
// expected error but error is nil
t.Errorf("expected but got no error")
}
match, err := regexp.MatchString(strings.TrimSpace(expOutput), strings.TrimSpace(stdout.String()))
if err != nil {
t.Error(err)
}
dmp := diffmatchpatch.New()
if !match {
diffs := dmp.DiffMain(strings.TrimSpace(expOutput), strings.TrimSpace(stdout.String()), false)
t.Errorf(
"got unexpected output, diff (ignoring line anchors ^ and $ and regex for creation time):\n"+
"diff: %s\n\n"+
" exp: %s\n\n"+
" got: %s",
dmp.DiffPrettyText(diffs),
expOutput,
stdout.String(),
)
}
}
@@ -0,0 +1,28 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["framework.go"],
importpath = "github.com/jetstack/cert-manager/test/integration/ctl/install_framework",
visibility = ["//visibility:public"],
deps = [
"//test/internal/apiserver:go_default_library",
"@io_k8s_client_go//kubernetes:go_default_library",
"@io_k8s_client_go//rest:go_default_library",
"@io_k8s_sigs_controller_runtime//pkg/envtest:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
@@ -0,0 +1,108 @@
/*
Copyright 2021 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 install_framework
import (
"os"
"testing"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/envtest"
"github.com/jetstack/cert-manager/test/internal/apiserver"
)
type TestInstallApiServer struct {
environment *envtest.Environment
testUser *envtest.AuthenticatedUser
kubeClient kubernetes.Interface
kubeConfig string
}
type CleanupFunction func()
func NewTestInstallApiServer(t *testing.T) (*TestInstallApiServer, CleanupFunction) {
env, stopFn := apiserver.RunBareControlPlane(t)
testUser, err := env.ControlPlane.AddUser(
envtest.User{
Name: "test",
Groups: []string{"system:masters"},
},
&rest.Config{
// gotta go fast during tests -- we don't really care about overwhelming our test API server
QPS: 1000.0,
Burst: 2000.0,
},
)
if err != nil {
t.Error(err)
}
kubeConfig, removeFile := createKubeConfigFile(t, testUser)
kubeClientset, err := kubernetes.NewForConfig(env.Config)
if err != nil {
t.Error(err)
}
return &TestInstallApiServer{
environment: env,
testUser: testUser,
kubeClient: kubeClientset,
kubeConfig: kubeConfig,
}, func() {
defer removeFile()
stopFn()
}
}
func createKubeConfigFile(t *testing.T, user *envtest.AuthenticatedUser) (string, CleanupFunction) {
tmpfile, err := os.CreateTemp("", "config")
if err != nil {
t.Fatal(err)
}
path := tmpfile.Name()
contents, err := user.KubeConfig()
if err != nil {
os.Remove(path)
t.Fatal(err)
}
if _, err := tmpfile.Write(contents); err != nil {
tmpfile.Close()
os.Remove(path)
t.Fatal(err)
}
if err := tmpfile.Close(); err != nil {
os.Remove(path)
t.Fatal(err)
}
return path, func() {
os.Remove(path)
}
}
func (s *TestInstallApiServer) KubeConfig() string {
return s.kubeConfig
}