IO-K8s
view release on metacpan or search on metacpan
t/26_build_verify.t view on Meta::CPAN
image => 'my-app:v1.0',
ports => [{ containerPort => 3000 }],
envFrom => [
{ configMapRef => { name => 'app-config' } },
{ secretRef => { name => 'app-secrets' } },
],
}],
},
},
},
});
my $deploy_json = $deploy->TO_JSON;
is($deploy_json->{kind}, 'Deployment', 'Deployment kind');
my $env_from = $deploy_json->{spec}{template}{spec}{containers}[0]{envFrom};
is(scalar @$env_from, 2, 'envFrom has 2 sources');
is($env_from->[0]{configMapRef}{name}, 'app-config', 'envFrom references ConfigMap');
is($env_from->[1]{secretRef}{name}, 'app-secrets', 'envFrom references Secret');
# Service
my $svc = $k8s->new_object('Service', {
metadata => {
name => 'fullstack-app',
namespace => 'staging',
labels => { app => 'fullstack' },
},
spec => {
selector => { app => 'fullstack' },
ports => [{ port => 80, targetPort => 3000, protocol => 'TCP' }],
},
});
my $svc_json = $svc->TO_JSON;
is($svc_json->{kind}, 'Service', 'Service kind');
is($svc_json->{spec}{ports}[0]{targetPort}, 3000, 'Service targets app port');
# All share the same namespace and labels
for my $obj_json ($cm_json, $secret_json, $deploy_json, $svc_json) {
is($obj_json->{metadata}{namespace}, 'staging', 'All in staging ns');
is($obj_json->{metadata}{labels}{app}, 'fullstack', 'All have app=fullstack');
}
};
# ============================================================================
# 21. Deployment with init containers, probes, and resource limits
# ============================================================================
subtest 'Deployment with init containers and full probe config' => sub {
my ($obj, $got) = build_and_verify('Deployment', {
metadata => {
name => 'web',
namespace => 'production',
},
spec => {
replicas => 3,
selector => { matchLabels => { app => 'web' } },
template => {
metadata => { labels => { app => 'web' } },
spec => {
initContainers => [{
name => 'wait-for-db',
image => 'busybox:1.36',
command => ['sh', '-c', 'until nc -z db 5432; do sleep 1; done'],
}],
containers => [{
name => 'web',
image => 'web-app:v3',
ports => [{ containerPort => 8080, name => 'http' }],
resources => {
requests => { cpu => '100m', memory => '128Mi' },
limits => { cpu => '500m', memory => '512Mi' },
},
livenessProbe => {
httpGet => { path => '/healthz', port => 8080 },
initialDelaySeconds => 15,
periodSeconds => 20,
failureThreshold => 3,
},
readinessProbe => {
httpGet => { path => '/ready', port => 8080 },
initialDelaySeconds => 5,
periodSeconds => 10,
},
startupProbe => {
httpGet => { path => '/healthz', port => 8080 },
failureThreshold => 30,
periodSeconds => 10,
},
}],
},
},
},
}, {
kind => 'Deployment',
spec => superhashof({
template => superhashof({
metadata => ignore(),
spec => superhashof({
initContainers => [superhashof({ name => 'wait-for-db' })],
containers => [superhashof({
name => 'web',
livenessProbe => superhashof({ httpGet => superhashof({ path => '/healthz' }) }),
readinessProbe => superhashof({ httpGet => superhashof({ path => '/ready' }) }),
startupProbe => superhashof({ httpGet => superhashof({ path => '/healthz' }) }),
})],
}),
}),
}),
}, 'Deployment with probes');
# Verify resource values are preserved exactly
my $container = $got->{spec}{template}{spec}{containers}[0];
is($container->{resources}{requests}{cpu}, '100m', 'CPU request preserved');
is($container->{resources}{limits}{memory}, '512Mi', 'Memory limit preserved');
};
# ============================================================================
# 22. Pod with multiple containers (sidecar pattern)
# ============================================================================
subtest 'Pod with sidecar containers' => sub {
build_and_verify('Pod', {
( run in 3.693 seconds using v1.01-cache-2.11-cpan-364913b4093 )