Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
012dab3
add kyma alpha module list stub
anoipm Apr 15, 2026
a5d433f
add under construction note to list cmd help
anoipm Apr 15, 2026
033079b
add ListService with InstalledModulesRepository
anoipm Apr 15, 2026
4544dcc
ListService returns core modules from InstalledModulesRepository
anoipm Apr 15, 2026
35d387b
wire ListService to list command, print module names
anoipm Apr 15, 2026
a6de9d7
add version and channel to ListResult
anoipm Apr 15, 2026
8a884d6
render list as table with module, version, channel columns
anoipm Apr 15, 2026
d76f5b6
update generated docs for alpha module list
anoipm Apr 15, 2026
6341e66
add output format support to list command (table, json)
anoipm Apr 15, 2026
9667039
add yaml output format to list command
anoipm Apr 15, 2026
f22c323
extract convertListToOutputFormat
anoipm Apr 15, 2026
240dadd
extract convertListToRows
anoipm Apr 15, 2026
14505c8
add -o output format flag to list command
anoipm Apr 15, 2026
8059e2f
sort list results by name
anoipm Apr 15, 2026
68c214e
add state field to ListResult
anoipm Apr 17, 2026
273becd
add state field to list rendering
anoipm Apr 17, 2026
19ed842
change InstalledModulesRepository to return KymaModuleInfo
anoipm Apr 17, 2026
d6a3b23
add managed field to ListResult
anoipm Apr 17, 2026
7d98767
add managed field to list rendering
anoipm Apr 17, 2026
155c63d
add customResourcePolicy field to ListResult
anoipm Apr 17, 2026
e50e9c7
add customResourcePolicy field to list rendering
anoipm Apr 17, 2026
2be1cc1
align list table columns with ADR-003
anoipm Apr 17, 2026
6eba781
add installation state via ModuleInstallationStateRepository
anoipm Apr 17, 2026
872ff1c
render installationState in all output formats
anoipm Apr 17, 2026
c48165c
combine module and installation status when they differ
anoipm Apr 17, 2026
31b823c
update list command description
anoipm Apr 17, 2026
a9b7f38
align JSON/YAML keys with column names
anoipm Apr 17, 2026
7af17ad
rename State to ModuleState in ListResult
anoipm Apr 17, 2026
ddd7143
introduce ModuleInstallation entity, move business logic to service
anoipm Apr 28, 2026
0fa1e4f
replace Template field with TemplateName and TemplateNamespace in Mod…
anoipm May 14, 2026
36da7da
merge spec and status when listing installed modules
anoipm May 19, 2026
37f8596
add IsBeingDeleted to ModuleInstallation, handle deleting state in re…
anoipm May 19, 2026
72d0cd8
add ModuleCRStateRepository to fetch module state from CR
anoipm May 19, 2026
8c01c11
handle unmanaged modules in ModuleCRStateRepository
anoipm May 19, 2026
3e0b3fb
log discovery errors instead of propagating them in ModuleCRStateRepo…
anoipm May 19, 2026
640e4c5
simplify installationStatus rendering - show InstallationState directly
anoipm May 19, 2026
5a3b538
extract extractStateFromObject, reuse in highestStateFromList
anoipm May 27, 2026
9cfd6cf
move state extraction helpers to stateextractor.go
anoipm May 27, 2026
7961b60
move ModuleCRState fetching to InstalledModulesRepository, add KymaMo…
anoipm May 28, 2026
f5c9d21
move installationState resolution to InstalledModulesRepository, simp…
anoipm May 28, 2026
71bdc36
simplify tests: remove trivial field-mapping tests, consolidate MapsA…
anoipm May 28, 2026
c68ba1c
fix gofmt formatting in modulecrstate.go
anoipm May 28, 2026
aed55a4
rename InstalledModulesRepository to ModuleInstallationsRepository
anoipm Jun 1, 2026
25d26e0
internalize ModuleCRStateRepository and ModuleInstallationStateReposi…
anoipm Jun 2, 2026
9762418
Merge branch 'main' into alpha-module-list
musztardem Jun 3, 2026
5a92ec0
update list command warning message
anoipm Jun 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/user/gen-docs/_sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export default [
{ text: 'kyma alpha kubeconfig generate', link: './gen-docs/kyma_alpha_kubeconfig_generate' },
{ text: 'kyma alpha module', link: './gen-docs/kyma_alpha_module' },
{ text: 'kyma alpha module catalog', link: './gen-docs/kyma_alpha_module_catalog' },
{ text: 'kyma alpha module list', link: './gen-docs/kyma_alpha_module_list' },
{ text: 'kyma alpha module pull', link: './gen-docs/kyma_alpha_module_pull' },
{ text: 'kyma alpha provision', link: './gen-docs/kyma_alpha_provision' },
{ text: 'kyma alpha reference-instance', link: './gen-docs/kyma_alpha_reference-instance' },
Expand Down
2 changes: 2 additions & 0 deletions docs/user/gen-docs/kyma_alpha_module.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ kyma alpha module <command> [flags]

```text
catalog - Lists modules catalog
list - Lists installed modules
pull - Pulls a module from a remote repository
```

Expand All @@ -31,4 +32,5 @@ kyma alpha module <command> [flags]

* [kyma alpha](kyma_alpha.md) - Groups command prototypes for which the API may still change
* [kyma alpha module catalog](kyma_alpha_module_catalog.md) - Lists modules catalog
* [kyma alpha module list](kyma_alpha_module_list.md) - Lists installed modules
* [kyma alpha module pull](kyma_alpha_module_pull.md) - Pulls a module from a remote repository
28 changes: 28 additions & 0 deletions docs/user/gen-docs/kyma_alpha_module_list.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# kyma alpha module list

Lists installed modules.

## Synopsis

Use this command to list the installed Kyma modules.

WARNING: This functionality is still under construction. Community modules are not yet supported.

```bash
kyma alpha module list [flags]
```

## Flags

```text
-o, --output string Output format (Possible values: table, json, yaml)
--context string The name of the kubeconfig context to use
-h, --help Help for the command
--kubeconfig string Path to the Kyma kubeconfig file
--show-extensions-error Prints a possible error when fetching extensions fails
--skip-extensions Skips fetching extensions from the target Kyma environment
```

## See also

* [kyma alpha module](kyma_alpha_module.md) - Manages Kyma modules
57 changes: 57 additions & 0 deletions internal/cmd/alpha/module/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package module

import (
"github.com/kyma-project/cli.v3/internal/clierror"
"github.com/kyma-project/cli.v3/internal/cmdcommon"
"github.com/kyma-project/cli.v3/internal/cmdcommon/types"
"github.com/kyma-project/cli.v3/internal/modulesv2"
"github.com/kyma-project/cli.v3/internal/out"
"github.com/spf13/cobra"
)

type listConfig struct {
*cmdcommon.KymaConfig
outputFormat types.Format
}

func NewListV2CMD(kymaConfig *cmdcommon.KymaConfig) *cobra.Command {
cfg := listConfig{
KymaConfig: kymaConfig,
}

cmd := &cobra.Command{
Use: "list [flags]",
Short: "Lists installed modules",
Long: `Use this command to list the installed Kyma modules.

WARNING: This functionality is still under construction. Community modules are not yet supported.`,
Run: func(_ *cobra.Command, _ []string) {
clierror.Check(listModulesV2(&cfg))
},
}

cmd.Flags().VarP(&cfg.outputFormat, "output", "o", "Output format (Possible values: table, json, yaml)")

return cmd
}

func listModulesV2(cfg *listConfig) clierror.Error {
moduleOperations := modulesv2.NewModuleOperations(cfg.KymaConfig)

listService, err := moduleOperations.List()
if err != nil {
return clierror.Wrap(err, clierror.New("failed to execute the list command"))
}

results, err := listService.Run(cfg.Ctx)
if err != nil {
return clierror.Wrap(err, clierror.New("failed to list installed modules"))
}

err = modulesv2.RenderList(results, cfg.outputFormat, out.Default)
if err != nil {
return clierror.Wrap(err, clierror.New("failed to render module list"))
}

return nil
}
19 changes: 19 additions & 0 deletions internal/cmd/alpha/module/list_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package module

import (
"testing"

"github.com/kyma-project/cli.v3/internal/cmdcommon"
"github.com/stretchr/testify/require"
)

func TestListCmd_Exists(t *testing.T) {
cmd := NewListV2CMD(&cmdcommon.KymaConfig{})
require.NotNil(t, cmd)
require.Equal(t, "list [flags]", cmd.Use)
}

func TestListCmd_HasOutputFlag(t *testing.T) {
cmd := NewListV2CMD(&cmdcommon.KymaConfig{})
require.NotNil(t, cmd.Flags().Lookup("output"))
}
1 change: 1 addition & 0 deletions internal/cmd/alpha/module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ func NewModuleCMD(kymaConfig *cmdcommon.KymaConfig) *cobra.Command {

cmd.AddCommand(NewCatalogV2CMD(kymaConfig))
cmd.AddCommand(NewPullV2CMD(kymaConfig))
cmd.AddCommand(NewListV2CMD(kymaConfig))

return cmd
}
35 changes: 30 additions & 5 deletions internal/modulesv2/dependencies.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@ import (
type ModuleOperations interface {
Catalog() (*CatalogService, error)
Pull() (*PullService, error)
// TODO
// Add() (*AddService, error)
// Install() (*InstallService, error)
// Pull() (*PullService, error)
// etc.
List() (*ListService, error)
}

type moduleOperations struct {
Expand All @@ -38,6 +34,17 @@ func (m *moduleOperations) Catalog() (*CatalogService, error) {
return catalogService, nil
}

func (m *moduleOperations) List() (*ListService, error) {
c := setupDIContainer(m.kymaConfig)

listService, err := di.GetTyped[*ListService](c)
if err != nil {
return nil, errors.New("failed to execute the list command")
}

return listService, nil
}

func (m *moduleOperations) Pull() (*PullService, error) {
c := setupDIContainer(m.kymaConfig)

Expand Down Expand Up @@ -83,6 +90,15 @@ func setupDIContainer(kymaConfig *cmdcommon.KymaConfig) *di.Container {
return repository.NewClusterMetadataRepository(kubeClient), nil
})

di.RegisterTyped(container, func(c *di.Container) (repository.ModuleInstallationsRepository, error) {
kubeClient, err := di.GetTyped[kube.Client](c)
if err != nil {
return nil, err
}

return repository.NewModuleInstallationsRepository(kubeClient), nil
})

// Services:

di.RegisterTyped(container, func(c *di.Container) (*CatalogService, error) {
Expand All @@ -108,5 +124,14 @@ func setupDIContainer(kymaConfig *cmdcommon.KymaConfig) *di.Container {
return NewPullService(moduleRepo), nil
})

di.RegisterTyped(container, func(c *di.Container) (*ListService, error) {
installedModulesRepo, err := di.GetTyped[repository.ModuleInstallationsRepository](c)
if err != nil {
return nil, err
}

return NewListService(installedModulesRepo), nil
})

return container
}
11 changes: 11 additions & 0 deletions internal/modulesv2/dtos/listresult.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package dtos

type ListResult struct {
Name string
Version string
Channel string
ModuleState string
Managed bool
CustomResourcePolicy string
InstallationState string
}
45 changes: 45 additions & 0 deletions internal/modulesv2/entities/moduleinstallation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package entities

import "github.com/kyma-project/cli.v3/internal/kube/kyma"

type ModuleInstallation struct {
Name string
Version string
Channel string
KymaModuleState string
ModuleState string
InstallationState string
Managed *bool
CustomResourcePolicy string
TemplateName string
TemplateNamespace string
specModuleName string
statusModuleName string
}

func NewModuleInstallationFromRaw(raw kyma.KymaModuleInfo) *ModuleInstallation {
name := raw.Status.Name
if name == "" {
name = raw.Spec.Name
}
return &ModuleInstallation{
Name: name,
Version: raw.Status.Version,
Channel: raw.Status.Channel,
KymaModuleState: raw.Status.State,
Managed: raw.Spec.Managed,
CustomResourcePolicy: raw.Spec.CustomResourcePolicy,
TemplateName: raw.Status.Template.GetName(),
TemplateNamespace: raw.Status.Template.GetNamespace(),
specModuleName: raw.Spec.Name,
statusModuleName: raw.Status.Name,
}
}

func (m *ModuleInstallation) IsManaged() bool {
return m.Managed == nil || *m.Managed
}

func (m *ModuleInstallation) IsBeingDeleted() bool {
return m.statusModuleName != "" && m.specModuleName == ""
}
88 changes: 88 additions & 0 deletions internal/modulesv2/entities/moduleinstallation_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package entities

import (
"testing"

"github.com/kyma-project/cli.v3/internal/kube/kyma"
"github.com/stretchr/testify/require"
)

func TestModuleInstallation_IsManaged_TrueWhenManagedIsNil(t *testing.T) {
m := ModuleInstallation{Managed: nil}
require.True(t, m.IsManaged())
}

func TestModuleInstallation_IsManaged_TrueWhenManagedIsTrue(t *testing.T) {
managed := true
m := ModuleInstallation{Managed: &managed}
require.True(t, m.IsManaged())
}

func TestModuleInstallation_IsManaged_FalseWhenManagedIsFalse(t *testing.T) {
managed := false
m := ModuleInstallation{Managed: &managed}
require.False(t, m.IsManaged())
}

func TestNewModuleInstallationFromRaw_MapsAllFields(t *testing.T) {
managed := false
status := kyma.ModuleStatus{
Name: "api-gateway",
Version: "3.5.1",
Channel: "regular",
State: "Ready",
}
status.Template.SetName("api-gateway-template")
status.Template.SetNamespace("kyma-system")
raw := kyma.KymaModuleInfo{
Spec: kyma.Module{
Name: "api-gateway",
Managed: &managed,
CustomResourcePolicy: "CreateAndDelete",
},
Status: status,
}

m := NewModuleInstallationFromRaw(raw)

require.Equal(t, "api-gateway", m.Name)
require.Equal(t, "3.5.1", m.Version)
require.Equal(t, "regular", m.Channel)
require.Equal(t, "Ready", m.KymaModuleState)
require.NotNil(t, m.Managed)
require.False(t, *m.Managed)
require.Equal(t, "CreateAndDelete", m.CustomResourcePolicy)
require.Equal(t, "api-gateway-template", m.TemplateName)
require.Equal(t, "kyma-system", m.TemplateNamespace)
}

func TestNewModuleInstallationFromRaw_UsesSpecNameWhenStatusNameIsEmpty(t *testing.T) {
raw := kyma.KymaModuleInfo{
Spec: kyma.Module{Name: "api-gateway"},
}

m := NewModuleInstallationFromRaw(raw)

require.Equal(t, "api-gateway", m.Name)
}

func TestModuleInstallation_IsBeingDeleted_TrueWhenOnlyInStatus(t *testing.T) {
raw := kyma.KymaModuleInfo{
Status: kyma.ModuleStatus{Name: "api-gateway", State: "Deleting"},
}

m := NewModuleInstallationFromRaw(raw)

require.True(t, m.IsBeingDeleted())
}

func TestModuleInstallation_IsBeingDeleted_FalseWhenSpecPresent(t *testing.T) {
raw := kyma.KymaModuleInfo{
Spec: kyma.Module{Name: "api-gateway"},
Status: kyma.ModuleStatus{Name: "api-gateway", State: "Ready"},
}

m := NewModuleInstallationFromRaw(raw)

require.False(t, m.IsBeingDeleted())
}
16 changes: 16 additions & 0 deletions internal/modulesv2/fake/installedmodules.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package fake

import (
"context"

"github.com/kyma-project/cli.v3/internal/modulesv2/entities"
)

type ModuleInstallationsRepository struct {
ListInstalledModulesResult []entities.ModuleInstallation
ListInstalledModulesError error
}

func (f *ModuleInstallationsRepository) ListInstalledModules(_ context.Context) ([]entities.ModuleInstallation, error) {
return f.ListInstalledModulesResult, f.ListInstalledModulesError
}
Loading
Loading