2020-01-24 15:30:27 +02:00
package cmd
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"testing"
2020-04-24 09:37:11 +02:00
"github.com/SAP/jenkins-library/pkg/mock"
2020-01-24 15:30:27 +02:00
"github.com/stretchr/testify/assert"
)
func TestRunKubernetesDeploy ( t * testing . T ) {
t . Run ( "test helm" , func ( t * testing . T ) {
opts := kubernetesDeployOptions {
ContainerRegistryURL : "https://my.registry:55555" ,
ContainerRegistryUser : "registryUser" ,
ContainerRegistryPassword : "********" ,
2020-08-14 17:16:25 +02:00
ContainerRegistrySecret : "testSecret" ,
2020-01-24 15:30:27 +02:00
ChartPath : "path/to/chart" ,
DeploymentName : "deploymentName" ,
DeployTool : "helm" ,
HelmDeployWaitSeconds : 400 ,
IngressHosts : [ ] string { "ingress.host1" , "ingress.host2" } ,
Image : "path/to/Image:latest" ,
AdditionalParameters : [ ] string { "--testParam" , "testValue" } ,
KubeContext : "testCluster" ,
Namespace : "deploymentNamespace" ,
}
dockerConfigJSON := ` { "kind": "Secret","data": { ".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}} `
2020-02-27 13:11:22 +02:00
e := mock . ExecMockRunner {
StdoutReturn : map [ string ] string {
2020-08-14 17:16:25 +02:00
` kubectl --insecure-skip-tls-verify=true create secret docker-registry testSecret --docker-server=my.registry:55555 --docker-username=registryUser --docker-password=\*\*\*\*\*\*\*\* --dry-run=true --output=json ` : dockerConfigJSON ,
2020-01-24 15:30:27 +02:00
} ,
}
var stdout bytes . Buffer
runKubernetesDeploy ( opts , & e , & stdout )
2020-02-27 13:11:22 +02:00
assert . Equal ( t , "helm" , e . Calls [ 0 ] . Exec , "Wrong init command" )
assert . Equal ( t , [ ] string { "init" , "--client-only" } , e . Calls [ 0 ] . Params , "Wrong init parameters" )
2020-01-24 15:30:27 +02:00
2020-02-27 13:11:22 +02:00
assert . Equal ( t , "kubectl" , e . Calls [ 1 ] . Exec , "Wrong secret creation command" )
2020-08-14 17:16:25 +02:00
assert . Equal ( t , [ ] string { "--insecure-skip-tls-verify=true" , "create" , "secret" , "docker-registry" , "testSecret" , "--docker-server=my.registry:55555" , "--docker-username=registryUser" , "--docker-password=********" , "--dry-run=true" , "--output=json" } , e . Calls [ 1 ] . Params , "Wrong secret creation parameters" )
2020-01-24 15:30:27 +02:00
2020-02-27 13:11:22 +02:00
assert . Equal ( t , "helm" , e . Calls [ 2 ] . Exec , "Wrong upgrade command" )
2020-01-24 15:30:27 +02:00
assert . Equal ( t , [ ] string {
"upgrade" ,
"deploymentName" ,
"path/to/chart" ,
"--install" ,
"--force" ,
"--namespace" ,
"deploymentNamespace" ,
2020-04-24 09:37:11 +02:00
"--set" ,
2020-08-14 17:16:25 +02:00
"image.repository=my.registry:55555/path/to/Image,image.tag=latest,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret,ingress.hosts[0]=ingress.host1,ingress.hosts[1]=ingress.host2" ,
2020-01-24 15:30:27 +02:00
"--wait" ,
"--timeout" ,
"400" ,
2020-04-24 09:37:11 +02:00
"--kube-context" ,
"testCluster" ,
"--testParam" ,
"testValue" ,
} , e . Calls [ 2 ] . Params , "Wrong upgrade parameters" )
} )
t . Run ( "test helm v3" , func ( t * testing . T ) {
opts := kubernetesDeployOptions {
ContainerRegistryURL : "https://my.registry:55555" ,
ContainerRegistryUser : "registryUser" ,
ContainerRegistryPassword : "********" ,
2020-08-14 17:16:25 +02:00
ContainerRegistrySecret : "testSecret" ,
2020-04-24 09:37:11 +02:00
ChartPath : "path/to/chart" ,
DeploymentName : "deploymentName" ,
DeployTool : "helm3" ,
HelmDeployWaitSeconds : 400 ,
IngressHosts : [ ] string { "ingress.host1" , "ingress.host2" } ,
Image : "path/to/Image:latest" ,
AdditionalParameters : [ ] string { "--testParam" , "testValue" } ,
KubeContext : "testCluster" ,
Namespace : "deploymentNamespace" ,
}
dockerConfigJSON := ` { "kind": "Secret","data": { ".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}} `
e := mock . ExecMockRunner {
StdoutReturn : map [ string ] string {
2020-08-14 17:16:25 +02:00
` kubectl --insecure-skip-tls-verify=true create secret docker-registry testSecret --docker-server=my.registry:55555 --docker-username=registryUser --docker-password=\*\*\*\*\*\*\*\* --dry-run=true --output=json ` : dockerConfigJSON ,
2020-04-24 09:37:11 +02:00
} ,
}
var stdout bytes . Buffer
runKubernetesDeploy ( opts , & e , & stdout )
assert . Equal ( t , "kubectl" , e . Calls [ 0 ] . Exec , "Wrong secret creation command" )
2020-08-14 17:16:25 +02:00
assert . Equal ( t , [ ] string { "--insecure-skip-tls-verify=true" , "create" , "secret" , "docker-registry" , "testSecret" , "--docker-server=my.registry:55555" , "--docker-username=registryUser" , "--docker-password=********" , "--dry-run=true" , "--output=json" } , e . Calls [ 0 ] . Params , "Wrong secret creation parameters" )
2020-04-24 09:37:11 +02:00
assert . Equal ( t , "helm" , e . Calls [ 1 ] . Exec , "Wrong upgrade command" )
assert . Equal ( t , [ ] string {
"upgrade" ,
"deploymentName" ,
"path/to/chart" ,
"--install" ,
"--force" ,
"--namespace" ,
"deploymentNamespace" ,
2020-01-24 15:30:27 +02:00
"--set" ,
2020-08-14 17:16:25 +02:00
"image.repository=my.registry:55555/path/to/Image,image.tag=latest,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret,ingress.hosts[0]=ingress.host1,ingress.hosts[1]=ingress.host2" ,
"--atomic" ,
"--timeout" ,
"400s" ,
"--kube-context" ,
"testCluster" ,
"--testParam" ,
"testValue" ,
} , e . Calls [ 1 ] . Params , "Wrong upgrade parameters" )
} )
t . Run ( "test helm v3 - no container credentials" , func ( t * testing . T ) {
opts := kubernetesDeployOptions {
ContainerRegistryURL : "https://my.registry:55555" ,
ChartPath : "path/to/chart" ,
ContainerRegistrySecret : "testSecret" ,
DeploymentName : "deploymentName" ,
DeployTool : "helm3" ,
HelmDeployWaitSeconds : 400 ,
IngressHosts : [ ] string { "ingress.host1" , "ingress.host2" } ,
Image : "path/to/Image:latest" ,
AdditionalParameters : [ ] string { "--testParam" , "testValue" } ,
KubeContext : "testCluster" ,
Namespace : "deploymentNamespace" ,
}
e := mock . ExecMockRunner { }
var stdout bytes . Buffer
runKubernetesDeploy ( opts , & e , & stdout )
assert . Equal ( t , "helm" , e . Calls [ 1 ] . Exec , "Wrong upgrade command" )
assert . Equal ( t , [ ] string {
"upgrade" ,
"deploymentName" ,
"path/to/chart" ,
"--install" ,
"--force" ,
"--namespace" ,
"deploymentNamespace" ,
"--set" ,
"image.repository=my.registry:55555/path/to/Image,image.tag=latest,imagePullSecrets[0].name=testSecret,ingress.hosts[0]=ingress.host1,ingress.hosts[1]=ingress.host2" ,
2020-04-24 09:37:11 +02:00
"--atomic" ,
"--timeout" ,
"400s" ,
2020-01-24 15:30:27 +02:00
"--kube-context" ,
"testCluster" ,
"--testParam" ,
"testValue" ,
2020-04-24 09:37:11 +02:00
} , e . Calls [ 1 ] . Params , "Wrong upgrade parameters" )
2020-01-24 15:30:27 +02:00
} )
t . Run ( "test kubectl - create secret/kubeconfig" , func ( t * testing . T ) {
dir , err := ioutil . TempDir ( "" , "" )
defer os . RemoveAll ( dir ) // clean up
assert . NoError ( t , err , "Error when creating temp dir" )
opts := kubernetesDeployOptions {
AppTemplate : filepath . Join ( dir , "test.yaml" ) ,
ContainerRegistryURL : "https://my.registry:55555" ,
ContainerRegistryUser : "registryUser" ,
ContainerRegistryPassword : "********" ,
ContainerRegistrySecret : "regSecret" ,
CreateDockerRegistrySecret : true ,
DeployTool : "kubectl" ,
Image : "path/to/Image:latest" ,
AdditionalParameters : [ ] string { "--testParam" , "testValue" } ,
KubeConfig : "This is my kubeconfig" ,
KubeContext : "testCluster" ,
Namespace : "deploymentNamespace" ,
}
kubeYaml := ` kind : Deployment
metadata :
spec :
spec :
image : < image - name > `
ioutil . WriteFile ( opts . AppTemplate , [ ] byte ( kubeYaml ) , 0755 )
2020-02-27 13:11:22 +02:00
e := mock . ExecMockRunner {
ShouldFailOnCommand : map [ string ] error {
2020-01-24 15:30:27 +02:00
"kubectl --insecure-skip-tls-verify=true --namespace=deploymentNamespace --context=testCluster get secret regSecret" : fmt . Errorf ( "secret not found" ) ,
} ,
}
var stdout bytes . Buffer
runKubernetesDeploy ( opts , & e , & stdout )
2020-03-03 10:26:32 +02:00
assert . Equal ( t , e . Env , [ ] string { "KUBECONFIG=This is my kubeconfig" } )
2020-01-24 15:30:27 +02:00
2020-02-27 13:11:22 +02:00
assert . Equal ( t , "kubectl" , e . Calls [ 0 ] . Exec , "Wrong secret lookup command" )
2020-01-24 15:30:27 +02:00
assert . Equal ( t , [ ] string {
"--insecure-skip-tls-verify=true" ,
fmt . Sprintf ( "--namespace=%v" , opts . Namespace ) ,
fmt . Sprintf ( "--context=%v" , opts . KubeContext ) ,
"get" ,
"secret" ,
opts . ContainerRegistrySecret ,
2020-02-27 13:11:22 +02:00
} , e . Calls [ 0 ] . Params , "kubectl parameters incorrect" )
2020-01-24 15:30:27 +02:00
2020-02-27 13:11:22 +02:00
assert . Equal ( t , "kubectl" , e . Calls [ 1 ] . Exec , "Wrong secret create command" )
2020-01-24 15:30:27 +02:00
assert . Equal ( t , [ ] string {
"--insecure-skip-tls-verify=true" ,
fmt . Sprintf ( "--namespace=%v" , opts . Namespace ) ,
fmt . Sprintf ( "--context=%v" , opts . KubeContext ) ,
"create" ,
"secret" ,
"docker-registry" ,
opts . ContainerRegistrySecret ,
"--docker-server=my.registry:55555" ,
fmt . Sprintf ( "--docker-username=%v" , opts . ContainerRegistryUser ) ,
fmt . Sprintf ( "--docker-password=%v" , opts . ContainerRegistryPassword ) ,
2020-02-27 13:11:22 +02:00
} , e . Calls [ 1 ] . Params , "kubectl parameters incorrect" )
2020-01-24 15:30:27 +02:00
2020-02-27 13:11:22 +02:00
assert . Equal ( t , "kubectl" , e . Calls [ 2 ] . Exec , "Wrong apply command" )
2020-01-24 15:30:27 +02:00
assert . Equal ( t , [ ] string {
"--insecure-skip-tls-verify=true" ,
fmt . Sprintf ( "--namespace=%v" , opts . Namespace ) ,
fmt . Sprintf ( "--context=%v" , opts . KubeContext ) ,
"apply" ,
"--filename" ,
opts . AppTemplate ,
"--testParam" ,
"testValue" ,
2020-02-27 13:11:22 +02:00
} , e . Calls [ 2 ] . Params , "kubectl parameters incorrect" )
2020-01-24 15:30:27 +02:00
appTemplate , err := ioutil . ReadFile ( opts . AppTemplate )
assert . Contains ( t , string ( appTemplate ) , "my.registry:55555/path/to/Image:latest" )
} )
t . Run ( "test kubectl - lookup secret/kubeconfig" , func ( t * testing . T ) {
dir , err := ioutil . TempDir ( "" , "" )
defer os . RemoveAll ( dir ) // clean up
assert . NoError ( t , err , "Error when creating temp dir" )
opts := kubernetesDeployOptions {
AppTemplate : filepath . Join ( dir , "test.yaml" ) ,
ContainerRegistryURL : "https://my.registry:55555" ,
ContainerRegistryUser : "registryUser" ,
ContainerRegistryPassword : "********" ,
ContainerRegistrySecret : "regSecret" ,
CreateDockerRegistrySecret : true ,
DeployTool : "kubectl" ,
Image : "path/to/Image:latest" ,
KubeConfig : "This is my kubeconfig" ,
Namespace : "deploymentNamespace" ,
}
ioutil . WriteFile ( opts . AppTemplate , [ ] byte ( "testYaml" ) , 0755 )
2020-02-27 13:11:22 +02:00
e := mock . ExecMockRunner { }
2020-01-24 15:30:27 +02:00
var stdout bytes . Buffer
runKubernetesDeploy ( opts , & e , & stdout )
2020-02-27 13:11:22 +02:00
assert . Equal ( t , "kubectl" , e . Calls [ 0 ] . Exec , "Wrong secret lookup command" )
2020-01-24 15:30:27 +02:00
assert . Equal ( t , [ ] string {
"--insecure-skip-tls-verify=true" ,
fmt . Sprintf ( "--namespace=%v" , opts . Namespace ) ,
"get" ,
"secret" ,
opts . ContainerRegistrySecret ,
2020-02-27 13:11:22 +02:00
} , e . Calls [ 0 ] . Params , "kubectl parameters incorrect" )
2020-01-24 15:30:27 +02:00
2020-02-27 13:11:22 +02:00
assert . Equal ( t , "kubectl" , e . Calls [ 1 ] . Exec , "Wrong apply command" )
2020-01-24 15:30:27 +02:00
assert . Equal ( t , [ ] string {
"--insecure-skip-tls-verify=true" ,
fmt . Sprintf ( "--namespace=%v" , opts . Namespace ) ,
"apply" ,
"--filename" ,
opts . AppTemplate ,
2020-02-27 13:11:22 +02:00
} , e . Calls [ 1 ] . Params , "kubectl parameters incorrect" )
2020-01-24 15:30:27 +02:00
} )
t . Run ( "test kubectl - token only" , func ( t * testing . T ) {
dir , err := ioutil . TempDir ( "" , "" )
defer os . RemoveAll ( dir ) // clean up
assert . NoError ( t , err , "Error when creating temp dir" )
opts := kubernetesDeployOptions {
APIServer : "https://my.api.server" ,
AppTemplate : filepath . Join ( dir , "test.yaml" ) ,
ContainerRegistryURL : "https://my.registry:55555" ,
ContainerRegistryUser : "registryUser" ,
ContainerRegistryPassword : "********" ,
ContainerRegistrySecret : "regSecret" ,
DeployTool : "kubectl" ,
Image : "path/to/Image:latest" ,
KubeToken : "testToken" ,
Namespace : "deploymentNamespace" ,
}
ioutil . WriteFile ( opts . AppTemplate , [ ] byte ( "testYaml" ) , 0755 )
2020-02-27 13:11:22 +02:00
e := mock . ExecMockRunner {
ShouldFailOnCommand : map [ string ] error { } ,
2020-01-24 15:30:27 +02:00
}
var stdout bytes . Buffer
runKubernetesDeploy ( opts , & e , & stdout )
2020-02-27 13:11:22 +02:00
assert . Equal ( t , "kubectl" , e . Calls [ 0 ] . Exec , "Wrong apply command" )
2020-01-24 15:30:27 +02:00
assert . Equal ( t , [ ] string {
"--insecure-skip-tls-verify=true" ,
fmt . Sprintf ( "--namespace=%v" , opts . Namespace ) ,
fmt . Sprintf ( "--server=%v" , opts . APIServer ) ,
fmt . Sprintf ( "--token=%v" , opts . KubeToken ) ,
"apply" ,
"--filename" ,
opts . AppTemplate ,
2020-02-27 13:11:22 +02:00
} , e . Calls [ 0 ] . Params , "kubectl parameters incorrect" )
2020-01-24 15:30:27 +02:00
} )
}
func TestSplitRegistryURL ( t * testing . T ) {
tt := [ ] struct {
in string
outProtocol string
outRegistry string
outError error
} {
{ in : "https://my.registry.com" , outProtocol : "https" , outRegistry : "my.registry.com" , outError : nil } ,
{ in : "https://" , outProtocol : "" , outRegistry : "" , outError : fmt . Errorf ( "Failed to split registry url 'https://'" ) } ,
{ in : "my.registry.com" , outProtocol : "" , outRegistry : "" , outError : fmt . Errorf ( "Failed to split registry url 'my.registry.com'" ) } ,
{ in : "" , outProtocol : "" , outRegistry : "" , outError : fmt . Errorf ( "Failed to split registry url ''" ) } ,
{ in : "https://https://my.registry.com" , outProtocol : "" , outRegistry : "" , outError : fmt . Errorf ( "Failed to split registry url 'https://https://my.registry.com'" ) } ,
}
for _ , test := range tt {
p , r , err := splitRegistryURL ( test . in )
assert . Equal ( t , test . outProtocol , p , "Protocol value unexpected" )
assert . Equal ( t , test . outRegistry , r , "Registry value unexpected" )
assert . Equal ( t , test . outError , err , "Error value not as expected" )
}
}
func TestSplitImageName ( t * testing . T ) {
tt := [ ] struct {
in string
outImage string
outTag string
outError error
} {
{ in : "" , outImage : "" , outTag : "" , outError : fmt . Errorf ( "Failed to split image name ''" ) } ,
{ in : "path/to/image" , outImage : "path/to/image" , outTag : "" , outError : nil } ,
{ in : "path/to/image:tag" , outImage : "path/to/image" , outTag : "tag" , outError : nil } ,
{ in : "https://my.registry.com/path/to/image:tag" , outImage : "" , outTag : "" , outError : fmt . Errorf ( "Failed to split image name 'https://my.registry.com/path/to/image:tag'" ) } ,
}
for _ , test := range tt {
i , tag , err := splitFullImageName ( test . in )
assert . Equal ( t , test . outImage , i , "Image value unexpected" )
assert . Equal ( t , test . outTag , tag , "Tag value unexpected" )
assert . Equal ( t , test . outError , err , "Error value not as expected" )
}
}