mirror of https://github.com/hashicorp/consul
364 lines
9.1 KiB
Go
364 lines
9.1 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package expose
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/mitchellh/cli"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/hashicorp/consul/agent"
|
|
"github.com/hashicorp/consul/api"
|
|
"github.com/hashicorp/consul/testrpc"
|
|
)
|
|
|
|
func TestConnectExpose(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Skip("too slow for testing.Short")
|
|
}
|
|
|
|
t.Parallel()
|
|
a := agent.NewTestAgent(t, ``)
|
|
client := a.Client()
|
|
defer a.Shutdown()
|
|
|
|
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
|
|
{
|
|
ui := cli.NewMockUi()
|
|
c := New(ui)
|
|
args := []string{
|
|
"-http-addr=" + a.HTTPAddr(),
|
|
"-service=foo",
|
|
"-ingress-gateway=ingress",
|
|
"-port=8888",
|
|
"-protocol=tcp",
|
|
}
|
|
|
|
code := c.Run(args)
|
|
if code != 0 {
|
|
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
|
}
|
|
}
|
|
|
|
// Make sure the config entry and intention have been created.
|
|
entry, _, err := client.ConfigEntries().Get(api.IngressGateway, "ingress", nil)
|
|
require.NoError(t, err)
|
|
ns := entry.(*api.IngressGatewayConfigEntry).Namespace
|
|
ap := entry.(*api.IngressGatewayConfigEntry).Partition
|
|
expected := &api.IngressGatewayConfigEntry{
|
|
Kind: api.IngressGateway,
|
|
Name: "ingress",
|
|
Namespace: ns,
|
|
Partition: ap,
|
|
Listeners: []api.IngressListener{
|
|
{
|
|
Port: 8888,
|
|
Protocol: "tcp",
|
|
Services: []api.IngressService{
|
|
{
|
|
Name: "foo",
|
|
Namespace: ns,
|
|
Partition: ap,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
expected.CreateIndex = entry.GetCreateIndex()
|
|
expected.ModifyIndex = entry.GetModifyIndex()
|
|
require.Equal(t, expected, entry)
|
|
|
|
ixns, _, err := client.Connect().Intentions(nil)
|
|
require.NoError(t, err)
|
|
require.Len(t, ixns, 1)
|
|
require.Equal(t, "ingress", ixns[0].SourceName)
|
|
require.Equal(t, "foo", ixns[0].DestinationName)
|
|
|
|
// Run the command again with a different port, make sure the config entry
|
|
// is updated while intentions are unmodified.
|
|
{
|
|
ui := cli.NewMockUi()
|
|
c := New(ui)
|
|
args := []string{
|
|
"-http-addr=" + a.HTTPAddr(),
|
|
"-service=foo",
|
|
"-ingress-gateway=ingress",
|
|
"-port=7777",
|
|
"-protocol=tcp",
|
|
}
|
|
|
|
code := c.Run(args)
|
|
if code != 0 {
|
|
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
|
}
|
|
|
|
expected.Listeners = append(expected.Listeners, api.IngressListener{
|
|
Port: 7777,
|
|
Protocol: "tcp",
|
|
Services: []api.IngressService{
|
|
{
|
|
Name: "foo",
|
|
Namespace: ns,
|
|
Partition: ap,
|
|
},
|
|
},
|
|
})
|
|
|
|
// Make sure the config entry/intention weren't affected.
|
|
entry, _, err = client.ConfigEntries().Get(api.IngressGateway, "ingress", nil)
|
|
require.NoError(t, err)
|
|
expected.ModifyIndex = entry.GetModifyIndex()
|
|
require.Equal(t, expected, entry)
|
|
|
|
ixns, _, err = client.Connect().Intentions(nil)
|
|
require.NoError(t, err)
|
|
require.Len(t, ixns, 1)
|
|
require.Equal(t, "ingress", ixns[0].SourceName)
|
|
require.Equal(t, "foo", ixns[0].DestinationName)
|
|
}
|
|
|
|
// Run the command again with a conflicting protocol, should exit with an error and
|
|
// cause no changes to config entry/intentions.
|
|
{
|
|
ui := cli.NewMockUi()
|
|
c := New(ui)
|
|
args := []string{
|
|
"-http-addr=" + a.HTTPAddr(),
|
|
"-service=bar",
|
|
"-ingress-gateway=ingress",
|
|
"-port=8888",
|
|
"-protocol=http",
|
|
}
|
|
|
|
code := c.Run(args)
|
|
if code != 1 {
|
|
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
|
}
|
|
require.Contains(t, ui.ErrorWriter.String(), `conflicting protocol "tcp"`)
|
|
|
|
// Make sure the config entry/intention weren't affected.
|
|
entry, _, err = client.ConfigEntries().Get(api.IngressGateway, "ingress", nil)
|
|
require.NoError(t, err)
|
|
require.Equal(t, expected, entry)
|
|
|
|
ixns, _, err = client.Connect().Intentions(nil)
|
|
require.NoError(t, err)
|
|
require.Len(t, ixns, 1)
|
|
require.Equal(t, "ingress", ixns[0].SourceName)
|
|
require.Equal(t, "foo", ixns[0].DestinationName)
|
|
}
|
|
}
|
|
|
|
func TestConnectExpose_invalidFlags(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Skip("too slow for testing.Short")
|
|
}
|
|
|
|
t.Parallel()
|
|
a := agent.NewTestAgent(t, ``)
|
|
defer a.Shutdown()
|
|
|
|
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
|
|
t.Run("missing service", func(t *testing.T) {
|
|
ui := cli.NewMockUi()
|
|
c := New(ui)
|
|
args := []string{
|
|
"-http-addr=" + a.HTTPAddr(),
|
|
}
|
|
|
|
code := c.Run(args)
|
|
if code != 1 {
|
|
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
|
}
|
|
require.Contains(t, ui.ErrorWriter.String(), "A service name must be given")
|
|
})
|
|
t.Run("missing gateway", func(t *testing.T) {
|
|
ui := cli.NewMockUi()
|
|
c := New(ui)
|
|
args := []string{
|
|
"-http-addr=" + a.HTTPAddr(),
|
|
"-service=foo",
|
|
}
|
|
|
|
code := c.Run(args)
|
|
if code != 1 {
|
|
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
|
}
|
|
require.Contains(t, ui.ErrorWriter.String(), "An ingress gateway service must be given")
|
|
})
|
|
t.Run("missing port", func(t *testing.T) {
|
|
ui := cli.NewMockUi()
|
|
c := New(ui)
|
|
args := []string{
|
|
"-http-addr=" + a.HTTPAddr(),
|
|
"-service=foo",
|
|
"-ingress-gateway=ingress",
|
|
}
|
|
|
|
code := c.Run(args)
|
|
if code != 1 {
|
|
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
|
}
|
|
require.Contains(t, ui.ErrorWriter.String(), "A port must be provided")
|
|
})
|
|
}
|
|
|
|
func TestConnectExpose_existingConfig(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Skip("too slow for testing.Short")
|
|
}
|
|
|
|
t.Parallel()
|
|
a := agent.NewTestAgent(t, ``)
|
|
client := a.Client()
|
|
defer a.Shutdown()
|
|
|
|
// Create some service config entries to set their protocol.
|
|
for _, service := range []string{"bar", "zoo"} {
|
|
_, _, err := client.ConfigEntries().Set(&api.ServiceConfigEntry{
|
|
Kind: "service-defaults",
|
|
Name: service,
|
|
Protocol: "http",
|
|
}, nil)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Create an existing ingress config entry with some services.
|
|
ingressConf := &api.IngressGatewayConfigEntry{
|
|
Kind: api.IngressGateway,
|
|
Name: "ingress",
|
|
Listeners: []api.IngressListener{
|
|
{
|
|
Port: 8888,
|
|
Protocol: "tcp",
|
|
Services: []api.IngressService{
|
|
{
|
|
Name: "foo",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Port: 9999,
|
|
Protocol: "http",
|
|
Services: []api.IngressService{
|
|
{
|
|
Name: "bar",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
_, _, err := client.ConfigEntries().Set(ingressConf, nil)
|
|
require.NoError(t, err)
|
|
|
|
// Add a service on a new port.
|
|
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
|
|
{
|
|
ui := cli.NewMockUi()
|
|
c := New(ui)
|
|
args := []string{
|
|
"-http-addr=" + a.HTTPAddr(),
|
|
"-service=baz",
|
|
"-ingress-gateway=ingress",
|
|
"-port=10000",
|
|
"-protocol=tcp",
|
|
}
|
|
|
|
code := c.Run(args)
|
|
if code != 0 {
|
|
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
|
}
|
|
|
|
// Make sure the ingress config was updated and existing services preserved.
|
|
entry, _, err := client.ConfigEntries().Get(api.IngressGateway, "ingress", nil)
|
|
require.NoError(t, err)
|
|
|
|
entryConf := entry.(*api.IngressGatewayConfigEntry)
|
|
ingressConf.Listeners = append(ingressConf.Listeners, api.IngressListener{
|
|
Port: 10000,
|
|
Protocol: "tcp",
|
|
Services: []api.IngressService{
|
|
{
|
|
Name: "baz",
|
|
},
|
|
},
|
|
})
|
|
ingressConf.Partition = entryConf.Partition
|
|
ingressConf.Namespace = entryConf.Namespace
|
|
for i, listener := range ingressConf.Listeners {
|
|
listener.Services[0].Namespace = entryConf.Listeners[i].Services[0].Namespace
|
|
listener.Services[0].Partition = entryConf.Listeners[i].Services[0].Partition
|
|
}
|
|
ingressConf.CreateIndex = entry.GetCreateIndex()
|
|
ingressConf.ModifyIndex = entry.GetModifyIndex()
|
|
require.Equal(t, ingressConf, entry)
|
|
}
|
|
|
|
// Add an service on a port shared with an existing listener.
|
|
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
|
|
{
|
|
ui := cli.NewMockUi()
|
|
c := New(ui)
|
|
args := []string{
|
|
"-http-addr=" + a.HTTPAddr(),
|
|
"-service=zoo",
|
|
"-ingress-gateway=ingress",
|
|
"-port=9999",
|
|
"-protocol=http",
|
|
"-host=foo.com",
|
|
"-host=foo.net",
|
|
}
|
|
|
|
code := c.Run(args)
|
|
if code != 0 {
|
|
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
|
}
|
|
|
|
// Make sure the ingress config was updated and existing services preserved.
|
|
entry, _, err := client.ConfigEntries().Get(api.IngressGateway, "ingress", nil)
|
|
require.NoError(t, err)
|
|
|
|
entryConf := entry.(*api.IngressGatewayConfigEntry)
|
|
ingressConf.Listeners[1].Services = append(ingressConf.Listeners[1].Services, api.IngressService{
|
|
Name: "zoo",
|
|
Namespace: entryConf.Listeners[1].Services[1].Namespace,
|
|
Partition: entryConf.Listeners[1].Services[1].Partition,
|
|
Hosts: []string{"foo.com", "foo.net"},
|
|
})
|
|
ingressConf.CreateIndex = entry.GetCreateIndex()
|
|
ingressConf.ModifyIndex = entry.GetModifyIndex()
|
|
require.Equal(t, ingressConf, entry)
|
|
}
|
|
|
|
// Update the bar service and add a custom host.
|
|
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
|
|
{
|
|
ui := cli.NewMockUi()
|
|
c := New(ui)
|
|
args := []string{
|
|
"-http-addr=" + a.HTTPAddr(),
|
|
"-service=bar",
|
|
"-ingress-gateway=ingress",
|
|
"-port=9999",
|
|
"-protocol=http",
|
|
"-host=bar.com",
|
|
}
|
|
|
|
code := c.Run(args)
|
|
if code != 0 {
|
|
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
|
}
|
|
|
|
// Make sure the ingress config was updated and existing services preserved.
|
|
entry, _, err := client.ConfigEntries().Get(api.IngressGateway, "ingress", nil)
|
|
require.NoError(t, err)
|
|
|
|
ingressConf.Listeners[1].Services[0].Hosts = []string{"bar.com"}
|
|
ingressConf.CreateIndex = entry.GetCreateIndex()
|
|
ingressConf.ModifyIndex = entry.GetModifyIndex()
|
|
require.Equal(t, ingressConf, entry)
|
|
}
|
|
}
|