Skip to content

Commit

Permalink
Move all methods related to model.json to a separate file (#2132)
Browse files Browse the repository at this point in the history
  • Loading branch information
Cortey authored Jun 17, 2024
1 parent 66a3d8b commit c99b5b6
Show file tree
Hide file tree
Showing 2 changed files with 168 additions and 138 deletions.
168 changes: 30 additions & 138 deletions internal/cmd/modules/modules.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
package modules

import (
"encoding/json"
"fmt"
"github.com/kyma-project/cli.v3/internal/clierror"
"github.com/kyma-project/cli.v3/internal/cmdcommon"
"github.com/kyma-project/cli.v3/internal/model"
"io"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"net/http"
"strings"

"github.com/kyma-project/cli.v3/internal/clierror"
"github.com/spf13/cobra"
)

Expand All @@ -26,8 +17,6 @@ type modulesConfig struct {
installed bool
}

const URL = "https://raw.githubusercontent.com/kyma-project/community-modules/main/model.json"

func NewModulesCMD(kymaConfig *cmdcommon.KymaConfig) *cobra.Command {
cfg := modulesConfig{
KymaConfig: kymaConfig,
Expand All @@ -42,7 +31,7 @@ func NewModulesCMD(kymaConfig *cmdcommon.KymaConfig) *cobra.Command {
clierror.Check(cfg.KubeClientConfig.Complete())
},
Run: func(_ *cobra.Command, _ []string) {
clierror.Check(runModules(&cfg))
clierror.Check(listModules(&cfg))
},
}
cfg.KubeClientConfig.AddFlag(cmd)
Expand All @@ -59,165 +48,68 @@ func NewModulesCMD(kymaConfig *cmdcommon.KymaConfig) *cobra.Command {
return cmd
}

func runModules(cfg *modulesConfig) clierror.Error {
var err error
func listModules(cfg *modulesConfig) clierror.Error {
var err clierror.Error

if cfg.catalog {
modules, err := listAllModules()
err = listAllModules()
if err != nil {
return clierror.WrapE(err, clierror.New("failed to list all Kyma modules"))
}
fmt.Println("Available modules:\n")
for _, rec := range modules {
fmt.Println(rec)
}
return nil
}

if cfg.managed {
managed, err := listManagedModules(cfg)
err = listManagedModules(cfg)
if err != nil {
return clierror.WrapE(err, clierror.New("failed to list managed Kyma modules"))
}
fmt.Println("Managed modules:\n")
for _, rec := range managed {
fmt.Println(rec)
}
return nil
}

if cfg.installed {
installed, err := listInstalledModules(cfg)
err = listInstalledModules(cfg)
if err != nil {
return clierror.WrapE(err, clierror.New("failed to list installed Kyma modules"))
}
fmt.Println("Installed modules:\n")
for _, rec := range installed {
fmt.Println(rec)
}
return nil
}

return clierror.Wrap(err, clierror.New("failed to get modules", "please use one of: catalog, managed or installed flags"))
}

func listAllModules() ([]string, clierror.Error) {
resp, err := http.Get(URL)
if err != nil {
return nil, clierror.Wrap(err, clierror.New("while getting modules list from github"))
}
defer resp.Body.Close()

var template model.Module

template, respErr := handleResponse(err, resp, template)
if respErr != nil {
return nil, clierror.WrapE(respErr, clierror.New("while handling response"))
}

var out []string
for _, rec := range template {
out = append(out, rec.Name)
}
return out, nil
return clierror.WrapE(err, clierror.New("failed to get modules", "please use one of: catalog, managed or installed flags"))
}

func handleResponse(err error, resp *http.Response, template model.Module) (model.Module, clierror.Error) {
bodyText, err := io.ReadAll(resp.Body)
func listInstalledModules(cfg *modulesConfig) clierror.Error {
installed, err := model.GetInstalledModules(cfg.KubeClientConfig, *cfg.KymaConfig)
if err != nil {
return nil, clierror.Wrap(err, clierror.New("while reading http response"))
return clierror.WrapE(err, clierror.New("failed to get installed Kyma modules"))
}
err = json.Unmarshal(bodyText, &template)
if err != nil {
return nil, clierror.Wrap(err, clierror.New("while unmarshalling"))
fmt.Println("Installed modules:\n")
for _, rec := range installed {
fmt.Println(rec)
}
return template, nil
return nil
}

func listManagedModules(cfg *modulesConfig) ([]string, clierror.Error) {
GVRKyma := schema.GroupVersionResource{
Group: "operator.kyma-project.io",
Version: "v1beta2",
Resource: "kymas",
}

unstruct, err := cfg.KubeClient.Dynamic().Resource(GVRKyma).Namespace("kyma-system").Get(cfg.Ctx, "default", metav1.GetOptions{})
func listManagedModules(cfg *modulesConfig) clierror.Error {
managed, err := model.GetManagedModules(cfg.KubeClientConfig, *cfg.KymaConfig)
if err != nil {
return nil, clierror.Wrap(err, clierror.New("while getting Kyma CR"))
return clierror.WrapE(err, clierror.New("failed to get managed Kyma modules"))
}

moduleNames, err := getModuleNames(unstruct)
if err != nil {
return nil, clierror.Wrap(err, clierror.New("while getting module names from CR"))
fmt.Println("Managed modules:\n")
for _, rec := range managed {
fmt.Println(rec)
}

return moduleNames, nil
return nil
}

func listInstalledModules(cfg *modulesConfig) ([]string, clierror.Error) {
resp, err := http.Get(URL)
func listAllModules() clierror.Error {
modules, err := model.GetAllModules()
if err != nil {
return nil, clierror.Wrap(err, clierror.New("while getting modules list from github"))
}
defer resp.Body.Close()

var template model.Module

template, respErr := handleResponse(err, resp, template)
if respErr != nil {
return nil, clierror.WrapE(respErr, clierror.New("while handling response"))
}

var out []string
for _, rec := range template {
managerPath := strings.Split(rec.Versions[0].ManagerPath, "/")
managerName := managerPath[len(managerPath)-1]
version := rec.Versions[0].Version
deployment, err := cfg.KubeClient.Static().AppsV1().Deployments("kyma-system").Get(cfg.Ctx, managerName, metav1.GetOptions{})
if err != nil && !errors.IsNotFound(err) {
msg := "while getting the " + managerName + " deployment"
return nil, clierror.Wrap(err, clierror.New(msg))
}
if !errors.IsNotFound(err) {
deploymentImage := strings.Split(deployment.Spec.Template.Spec.Containers[0].Image, "/")
installedVersion := strings.Split(deploymentImage[len(deploymentImage)-1], ":")

if version == installedVersion[len(installedVersion)-1] {
out = append(out, rec.Name+" - "+installedVersion[len(installedVersion)-1])
} else {
out = append(out, rec.Name+" - "+"outdated version, latest version is "+version)
}
}
return clierror.WrapE(err, clierror.New("failed to get all Kyma modules"))
}
return out, nil
}

func getModuleNames(unstruct *unstructured.Unstructured) ([]string, error) {
var moduleNames []string
managedFields := unstruct.GetManagedFields()
for _, field := range managedFields {
var data map[string]interface{}
err := json.Unmarshal(field.FieldsV1.Raw, &data)
if err != nil {
return nil, err
}

spec, ok := data["f:spec"].(map[string]interface{})
if !ok {
continue
}

modules, ok := spec["f:modules"].(map[string]interface{})
if !ok {
continue
}

for key := range modules {
if strings.Contains(key, "name") {
name := strings.TrimPrefix(key, "k:{\"name\":\"")
name = strings.Trim(name, "\"}")
moduleNames = append(moduleNames, name)
}
}
fmt.Println("Available modules:\n")
for _, rec := range modules {
fmt.Println(rec)
}
return moduleNames, nil
return nil
}
138 changes: 138 additions & 0 deletions internal/model/modules.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package model

import (
"encoding/json"
"github.com/kyma-project/cli.v3/internal/clierror"
"github.com/kyma-project/cli.v3/internal/cmdcommon"
"io"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"net/http"
"strings"
)

const URL = "https://raw.githubusercontent.com/kyma-project/community-modules/main/model.json"

func GetAllModules() ([]string, clierror.Error) {
resp, err := http.Get(URL)
if err != nil {
return nil, clierror.Wrap(err, clierror.New("while getting modules list from github"))
}
defer resp.Body.Close()

var template Module

template, respErr := handleResponse(err, resp, template)
if respErr != nil {
return nil, clierror.WrapE(respErr, clierror.New("while handling response"))
}

var modules []string
for _, rec := range template {
modules = append(modules, rec.Name)
}
return modules, nil
}

func GetManagedModules(client cmdcommon.KubeClientConfig, cfg cmdcommon.KymaConfig) ([]string, clierror.Error) {
GVRKyma := schema.GroupVersionResource{
Group: "operator.kyma-project.io",
Version: "v1beta2",
Resource: "kymas",
}

unstruct, err := client.KubeClient.Dynamic().Resource(GVRKyma).Namespace("kyma-system").Get(cfg.Ctx, "default", metav1.GetOptions{})
if err != nil {
return nil, clierror.Wrap(err, clierror.New("while getting Kyma CR"))
}

managed, err := getModuleNames(unstruct)
if err != nil {
return nil, clierror.Wrap(err, clierror.New("while getting module names from CR"))
}

return managed, nil
}

func GetInstalledModules(client cmdcommon.KubeClientConfig, cfg cmdcommon.KymaConfig) ([]string, clierror.Error) {
resp, err := http.Get(URL)
if err != nil {
return nil, clierror.Wrap(err, clierror.New("while getting modules list from github"))
}
defer resp.Body.Close()

var template Module

template, respErr := handleResponse(err, resp, template)
if respErr != nil {
return nil, clierror.WrapE(respErr, clierror.New("while handling response"))
}

var installed []string
for _, rec := range template {
managerPath := strings.Split(rec.Versions[0].ManagerPath, "/")
managerName := managerPath[len(managerPath)-1]
version := rec.Versions[0].Version
deployment, err := client.KubeClient.Static().AppsV1().Deployments("kyma-system").Get(cfg.Ctx, managerName, metav1.GetOptions{})
if err != nil && !errors.IsNotFound(err) {
msg := "while getting the " + managerName + " deployment"
return nil, clierror.Wrap(err, clierror.New(msg))
}
if !errors.IsNotFound(err) {
deploymentImage := strings.Split(deployment.Spec.Template.Spec.Containers[0].Image, "/")
installedVersion := strings.Split(deploymentImage[len(deploymentImage)-1], ":")

if version == installedVersion[len(installedVersion)-1] {
installed = append(installed, rec.Name+" - "+installedVersion[len(installedVersion)-1])
} else {
installed = append(installed, rec.Name+" - "+"outdated version, latest version is "+version)
}
}
}
return installed, nil
}

func handleResponse(err error, resp *http.Response, template Module) (Module, clierror.Error) {
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
return nil, clierror.Wrap(err, clierror.New("while reading http response"))
}
err = json.Unmarshal(bodyText, &template)
if err != nil {
return nil, clierror.Wrap(err, clierror.New("while unmarshalling"))
}
return template, nil
}

func getModuleNames(unstruct *unstructured.Unstructured) ([]string, error) {
var moduleNames []string
managedFields := unstruct.GetManagedFields()
for _, field := range managedFields {
var data map[string]interface{}
err := json.Unmarshal(field.FieldsV1.Raw, &data)
if err != nil {
return nil, err
}

spec, ok := data["f:spec"].(map[string]interface{})
if !ok {
continue
}

modules, ok := spec["f:modules"].(map[string]interface{})
if !ok {
continue
}

for key := range modules {
if strings.Contains(key, "name") {
name := strings.TrimPrefix(key, "k:{\"name\":\"")
name = strings.Trim(name, "\"}")
moduleNames = append(moduleNames, name)
}
}
}
return moduleNames, nil
}

0 comments on commit c99b5b6

Please sign in to comment.