Skip to content

Commit

Permalink
feat(test): introduce a test that executes the validatingwebhook (#168)
Browse files Browse the repository at this point in the history
Closes #167.

In #151 we updated some libraries and
we missed the fact that
kubernetes-sigs/controller-runtime#2134 removed
the `InjectDecoder` call entirely. This PR implements a live test of the
`CONNECT` functionality, as well as fixes for the decoder.
  • Loading branch information
diranged authored Aug 16, 2023
1 parent 37bd4de commit df43a3e
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 30 deletions.
2 changes: 1 addition & 1 deletion .github/actions/setup-go/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ runs:
using: composite
steps:
- name: Set up Go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
cache: true
go-version-file: "go.mod"
13 changes: 12 additions & 1 deletion .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,19 @@ jobs:
- name: Checkout code
uses: actions/checkout@v3

# https://github.com/golangci/golangci-lint-action/issues/807
#
# when the files to be extracted are already present,
# tar extraction in Golangci Lint fails with the "File exists"
# errors. These files appear to be present because of
# cache in setup-go, on disabling the cache we are no more seeing
# such error. Cache is to be enabled once the fix is available for
# this issue.
- name: Set up Go
uses: ./.github/actions/setup-go
uses: actions/setup-go@v4
with:
cache: false
go-version-file: "go.mod"

- name: Run Revive Action by pulling pre-built image
uses: docker://morphy/revive-action:v2
Expand Down
12 changes: 6 additions & 6 deletions Custom.mk
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
SOURCE := $(wildcard api/*/*.go controller/*.go ozctl/*.go ozctl/*/*.go)

ifeq (true,$(PUBLISH))
GORELEASER_FLAGS := --rm-dist
GORELEASER_FLAGS := --clean
else
GORELEASER_FLAGS := --skip-publish --snapshot --rm-dist
GORELEASER_FLAGS := --skip-publish --snapshot --clean
endif

## Tool Binaries
REVIVE_VER ?= v1.3.1
REVIVE ?= $(LOCALBIN)/revive

GOLANGCI_VER ?= v1.52.2
GOLANGCI_VER ?= v1.54.1
GOLANGCI ?= $(LOCALBIN)/golangci-lint

GOFUMPT_VER ?= v0.4.0
GOFUMPT_VER ?= v0.5.0
GOFUMPT ?= $(LOCALBIN)/gofumpt

GOLINES_VER ?= v0.11.0
GOLINES ?= $(LOCALBIN)/golines

GORELEASER_VER ?= v1.13.1
GORELEASER_VER ?= v1.20.0
GORELEASER ?= $(LOCALBIN)/goreleaser

GEN_CRD_API_DOCS_VER ?= v0.3.1-0.20220223025230-af7c5e0048a3
Expand Down Expand Up @@ -89,7 +89,7 @@ build: $(GORELEASER)
PUBLISH=false $(MAKE) release dist/docker.tar

.PHONY: docker-load
docker-load:
docker-load: dist/docker.tar
docker load --input dist/docker.tar && kind load docker-image $(IMG)

dist/docker.tar:
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/diranged/oz

go 1.19
go 1.20

require (
github.com/fatih/color v1.15.0
Expand Down
2 changes: 1 addition & 1 deletion internal/controllers/podwatcher/handle_attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,5 @@ func (w *PodWatcher) HandleAttach(ctx context.Context, req admission.Request) ad
w.recorder.Event(pod, "Normal", "PodAttach", eventMsg)
logger.Info(eventMsg)

return admission.Allowed("");
return admission.Allowed("")
}
5 changes: 1 addition & 4 deletions internal/controllers/podwatcher/handle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,11 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/tools/record"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)

var _ = Describe("PodWatcher", Ordered, func() {
decoder := admission.NewDecoder(scheme.Scheme)

Context("Functional Unit Tests", func() {
var (
admissionRequest *admission.Request
Expand All @@ -28,7 +25,7 @@ var _ = Describe("PodWatcher", Ordered, func() {
recorder = record.NewFakeRecorder(50)
watcher = &PodWatcher{
Client: k8sClient,
decoder: decoder,
decoder: *admission.NewDecoder(runtime.NewScheme()),
recorder: recorder,
}
resource = metav1.GroupVersionResource{
Expand Down
3 changes: 2 additions & 1 deletion internal/controllers/podwatcher/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
. "github.com/onsi/gomega"
"go.uber.org/zap/zapcore"

"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -75,7 +76,7 @@ var _ = BeforeSuite(func() {

//+kubebuilder:scaffold:scheme

k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
k8sClient, err = client.New(cfg, client.Options{Scheme: runtime.NewScheme()})
Expect(err).NotTo(HaveOccurred())
Expect(k8sClient).NotTo(BeNil())
})
Expand Down
12 changes: 2 additions & 10 deletions internal/controllers/podwatcher/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,10 @@ import (
// layer of security for Pod Exec access.
type PodWatcher struct {
Client client.Client
decoder *admission.Decoder
decoder admission.Decoder
recorder record.EventRecorder
}

// PodWatcher implements admission.DecoderInjector.
// A decoder will be automatically injected.

// InjectDecoder injects the decoder.
func (w *PodWatcher) InjectDecoder(d *admission.Decoder) error {
w.decoder = d
return nil
}

// NewPodWatcherRegistration creates a PodWatcher{} object and registers it at the supplied path.
func NewPodWatcherRegistration(
mgr manager.Manager,
Expand All @@ -43,6 +34,7 @@ func NewPodWatcherRegistration(
&webhook.Admission{
Handler: &PodWatcher{
Client: mgr.GetClient(),
decoder: *admission.NewDecoder(mgr.GetScheme()),
recorder: mgr.GetEventRecorderFor(controllers.EventRecorderName),
},
},
Expand Down
43 changes: 40 additions & 3 deletions internal/testing/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"os/exec"
"path/filepath"
"strings"
"time"

. "github.com/onsi/ginkgo/v2"
Expand Down Expand Up @@ -126,6 +127,7 @@ var _ = Describe("oz-controller", Ordered, func() {
}
})
})

Context("PodAccessTemplate / PodAccessRequest", func() {
template := filepath.Join(projectDir, "examples/pod_access_template.yaml")
request := filepath.Join(projectDir, "examples/pod_access_request.yaml")
Expand Down Expand Up @@ -158,9 +160,9 @@ var _ = Describe("oz-controller", Ordered, func() {
})

//
// AccessRequest tests are next - create the PodAccessRquest and wait until they have had
// their various Conditions marked True, indicating that the Oz Controller has processed
// them properly.
// PodAccessRequest tests are next - create the PodAccessRquest and
// wait until they have had their various Conditions marked True,
// indicating that the Oz Controller has processed them properly.
//
It("Should allow creating the Access Request", func() {
By("Creating PodAccessRequest")
Expand Down Expand Up @@ -199,5 +201,40 @@ var _ = Describe("oz-controller", Ordered, func() {
message,
).To(MatchRegexp("kubectl exec -ti -n oz-system deployment-example-.* -- /bin/bash"))
})

It("Should allow CONNECTing to the Pod", func() {
By("Execing into the pod")
var podName string

EventuallyWithOffset(1, func() error {
cmd := exec.Command(
"kubectl", "get", "-f", request, "-n", namespace, "-o", "jsonpath='{.status.podName}'",
)

// Get the podname from the template. Note, it comes back wrapped in single quotes.
podName, err = utils.Run(cmd)
Expect(err).To(Not(HaveOccurred()))
Expect(podName).NotTo(BeEmpty())

// Strip the single quotes from the podName string.
podName = strings.Replace(podName, "'", "", -1)
Expect(podName).NotTo(BeEmpty())

return err
}, time.Minute, time.Second).Should(Succeed())

// Verify that the CONNECT and validating webhook handler work
EventuallyWithOffset(1, func() error {
cmd := exec.Command(
"kubectl", "exec", "-t", "-n", namespace, podName, "--", "whoami",
)
whoami, err := utils.Run(cmd)
Expect(err).To(Not(HaveOccurred()))
Expect(
whoami,
).To(MatchRegexp("root"))
return err
}, time.Minute, time.Second).Should(Succeed())
})
})
})
4 changes: 2 additions & 2 deletions internal/testing/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ func GetNonEmptyLines(output string) []string {

// RandomString is a function for generating a random string for certain tests
func RandomString(length int) string {
rand.Seed(time.Now().UnixNano())
random := rand.New(rand.NewSource(time.Now().UnixNano()))
b := make([]byte, length)
rand.Read(b)
random.Read(b)
return fmt.Sprintf("%x", b)[:length]
}

Expand Down

0 comments on commit df43a3e

Please sign in to comment.