Skip to content

Commit e74adc5

Browse files
authored
Added community modules existence validation (#2572)
1 parent b103b1a commit e74adc5

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed

internal/cmd/module/add.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ func loadCustomCRs(crPath string) ([]unstructured.Unstructured, clierror.Error)
8989

9090
func addModule(cfg *addConfig, client *kube.Client, crs ...unstructured.Unstructured) clierror.Error {
9191
moduleTemplatesRepo := repo.NewModuleTemplatesRepo(*client)
92+
9293
if cfg.community {
9394
return installCommunityModule(cfg, client, moduleTemplatesRepo, crs...)
9495
}
@@ -97,6 +98,11 @@ func addModule(cfg *addConfig, client *kube.Client, crs ...unstructured.Unstruct
9798
}
9899

99100
func installCommunityModule(cfg *addConfig, client *kube.Client, repo repo.ModuleTemplatesRepository, crs ...unstructured.Unstructured) clierror.Error {
101+
err := modules.VerifyModuleExistence(cfg.Ctx, cfg.module, cfg.version, repo)
102+
if err != nil {
103+
return clierror.Wrap(err, clierror.New("failed to install the community module"))
104+
}
105+
100106
fmt.Println("Warning:\n You are about to install a community module.\n" +
101107
" Community modules are not officially supported and come with no binding Service Level Agreement (SLA).\n" +
102108
" There is no guarantee of support, maintenance, or compatibility.")

internal/modules/install.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"io"
77
"net/http"
8+
"slices"
89
"strings"
910
"time"
1011

@@ -46,6 +47,40 @@ func Install(ctx context.Context, client kube.Client, repo repo.ModuleTemplatesR
4647
return nil
4748
}
4849

50+
func VerifyModuleExistence(ctx context.Context, moduleName, version string, repo repo.ModuleTemplatesRepository) error {
51+
communityModules, err := repo.Community(ctx)
52+
if err != nil {
53+
return fmt.Errorf("failed to retrieve community modules: %v", err)
54+
}
55+
56+
var existingModules []kyma.ModuleTemplate
57+
58+
for _, communityModule := range communityModules {
59+
if communityModule.Spec.ModuleName == moduleName {
60+
existingModules = append(existingModules, communityModule)
61+
}
62+
}
63+
64+
if len(existingModules) == 0 {
65+
return fmt.Errorf("community module %s is not available in the catalog", moduleName)
66+
}
67+
68+
if version == "" {
69+
return nil
70+
}
71+
72+
var availableVersions []string
73+
for _, module := range existingModules {
74+
availableVersions = append(availableVersions, module.Spec.Version)
75+
}
76+
77+
if !slices.Contains(availableVersions, version) {
78+
return fmt.Errorf("community module %s in version %s does not exist. Available versions: %s", moduleName, version, strings.Join(availableVersions, ", "))
79+
}
80+
81+
return nil
82+
}
83+
4984
func applyCustomResources(ctx context.Context, client kube.Client, existingModule *kyma.ModuleTemplate, data InstallCommunityModuleData) error {
5085
if data.IsDefaultCRApplicable && len(data.CustomResources) > 0 {
5186
return fmt.Errorf("default custom resource and custom resources list cannot be applied together")

internal/modules/install_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,61 @@ func TestInstall_ModuleSuccessfullyInstalledWithCustomCR(t *testing.T) {
258258
require.Nil(t, clierr)
259259
}
260260

261+
func TestVerifyModuleExistence(t *testing.T) {
262+
ctx := context.Background()
263+
moduleName := "test-module"
264+
version := "1.0.0"
265+
266+
t.Run("module not found", func(t *testing.T) {
267+
repo := modulesfake.ModuleTemplatesRepo{
268+
ReturnCommunity: []kyma.ModuleTemplate{},
269+
}
270+
err := VerifyModuleExistence(ctx, moduleName, version, &repo)
271+
require.Error(t, err)
272+
require.Contains(t, err.Error(), "module test-module is not available in the catalog")
273+
})
274+
275+
t.Run("version not found", func(t *testing.T) {
276+
repo := modulesfake.ModuleTemplatesRepo{
277+
ReturnCommunity: []kyma.ModuleTemplate{
278+
{Spec: kyma.ModuleTemplateSpec{ModuleName: moduleName, Version: "2.0.0"}},
279+
},
280+
}
281+
err := VerifyModuleExistence(ctx, moduleName, version, &repo)
282+
require.Error(t, err)
283+
require.Contains(t, err.Error(), "community module test-module in version 1.0.0 does not exist. Available versions: 2.0.0")
284+
})
285+
286+
t.Run("version found", func(t *testing.T) {
287+
repo := modulesfake.ModuleTemplatesRepo{
288+
ReturnCommunity: []kyma.ModuleTemplate{
289+
{Spec: kyma.ModuleTemplateSpec{ModuleName: moduleName, Version: version}},
290+
},
291+
}
292+
err := VerifyModuleExistence(ctx, moduleName, version, &repo)
293+
require.NoError(t, err)
294+
})
295+
296+
t.Run("version empty (any version is valid)", func(t *testing.T) {
297+
repo := modulesfake.ModuleTemplatesRepo{
298+
ReturnCommunity: []kyma.ModuleTemplate{
299+
{Spec: kyma.ModuleTemplateSpec{ModuleName: moduleName, Version: "2.0.0"}},
300+
},
301+
}
302+
err := VerifyModuleExistence(ctx, moduleName, "", &repo)
303+
require.NoError(t, err)
304+
})
305+
306+
t.Run("repo error", func(t *testing.T) {
307+
repo := modulesfake.ModuleTemplatesRepo{
308+
CommunityErr: errors.New("repo error"),
309+
}
310+
err := VerifyModuleExistence(ctx, moduleName, version, &repo)
311+
require.Error(t, err)
312+
require.Contains(t, err.Error(), "failed to retrieve community modules: repo error")
313+
})
314+
}
315+
261316
func getTestHttpServerWithResponse(response string) *httptest.Server {
262317
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
263318
_, _ = w.Write([]byte(response))

0 commit comments

Comments
 (0)