traefik/pkg/provider/nomad/nomad_test.go
2024-04-04 11:54:04 +02:00

471 lines
13 KiB
Go

package nomad
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/traefik/traefik/v3/pkg/types"
)
var responses = map[string][]byte{}
func TestMain(m *testing.M) {
err := setup()
if err != nil {
fmt.Fprintf(os.Stderr, "%s", err.Error())
os.Exit(1)
}
m.Run()
}
func Test_globalConfig(t *testing.T) {
cases := []struct {
Name string
Prefix string
Tags []string
ExposedByDefault bool
exp configuration
}{
{
Name: "expose_by_default_no_tags",
Prefix: "traefik",
Tags: nil,
ExposedByDefault: true,
exp: configuration{Enable: true},
},
{
Name: "not_expose_by_default_no_tags",
Prefix: "traefik",
Tags: nil,
ExposedByDefault: false,
exp: configuration{Enable: false},
},
{
Name: "expose_by_default_tags_enable",
Prefix: "traefik",
Tags: []string{"traefik.enable=true"},
ExposedByDefault: true,
exp: configuration{Enable: true},
},
{
Name: "expose_by_default_tags_disable",
Prefix: "traefik",
Tags: []string{"traefik.enable=false"},
ExposedByDefault: true,
exp: configuration{Enable: false},
},
{
Name: "expose_by_default_tags_enable_custom_prefix",
Prefix: "custom",
Tags: []string{"custom.enable=true"},
ExposedByDefault: true,
exp: configuration{Enable: true},
},
{
Name: "expose_by_default_tags_disable_custom_prefix",
Prefix: "custom",
Tags: []string{"custom.enable=false"},
ExposedByDefault: true,
exp: configuration{Enable: false},
},
}
for _, test := range cases {
t.Run(test.Name, func(t *testing.T) {
p := Provider{
Configuration: Configuration{
ExposedByDefault: test.ExposedByDefault,
Prefix: test.Prefix,
},
}
result := p.getExtraConf(test.Tags)
require.Equal(t, test.exp, result)
})
}
}
func TestProvider_SetDefaults_Endpoint(t *testing.T) {
testCases := []struct {
desc string
envs map[string]string
expected *EndpointConfig
}{
{
desc: "without env vars",
envs: map[string]string{},
expected: &EndpointConfig{
Address: "http://127.0.0.1:4646",
},
},
{
desc: "with env vars",
envs: map[string]string{
"NOMAD_ADDR": "https://nomad.example.com",
"NOMAD_REGION": "us-west",
"NOMAD_TOKEN": "almighty_token",
"NOMAD_CACERT": "/etc/ssl/private/nomad-agent-ca.pem",
"NOMAD_CLIENT_CERT": "/etc/ssl/private/global-client-nomad.pem",
"NOMAD_CLIENT_KEY": "/etc/ssl/private/global-client-nomad-key.pem",
"NOMAD_SKIP_VERIFY": "true",
},
expected: &EndpointConfig{
Address: "https://nomad.example.com",
Region: "us-west",
Token: "almighty_token",
TLS: &types.ClientTLS{
CA: "/etc/ssl/private/nomad-agent-ca.pem",
Cert: "/etc/ssl/private/global-client-nomad.pem",
Key: "/etc/ssl/private/global-client-nomad-key.pem",
InsecureSkipVerify: true,
},
EndpointWaitTime: 0,
},
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
for k, v := range test.envs {
t.Setenv(k, v)
}
p := &Provider{}
p.SetDefaults()
assert.Equal(t, test.expected, p.Endpoint)
})
}
}
func Test_getNomadServiceDataWithEmptyServices_GroupService_Scaling1(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch {
case strings.HasSuffix(r.RequestURI, "/v1/jobs"):
_, _ = w.Write(responses["jobs_job1"])
case strings.HasSuffix(r.RequestURI, "/v1/job/job1"):
_, _ = w.Write(responses["job_job1_WithGroupService_Scaling1"])
case strings.HasSuffix(r.RequestURI, "/v1/service/job1"):
_, _ = w.Write(responses["service_job1"])
}
}))
t.Cleanup(ts.Close)
p := new(Provider)
p.SetDefaults()
p.Endpoint.Address = ts.URL
err := p.Init()
require.NoError(t, err)
// fudge client, avoid starting up via Provide
p.client, err = createClient(p.namespace, p.Endpoint)
require.NoError(t, err)
// make the query for services
items, err := p.getNomadServiceDataWithEmptyServices(context.TODO())
require.NoError(t, err)
require.Len(t, items, 1)
}
func Test_getNomadServiceDataWithEmptyServices_GroupService_Scaling0(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch {
case strings.HasSuffix(r.RequestURI, "/v1/jobs"):
_, _ = w.Write(responses["jobs_job2"])
case strings.HasSuffix(r.RequestURI, "/v1/job/job2"):
_, _ = w.Write(responses["job_job2_WithGroupService_Scaling0"])
case strings.HasSuffix(r.RequestURI, "/v1/service/job2"):
_, _ = w.Write(responses["service_job2"])
}
}))
t.Cleanup(ts.Close)
p := new(Provider)
p.SetDefaults()
p.Endpoint.Address = ts.URL
err := p.Init()
require.NoError(t, err)
// fudge client, avoid starting up via Provide
p.client, err = createClient(p.namespace, p.Endpoint)
require.NoError(t, err)
// make the query for services
items, err := p.getNomadServiceDataWithEmptyServices(context.TODO())
require.NoError(t, err)
require.Len(t, items, 1)
}
func Test_getNomadServiceDataWithEmptyServices_GroupService_ScalingDisabled(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch {
case strings.HasSuffix(r.RequestURI, "/v1/jobs"):
_, _ = w.Write(responses["jobs_job3"])
case strings.HasSuffix(r.RequestURI, "/v1/job/job3"):
_, _ = w.Write(responses["job_job3_WithGroupService_ScalingDisabled"])
case strings.HasSuffix(r.RequestURI, "/v1/service/job3"):
_, _ = w.Write(responses["service_job3"])
}
}))
t.Cleanup(ts.Close)
p := new(Provider)
p.SetDefaults()
p.Endpoint.Address = ts.URL
err := p.Init()
require.NoError(t, err)
// fudge client, avoid starting up via Provide
p.client, err = createClient(p.namespace, p.Endpoint)
require.NoError(t, err)
// make the query for services
items, err := p.getNomadServiceDataWithEmptyServices(context.TODO())
require.NoError(t, err)
require.Len(t, items, 1)
}
func Test_getNomadServiceDataWithEmptyServices_GroupService_ScalingDisabled_Stopped(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch {
case strings.HasSuffix(r.RequestURI, "/v1/jobs"):
_, _ = w.Write(responses["jobs_job4"])
case strings.HasSuffix(r.RequestURI, "/v1/job/job4"):
_, _ = w.Write(responses["job_job4_WithGroupService_ScalingDisabled_Stopped"])
case strings.HasSuffix(r.RequestURI, "/v1/service/job4"):
_, _ = w.Write(responses["service_job4"])
}
}))
t.Cleanup(ts.Close)
p := new(Provider)
p.SetDefaults()
p.Endpoint.Address = ts.URL
err := p.Init()
require.NoError(t, err)
// fudge client, avoid starting up via Provide
p.client, err = createClient(p.namespace, p.Endpoint)
require.NoError(t, err)
// make the query for services
items, err := p.getNomadServiceDataWithEmptyServices(context.TODO())
require.NoError(t, err)
// Should not be listed as job is stopped
require.Empty(t, items)
}
func Test_getNomadServiceDataWithEmptyServices_GroupTaskService_Scaling1(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch {
case strings.HasSuffix(r.RequestURI, "/v1/jobs"):
_, _ = w.Write(responses["jobs_job5"])
case strings.HasSuffix(r.RequestURI, "/v1/job/job5"):
_, _ = w.Write(responses["job_job5_WithGroupTaskService_Scaling1"])
case strings.HasSuffix(r.RequestURI, "/v1/service/job5task1"):
_, _ = w.Write(responses["service_job5task1"])
case strings.HasSuffix(r.RequestURI, "/v1/service/job5task2"):
_, _ = w.Write(responses["service_job5task2"])
}
}))
t.Cleanup(ts.Close)
p := new(Provider)
p.SetDefaults()
p.Endpoint.Address = ts.URL
err := p.Init()
require.NoError(t, err)
// fudge client, avoid starting up via Provide
p.client, err = createClient(p.namespace, p.Endpoint)
require.NoError(t, err)
// make the query for services
items, err := p.getNomadServiceDataWithEmptyServices(context.TODO())
require.NoError(t, err)
require.Len(t, items, 2)
}
func Test_getNomadServiceDataWithEmptyServices_GroupTaskService_Scaling0(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch {
case strings.HasSuffix(r.RequestURI, "/v1/jobs"):
_, _ = w.Write(responses["jobs_job6"])
case strings.HasSuffix(r.RequestURI, "/v1/job/job6"):
_, _ = w.Write(responses["job_job6_WithGroupTaskService_Scaling0"])
case strings.HasSuffix(r.RequestURI, "/v1/service/job6task1"):
_, _ = w.Write(responses["service_job6task1"])
case strings.HasSuffix(r.RequestURI, "/v1/service/job6task2"):
_, _ = w.Write(responses["service_job6task2"])
}
}))
t.Cleanup(ts.Close)
p := new(Provider)
p.SetDefaults()
p.Endpoint.Address = ts.URL
err := p.Init()
require.NoError(t, err)
// fudge client, avoid starting up via Provide
p.client, err = createClient(p.namespace, p.Endpoint)
require.NoError(t, err)
// make the query for services
items, err := p.getNomadServiceDataWithEmptyServices(context.TODO())
require.NoError(t, err)
require.Len(t, items, 2)
}
func Test_getNomadServiceDataWithEmptyServices_TCP(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch {
case strings.HasSuffix(r.RequestURI, "/v1/jobs"):
_, _ = w.Write(responses["jobs_job7"])
case strings.HasSuffix(r.RequestURI, "/v1/job/job7"):
_, _ = w.Write(responses["job_job7_TCP"])
case strings.HasSuffix(r.RequestURI, "/v1/service/job7"):
_, _ = w.Write(responses["service_job7"])
}
}))
t.Cleanup(ts.Close)
p := new(Provider)
p.SetDefaults()
p.Endpoint.Address = ts.URL
err := p.Init()
require.NoError(t, err)
// fudge client, avoid starting up via Provide
p.client, err = createClient(p.namespace, p.Endpoint)
require.NoError(t, err)
// make the query for services
items, err := p.getNomadServiceDataWithEmptyServices(context.TODO())
require.NoError(t, err)
require.Len(t, items, 1)
}
func Test_getNomadServiceDataWithEmptyServices_UDP(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch {
case strings.HasSuffix(r.RequestURI, "/v1/jobs"):
_, _ = w.Write(responses["jobs_job8"])
case strings.HasSuffix(r.RequestURI, "/v1/job/job8"):
_, _ = w.Write(responses["job_job8_UDP"])
case strings.HasSuffix(r.RequestURI, "/v1/service/job8"):
_, _ = w.Write(responses["service_job8"])
}
}))
t.Cleanup(ts.Close)
p := new(Provider)
p.SetDefaults()
p.Endpoint.Address = ts.URL
err := p.Init()
require.NoError(t, err)
// fudge client, avoid starting up via Provide
p.client, err = createClient(p.namespace, p.Endpoint)
require.NoError(t, err)
// make the query for services
items, err := p.getNomadServiceDataWithEmptyServices(context.TODO())
require.NoError(t, err)
require.Len(t, items, 1)
}
func Test_getNomadServiceDataWithEmptyServices_ScalingEnabled_Stopped(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch {
case strings.HasSuffix(r.RequestURI, "/v1/jobs"):
_, _ = w.Write(responses["jobs_job9"])
case strings.HasSuffix(r.RequestURI, "/v1/job/job9"):
_, _ = w.Write(responses["job_job9_ScalingEnabled_Stopped"])
case strings.HasSuffix(r.RequestURI, "/v1/service/job9"):
_, _ = w.Write(responses["service_job9"])
}
}))
t.Cleanup(ts.Close)
p := new(Provider)
p.SetDefaults()
p.Endpoint.Address = ts.URL
err := p.Init()
require.NoError(t, err)
// fudge client, avoid starting up via Provide
p.client, err = createClient(p.namespace, p.Endpoint)
require.NoError(t, err)
// make the query for services
items, err := p.getNomadServiceDataWithEmptyServices(context.TODO())
require.NoError(t, err)
// Should not be listed as job is stopped
require.Empty(t, items)
}
func setup() error {
responsesDir := "./fixtures"
files, err := os.ReadDir(responsesDir)
if err != nil {
return err
}
for _, file := range files {
if !file.IsDir() && filepath.Ext(file.Name()) == ".json" {
content, err := os.ReadFile(filepath.Join(responsesDir, file.Name()))
if err != nil {
return err
}
responses[strings.TrimSuffix(filepath.Base(file.Name()), filepath.Ext(file.Name()))] = content
}
}
return nil
}
func Test_getNomadServiceData(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch {
case strings.HasSuffix(r.RequestURI, "/v1/services"):
_, _ = w.Write(responses["services"])
case strings.HasSuffix(r.RequestURI, "/v1/service/redis"):
_, _ = w.Write(responses["service_redis"])
case strings.HasSuffix(r.RequestURI, "/v1/service/hello-nomad"):
_, _ = w.Write(responses["service_hello"])
}
}))
t.Cleanup(ts.Close)
p := new(Provider)
p.SetDefaults()
p.Endpoint.Address = ts.URL
err := p.Init()
require.NoError(t, err)
// fudge client, avoid starting up via Provide
p.client, err = createClient(p.namespace, p.Endpoint)
require.NoError(t, err)
// make the query for services
items, err := p.getNomadServiceData(context.TODO())
require.NoError(t, err)
require.Len(t, items, 2)
}