package main

import (
	"errors"
	"io"
	"os"
	"testing"

	. "github.com/onsi/gomega"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"

	"github.com/nginx/nginx-gateway-fabric/v2/internal/controller/config"
)

type flagTestCase struct {
	name              string
	expectedErrPrefix string
	args              []string
	wantErr           bool
}

func testFlag(t *testing.T, cmd *cobra.Command, test flagTestCase) {
	t.Helper()
	g := NewWithT(t)
	// discard any output generated by cobra
	cmd.SetOut(io.Discard)
	cmd.SetErr(io.Discard)

	// override RunE to avoid executing the command
	cmd.RunE = func(_ *cobra.Command, _ []string) error {
		return nil
	}

	cmd.SetArgs(test.args)
	err := cmd.Execute()

	if test.wantErr {
		g.Expect(err).To(HaveOccurred())
		g.Expect(err.Error()).To(HavePrefix(test.expectedErrPrefix))
	} else {
		g.Expect(err).NotTo(HaveOccurred())
	}
}

func TestRootCmd(t *testing.T) {
	t.Parallel()
	testCase := flagTestCase{
		name:    "no flags",
		args:    nil,
		wantErr: false,
	}

	testFlag(t, createRootCommand(), testCase)
}

func TestCommonFlagsValidation(t *testing.T) {
	t.Parallel()
	tests := []flagTestCase{
		{
			name: "valid flags",
			args: []string{
				"--gateway-ctlr-name=gateway.nginx.org/nginx-gateway",
				"--gatewayclass=nginx",
			},
			wantErr: false,
		},
		{
			name: "gateway-ctlr-name is not set",
			args: []string{
				"--gatewayclass=nginx",
			},
			wantErr:           true,
			expectedErrPrefix: `required flag(s) "gateway-ctlr-name" not set`,
		},
		{
			name: "gateway-ctlr-name is set to empty string",
			args: []string{
				"--gateway-ctlr-name=",
				"--gatewayclass=nginx",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "" for "--gateway-ctlr-name" flag: must be set`,
		},
		{
			name: "gateway-ctlr-name is invalid",
			args: []string{
				"--gateway-ctlr-name=nginx-gateway",
				"--gatewayclass=nginx",
			},
			wantErr: true,
			expectedErrPrefix: `invalid argument "nginx-gateway" for "--gateway-ctlr-name" flag: invalid format; ` +
				"must be DOMAIN/PATH",
		},
		{
			name: "gatewayclass is not set",
			args: []string{
				"--gateway-ctlr-name=gateway.nginx.org/nginx-gateway",
			},
			wantErr:           true,
			expectedErrPrefix: `required flag(s) "gatewayclass" not set`,
		},
		{
			name: "gatewayclass is set to empty string",
			args: []string{
				"--gateway-ctlr-name=gateway.nginx.org/nginx-gateway",
				"--gatewayclass=",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "" for "--gatewayclass" flag: must be set`,
		},
		{
			name: "gatewayclass is invalid",
			args: []string{
				"--gateway-ctlr-name=gateway.nginx.org/nginx-gateway",
				"--gatewayclass=@",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "@" for "--gatewayclass" flag: invalid format`,
		},
	}

	for _, test := range tests {
		t.Run(test.name+"_controller", func(t *testing.T) {
			t.Parallel()
			testFlag(t, createControllerCommand(), test)
		})
	}
}

func TestControllerCmdFlagValidation(t *testing.T) {
	t.Parallel()
	tests := []flagTestCase{
		{
			name: "valid flags",
			args: []string{
				"--gateway-ctlr-name=gateway.nginx.org/nginx-gateway", // common and required flag
				"--gatewayclass=nginx",                                // common and required flag
				"--config=nginx-gateway-config",
				"--service=nginx-gateway",
				"--agent-tls-secret=agent-tls",
				"--metrics-port=9114",
				"--metrics-disable",
				"--metrics-secure-serving",
				"--health-port=8081",
				"--health-disable",
				"--leader-election-lock-name=my-lock",
				"--leader-election-disable=false",
				"--nginx-plus",
				"--nginx-docker-secret=secret1",
				"--nginx-docker-secret=secret2",
				"--usage-report-secret=my-secret",
				"--usage-report-endpoint=example.com",
				"--usage-report-resolver=resolver.com",
				"--usage-report-ca-secret=ca-secret",
				"--usage-report-client-ssl-secret=client-secret",
				"--snippets-filters",
				"--nginx-scc=nginx-sscc-name",
				"--nginx-one-dataplane-key-secret=dataplane-key-secret",
				"--nginx-one-telemetry-endpoint-host=telemetry-endpoint-host",
				"--nginx-one-telemetry-endpoint-port=443",
				"--nginx-one-tls-skip-verify",
			},
			wantErr: false,
		},
		{
			name: "valid flags, non-required not set",
			args: []string{
				"--gateway-ctlr-name=gateway.nginx.org/nginx-gateway", // common and required flag
				"--gatewayclass=nginx",                                // common and required flag,
			},
			wantErr: false,
		},
		{
			name: "config is set to empty string",
			args: []string{
				"--config=",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "" for "-c, --config" flag: must be set`,
		},
		{
			name: "config is set to invalid string",
			args: []string{
				"--config=!@#$",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "!@#$" for "-c, --config" flag: invalid format`,
		},
		{
			name: "service is set to empty string",
			args: []string{
				"--service=",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "" for "--service" flag: must be set`,
		},
		{
			name: "service is set to invalid string",
			args: []string{
				"--service=!@#$",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "!@#$" for "--service" flag: invalid format`,
		},
		{
			name: "agent-tls-secret is set to empty string",
			args: []string{
				"--agent-tls-secret=",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "" for "--agent-tls-secret" flag: must be set`,
		},
		{
			name: "agent-tls-secret is set to invalid string",
			args: []string{
				"--agent-tls-secret=!@#$",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "!@#$" for "--agent-tls-secret" flag: invalid format`,
		},
		{
			name: "metrics-port is invalid type",
			args: []string{
				"--metrics-port=invalid", // not an int
			},
			wantErr: true,
			expectedErrPrefix: `invalid argument "invalid" for "--metrics-port" flag: failed to parse int value:` +
				` strconv.ParseInt: parsing "invalid": invalid syntax`,
		},
		{
			name: "metrics-port is outside of range",
			args: []string{
				"--metrics-port=999", // outside of range
			},
			wantErr: true,
			expectedErrPrefix: `invalid argument "999" for "--metrics-port" flag:` +
				` port outside of valid port range [1024 - 65535]: 999`,
		},
		{
			name: "metrics-disable is not a bool",
			args: []string{
				"--metrics-disable=999", // not a bool
			},
			wantErr: true,
			expectedErrPrefix: `invalid argument "999" for "--metrics-disable" flag: strconv.ParseBool:` +
				` parsing "999": invalid syntax`,
		},
		{
			name: "metrics-secure-serving is not a bool",
			args: []string{
				"--metrics-secure-serving=999", // not a bool
			},
			wantErr: true,
			expectedErrPrefix: `invalid argument "999" for "--metrics-secure-serving" flag: strconv.ParseBool:` +
				` parsing "999": invalid syntax`,
		},
		{
			name: "health-port is invalid type",
			args: []string{
				"--health-port=invalid", // not an int
			},
			wantErr: true,
			expectedErrPrefix: `invalid argument "invalid" for "--health-port" flag: failed to parse int value:` +
				` strconv.ParseInt: parsing "invalid": invalid syntax`,
		},
		{
			name: "health-port is outside of range",
			args: []string{
				"--health-port=999", // outside of range
			},
			wantErr: true,
			expectedErrPrefix: `invalid argument "999" for "--health-port" flag:` +
				` port outside of valid port range [1024 - 65535]: 999`,
		},
		{
			name: "health-disable is not a bool",
			args: []string{
				"--health-disable=999", // not a bool
			},
			wantErr: true,
			expectedErrPrefix: `invalid argument "999" for "--health-disable" flag: strconv.ParseBool:` +
				` parsing "999": invalid syntax`,
		},
		{
			name: "leader-election-lock-name is set to invalid string",
			args: []string{
				"--leader-election-lock-name=!@#$",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "!@#$" for "--leader-election-lock-name" flag: invalid format`,
		},
		{
			name: "leader-election-disable is set to empty string",
			args: []string{
				"--leader-election-disable=",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "" for "--leader-election-disable" flag: strconv.ParseBool`,
		},
		{
			name: "nginx-docker-secret is set to empty string",
			args: []string{
				"--nginx-docker-secret=",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "" for "--nginx-docker-secret" flag: must be set`,
		},
		{
			name: "nginx-docker-secret is invalid",
			args: []string{
				"--nginx-docker-secret=!@#$",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "!@#$" for "--nginx-docker-secret" flag: invalid format: `,
		},
		{
			name: "one nginx-docker-secret is invalid",
			args: []string{
				"--nginx-docker-secret=valid",
				"--nginx-docker-secret=!@#$",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "!@#$" for "--nginx-docker-secret" flag: invalid format: `,
		},
		{
			name: "usage-report-secret is set to empty string",
			args: []string{
				"--usage-report-secret=",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "" for "--usage-report-secret" flag: must be set`,
		},
		{
			name: "usage-report-secret is invalid",
			args: []string{
				"--usage-report-secret=!@#$",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "!@#$" for "--usage-report-secret" flag: invalid format: `,
		},
		{
			name: "usage-report-endpoint is set to empty string",
			args: []string{
				"--usage-report-endpoint=",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "" for "--usage-report-endpoint" flag: must be set`,
		},
		{
			name: "usage-report-endpoint is an invalid endpoint",
			args: []string{
				"--usage-report-endpoint=$*(invalid)",
			},
			wantErr: true,
			expectedErrPrefix: `invalid argument "$*(invalid)" for "--usage-report-endpoint" flag: ` +
				`"$*(invalid)" must be a domain name or IP address with optional port`,
		},
		{
			name: "usage-report-resolver is set to empty string",
			args: []string{
				"--usage-report-resolver=",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "" for "--usage-report-resolver" flag: must be set`,
		},
		{
			name: "usage-report-resolver is an invalid endpoint",
			args: []string{
				"--usage-report-resolver=$*(invalid)",
			},
			wantErr: true,
			expectedErrPrefix: `invalid argument "$*(invalid)" for "--usage-report-resolver" flag: ` +
				`"$*(invalid)" must be a domain name or IP address with optional port`,
		},
		{
			name: "usage-report-ca-secret is set to empty string",
			args: []string{
				"--usage-report-ca-secret=",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "" for "--usage-report-ca-secret" flag: must be set`,
		},
		{
			name: "usage-report-ca-secret is invalid",
			args: []string{
				"--usage-report-ca-secret=!@#$",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "!@#$" for "--usage-report-ca-secret" flag: invalid format: `,
		},
		{
			name: "usage-report-client-ssl-secret is set to empty string",
			args: []string{
				"--usage-report-client-ssl-secret=",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "" for "--usage-report-client-ssl-secret" flag: must be set`,
		},
		{
			name: "usage-report-client-ssl-secret is invalid",
			args: []string{
				"--usage-report-client-ssl-secret=!@#$",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "!@#$" for "--usage-report-client-ssl-secret" flag: invalid format: `,
		},
		{
			name: "snippets-filters is not a bool",
			expectedErrPrefix: `invalid argument "not-a-bool" for "--snippets-filters" flag: strconv.ParseBool:` +
				` parsing "not-a-bool": invalid syntax`,
			args: []string{
				"--snippets-filters=not-a-bool",
			},
			wantErr: true,
		},
		{
			name: "nginx-scc is set to empty string",
			args: []string{
				"--nginx-scc=",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "" for "--nginx-scc" flag: must be set`,
		},
		{
			name: "nginx-scc is invalid",
			args: []string{
				"--nginx-scc=!@#$",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "!@#$" for "--nginx-scc" flag: invalid format: `,
		},
		{
			name: "nginx-one-dataplane-key-secret is set to empty string",
			args: []string{
				"--nginx-one-dataplane-key-secret=",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "" for "--nginx-one-dataplane-key-secret" flag: must be set`,
		},
		{
			name: "nginx-one-dataplane-key-secret is invalid",
			args: []string{
				"--nginx-one-dataplane-key-secret=!@#$",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "!@#$" for "--nginx-one-dataplane-key-secret" flag: invalid format: `,
		},
		{
			name: "nginx-one-telemetry-endpoint-host is set to empty string",
			args: []string{
				"--nginx-one-telemetry-endpoint-host=",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "" for "--nginx-one-telemetry-endpoint-host" flag: must be set`,
		},
		{
			name: "nginx-one-telemetry-endpoint-host is invalid",
			args: []string{
				"--nginx-one-telemetry-endpoint-host=!@#$",
			},
			wantErr: true,
			expectedErrPrefix: `invalid argument "!@#$" for "--nginx-one-telemetry-endpoint-host" ` +
				`flag: invalid format: `,
		},
		{
			name: "nginx-one-telemetry-endpoint-port is invalid type",
			args: []string{
				"--nginx-one-telemetry-endpoint-port=invalid", // not an int
			},
			wantErr: true,
			expectedErrPrefix: `invalid argument "invalid" for "--nginx-one-telemetry-endpoint-port" ` +
				`flag: failed to parse int value: strconv.ParseInt: parsing "invalid": invalid syntax`,
		},
		{
			name: "nginx-one-telemetry-endpoint-port is outside of range",
			args: []string{
				"--nginx-one-telemetry-endpoint-port=65536", // outside of range
			},
			wantErr: true,
			expectedErrPrefix: `invalid argument "65536" for "--nginx-one-telemetry-endpoint-port" flag:` +
				` port outside of valid port range [1 - 65535]: 65536`,
		},
		{
			name: "nginx-one-tls-skip-verify is not a bool",
			expectedErrPrefix: `invalid argument "not-a-bool" for "--nginx-one-tls-skip-verify" flag:` +
				` strconv.ParseBool: parsing "not-a-bool": invalid syntax`,
			args: []string{
				"--nginx-one-tls-skip-verify=not-a-bool",
			},
			wantErr: true,
		},
	}

	// common flags validation is tested separately

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			t.Parallel()
			cmd := createControllerCommand()
			testFlag(t, cmd, test)
		})
	}
}

func TestGenerateCertsCmdFlagValidation(t *testing.T) {
	t.Parallel()

	tests := []flagTestCase{
		{
			name: "valid flags",
			args: []string{
				"--server-tls-secret=server-secret",
				"--agent-tls-secret=agent-secret",
				"--service=my-service",
				"--cluster-domain=cluster.local",
				"--overwrite",
			},
			wantErr: false,
		},
		{
			name:    "omitted flags",
			args:    nil,
			wantErr: false,
		},
		{
			name: "server-tls-secret is set to empty string",
			args: []string{
				"--server-tls-secret=",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "" for "--server-tls-secret" flag: must be set`,
		},
		{
			name: "server-tls-secret is invalid",
			args: []string{
				"--server-tls-secret=!@#$",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "!@#$" for "--server-tls-secret" flag: invalid format`,
		},
		{
			name: "agent-tls-secret is set to empty string",
			args: []string{
				"--agent-tls-secret=",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "" for "--agent-tls-secret" flag: must be set`,
		},
		{
			name: "agent-tls-secret is invalid",
			args: []string{
				"--agent-tls-secret=!@#$",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "!@#$" for "--agent-tls-secret" flag: invalid format`,
		},
		{
			name: "service is set to empty string",
			args: []string{
				"--service=",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "" for "--service" flag: must be set`,
		},
		{
			name: "service is invalid",
			args: []string{
				"--service=!@#$",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "!@#$" for "--service" flag: invalid format`,
		},
		{
			name: "cluster-domain is set to empty string",
			args: []string{
				"--cluster-domain=",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "" for "--cluster-domain" flag: must be set`,
		},
		{
			name: "cluster-domain is invalid",
			args: []string{
				"--cluster-domain=!@#$",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "!@#$" for "--cluster-domain" flag: invalid format`,
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			t.Parallel()
			cmd := createGenerateCertsCommand()
			testFlag(t, cmd, test)
		})
	}
}

func TestInitializeCmdFlagValidation(t *testing.T) {
	t.Parallel()
	tests := []flagTestCase{
		{
			name: "valid flags",
			args: []string{
				"--source=/my/file",
				"--destination=dest/file",
				"--nginx-plus",
			},
			wantErr: false,
		},
		{
			name:    "omitted flags",
			args:    nil,
			wantErr: false,
		},
		{
			name: "source set without destination",
			args: []string{
				"--source=/my/file",
			},
			wantErr: true,
			expectedErrPrefix: "if any flags in the group [source destination] are set they must all be set; " +
				"missing [destination]",
		},
		{
			name: "destination set without source",
			args: []string{
				"--destination=/dest/file",
			},
			wantErr: true,
			expectedErrPrefix: "if any flags in the group [source destination] are set they must all be set; " +
				"missing [source]",
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			t.Parallel()
			cmd := createInitializeCommand()
			testFlag(t, cmd, test)
		})
	}
}

func TestSleepCmdFlagValidation(t *testing.T) {
	t.Parallel()
	tests := []flagTestCase{
		{
			name: "valid flags",
			args: []string{
				"--duration=1s",
			},
			wantErr: false,
		},
		{
			name:    "omitted flags",
			args:    nil,
			wantErr: false,
		},
		{
			name: "duration is set to empty string",
			args: []string{
				"--duration=",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "" for "--duration" flag: time: invalid duration ""`,
		},
		{
			name: "duration is invalid",
			args: []string{
				"--duration=invalid",
			},
			wantErr:           true,
			expectedErrPrefix: `invalid argument "invalid" for "--duration" flag: time: invalid duration "invalid"`,
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			t.Parallel()
			cmd := createSleepCommand()
			testFlag(t, cmd, test)
		})
	}
}

func TestParseFlags(t *testing.T) {
	t.Parallel()
	g := NewWithT(t)

	flagSet := pflag.NewFlagSet("flagSet", 0)
	// set SortFlags to false for testing purposes so when parseFlags loops over the flagSet it
	// goes off of primordial order.
	flagSet.SortFlags = false

	var boolFlagTrue bool
	flagSet.BoolVar(
		&boolFlagTrue,
		"boolFlagTrue",
		true,
		"boolean true test flag",
	)

	var boolFlagFalse bool
	flagSet.BoolVar(
		&boolFlagFalse,
		"boolFlagFalse",
		false,
		"boolean false test flag",
	)

	customIntFlagDefault := intValidatingValue{
		validator: validatePort,
		value:     8080,
	}
	flagSet.Var(
		&customIntFlagDefault,
		"customIntFlagDefault",
		"default custom int test flag",
	)

	customIntFlagUserDefined := intValidatingValue{
		validator: validatePort,
		value:     8080,
	}
	flagSet.Var(
		&customIntFlagUserDefined,
		"customIntFlagUserDefined",
		"user defined custom int test flag",
	)
	err := flagSet.Set("customIntFlagUserDefined", "8081")
	g.Expect(err).To(Not(HaveOccurred()))

	customStringFlagDefault := stringValidatingValue{
		validator: validateResourceName,
		value:     "default-custom-string-test-flag",
	}
	flagSet.Var(
		&customStringFlagDefault,
		"customStringFlagDefault",
		"default custom string test flag",
	)

	customStringFlagUserDefined := stringValidatingValue{
		validator: validateResourceName,
		value:     "user-defined-custom-string-test-flag",
	}
	flagSet.Var(
		&customStringFlagUserDefined,
		"customStringFlagUserDefined",
		"user defined custom string test flag",
	)
	err = flagSet.Set("customStringFlagUserDefined", "changed-test-flag-value")
	g.Expect(err).To(Not(HaveOccurred()))

	expectedKeys := []string{
		"boolFlagTrue",
		"boolFlagFalse",

		"customIntFlagDefault",
		"customIntFlagUserDefined",

		"customStringFlagDefault",
		"customStringFlagUserDefined",
	}
	expectedValues := []string{
		"true",
		"false",

		"default",
		"user-defined",

		"default",
		"user-defined",
	}

	flagKeys, flagValues := parseFlags(flagSet)

	g.Expect(flagKeys).Should(Equal(expectedKeys))
	g.Expect(flagValues).Should(Equal(expectedValues))
}

func TestGetBuildInfo(t *testing.T) {
	t.Parallel()
	g := NewWithT(t)

	commitHash, commitTime, dirtyBuild := getBuildInfo()

	g.Expect(commitHash).To(Not(BeEmpty()))
	g.Expect(commitTime).To(Not(BeEmpty()))
	g.Expect(dirtyBuild).To(Not(BeEmpty()))

	g.Expect(commitHash).To(Not(Equal("unknown")))
	g.Expect(commitTime).To(Not(Equal("unknown")))
	g.Expect(dirtyBuild).To(Not(Equal("unknown")))
}

func TestCreateGatewayPodConfig(t *testing.T) {
	t.Parallel()
	g := NewWithT(t)

	// Order matters here
	// We start with all env vars set
	g.Expect(os.Setenv("POD_UID", "1234")).To(Succeed())
	g.Expect(os.Setenv("POD_NAMESPACE", "default")).To(Succeed())
	g.Expect(os.Setenv("POD_NAME", "my-pod")).To(Succeed())
	g.Expect(os.Setenv("INSTANCE_NAME", "my-pod-xyz")).To(Succeed())
	g.Expect(os.Setenv("IMAGE_NAME", "my-pod-image:tag")).To(Succeed())

	version := "0.0.0"

	expCfg := config.GatewayPodConfig{
		ServiceName:  "svc",
		Namespace:    "default",
		Name:         "my-pod",
		UID:          "1234",
		InstanceName: "my-pod-xyz",
		Version:      "0.0.0",
		Image:        "my-pod-image:tag",
	}
	cfg, err := createGatewayPodConfig(version, "svc")
	g.Expect(err).To(Not(HaveOccurred()))
	g.Expect(cfg).To(Equal(expCfg))

	// unset image name
	g.Expect(os.Unsetenv("IMAGE_NAME")).To(Succeed())
	cfg, err = createGatewayPodConfig(version, "svc")
	g.Expect(err).To(MatchError(errors.New("environment variable IMAGE_NAME not set")))
	g.Expect(cfg).To(Equal(config.GatewayPodConfig{}))

	// unset instance name
	g.Expect(os.Unsetenv("INSTANCE_NAME")).To(Succeed())
	cfg, err = createGatewayPodConfig(version, "svc")
	g.Expect(err).To(MatchError(errors.New("environment variable INSTANCE_NAME not set")))
	g.Expect(cfg).To(Equal(config.GatewayPodConfig{}))

	// unset name
	g.Expect(os.Unsetenv("POD_NAME")).To(Succeed())
	cfg, err = createGatewayPodConfig(version, "svc")
	g.Expect(err).To(MatchError(errors.New("environment variable POD_NAME not set")))
	g.Expect(cfg).To(Equal(config.GatewayPodConfig{}))

	// unset namespace
	g.Expect(os.Unsetenv("POD_NAMESPACE")).To(Succeed())
	cfg, err = createGatewayPodConfig(version, "svc")
	g.Expect(err).To(MatchError(errors.New("environment variable POD_NAMESPACE not set")))
	g.Expect(cfg).To(Equal(config.GatewayPodConfig{}))

	// unset pod UID
	g.Expect(os.Unsetenv("POD_UID")).To(Succeed())
	cfg, err = createGatewayPodConfig(version, "svc")
	g.Expect(err).To(MatchError(errors.New("environment variable POD_UID not set")))
	g.Expect(cfg).To(Equal(config.GatewayPodConfig{}))
}
