Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,18 @@ test-e2e: manifests generate fmt vet ## Run the e2e tests. Expected an isolated
}
go test ./test/e2e/ -v -ginkgo.v

.PHONY: test-integration
test-integration: manifests generate fmt vet ## Run the integration tests. Requires a running Kubernetes cluster.
@command -v kubectl >/dev/null 2>&1 || { \
echo "kubectl is not installed. Please install kubectl manually."; \
exit 1; \
}
@kubectl cluster-info >/dev/null 2>&1 || { \
echo "No Kubernetes cluster is accessible. Please ensure kubectl is configured with a valid cluster."; \
exit 1; \
}
go test ./test/integration/ -v -ginkgo.v

.PHONY: lint
lint: golangci-lint ## Run golangci-lint linter
$(GOLANGCI_LINT) run
Expand Down
3 changes: 0 additions & 3 deletions config/crd/kustomizeconfig.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ varReference:
- path: metadata/annotations

versions:
- name: v1alpha1
served: false # 더 이상 제공하지 않음
storage: false # 저장 버전이 아님
- name: v2alpha1
served: true # 현재 제공 중
storage: true # 저장 버전
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ require (
github.com/spf13/cobra v1.8.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stoewer/go-strcase v1.2.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
go.opentelemetry.io/otel v1.28.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
Expand Down
263 changes: 263 additions & 0 deletions internal/controller/v2/benchmark_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
package controller

import (
"context"
"testing"

hexactfproj "github.com/hexactf/challenge-operator/api/v2alpha1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
)

func BenchmarkChallengeReconciliation(b *testing.B) {
// Setup
scheme := runtime.NewScheme()
_ = hexactfproj.AddToScheme(scheme)
_ = corev1.AddToScheme(scheme)

client := fake.NewClientBuilder().WithScheme(scheme).Build()
reconciler := &ChallengeReconciler{
Client: client,
Scheme: scheme,
}
ctx := context.Background()

// Create definition
definition := &hexactfproj.ChallengeDefinition{
ObjectMeta: metav1.ObjectMeta{
Name: "benchmark-definition",
Namespace: "default",
},
Spec: hexactfproj.ChallengeDefinitionSpec{
Resource: hexactfproj.Resource{
Pod: &hexactfproj.PodConfig{
Containers: []hexactfproj.ContainerConfig{
{
Name: "benchmark-container",
Image: "nginx:latest",
},
},
},
Service: &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "benchmark-service",
},
Spec: corev1.ServiceSpec{
Type: corev1.ServiceTypeNodePort,
Ports: []corev1.ServicePort{
{
Port: 80,
NodePort: 30080,
},
},
},
},
},
},
}
_ = client.Create(ctx, definition)

b.ResetTimer()
b.ReportAllocs()

for i := 0; i < b.N; i++ {
// Create challenge
challenge := NewChallengeBuilder().
WithName("benchmark-challenge").
WithNamespace("default").
WithFinalizer("challenge.hexactf.io/finalizer").
WithPodName("benchmark-pod").
Build()
challenge.Spec.Definition = "benchmark-definition"

_ = client.Create(ctx, challenge)

// Create pod
pod := NewPodBuilder().
WithName("benchmark-pod").
WithNamespace("default").
WithPhase(corev1.PodRunning).
Build()
_ = client.Create(ctx, pod)

// Reconcile
req := ctrl.Request{
NamespacedName: types.NamespacedName{
Name: "benchmark-challenge",
Namespace: "default",
},
}
_, _ = reconciler.Reconcile(ctx, req)

// Cleanup
_ = client.Delete(ctx, challenge)
_ = client.Delete(ctx, pod)
}
}

func BenchmarkLoadChallengeDefinition(b *testing.B) {
// Setup
scheme := runtime.NewScheme()
_ = hexactfproj.AddToScheme(scheme)
_ = corev1.AddToScheme(scheme)

client := fake.NewClientBuilder().WithScheme(scheme).Build()
reconciler := &ChallengeReconciler{
Client: client,
Scheme: scheme,
}
ctx := context.Background()

// Create definition
definition := &hexactfproj.ChallengeDefinition{
ObjectMeta: metav1.ObjectMeta{
Name: "benchmark-definition",
Namespace: "default",
},
Spec: hexactfproj.ChallengeDefinitionSpec{
Resource: hexactfproj.Resource{
Pod: &hexactfproj.PodConfig{
Containers: []hexactfproj.ContainerConfig{
{
Name: "benchmark-container",
Image: "nginx:latest",
},
},
},
Service: &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "benchmark-service",
},
Spec: corev1.ServiceSpec{
Type: corev1.ServiceTypeNodePort,
Ports: []corev1.ServicePort{
{
Port: 80,
NodePort: 30080,
},
},
},
},
},
},
}
_ = client.Create(ctx, definition)

b.ResetTimer()
b.ReportAllocs()

for i := 0; i < b.N; i++ {
challenge := NewChallengeBuilder().
WithName("benchmark-challenge").
WithNamespace("default").
Build()
challenge.Spec.Definition = "benchmark-definition"

_ = client.Create(ctx, challenge)

// Get the challenge from client to ensure it exists
_ = client.Get(ctx, types.NamespacedName{
Name: challenge.Name,
Namespace: challenge.Namespace,
}, challenge)

_ = reconciler.loadChallengeDefinition(ctx, ctrl.Request{}, challenge)

// Cleanup
_ = client.Delete(ctx, challenge)
}
}

func BenchmarkHandlePendingState(b *testing.B) {
// Setup
scheme := runtime.NewScheme()
_ = hexactfproj.AddToScheme(scheme)
_ = corev1.AddToScheme(scheme)

client := fake.NewClientBuilder().WithScheme(scheme).Build()
reconciler := &ChallengeReconciler{
Client: client,
Scheme: scheme,
}
ctx := context.Background()

b.ResetTimer()
b.ReportAllocs()

for i := 0; i < b.N; i++ {
// Create challenge with pending status
challenge := NewChallengeBuilder().
WithName("benchmark-challenge").
WithNamespace("default").
WithPodName("benchmark-pod").
Build()

_ = client.Create(ctx, challenge)

// Create pod
pod := NewPodBuilder().
WithName("benchmark-pod").
WithNamespace("default").
WithPhase(corev1.PodRunning).
Build()
_ = client.Create(ctx, pod)

// Get the challenge from client to ensure it exists
_ = client.Get(ctx, types.NamespacedName{
Name: challenge.Name,
Namespace: challenge.Namespace,
}, challenge)

_, _ = reconciler.handlePendingState(ctx, challenge)

// Cleanup
_ = client.Delete(ctx, challenge)
_ = client.Delete(ctx, pod)
}
}

func BenchmarkHandleRunningState(b *testing.B) {
// Setup
scheme := runtime.NewScheme()
_ = hexactfproj.AddToScheme(scheme)
_ = corev1.AddToScheme(scheme)

client := fake.NewClientBuilder().WithScheme(scheme).Build()
reconciler := &ChallengeReconciler{
Client: client,
Scheme: scheme,
}
ctx := context.Background()

b.ResetTimer()
b.ReportAllocs()

for i := 0; i < b.N; i++ {
// Create challenge with running status
status := hexactfproj.NewCurrentStatus()
status.Running()

challenge := NewChallengeBuilder().
WithName("benchmark-challenge").
WithNamespace("default").
Build()
challenge.Status.CurrentStatus = *status

_ = client.Create(ctx, challenge)

// Get the challenge from client to ensure it exists
_ = client.Get(ctx, types.NamespacedName{
Name: challenge.Name,
Namespace: challenge.Namespace,
}, challenge)

_, _ = reconciler.handleRunningState(ctx, challenge)

// Cleanup
_ = client.Delete(ctx, challenge)
}
}
Loading