Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for multiple hosts, default to no host #110

Merged
merged 2 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/airbytehq/abctl

go 1.22.2
go 1.23.1

require (
github.com/alecthomas/kong v0.9.0
Expand All @@ -15,6 +15,7 @@ require (
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58
github.com/pterm/pterm v0.12.79
golang.org/x/mod v0.17.0
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
helm.sh/helm/v3 v3.14.2
k8s.io/api v0.29.2
Expand Down Expand Up @@ -157,7 +158,6 @@ require (
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/evanphx/json-patch.v5 v5.7.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/apiextensions-apiserver v0.29.0 // indirect
k8s.io/apiserver v0.29.0 // indirect
k8s.io/cli-runtime v0.29.0 // indirect
Expand Down
6 changes: 0 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
Expand Down Expand Up @@ -50,8 +48,6 @@ github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0=
github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
github.com/alessio/shellescape v1.4.2 h1:MHPfaU+ddJ0/bYWpgIeUnQUqKrlJ1S7BfEYPM4uEoM0=
github.com/alessio/shellescape v1.4.2/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
Expand Down Expand Up @@ -618,8 +614,6 @@ oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo=
oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/kind v0.23.0 h1:8fyDGWbWTeCcCTwA04v4Nfr45KKxbSPH1WO9K+jVrBg=
sigs.k8s.io/kind v0.23.0/go.mod h1:ZQ1iZuJLh3T+O8fzhdi3VWcFTzsdXtNv2ppsHc8JQ7s=
sigs.k8s.io/kind v0.24.0 h1:g4y4eu0qa+SCeKESLpESgMmVFBebL0BDa6f777OIWrg=
sigs.k8s.io/kind v0.24.0/go.mod h1:t7ueEpzPYJvHA8aeLtI52rtFftNgUYUaCwvxjk7phfw=
sigs.k8s.io/kustomize/api v0.16.0 h1:/zAR4FOQDCkgSDmVzV2uiFbuy9bhu3jEzthrHCuvm1g=
Expand Down
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
28 changes: 20 additions & 8 deletions internal/cmd/local/local/specs.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,34 @@ package local

import (
"fmt"
"slices"

networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// 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 !slices.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 !slices.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
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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

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