diff --git a/changes/43142-script-package-icon-gitops b/changes/43142-script-package-icon-gitops new file mode 100644 index 0000000000..d212fcd880 --- /dev/null +++ b/changes/43142-script-package-icon-gitops @@ -0,0 +1 @@ +- Fixed an issue where adding a custom icon for a script-only package was not allowed in GitOps. diff --git a/pkg/spec/gitops.go b/pkg/spec/gitops.go index c5986c884e..280b9ab287 100644 --- a/pkg/spec/gitops.go +++ b/pkg/spec/gitops.go @@ -275,12 +275,19 @@ type SoftwarePackage struct { fleet.SoftwarePackageSpec } -func (spec SoftwarePackage) HydrateToPackageLevel(packageLevel fleet.SoftwarePackageSpec) (fleet.SoftwarePackageSpec, error) { - if spec.Icon.Path != "" || spec.InstallScript.Path != "" || spec.UninstallScript.Path != "" || +func (spec SoftwarePackage) HydrateToPackageLevel(packageLevel fleet.SoftwarePackageSpec, ext string) (fleet.SoftwarePackageSpec, error) { + if spec.InstallScript.Path != "" || spec.UninstallScript.Path != "" || spec.PostInstallScript.Path != "" || spec.URL != "" || spec.SHA256 != "" || spec.PreInstallQuery.Path != "" { return packageLevel, fmt.Errorf("the software package defined in %s must not have icons, scripts, queries, URL, or hash specified at the team level", *spec.Path) } + // Icon should be allowed at the team level yaml for script packages which must be specified as a path + if spec.Icon.Path != "" { + if ext != ".sh" && ext != ".ps1" { + return packageLevel, fmt.Errorf("the software package defined in %s must not have icons, scripts, queries, URL, or hash specified at the team level", *spec.Path) + } + } + packageLevel.Categories = spec.Categories packageLevel.LabelsIncludeAny = spec.LabelsIncludeAny packageLevel.LabelsExcludeAny = spec.LabelsExcludeAny @@ -1877,10 +1884,15 @@ func parseSoftware(top map[string]json.RawMessage, result *GitOps, baseDir strin } // Script file becomes the install script for a script-only package scriptSpec := fleet.SoftwarePackageSpec{ - InstallScript: fleet.TeamSpecSoftwareAsset{Path: resolvedPath}, ReferencedYamlPath: resolvedPath, + Icon: teamLevelPackage.Icon, } - scriptSpec, err = teamLevelPackage.HydrateToPackageLevel(scriptSpec) + // Icon path needs to be resolved, but since this function will set + // the install script it needs to be set to the correct path again. + scriptSpec = scriptSpec.ResolveSoftwarePackagePaths(baseDir) + scriptSpec.InstallScript.Path = resolvedPath + + scriptSpec, err = teamLevelPackage.HydrateToPackageLevel(scriptSpec, ext) if err != nil { multiError = multierror.Append(multiError, err) continue @@ -1922,7 +1934,7 @@ func parseSoftware(top map[string]json.RawMessage, result *GitOps, baseDir strin for i, spec := range softwarePackageSpecs { softwarePackageSpec := spec.ResolveSoftwarePackagePaths(filepath.Dir(spec.ReferencedYamlPath)) - softwarePackageSpec, err = teamLevelPackage.HydrateToPackageLevel(softwarePackageSpec) + softwarePackageSpec, err = teamLevelPackage.HydrateToPackageLevel(softwarePackageSpec, ext) if err != nil { multiError = multierror.Append(multiError, err) continue diff --git a/pkg/spec/gitops_test.go b/pkg/spec/gitops_test.go index 1346ccedeb..6dea822184 100644 --- a/pkg/spec/gitops_test.go +++ b/pkg/spec/gitops_test.go @@ -1524,6 +1524,36 @@ software: assert.ErrorContains(t, err, "the software package defined in software/single-package.yml must not have icons, scripts, queries, URL, or hash specified at the team level") } +func TestScriptOnlyPackagesPathWithInline(t *testing.T) { + t.Parallel() + config := getTeamConfig([]string{"software"}) + config += ` +software: + packages: + - path: software/script-only.sh + icon: + path: ./foo/bar.png +` + + path, basePath := createTempFile(t, "", config) + + err := file.Copy( + filepath.Join("testdata", "software", "script-only.sh"), + filepath.Join(basePath, "software", "script-only.sh"), + os.FileMode(0o755), + ) + require.NoError(t, err) + + appConfig := fleet.EnrichedAppConfig{} + appConfig.License = &fleet.LicenseInfo{ + Tier: fleet.TierPremium, + } + gitops, err := GitOpsFromFile(path, basePath, &appConfig, nopLogf) + require.NoError(t, err) + require.Len(t, gitops.Software.Packages, 1) + assert.Equal(t, filepath.Join(basePath, "foo", "bar.png"), gitops.Software.Packages[0].Icon.Path) +} + func TestIllegalFleetSecret(t *testing.T) { t.Parallel() config := getGlobalConfig([]string{"policies"}) diff --git a/pkg/spec/testdata/software/script-only.sh b/pkg/spec/testdata/software/script-only.sh new file mode 100644 index 0000000000..89977331ff --- /dev/null +++ b/pkg/spec/testdata/software/script-only.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +echo "hello world"