Skip to content
This repository has been archived by the owner on Jun 29, 2022. It is now read-only.

Lokoctl uses global variable which gives wrong results if used via APIs #992

Closed
surajssd opened this issue Sep 22, 2020 · 4 comments · Fixed by #1147
Closed

Lokoctl uses global variable which gives wrong results if used via APIs #992

surajssd opened this issue Sep 22, 2020 · 4 comments · Fixed by #1147
Assignees
Labels
bug Something isn't working size/m Issues which likely require up to a couple of work days technical-debt Technical debt-related issues
Milestone

Comments

@surajssd
Copy link
Member

surajssd commented Sep 22, 2020

Consider following test code:

func TestConversion(t *testing.T) {
	testCases := []struct {
		Name        string
		InputConfig string
		Contains    string
	}{
		{
			Name:     "use external_url param",
			Contains: "https://prometheus.externalurl.net",
			InputConfig: `
component "prometheus-operator" {
  prometheus {
    external_url = "https://prometheus.externalurl.net"
  }
}
`,
		},
		{
			Name:     "no external_url param",
			Contains: "https://prometheus.mydomain.net",
			InputConfig: `
component "prometheus-operator" {
  prometheus {
    ingress {
      host                       = "prometheus.mydomain.net"
      class                      = "contour"
      certmanager_cluster_issuer = "letsencrypt-production"
    }
  }
}
`,
		},
	}

	for _, tc := range testCases {
		tc := tc
		t.Run(tc.Name, func(t *testing.T) {
			m := renderManifests(t, tc.InputConfig)
			gotConfig := m["prometheus-operator/templates/prometheus/prometheus.yaml"]

			scanner := bufio.NewScanner(strings.NewReader(gotConfig))
			for scanner.Scan() {
				line := scanner.Text()
				if !strings.Contains(line, "externalUrl") {
					continue
				}

				t.Logf("\nwanted =   externalUrl: %q.\ngot    = %s", tc.Contains, line)
			}
		})
	}
}

Whose output looks like this:

$ go test -v github.com/kinvolk/lokomotive/pkg/components/prometheus-operator -run TestConversion
=== RUN   TestConversion
=== RUN   TestConversion/use_external_url_param
    component_conversion_test.go:92: 
        wanted =   externalUrl: "https://prometheus.externalurl.net".
        got    =   externalUrl: "https://prometheus.externalurl.net"
=== RUN   TestConversion/no_external_url_param
    component_conversion_test.go:92: 
        wanted =   externalUrl: "https://prometheus.mydomain.net".
        got    =   externalUrl: "https://prometheus.externalurl.net"
--- PASS: TestConversion (1.86s)
    --- PASS: TestConversion/use_external_url_param (0.89s)
    --- PASS: TestConversion/no_external_url_param (0.97s)
PASS
ok      github.com/kinvolk/lokomotive/pkg/components/prometheus-operator        1.906s

Notice that in second test case we should see https://prometheus.mydomain.net but the old result persists for some reason. My first guess is that this is due to use of globals.

I think component.LoadConfig and component.RenderManifests don't do the right thing. Or we should flush out old values when components.Get is called.

func renderManifests(t *testing.T, configHCL string) map[string]string {
	name := "prometheus-operator"

	component, err := components.Get(name)
	if err != nil {
		t.Fatalf("Getting component %q: %v", name, err)
	}

	body, diagnostics := util.GetComponentBody(configHCL, name)
	if diagnostics != nil {
		t.Fatalf("Getting component body: %v", diagnostics)
	}

	diagnostics = component.LoadConfig(body, &hcl.EvalContext{})
	if diagnostics.HasErrors() {
		t.Fatalf("Valid config should not return an error, got: %s", diagnostics)
	}

	ret, err := component.RenderManifests()
	if err != nil {
		t.Fatalf("Rendering manifests with valid config should succeed, got: %s", err)
	}

	return ret
}
@surajssd surajssd added the bug Something isn't working label Sep 22, 2020
@invidian
Copy link
Member

This is what #971 addresses.

Also related: #597.

@invidian invidian added proposed/next-sprint Issues proposed for next sprint technical-debt Technical debt-related issues labels Sep 22, 2020
@johananl johananl added the size/m Issues which likely require up to a couple of work days label Sep 23, 2020
@surajssd surajssd added this to the v0.5.0 milestone Sep 23, 2020
@surajssd surajssd removed the proposed/next-sprint Issues proposed for next sprint label Sep 23, 2020
@knrt10
Copy link
Member

knrt10 commented Sep 30, 2020

As this is already addressed PR of @invidian. Would you mind if this is assigned to you?

@invidian invidian self-assigned this Sep 30, 2020
@surajssd surajssd modified the milestones: v0.5.0, v0.6.0 Oct 12, 2020
invidian added a commit that referenced this issue Oct 29, 2020
As a preparation for solving #992.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Oct 29, 2020
As a preparation for #992.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Oct 29, 2020
As a preparation to #992, so platform name from the configuration don't
need to be duplicated.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Oct 29, 2020
As a preparation for solving #992.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Oct 29, 2020
As a preparation for #992.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Oct 29, 2020
As a preparation to #992, so platform name from the configuration don't
need to be duplicated.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Oct 29, 2020
As a preparation for #992.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Oct 29, 2020
As a preparation for solving #992.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Oct 29, 2020
As a preparation for #992.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Oct 29, 2020
As a preparation to #992, so platform name from the configuration don't
need to be duplicated.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Oct 29, 2020
As a preparation for #992.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
@invidian
Copy link
Member

Okay, this again turns out to be never-ending story to do right:

  • Right now we call function returning default configuration in each of the platform/component packages itself. The plan is to shift the calling to central platform/components packages, so function returning default configuration should become exporter.
  • Exporting function returning default configuration without exporting configuration struct itself limits the usage (I can imagine one getting default config and zero-ing all fields on purpose manually).
  • Exporting configuration struct builds up an API around it, exposing LoadConfig, Meta, Apply, Destroy, Initialize and PostApplyHook functions which can be misused when called on bad configuration. LoadConfig should be completely removed from it and Meta, Apply, Destroy, Initialize and PostApplyHook methods should be gated by a verifying function. Configuration struct should not implement Component/Platform interface. Validated configuration struct should.

Edit:

  • Right now we call function returning default configuration in each of the platform/component packages itself. The plan is to shift the calling to central platform/components packages, so function returning default configuration should become exporter.

Platforms already have NewConfig() function exported, only aks platform didn't, so I think this can be used for now.

However, the problem still applies for components. I guess they could follow the same convention as platforms for now.

invidian added a commit that referenced this issue Nov 2, 2020
As a preparation for solving #992.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Nov 2, 2020
As a preparation for #992.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Nov 2, 2020
As a preparation to #992, so platform name from the configuration don't
need to be duplicated.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Nov 2, 2020
This commit moves platforms registration logic from using globals to
single function in cli/cmd/cluster package, as this is the only user of
old GetPlatforms() function.

For platform unit tests, NewConfig() function exported by each platform
package should be used instead.

Refs #992

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Nov 2, 2020
As a preparation for #992.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 2, 2020
As a preparation for #992.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 2, 2020
As a preparation to #992, so platform name from the configuration don't
need to be duplicated.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 2, 2020
This commit moves platforms registration logic from using globals to
single function in cli/cmd/cluster package, as this is the only user of
old GetPlatforms() function.

For platform unit tests, NewConfig() function exported by each platform
package should be used instead.

Refs #992

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 2, 2020
As a preparation for #992.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 2, 2020
To make it consistent with pkg/platform/* packages and to make it
available outside of package, so we can avoid using globals and init()
functions for collecting available components default configurations.

Refs #992

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 2, 2020
So no globals or HCL parsing is involved in testing. Also
components.Get() is now deprecated, as we want to avoid relying on
globals and init() functions.

Part of #992

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 2, 2020
So we don't rely on other packages while running unit tests.

Refs #992

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 2, 2020
Instead, add few helper functions, which will also replace
components.Get().

Refs #992

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 2, 2020
As a next step of not using globals and init() functions across our
code.

Refs #992

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 2, 2020
They are not used anymore, so can be removed.

Refs #992.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 2, 2020
To be consistent with platform and component packages.

Refs #992

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 2, 2020
To be consistent with platform and component packages.

Refs #992

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 2, 2020
Import all available backends locally instead, to avoid using globals.

Refs #992

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 2, 2020
We no longer use registration pattern for backends, as it is using
globals and init() which we want to avoid using.

We also moved the interface to cli/cmd/cluster package, as it was
the only consumer of it, so actually the entire package can be now
removed, as it no longer has any use.

Refs #992

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 3, 2020
As a preparation for solving #992.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 3, 2020
As a preparation for #992.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 3, 2020
As a preparation to #992, so platform name from the configuration don't
need to be duplicated.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 3, 2020
This commit moves platforms registration logic from using globals to
single function in cli/cmd/cluster package, as this is the only user of
old GetPlatforms() function.

For platform unit tests, NewConfig() function exported by each platform
package should be used instead.

Refs #992

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 3, 2020
As a preparation for #992.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 3, 2020
To make it consistent with pkg/platform/* packages and to make it
available outside of package, so we can avoid using globals and init()
functions for collecting available components default configurations.

Refs #992

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 3, 2020
So no globals or HCL parsing is involved in testing. Also
components.Get() is now deprecated, as we want to avoid relying on
globals and init() functions.

Part of #992

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 3, 2020
So we don't rely on other packages while running unit tests.

Refs #992

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 3, 2020
Instead, add few helper functions, which will also replace
components.Get().

Refs #992

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 3, 2020
As a next step of not using globals and init() functions across our
code.

Refs #992

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 3, 2020
They are not used anymore, so can be removed.

Refs #992.

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 3, 2020
To be consistent with platform and component packages.

Refs #992

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 3, 2020
To be consistent with platform and component packages.

Refs #992

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 3, 2020
Import all available backends locally instead, to avoid using globals.

Refs #992

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
invidian added a commit that referenced this issue Dec 3, 2020
We no longer use registration pattern for backends, as it is using
globals and init() which we want to avoid using.

We also moved the interface to cli/cmd/cluster package, as it was
the only consumer of it, so actually the entire package can be now
removed, as it no longer has any use.

Refs #992

Signed-off-by: Mateusz Gozdek <mateusz@kinvolk.io>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working size/m Issues which likely require up to a couple of work days technical-debt Technical debt-related issues
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants