Skip to content

Commit

Permalink
feat: test definition with dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
qvalentin committed Aug 21, 2024
1 parent 172d197 commit a539d34
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 29 deletions.
31 changes: 16 additions & 15 deletions internal/charts/chart.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,48 +79,48 @@ func (c *Chart) ResolveValueFiles(query []string, chartStore *ChartStore) []*Que
logger.Error("Could not resolve values files for nil chart")
return []*QueriedValuesFiles{}
}
// logger.Debug(fmt.Sprintf("Resolving values files for %s with query %s", c.HelmChart.Name(), query))
result := []*QueriedValuesFiles{{Selector: query, ValuesFiles: c.ValuesFiles}}

if len(query) == 0 {
return result
}

if c.HelmChart != nil {
result = c.resolveValuesFilesOfDependencies(query, chartStore, result)
}
result = append(result, c.resolveValuesFilesOfDependencies(query, chartStore)...)

result = append(result, c.resolveValuesFilesOfParent(chartStore, query)...)

return result
}

func (c *Chart) resolveValuesFilesOfParent(chartStore *ChartStore, query []string) (result []*QueriedValuesFiles) {
parentChart := c.ParentChart.GetParentChart(chartStore)
if parentChart == nil {
return []*QueriedValuesFiles{}
}

if query[0] == "global" {
if parentChart == nil {
return result
}

return append(result,
parentChart.ResolveValueFiles(query, chartStore)...)
}

if parentChart == nil {
return result
}

chartName := c.ChartMetadata.Metadata.Name
extendedQuery := append([]string{chartName}, query...)

return append(result,
parentChart.ResolveValueFiles(extendedQuery, chartStore)...)
}

func (c *Chart) resolveValuesFilesOfDependencies(query []string, chartStore *ChartStore, result []*QueriedValuesFiles) []*QueriedValuesFiles {
func (c *Chart) resolveValuesFilesOfDependencies(query []string, chartStore *ChartStore) (result []*QueriedValuesFiles) {
if c.HelmChart == nil {
return []*QueriedValuesFiles{}
}
for _, dependency := range c.HelmChart.Dependencies() {
logger.Debug(fmt.Sprintf("Resolving dependency %s with query %s", dependency.Name(), query))

if dependency.Name() == query[0] || query[0] == "global" {
subQuery := query

if dependency.Name() == query[0] {
if len(query) > 1 {
if len(query) >= 1 {
subQuery = query[1:]
}
}
Expand All @@ -132,6 +132,7 @@ func (c *Chart) resolveValuesFilesOfDependencies(query []string, chartStore *Cha
}

// TODO: why does this cause infinite recursion?
// because dependencyChart have the parent as dependency
// result = append(result, dependencyChart.ResolveValueFiles(subQuery, chartStore)...)

result = append(result,
Expand Down
30 changes: 29 additions & 1 deletion internal/charts/chart_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,25 @@ func TestResolvesValuesFileOfDependencyWithChartName(t *testing.T) {
assert.Contains(t, selectors, []string{"foo"})
}

func TestResolvesValuesFileOfDependencyWithOnlyChartName(t *testing.T) {
var (
rootDir = "../../testdata/dependenciesExample"
chartStore = charts.NewChartStore(uri.File(rootDir), charts.NewChart)
chart, err = chartStore.GetChartForDoc(uri.File(filepath.Join(rootDir, "templates", "deployment.yaml")))
valueFiles = chart.ResolveValueFiles([]string{"subchartexample"}, chartStore)
)

assert.NoError(t, err)
assert.Len(t, valueFiles, 2)

selectors := [][]string{}
for _, valueFile := range valueFiles {
selectors = append(selectors, valueFile.Selector)
}
assert.Contains(t, selectors, []string{"subchartexample"})
assert.Contains(t, selectors, []string{})
}

func TestResolvesValuesFileOfDependencyWithChartNameForPackedDependency(t *testing.T) {
var (
rootDir = "../../testdata/dependenciesExample"
Expand Down Expand Up @@ -202,5 +221,14 @@ func TestLoadsHelmChartWithDependecies(t *testing.T) {
chart := charts.NewChart(uri.File("../../testdata/dependenciesExample/"), util.ValuesFilesConfig{})

dependecyTemplates := chart.GetDependeciesTemplates()
assert.Len(t, dependecyTemplates, 21)
assert.Len(t, dependecyTemplates, 23)

filePaths := []string{}
for _, dependency := range dependecyTemplates {
filePaths = append(filePaths, dependency.Path)
}
path, _ := filepath.Abs("../../testdata/dependenciesExample/charts/subchartexample/templates/subchart.yaml")
assert.Contains(t, filePaths, path)
path, _ = filepath.Abs("../../testdata/dependenciesExample/charts/" + charts.DependencyCacheFolder + "/common/templates/_names.tpl")
assert.Contains(t, filePaths, path)
}
11 changes: 10 additions & 1 deletion internal/charts/dependency_files.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type DependencyTemplateFile struct {
var DependencyCacheFolder = ".helm_ls_cache"

func (c *Chart) NewDependencyTemplateFile(chartName string, file *chart.File) *DependencyTemplateFile {
path := filepath.Join(c.RootURI.Filename(), "charts", DependencyCacheFolder, chartName, file.Name)
path := filepath.Join(c.getDependencyDir(chartName), file.Name)

return &DependencyTemplateFile{Content: file.Data, Path: path}
}
Expand All @@ -26,6 +26,15 @@ type PossibleDependencyFile interface {
GetPath() string
}

func (c *Chart) getDependencyDir(chartName string) string {
extractedPath := filepath.Join(c.RootURI.Filename(), "charts", chartName)
_, err := os.Stat(extractedPath)
if err == nil {
return extractedPath
}
return filepath.Join(c.RootURI.Filename(), "charts", DependencyCacheFolder, chartName)
}

// SyncToDisk writes the content of the document to disk if it is a dependency file.
// If it is a dependency file, it was read from a archive, so we need to write it back,
// to be able to open it in a editor when using go-to-definition or go-to-reference.
Expand Down
81 changes: 72 additions & 9 deletions internal/handler/definition_chart_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ import (
)

var (
rootUri = uri.File("../../testdata/dependenciesExample/")
fileURI = uri.File("../../testdata/dependenciesExample/templates/deployment.yaml")
rootUri = uri.File("../../testdata/dependenciesExample/")
fileURI = uri.File("../../testdata/dependenciesExample/templates/deployment.yaml")
fileURIInSubchart = uri.File("../../testdata/dependenciesExample/charts/subchartexample/templates/subchart.yaml")
)

type testCase struct {
Expand All @@ -29,8 +30,10 @@ type testCase struct {
expectedFileCount int
expectedStartPosition lsp.Position
expectedError error
inSubchart bool
}

// Test definition on a real chart found in $rootUri
func TestDefinitionChart(t *testing.T) {
testCases := []testCase{
{
Expand All @@ -39,27 +42,31 @@ func TestDefinitionChart(t *testing.T) {
1,
lsp.Position{Line: 9, Character: 0},
nil,
false,
},
{
`{{- include "dependeciesEx^ample.labels" . | nindent 4 }}`,
"templates/_helpers.tpl",
1,
lsp.Position{Line: 35, Character: 0},
nil,
false,
},
{
`{{ .Values.gl^obal.subchart }}`,
"values.yaml",
2,
lsp.Position{Line: 7, Character: 0},
nil,
false,
},
{
`{{ .Values.gl^obal.subchart }}`,
"charts/subchartexample/values.yaml",
2,
lsp.Position{Line: 0, Character: 0},
nil,
false,
},
{
`{{ .Values.common.exa^mpleValue }}`,
Expand All @@ -68,16 +75,70 @@ func TestDefinitionChart(t *testing.T) {
// this tests, that the file also contains comments
lsp.Position{Line: 7, Character: 0},
nil,
false,
},
{
`{{ .Values.comm^on.exampleValue }}`,
"charts/.helm_ls_cache/common/values.yaml",
1,
lsp.Position{Line: 7, Character: 0},
nil,
false,
},
{
`{{ .Values.subch^artexample.subchartWithoutGlobal }}`,
"values.yaml",
2,
lsp.Position{Line: 49, Character: 0},
nil,
false,
},
{
`{{ .Values.subch^artexample.subchartWithoutGlobal }}`,
"charts/subchartexample/values.yaml",
2,
lsp.Position{Line: 0, Character: 0},
nil,
false,
},
{
`{{ .Values.subchartexample.subchartWith^outGlobal }}`,
"values.yaml",
2,
lsp.Position{Line: 50, Character: 2},
nil,
false,
},
{
`{{ .Values.subchartexample.subchart^WithoutGlobal }}`,
"charts/subchartexample/values.yaml",
2,
lsp.Position{Line: 2, Character: 0},
nil,
false,
},
{
`{{ .Values.subchart^WithoutGlobal }}`,
"charts/subchartexample/values.yaml",
2, // TODO: this should also find the parent, but the parent of the chart is not found :?
lsp.Position{Line: 2, Character: 0},
nil,
true,
},
}

fileContent, err := os.ReadFile(fileURI.Filename())
if err != nil {
t.Fatal(err)
}
lines := strings.Split(string(fileContent), "\n")
for _, tc := range testCases {
t.Run("Definition on "+tc.templateLineWithMarker, func(t *testing.T) {
uri := fileURI
if tc.inSubchart {
uri = fileURIInSubchart
}
fileContent, err := os.ReadFile(uri.Filename())
if err != nil {
t.Fatal(err)
}
lines := strings.Split(string(fileContent), "\n")

pos, found := getPosition(tc, lines)
if !found {
t.Fatal(fmt.Sprintf("%s is not in the file %s", tc.templateLineWithMarker, fileURI.Filename()))
Expand All @@ -88,19 +149,21 @@ func TestDefinitionChart(t *testing.T) {
chart := charts.NewChart(rootUri, util.DefaultConfig.ValuesFilesConfig)

chartStore := charts.NewChartStore(rootUri, charts.NewChart)
chartStore.GetChartForURI(rootUri)
_, err = chartStore.GetChartForURI(rootUri)
h := &langHandler{
chartStore: chartStore,
documents: documents,
yamllsConnector: &yamlls.Connector{},
helmlsConfig: util.DefaultConfig,
}

assert.NoError(t, err)

h.LoadDocsOnNewChart(chart)

locations, err := h.Definition(context.TODO(), &lsp.DefinitionParams{
TextDocumentPositionParams: lsp.TextDocumentPositionParams{
TextDocument: lsp.TextDocumentIdentifier{URI: fileURI},
TextDocument: lsp.TextDocumentIdentifier{URI: uri},
Position: pos,
},
})
Expand Down
5 changes: 2 additions & 3 deletions internal/handler/definition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import (
"helm.sh/helm/v3/pkg/chart"
)

var testFileContent = `
var (
testFileContent = `
{{ $variable := "text" }} # line 1
{{ $variable }} # line 2
Expand All @@ -34,8 +35,6 @@ var testFileContent = `
{{ end }}
{{ range $index, $element := pipeline }}{{ $index }}{{ $element }}{{ end }} # line 14
`

var (
testDocumentTemplateURI = uri.URI("file:///templates/test.yaml")
testValuesURI = uri.URI("file:///values.yaml")
testOtherValuesURI = uri.URI("file:///values.other.yaml")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "subchartexample.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
example2: {{ .Values.global.subchart }}
example3: {{ .Values.subchartWithoutGlobal }}
1 change: 1 addition & 0 deletions testdata/dependenciesExample/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,4 @@ spec:
example: {{ .Values.common.exampleValue }}
example2: {{ .Values.global.subchart }}
example3: {{ .Values.subchartexample.subchartWithoutGlobal }} # todo fix this: missing hover, completion etc.
example4: {{ include "subchartexample.name" . }}

0 comments on commit a539d34

Please sign in to comment.