Now that the InitKube initialization happens inside its own package, the private .values field can be populated at the same time, rather than having to wait for Prepare(). Also clarified the config/template filename fields (configFile vs. ConfigFile was particularly ambiguous).
264 lines
7 KiB
Go
264 lines
7 KiB
Go
package run
|
|
|
|
import (
|
|
"github.com/pelotech/drone-helm3/internal/env"
|
|
"github.com/stretchr/testify/suite"
|
|
yaml "gopkg.in/yaml.v2"
|
|
"io/ioutil"
|
|
"os"
|
|
"testing"
|
|
"text/template"
|
|
)
|
|
|
|
type InitKubeTestSuite struct {
|
|
suite.Suite
|
|
}
|
|
|
|
func TestInitKubeTestSuite(t *testing.T) {
|
|
suite.Run(t, new(InitKubeTestSuite))
|
|
}
|
|
|
|
func (suite *InitKubeTestSuite) TestNewInitKube() {
|
|
cfg := env.Config{
|
|
SkipTLSVerify: true,
|
|
Certificate: "cHJvY2xhaW1zIHdvbmRlcmZ1bCBmcmllbmRzaGlw",
|
|
APIServer: "98.765.43.21",
|
|
ServiceAccount: "greathelm",
|
|
KubeToken: "b2YgbXkgYWZmZWN0aW9u",
|
|
}
|
|
|
|
init := NewInitKube(cfg, "conf.tpl", "conf.yml")
|
|
suite.Equal(&InitKube{
|
|
values: kubeValues{
|
|
SkipTLSVerify: true,
|
|
Certificate: "cHJvY2xhaW1zIHdvbmRlcmZ1bCBmcmllbmRzaGlw",
|
|
APIServer: "98.765.43.21",
|
|
ServiceAccount: "greathelm",
|
|
Token: "b2YgbXkgYWZmZWN0aW9u",
|
|
},
|
|
templateFilename: "conf.tpl",
|
|
configFilename: "conf.yml",
|
|
}, init)
|
|
}
|
|
|
|
func (suite *InitKubeTestSuite) TestPrepareExecute() {
|
|
templateFile, err := tempfile("kubeconfig********.yml.tpl", `
|
|
certificate: {{ .Certificate }}
|
|
namespace: {{ .Namespace }}
|
|
`)
|
|
defer os.Remove(templateFile.Name())
|
|
suite.Require().Nil(err)
|
|
|
|
configFile, err := tempfile("kubeconfig********.yml", "")
|
|
defer os.Remove(configFile.Name())
|
|
suite.Require().Nil(err)
|
|
|
|
init := InitKube{
|
|
values: kubeValues{
|
|
APIServer: "Sysadmin",
|
|
Certificate: "CCNA",
|
|
Token: "Aspire virtual currency",
|
|
Namespace: "Cisco",
|
|
},
|
|
templateFilename: templateFile.Name(),
|
|
configFilename: configFile.Name(),
|
|
}
|
|
cfg := Config{}
|
|
err = init.Prepare(cfg)
|
|
suite.Require().Nil(err)
|
|
|
|
suite.IsType(&template.Template{}, init.template)
|
|
suite.NotNil(init.configFile)
|
|
|
|
err = init.Execute(cfg)
|
|
suite.Require().Nil(err)
|
|
|
|
conf, err := ioutil.ReadFile(configFile.Name())
|
|
suite.Require().Nil(err)
|
|
|
|
want := `
|
|
certificate: CCNA
|
|
namespace: Cisco
|
|
`
|
|
suite.Equal(want, string(conf))
|
|
}
|
|
|
|
func (suite *InitKubeTestSuite) TestExecuteGeneratesConfig() {
|
|
configFile, err := tempfile("kubeconfig********.yml", "")
|
|
defer os.Remove(configFile.Name())
|
|
suite.Require().NoError(err)
|
|
|
|
cfg := Config{}
|
|
init := InitKube{
|
|
configFilename: configFile.Name(),
|
|
templateFilename: "../../assets/kubeconfig.tpl", // the actual kubeconfig template
|
|
values: kubeValues{
|
|
APIServer: "https://kube.cluster/peanut",
|
|
ServiceAccount: "chef",
|
|
Token: "eWVhaCB3ZSB0b2tpbic=",
|
|
Certificate: "d293LCB5b3UgYXJlIHNvIGNvb2wgZm9yIHNtb2tpbmcgd2VlZCDwn5mE",
|
|
Namespace: "marshmallow",
|
|
},
|
|
}
|
|
suite.Require().NoError(init.Prepare(cfg))
|
|
suite.Require().NoError(init.Execute(cfg))
|
|
|
|
contents, err := ioutil.ReadFile(configFile.Name())
|
|
suite.Require().NoError(err)
|
|
|
|
// each setting should be reflected in the generated file
|
|
expectations := []string{
|
|
"namespace: marshmallow",
|
|
"server: https://kube.cluster/peanut",
|
|
"user: chef",
|
|
"name: chef",
|
|
"token: eWVhaCB3ZSB0b2tpbic",
|
|
"certificate-authority-data: d293LCB5b3UgYXJlIHNvIGNvb2wgZm9yIHNtb2tpbmcgd2VlZCDwn5mE",
|
|
}
|
|
for _, expected := range expectations {
|
|
suite.Contains(string(contents), expected)
|
|
}
|
|
|
|
// the generated config should be valid yaml, with no repeated keys
|
|
conf := map[string]interface{}{}
|
|
suite.NoError(yaml.UnmarshalStrict(contents, &conf))
|
|
|
|
// test the other branch of the certificate/SkipTLSVerify conditional
|
|
init.values.SkipTLSVerify = true
|
|
init.values.Certificate = ""
|
|
|
|
suite.Require().NoError(init.Prepare(cfg))
|
|
suite.Require().NoError(init.Execute(cfg))
|
|
contents, err = ioutil.ReadFile(configFile.Name())
|
|
suite.Require().NoError(err)
|
|
suite.Contains(string(contents), "insecure-skip-tls-verify: true")
|
|
|
|
conf = map[string]interface{}{}
|
|
suite.NoError(yaml.UnmarshalStrict(contents, &conf))
|
|
}
|
|
|
|
func (suite *InitKubeTestSuite) TestPrepareParseError() {
|
|
templateFile, err := tempfile("kubeconfig********.yml.tpl", `{{ NonexistentFunction }}`)
|
|
defer os.Remove(templateFile.Name())
|
|
suite.Require().Nil(err)
|
|
|
|
init := InitKube{
|
|
values: kubeValues{
|
|
APIServer: "Sysadmin",
|
|
Certificate: "CCNA",
|
|
Token: "Aspire virtual currency",
|
|
},
|
|
templateFilename: templateFile.Name(),
|
|
}
|
|
err = init.Prepare(Config{})
|
|
suite.Error(err)
|
|
suite.Regexp("could not load kubeconfig .* function .* not defined", err)
|
|
}
|
|
|
|
func (suite *InitKubeTestSuite) TestPrepareNonexistentTemplateFile() {
|
|
init := InitKube{
|
|
values: kubeValues{
|
|
APIServer: "Sysadmin",
|
|
Certificate: "CCNA",
|
|
Token: "Aspire virtual currency",
|
|
},
|
|
templateFilename: "/usr/foreign/exclude/kubeprofig.tpl",
|
|
}
|
|
err := init.Prepare(Config{})
|
|
suite.Error(err)
|
|
suite.Regexp("could not load kubeconfig .* no such file or directory", err)
|
|
}
|
|
|
|
func (suite *InitKubeTestSuite) TestPrepareCannotOpenDestinationFile() {
|
|
templateFile, err := tempfile("kubeconfig********.yml.tpl", "hurgity burgity")
|
|
defer os.Remove(templateFile.Name())
|
|
suite.Require().Nil(err)
|
|
init := InitKube{
|
|
values: kubeValues{
|
|
APIServer: "Sysadmin",
|
|
Certificate: "CCNA",
|
|
Token: "Aspire virtual currency",
|
|
},
|
|
templateFilename: templateFile.Name(),
|
|
configFilename: "/usr/foreign/exclude/kubeprofig",
|
|
}
|
|
|
|
cfg := Config{}
|
|
err = init.Prepare(cfg)
|
|
suite.Error(err)
|
|
suite.Regexp("could not open .* for writing: .* no such file or directory", err)
|
|
}
|
|
|
|
func (suite *InitKubeTestSuite) TestPrepareRequiredConfig() {
|
|
templateFile, err := tempfile("kubeconfig********.yml.tpl", "hurgity burgity")
|
|
defer os.Remove(templateFile.Name())
|
|
suite.Require().Nil(err)
|
|
|
|
configFile, err := tempfile("kubeconfig********.yml", "")
|
|
defer os.Remove(configFile.Name())
|
|
suite.Require().Nil(err)
|
|
|
|
// initial config with all required fields present
|
|
init := InitKube{
|
|
values: kubeValues{
|
|
APIServer: "Sysadmin",
|
|
Certificate: "CCNA",
|
|
Token: "Aspire virtual currency",
|
|
},
|
|
templateFilename: templateFile.Name(),
|
|
configFilename: configFile.Name(),
|
|
}
|
|
|
|
cfg := Config{}
|
|
|
|
suite.NoError(init.Prepare(cfg)) // consistency check; we should be starting in a happy state
|
|
|
|
init.values.APIServer = ""
|
|
suite.Error(init.Prepare(cfg), "APIServer should be required.")
|
|
|
|
init.values.APIServer = "Sysadmin"
|
|
init.values.Token = ""
|
|
suite.Error(init.Prepare(cfg), "Token should be required.")
|
|
}
|
|
|
|
func (suite *InitKubeTestSuite) TestPrepareDefaultsServiceAccount() {
|
|
templateFile, err := tempfile("kubeconfig********.yml.tpl", "hurgity burgity")
|
|
defer os.Remove(templateFile.Name())
|
|
suite.Require().Nil(err)
|
|
|
|
configFile, err := tempfile("kubeconfig********.yml", "")
|
|
defer os.Remove(configFile.Name())
|
|
suite.Require().Nil(err)
|
|
|
|
init := InitKube{
|
|
values: kubeValues{
|
|
APIServer: "Sysadmin",
|
|
Certificate: "CCNA",
|
|
Token: "Aspire virtual currency",
|
|
},
|
|
templateFilename: templateFile.Name(),
|
|
configFilename: configFile.Name(),
|
|
}
|
|
|
|
cfg := Config{}
|
|
|
|
init.Prepare(cfg)
|
|
suite.Equal("helm", init.values.ServiceAccount)
|
|
}
|
|
|
|
func tempfile(name, contents string) (*os.File, error) {
|
|
file, err := ioutil.TempFile("", name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
_, err = file.Write([]byte(contents))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = file.Close()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return file, nil
|
|
}
|