Skip to content

Commit

Permalink
add support for multiple hosts, default to no host
Browse files Browse the repository at this point in the history
  • Loading branch information
colesnodgrass committed Sep 10, 2024
1 parent cd48a2a commit 0ecfa9d
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 16 deletions.
12 changes: 6 additions & 6 deletions internal/cmd/local/local/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ import (
"helm.sh/helm/v3/pkg/release"
"helm.sh/helm/v3/pkg/repo"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
eventsv1 "k8s.io/api/events/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
Expand All @@ -46,7 +46,7 @@ type InstallOpts struct {
ValuesFile string
Secrets []string
Migrate bool
Host string
Hosts []string

Docker *docker.Docker

Expand Down Expand Up @@ -307,7 +307,7 @@ func (c *Command) Install(ctx context.Context, opts InstallOpts) error {
return fmt.Errorf("unable to install nginx chart: %w", err)
}

if err := c.handleIngress(ctx, opts.Host); err != nil {
if err := c.handleIngress(ctx, opts.Hosts); err != nil {
return err
}

Expand All @@ -329,12 +329,12 @@ func (c *Command) Install(ctx context.Context, opts InstallOpts) error {
return nil
}

func (c *Command) handleIngress(ctx context.Context, host string) error {
func (c *Command) handleIngress(ctx context.Context, hosts []string) error {
c.spinner.UpdateText("Checking for existing Ingress")

if c.k8s.IngressExists(ctx, airbyteNamespace, airbyteIngress) {
pterm.Success.Println("Found existing Ingress")
if err := c.k8s.IngressUpdate(ctx, airbyteNamespace, ingress(host)); err != nil {
if err := c.k8s.IngressUpdate(ctx, airbyteNamespace, ingress(hosts)); err != nil {
pterm.Error.Printfln("Unable to update existing Ingress")
return fmt.Errorf("unable to update existing ingress: %w", err)
}
Expand All @@ -343,7 +343,7 @@ func (c *Command) handleIngress(ctx context.Context, host string) error {
}

pterm.Info.Println("No existing Ingress found, creating one")
if err := c.k8s.IngressCreate(ctx, airbyteNamespace, ingress(host)); err != nil {
if err := c.k8s.IngressCreate(ctx, airbyteNamespace, ingress(hosts)); err != nil {
pterm.Error.Println("Unable to create ingress")
return fmt.Errorf("unable to create ingress: %w", err)
}
Expand Down
38 changes: 30 additions & 8 deletions internal/cmd/local/local/specs.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,27 @@ import (
)

// ingress creates an ingress type for defining the webapp ingress rules.
func ingress(host string) *networkingv1.Ingress {
func ingress(hosts []string) *networkingv1.Ingress {
var ingressClassName = "nginx"

// Always add a localhost and host.docker.internal route.
// This is necessary to ensure that this code can verify the Airbyte installation via `localhost`.
// Additionally, make it easy for dockerized applications (Airflow) to talk with Airbyte over the docker host.
rules := []networkingv1.IngressRule{ingressRule("localhost"), ingressRule("host.docker.internal")}
// If a host that isn't `localhost` was provided, create a second rule for that host.
// This is required to support non-local installation, such as running on an EC2 instance.
if host != "localhost" {
// if no host is defined, default to an empty host
if len(hosts) == 0 {
hosts = append(hosts, "")
} else {
// If a host that isn't `localhost` was provided, create a second rule for localhost.
// This is required to ensure we can talk to Airbyte via localhost
if !contains(hosts, "localhost") {
hosts = append(hosts, "localhost")
}
// If a host that isn't `host.docker.internal` was provided, create a second rule for localhost.
// This is required to ensure we can talk to other containers.
if !contains(hosts, "host.docker.internal") {
hosts = append(hosts, "host.docker.internal")
}
}

var rules []networkingv1.IngressRule
for _, host := range hosts {
rules = append(rules, ingressRule(host))
}

Expand Down Expand Up @@ -60,3 +71,14 @@ func ingressRule(host string) networkingv1.IngressRule {
},
}
}

// contains returns true if the slice contains the item, otherwise false.
func contains[T comparable](slice []T, item T) bool {
for _, v := range slice {
if v == item {
return true
}
}

return false
}
68 changes: 68 additions & 0 deletions internal/cmd/local/local/specs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package local

import (
"sort"
"testing"

"github.com/google/go-cmp/cmp"
networkingv1 "k8s.io/api/networking/v1"
)

func TestIngress(t *testing.T) {
tests := []struct {
name string
hosts []string
expHosts []string
}{
{
name: "nil hosts",
hosts: nil,
expHosts: []string{""},
},
{
name: "empty hosts",
hosts: []string{},
expHosts: []string{""},
},
{
name: "single new host",
hosts: []string{"example.test"},
expHosts: []string{"example.test", "localhost", "host.docker.internal"},
},
{
name: "localhost",
hosts: []string{"localhost"},
expHosts: []string{"localhost", "host.docker.internal"},
},
{
name: "host.docker.internal",
hosts: []string{"host.docker.internal"},
expHosts: []string{"localhost", "host.docker.internal"},
},
{
name: "multiple new hosts",
hosts: []string{"abc.test", "xyz.test"},
expHosts: []string{"abc.test", "localhost", "host.docker.internal", "xyz.test"},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
actHosts := extractHosts(ingress(tt.hosts))
sort.Strings(actHosts)
sort.Strings(tt.expHosts)
if d := cmp.Diff(tt.expHosts, actHosts); d != "" {
t.Errorf("unexpected hosts (-want, +got):\n%v", d)
}
})
}
}

// extractHosts returns the host fields from the ingress rules.
func extractHosts(ingress *networkingv1.Ingress) []string {
var hosts []string
for _, h := range ingress.Spec.Rules {
hosts = append(hosts, h.Host)
}
return hosts
}
4 changes: 2 additions & 2 deletions internal/cmd/local/local_install.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type InstallCmd struct {
DockerPassword string `group:"docker" help:"Docker password." env:"ABCTL_LOCAL_INSTALL_DOCKER_PASSWORD"`
DockerServer string `group:"docker" default:"https://index.docker.io/v1/" help:"Docker server." env:"ABCTL_LOCAL_INSTALL_DOCKER_SERVER"`
DockerUsername string `group:"docker" help:"Docker username." env:"ABCTL_LOCAL_INSTALL_DOCKER_USERNAME"`
Host string `default:"localhost" help:"HTTP ingress host."`
Host []string `help:"HTTP ingress host."`
InsecureCookies bool `help:"Allow cookies to be served over HTTP."`
LowResourceMode bool `help:"Run Airbyte in low resource mode."`
Migrate bool `help:"Migrate data from a previous Docker Compose Airbyte installation."`
Expand Down Expand Up @@ -106,7 +106,7 @@ func (i *InstallCmd) Run(ctx context.Context, provider k8s.Provider, telClient t
Secrets: i.Secret,
Migrate: i.Migrate,
Docker: dockerClient,
Host: i.Host,
Hosts: i.Host,

DockerServer: i.DockerServer,
DockerUser: i.DockerUsername,
Expand Down

0 comments on commit 0ecfa9d

Please sign in to comment.