-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ADDED] system model command #8284
Merged
Merged
Changes from all commits
Commits
Show all changes
43 commits
Select commit
Hold shift + click to select a range
e1d4211
"system model list" command is added
zakisk 25389b6
error and links are added for list command
zakisk 8e516a2
"system model list" command is added
zakisk a989e4e
error and links are added for list command
zakisk 8c78182
"system model view" command is added
zakisk 59821db
Merge branch 'meshery:master' into add_system_model_command
zakisk 62c8f58
minor changes
zakisk c707a22
Merge remote-tracking branch 'upstream/master' into add_system_model_…
zakisk d149bff
[TEST] Add Unit Test for `mesheryctl system model list` command
zakisk 6377c27
Merge branch 'meshery:master' into add_system_model_command
zakisk cea9125
[TEST] Add Unit Test for `mesheryctl system model view` command
zakisk f19f89a
Merge branch 'meshery:master' into add_system_model_command
zakisk dabd8b7
Revert "[TEST] Add Unit Test for `mesheryctl system model view` command"
zakisk 88d8809
minor rename
zakisk 6fd6987
Merge remote-tracking branch 'upstream/master' into add_system_model_…
zakisk c6b2dea
Merge branch 'meshery:master' into add_system_model_command
zakisk 468fa1c
Merge branch 'add_system_model_command' of https://github.com/zakisk/…
zakisk 1bd4baf
Merge branch 'meshery:master' into add_system_model_command
zakisk 183e62a
Merged latest changes from origin
zakisk ff6e87c
used utils.MakeRequest
zakisk fbe5ea2
renamed variable cfg and deleted unused comments
zakisk 45f0132
added error.go file
zakisk 5f44d18
Merge branch 'meshery:master' into add_system_model_command
zakisk 4c7b439
changes suggested by @suhail34
zakisk 20ac6ef
deleted duplicate errors
zakisk f44ef28
Merge branch 'meshery:master' into add_system_model_command
zakisk 0e5787a
Merge branch 'meshery:master' into add_system_model_command
zakisk a3e9cc8
Merge branch 'meshery:master' into add_system_model_command
zakisk d784e1d
Merge branch 'meshery:master' into add_system_model_command
zakisk d0261a3
Merge branch 'meshery:master' into add_system_model_command
zakisk a42df4d
formatted output of model list command in tabular form
zakisk e04c3e8
Merge remote-tracking branch 'upstream/master' into add_system_model_…
zakisk 60427ca
minor changes
zakisk 0ede87c
Merge remote-tracking branch 'upstream/master' into add_system_model_…
zakisk f1f2c41
minor error messages changes
zakisk 67054c7
Merge remote-tracking branch 'upstream/master' into add_system_model_…
zakisk eda44e5
Merge remote-tracking branch 'upstream/master' into add_system_model_…
zakisk aad1845
"system model list" command is added
zakisk 8db6406
Merge remote-tracking branch 'upstream/master' into add_system_model_…
zakisk 100c595
added server running status check before executing system model subco…
zakisk 5e487f2
Merge remote-tracking branch 'upstream/master' into add_system_model_…
zakisk 436f2e8
Merge remote-tracking branch 'upstream/master' into add_system_model_…
zakisk b3afb62
moved `model` command behind `exp` command
zakisk File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
mesheryctl/internal/cli/root/system/fixtures/list.model.api.response.golden
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{"meshery-provider":"Meshery","token":"eyJhY2Nlc3NfdG9rZW4iOiJleUpoYkdjaU9pSlNVekkxTmlJc0ltdHBaQ0k2SW5CMVlteHBZenBsT0dWbU5ERmpNeTFpWldWbUxUUmlZakV0T0dVNE1DMHpOakExTVRZeU4yTTJNakVpTENKMGVYQWlPaUpLVjFRaWZRLmV5SmhkV1FpT2x0ZExDSmpiR2xsYm5SZmFXUWlPaUp0WlhOb1pYSjVMV05zYjNWa0lpd2laWGh3SWpveE5qSXlPREk1TlRRMExDSmxlSFFpT250OUxDSnBZWFFpT2pFMk1qSTRNalU1TkRNc0ltbHpjeUk2SW1oMGRIQnpPaTh2YldWemFHVnllUzVzWVhsbGNqVXVhVzh2YUhsa2NtRXZJaXdpYW5ScElqb2lPRGMxT0RGbVpXSXROMlZpTnkwMFlqSTFMV0l3TURndE9XWTJaVEE0WXpabFkyVTJJaXdpYm1KbUlqb3hOakl5T0RJMU9UUXpMQ0p6WTNBaU9sc2liM0JsYm1sa0lpd2liMlptYkdsdVpTSmRMQ0p6ZFdJaU9pSmpSMncxWkZoT2IyTXliSFZhTWtaNVlWaHNhRHBhTW13d1lVaFdhU0o5Lk90aDJwYkJFNmFBcnBfUFVwR3E3b2ZsaEVWYmdsdTAtamdXNG44eWxHeVVTandOc0k4SmdoallIVGU5YjlUSzhWQUhoNVRyT0YwV1VRb0h4QVJGUmN6OHl2ZEdpbm1HcUZEZTd6RVpoSjZHZmNlZFl6bmpCc3FvVWthMTNXYzhvM0J2bGR2T2gtTjFGNzdHM3ZLenI0UEJaM2pXRHVEeWpjSUJnOTJVUzd0Nlg5Ymd6YklrT3lOOVhpWGVVNXQtbEJIamt2cklRazhqdWRKaTliOHVGaVBuMmdIMDVJbnhUdFJtSlFJdUhvSzV2WmxFQW0xN1J6ZER4WVI0cndqeTBqanFWdXdvWnBjbUJQM1dUNjdIVHhkYmo5N3hZM2IzNHh5ZFkxeVFVS09XR1NOckZVeXhMbW9QMmJUM24tQ0dVczJ1SWhnZExXNlZlNVQ1LV9tSGY0Z212X0NGWlFNelRsbjRFVmw2bTUxdjFxNXJzQmdfWmFuVmtXdGNHWF9ZSGs3WHpKdndXRDhvSmt5NzBleGUwYXJ3cmg2bjJkLU9jMi1Jc1F2OTBFM1hYeHBJcWxrckNfU3NiM1NpOU1jM1ptal9HY2JtOHVHbUZEejhaZEYxUEdpeDdKTjM3TzJyQnpaVldRaHFrZTV6MW42VUVITXJGSGJBNXBKVkxzUmE0ZUNBaFdwODVlZVV3ZjlUMnByc3FzNHBaMkh0eVpSMlBTdGFLZVFFai1SUXdvRHpDTEN4Zm85RnBvbEN6WmN3ZzRvLXhrb0Q0aS1MczIzODd0dm5xSTVESl8xaUlMX1hNTHByZXJtcDdxeGV2NEVDOW9abzdWenZmTDd4cDZTcnhIaldZQVpuZS12eURjQlhNZUlSMVVoeVdVZDQtaWJfZmxzdFVEME5XVV9ZIiwidG9rZW5fdHlwZSI6ImJlYXJlciIsInJlZnJlc2hfdG9rZW4iOiJXS3pZWW5BQkVJQkduekNfaWR2VW1IZUtsZlgzLWxjWm12TzBxY2ZCNlRzLm5kNXhXUFFIeWVTcTY0OUV2dy1tX2t3WDdqYWF1RDZiSExXTW9fQVhxZVUiLCJleHBpcnkiOiIyMDIxLTA2LTA0VDE3OjU5OjAzLjg0ODAyODAwOVoifQ"} | ||
alphaX86 marked this conversation as resolved.
Show resolved
Hide resolved
|
1 change: 1 addition & 0 deletions
1
mesheryctl/internal/cli/root/system/fixtures/view.model.api.response.golden
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{"page":1,"page_size":1,"total_count":1,"models":[{"name":"spire","version":"0.12.2","displayName":"SPIRE","category":{"name":"Security \u0026 Compliance","metadata":null},"metadata":{"svgColor":"ui/public/static/img/meshmodels/identity-manager/color/workloadidentity-color.svg","svgWhite":"ui/public/static/img/meshmodels/identity-manager/white/workloadidentity-white.svg"},"duplicates":0}]} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,344 @@ | ||
// Copyright 2023 Layer5, Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package system | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
"os" | ||
"strings" | ||
|
||
"github.com/layer5io/meshery/mesheryctl/internal/cli/root/config" | ||
"github.com/layer5io/meshery/mesheryctl/pkg/utils" | ||
"github.com/layer5io/meshery/server/models" | ||
"github.com/layer5io/meshkit/models/meshmodel/core/v1alpha1" | ||
"github.com/manifoldco/promptui" | ||
"github.com/pkg/errors" | ||
log "github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
"github.com/spf13/viper" | ||
"gopkg.in/yaml.v2" | ||
) | ||
|
||
var ( | ||
// flag used to specify the page number in list command | ||
pageNumberFlag int | ||
// flag used to specify format of output of view {model-name} command | ||
outFormatFlag string | ||
) | ||
|
||
// represents the `mesheryctl system model list` subcommand. | ||
var listModelCmd = &cobra.Command{ | ||
Use: "list", | ||
Short: "list models", | ||
Long: "list name of all registered models", | ||
Example: ` | ||
// View list of models | ||
mesheryctl system model list | ||
|
||
// View list of models with specified page number (25 models per page) | ||
mesheryctl system model list --page 2 | ||
`, | ||
PreRunE: func(cmd *cobra.Command, args []string) error { | ||
//Check prerequisite | ||
|
||
mctlCfg, err := config.GetMesheryCtl(viper.GetViper()) | ||
if err != nil { | ||
return err | ||
} | ||
err = utils.IsServerRunning(mctlCfg.GetBaseMesheryURL()) | ||
if err != nil { | ||
return err | ||
} | ||
ctx, err := mctlCfg.GetCurrentContext() | ||
if err != nil { | ||
return err | ||
} | ||
err = ctx.ValidateVersion() | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
}, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
if len(args) != 0 { | ||
return errors.New(utils.SystemModelSubError("this command takes no arguments\n", "list")) | ||
} | ||
mctlCfg, err := config.GetMesheryCtl(viper.GetViper()) | ||
if err != nil { | ||
log.Fatalln(err, "error processing config") | ||
} | ||
|
||
baseUrl := mctlCfg.GetBaseMesheryURL() | ||
var url string | ||
if cmd.Flags().Changed("page") { | ||
url = fmt.Sprintf("%s/api/meshmodels/models?page=%d", baseUrl, pageNumberFlag) | ||
} else { | ||
url = fmt.Sprintf("%s/api/meshmodels/models?pagesize=all", baseUrl) | ||
} | ||
req, err := utils.NewRequest(http.MethodGet, url, nil) | ||
if err != nil { | ||
utils.Log.Error(err) | ||
return err | ||
} | ||
|
||
resp, err := utils.MakeRequest(req) | ||
if err != nil { | ||
utils.Log.Error(err) | ||
return err | ||
} | ||
|
||
// defers the closing of the response body after its use, ensuring that the resources are properly released. | ||
defer resp.Body.Close() | ||
|
||
data, err := io.ReadAll(resp.Body) | ||
if err != nil { | ||
utils.Log.Error(err) | ||
return err | ||
} | ||
|
||
modelsResponse := &models.MeshmodelsAPIResponse{} | ||
err = json.Unmarshal(data, modelsResponse) | ||
if err != nil { | ||
utils.Log.Error(err) | ||
return err | ||
} | ||
|
||
header := []string{"Category", "Model", "Version"} | ||
rows := [][]string{} | ||
|
||
for _, model := range modelsResponse.Models { | ||
if len(model.DisplayName) > 0 { | ||
rows = append(rows, []string{model.Category.Name, model.Name, model.Version}) | ||
} | ||
} | ||
|
||
if len(rows) == 0 { | ||
// if no model is found | ||
utils.Log.Info("No model(s) found") | ||
} else { | ||
utils.PrintToTable(header, rows) | ||
} | ||
|
||
return nil | ||
}, | ||
} | ||
|
||
// represents the `mesheryctl system model view [model-name]` subcommand. | ||
var viewModelCmd = &cobra.Command{ | ||
Use: "view", | ||
Short: "view model", | ||
Long: "view a model queried by its name", | ||
Example: ` | ||
// View current provider | ||
mesheryctl system model view [model-name] | ||
`, | ||
PreRunE: func(cmd *cobra.Command, args []string) error { | ||
//Check prerequisite | ||
|
||
mctlCfg, err := config.GetMesheryCtl(viper.GetViper()) | ||
if err != nil { | ||
return err | ||
} | ||
err = utils.IsServerRunning(mctlCfg.GetBaseMesheryURL()) | ||
if err != nil { | ||
return err | ||
} | ||
ctx, err := mctlCfg.GetCurrentContext() | ||
if err != nil { | ||
return err | ||
} | ||
err = ctx.ValidateVersion() | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
}, | ||
Args: func(_ *cobra.Command, args []string) error { | ||
const errMsg = "Usage: mesheryctl system model view [model-name]\nRun 'mesheryctl system model view --help' to see detailed help message" | ||
if len(args) == 0 { | ||
return fmt.Errorf("model name isn't specified\n\n%v", errMsg) | ||
} else if len(args) > 1 { | ||
return fmt.Errorf("too many arguments\n\n%v", errMsg) | ||
} | ||
return nil | ||
}, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
mctlCfg, err := config.GetMesheryCtl(viper.GetViper()) | ||
if err != nil { | ||
log.Fatalln(err, "error processing config") | ||
} | ||
|
||
baseUrl := mctlCfg.GetBaseMesheryURL() | ||
model := args[0] | ||
|
||
url := fmt.Sprintf("%s/api/meshmodels/models/%s?pagesize=all", baseUrl, model) | ||
req, err := utils.NewRequest(http.MethodGet, url, nil) | ||
if err != nil { | ||
utils.Log.Error(err) | ||
return err | ||
} | ||
|
||
resp, err := utils.MakeRequest(req) | ||
if err != nil { | ||
utils.Log.Error(err) | ||
return err | ||
} | ||
|
||
// defers the closing of the response body after its use, ensuring that the resources are properly released. | ||
defer resp.Body.Close() | ||
|
||
data, err := io.ReadAll(resp.Body) | ||
if err != nil { | ||
utils.Log.Error(err) | ||
return err | ||
} | ||
|
||
modelsResponse := &models.MeshmodelsAPIResponse{} | ||
err = json.Unmarshal(data, modelsResponse) | ||
if err != nil { | ||
utils.Log.Error(err) | ||
return err | ||
} | ||
|
||
var selectedModel v1alpha1.Model | ||
|
||
if modelsResponse.Count == 0 { | ||
utils.Log.Info("No model(s) found for the given name ", model) | ||
return nil | ||
} else if modelsResponse.Count == 1 { | ||
selectedModel = modelsResponse.Models[0] | ||
} else { | ||
selectedModel = selectModelPrompt(modelsResponse.Models) | ||
} | ||
|
||
var output []byte | ||
|
||
// user may pass flag in lower or upper case but we have to keep it lower | ||
// in order to make it consistent while checking output format | ||
outFormatFlag = strings.ToLower(outFormatFlag) | ||
if outFormatFlag == "yaml" { | ||
if output, err = yaml.Marshal(selectedModel); err != nil { | ||
return errors.Wrap(err, "failed to format output in YAML") | ||
} | ||
fmt.Print(string(output)) | ||
} else if outFormatFlag == "json" { | ||
return outputJson(selectedModel) | ||
} else { | ||
return errors.New("output-format choice invalid, use [json|yaml]") | ||
} | ||
|
||
return nil | ||
}, | ||
} | ||
|
||
// ModelCmd represents the `mesheryctl system model` command | ||
var ModelCmd = &cobra.Command{ | ||
Use: "model", | ||
Short: "View list of models and detail of models", | ||
Long: `View list of models and detailed information of a specific model`, | ||
Example: ` | ||
// To view list of components | ||
mesheryctl system model list | ||
|
||
// To view a specific model | ||
mesheryctl system model view [model-name] | ||
zakisk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
`, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
if len(args) == 0 { | ||
cmd.Help() | ||
} | ||
if ok := utils.IsValidSubcommand(availableSubcommands, args[0]); !ok { | ||
return errors.New(utils.SystemModelSubError(fmt.Sprintf("'%s' is an invalid subcommand. Please provide required options from [view]. Use 'mesheryctl system model --help' to display usage guide.\n", args[0]), "model")) | ||
} | ||
_, err := config.GetMesheryCtl(viper.GetViper()) | ||
if err != nil { | ||
log.Fatalln(err, "error processing config") | ||
} | ||
err = viewProviderCmd.RunE(cmd, args) | ||
if err != nil { | ||
return err | ||
} | ||
err = cmd.Usage() | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
}, | ||
} | ||
|
||
func init() { | ||
listModelCmd.Flags().IntVarP(&pageNumberFlag, "page", "p", 1, "(optional) List next set of models with --page (default = 1)") | ||
viewModelCmd.Flags().StringVarP(&outFormatFlag, "output-format", "o", "yaml", "(optional) format to display in [json|yaml]") | ||
availableSubcommands = []*cobra.Command{listModelCmd, viewModelCmd} | ||
ModelCmd.AddCommand(availableSubcommands...) | ||
} | ||
|
||
// `selectModelPrompt` lets user to select a model if models are more than one | ||
func selectModelPrompt(models []v1alpha1.Model) v1alpha1.Model { | ||
modelArray := []v1alpha1.Model{} | ||
modelNames := []string{} | ||
|
||
modelArray = append(modelArray, models...) | ||
|
||
for _, model := range modelArray { | ||
modelName := fmt.Sprintf("%s, version: %s", model.DisplayName, model.Version) | ||
modelNames = append(modelNames, modelName) | ||
} | ||
|
||
prompt := promptui.Select{ | ||
Label: "Select a model", | ||
Items: modelNames, | ||
} | ||
|
||
for { | ||
i, _, err := prompt.Run() | ||
if err != nil { | ||
continue | ||
} | ||
|
||
return modelArray[i] | ||
} | ||
} | ||
|
||
func outputJson(model v1alpha1.Model) error { | ||
if err = prettifyJson(model); err != nil { | ||
// if prettifyJson return error, marshal output in conventional way using json.MarshalIndent | ||
// but it doesn't convert unicode to its corresponding HTML string (it is default behavior) | ||
// e.g unicode representation of '&' will be printed as '\u0026' | ||
if output, err := json.MarshalIndent(model, "", " "); err != nil { | ||
return errors.Wrap(err, "failed to format output in JSON") | ||
} else { | ||
fmt.Print(string(output)) | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// prettifyJson takes a v1alpha1.Model struct as input, marshals it into a nicely formatted JSON representation, | ||
// and prints it to standard output with proper indentation and without escaping HTML entities. | ||
func prettifyJson(model v1alpha1.Model) error { | ||
// Create a new JSON encoder that writes to the standard output (os.Stdout). | ||
enc := json.NewEncoder(os.Stdout) | ||
// Configure the JSON encoder settings. | ||
// SetEscapeHTML(false) prevents special characters like '<', '>', and '&' from being escaped to their HTML entities. | ||
enc.SetEscapeHTML(false) | ||
enc.SetIndent("", " ") | ||
|
||
// Any errors during the encoding process will be returned as an error. | ||
return enc.Encode(model) | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we exposing a secret publicly like this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not yet answered...