@ -22,10 +22,14 @@ import (
"errors"
"io"
"os"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
fakeclientset "k8s.io/client-go/kubernetes/fake"
"helm.sh/helm/v4/pkg/cli"
"helm.sh/helm/v4/pkg/kube"
@ -89,7 +93,7 @@ func TestReleaseTestingGetPodLogs_PodRetrievalError(t *testing.T) {
} ,
}
require . ErrorContains ( t , client . GetPodLogs ( & bytes . Buffer { } , & release . Release { Hooks : hooks } ) , "unable to get pod logs ")
require . ErrorContains ( t , client . GetPodLogs ( & bytes . Buffer { } , & release . Release { Hooks : hooks } ) , "unable to get pod ")
}
func TestReleaseTesting_WaitOptionsPassedDownstream ( t * testing . T ) {
@ -117,3 +121,100 @@ func TestReleaseTesting_WaitOptionsPassedDownstream(t *testing.T) {
// Verify that WaitOptions were passed to GetWaiter
is . NotEmpty ( failer . RecordedWaitOptions , "WaitOptions should be passed to GetWaiter" )
}
func TestGetContainerLogs_MultipleContainers ( t * testing . T ) {
pod := & v1 . Pod {
ObjectMeta : metav1 . ObjectMeta {
Name : "test-pod" ,
Namespace : "default" ,
} ,
Spec : v1 . PodSpec {
Containers : [ ] v1 . Container {
{ Name : "main" } ,
{ Name : "sidecar" } ,
} ,
} ,
}
client := fakeclientset . NewClientset ( pod )
rt := & ReleaseTesting { Namespace : "default" }
var buf bytes . Buffer
err := rt . getContainerLogs ( & buf , client , "test-pod" )
// The fake client doesn't serve real log streams, so we expect
// per-container errors rather than success, but critically it should
// NOT fail with "a container name must be specified".
if err != nil {
assert . NotContains ( t , err . Error ( ) , "a container name must be specified" )
assert . Contains ( t , err . Error ( ) , "container main" )
assert . Contains ( t , err . Error ( ) , "container sidecar" )
}
}
func TestGetContainerLogs_WithInitContainers ( t * testing . T ) {
pod := & v1 . Pod {
ObjectMeta : metav1 . ObjectMeta {
Name : "test-pod" ,
Namespace : "default" ,
} ,
Spec : v1 . PodSpec {
InitContainers : [ ] v1 . Container {
{ Name : "init-setup" } ,
} ,
Containers : [ ] v1 . Container {
{ Name : "main" } ,
} ,
} ,
}
client := fakeclientset . NewClientset ( pod )
rt := & ReleaseTesting { Namespace : "default" }
var buf bytes . Buffer
err := rt . getContainerLogs ( & buf , client , "test-pod" )
if err != nil {
// Both init and regular containers should be attempted
assert . Contains ( t , err . Error ( ) , "container init-setup" )
assert . Contains ( t , err . Error ( ) , "container main" )
}
}
func TestGetContainerLogs_PodNotFound ( t * testing . T ) {
client := fakeclientset . NewClientset ( )
rt := & ReleaseTesting { Namespace : "default" }
var buf bytes . Buffer
err := rt . getContainerLogs ( & buf , client , "nonexistent-pod" )
require . Error ( t , err )
assert . Contains ( t , err . Error ( ) , "unable to get pod nonexistent-pod" )
}
func TestGetPodLogs_MultiContainerOutput ( t * testing . T ) {
pod := & v1 . Pod {
ObjectMeta : metav1 . ObjectMeta {
Name : "multi-test" ,
Namespace : "default" ,
} ,
Spec : v1 . PodSpec {
Containers : [ ] v1 . Container {
{ Name : "container-a" } ,
{ Name : "container-b" } ,
} ,
} ,
}
client := fakeclientset . NewClientset ( pod )
rt := & ReleaseTesting {
Namespace : "default" ,
Filters : map [ string ] [ ] string { } ,
}
// Call getContainerLogs directly to test output formatting
var buf bytes . Buffer
_ = rt . getContainerLogs ( & buf , client , "multi-test" )
output := buf . String ( )
// Even if logs fail, check that header formatting uses container names
if len ( output ) > 0 {
assert . True ( t , strings . Contains ( output , "(container-a)" ) || strings . Contains ( output , "(container-b)" ) )
}
}