Files
nuclei-operator/internal/jobmanager/jobmanager_test.go

152 lines
4.1 KiB
Go

/*
Copyright 2024.
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 jobmanager
import (
"testing"
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
nucleiv1alpha1 "github.com/mortenolsen/nuclei-operator/api/v1alpha1"
)
func TestBuildJob(t *testing.T) {
config := DefaultConfig()
manager := &JobManager{
Config: config,
}
scan := &nucleiv1alpha1.NucleiScan{
ObjectMeta: metav1.ObjectMeta{
Name: "test-scan",
Namespace: "default",
},
Spec: nucleiv1alpha1.NucleiScanSpec{
Targets: []string{"https://example.com"},
},
}
job := manager.buildJob(scan)
// Verify job name prefix - should include scan namespace to avoid collisions
if len(job.Name) == 0 {
t.Error("Job name should not be empty")
}
// Verify namespace - job should be created in operator namespace
if job.Namespace != config.OperatorNamespace {
t.Errorf("Expected namespace '%s', got '%s'", config.OperatorNamespace, job.Namespace)
}
// Verify scan labels are set correctly for cross-namespace tracking
if job.Labels[LabelScanName] != scan.Name {
t.Errorf("Expected scan name label '%s', got '%s'", scan.Name, job.Labels[LabelScanName])
}
if job.Labels[LabelScanNamespace] != scan.Namespace {
t.Errorf("Expected scan namespace label '%s', got '%s'", scan.Namespace, job.Labels[LabelScanNamespace])
}
// Verify labels
if job.Labels[LabelManagedBy] != "nuclei-operator" {
t.Error("Job should have managed-by label")
}
if job.Labels[LabelComponent] != "scanner" {
t.Error("Job should have component label")
}
// Verify container
if len(job.Spec.Template.Spec.Containers) != 1 {
t.Error("Job should have exactly one container")
}
container := job.Spec.Template.Spec.Containers[0]
if container.Image != config.ScannerImage {
t.Errorf("Expected image '%s', got '%s'", config.ScannerImage, container.Image)
}
// Verify security context
if job.Spec.Template.Spec.SecurityContext.RunAsNonRoot == nil || !*job.Spec.Template.Spec.SecurityContext.RunAsNonRoot {
t.Error("Pod should run as non-root")
}
}
func TestBuildJobWithCustomConfig(t *testing.T) {
config := DefaultConfig()
manager := &JobManager{
Config: config,
}
customImage := "custom/scanner:v1"
customTimeout := metav1.Duration{Duration: 45 * time.Minute}
scan := &nucleiv1alpha1.NucleiScan{
ObjectMeta: metav1.ObjectMeta{
Name: "test-scan",
Namespace: "default",
},
Spec: nucleiv1alpha1.NucleiScanSpec{
Targets: []string{"https://example.com"},
ScannerConfig: &nucleiv1alpha1.ScannerConfig{
Image: customImage,
Timeout: &customTimeout,
},
},
}
job := manager.buildJob(scan)
// Verify custom image
container := job.Spec.Template.Spec.Containers[0]
if container.Image != customImage {
t.Errorf("Expected custom image '%s', got '%s'", customImage, container.Image)
}
// Verify custom timeout
expectedDeadline := int64(45 * 60) // 45 minutes in seconds
if *job.Spec.ActiveDeadlineSeconds != expectedDeadline {
t.Errorf("Expected deadline %d, got %d", expectedDeadline, *job.Spec.ActiveDeadlineSeconds)
}
}
func TestBuildJobInSameNamespace(t *testing.T) {
config := DefaultConfig()
// Clear operator namespace to test same-namespace behavior
config.OperatorNamespace = ""
manager := &JobManager{
Config: config,
}
scan := &nucleiv1alpha1.NucleiScan{
ObjectMeta: metav1.ObjectMeta{
Name: "test-scan",
Namespace: "my-namespace",
},
Spec: nucleiv1alpha1.NucleiScanSpec{
Targets: []string{"https://example.com"},
},
}
job := manager.buildJob(scan)
// Verify namespace - when operator namespace is empty, job should be in scan's namespace
if job.Namespace != scan.Namespace {
t.Errorf("Expected namespace '%s', got '%s'", scan.Namespace, job.Namespace)
}
}