Skip to content

Commit

Permalink
Merge pull request meshery#11338 from humblenginr/model_export
Browse files Browse the repository at this point in the history
[Feat] `mesheryctl model export` command
  • Loading branch information
aabidsofi19 authored Jul 9, 2024
2 parents 0a543e8 + ff1959c commit 263e1c6
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 7 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ replace (
github.com/docker/cli => github.com/docker/cli v23.0.6+incompatible
github.com/docker/docker => github.com/docker/docker v23.0.6+incompatible
github.com/kubernetes/kompose => github.com/meshery/kompose v1.26.2-0.20230425025309-3bb778d54007

k8s.io/client-go => k8s.io/client-go v0.28.3
k8s.io/kubectl => k8s.io/kubectl v0.28.3
oras.land/oras-go v1.2.4 => oras.land/oras-go v1.2.3
Expand Down Expand Up @@ -333,4 +334,3 @@ require (
sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)
62 changes: 62 additions & 0 deletions mesheryctl/internal/cli/root/model/export.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package model

import (
"fmt"
"github.com/layer5io/meshery/mesheryctl/internal/cli/root/config"
"github.com/layer5io/meshery/mesheryctl/pkg/utils"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

// mesheryctl model export <designname>
var exportModal = &cobra.Command{
Use: "export",
Short: "export registered models",
Long: "export the registered model to the specified output type",
Example: `
// Export a model by name
mesheryctl model export <modelname> -o json
mesheryctl model export <modelname> -o yaml
mesheryctl model export <modelname> -l /home/meshery/
mesheryctl model export <modelname> --include-components true --include-relationships true
`,
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 model export [model-name]\nRun 'mesheryctl model export --help' to see detailed help message"
if len(args) == 0 {
return utils.ErrInvalidArgument(errors.New("Please provide a model name. " + 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()
modelName := args[0]
url := fmt.Sprintf("%s/api/meshmodels/models/%s?components=%t&relationships=%t&%s", baseUrl, modelName, includeCompsFlag, includeRelsFlag, utils.GetPageQueryParameter(cmd, pageNumberFlag))
return exportModel(args[0], cmd, url, false)
},
}
78 changes: 76 additions & 2 deletions mesheryctl/internal/cli/root/model/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// Unless required by a, filepath.Dir(${1:}modelDefPathpplicable 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
Expand All @@ -20,12 +20,14 @@ import (
"io"
"net/http"
"os"
"path/filepath"

"github.com/fatih/color"
"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/v1beta1"
"github.com/layer5io/meshkit/models/oci"
"github.com/manifoldco/promptui"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
Expand All @@ -39,13 +41,22 @@ var (
// flag used to specify format of output of view {model-name} command
outFormatFlag string

// flag used to specify output location of export {model-name} command
outLocationFlag string
// flag used to specify format of output of export {model-name} command
outTypeFlag string
// flag used to specify whether to include components in the model
includeCompsFlag bool
// flag used to specify whether to include relationships in the model
includeRelsFlag bool

// Maximum number of rows to be displayed in a page
maxRowsPerPage = 25

// Color for the whiteboard printer
whiteBoardPrinter = color.New(color.FgHiBlack, color.BgWhite, color.Bold)

availableSubcommands = []*cobra.Command{listModelCmd, viewModelCmd, searchModelCmd, importModelCmd}
availableSubcommands = []*cobra.Command{listModelCmd, viewModelCmd, searchModelCmd, importModelCmd, exportModal}

countFlag bool
)
Expand Down Expand Up @@ -133,6 +144,12 @@ mesheryctl model search [model-name]
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]")

exportModal.Flags().StringVarP(&outLocationFlag, "output-location", "l", "./", "(optional) output location (default = current directory)")
exportModal.Flags().StringVarP(&outTypeFlag, "output-type", "o", "yaml", "(optional) format to display in [json|yaml] (default = yaml)")
exportModal.Flags().BoolVarP(&includeCompsFlag, "include-components", "c", false, "whether to include components in the model definition (default = false)")
exportModal.Flags().BoolVarP(&includeRelsFlag, "include-relationships", "r", false, "whether to include components in the model definition (default = false)")

ModelCmd.AddCommand(availableSubcommands...)
ModelCmd.Flags().BoolVarP(&countFlag, "count", "", false, "(optional) Get the number of models in total")
}
Expand Down Expand Up @@ -255,3 +272,60 @@ func listModel(cmd *cobra.Command, url string, displayCountOnly bool) error {

return nil
}

func exportModel(modelName string, cmd *cobra.Command, url string, displayCountOnly bool) error {
// Find the entity with the model name
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
}

// ensure proper cleaning of resources
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
}
model := modelsResponse.Models[0]
// Convert it to the required output type and write it
if outTypeFlag == "yaml" {
err = model.WriteModelDefinition(filepath.Join(outLocationFlag, modelName, "model.yaml"), "yaml")
}
if outTypeFlag == "json" {
err = model.WriteModelDefinition(filepath.Join(outLocationFlag, modelName, "model.json"), "json")
}
if outTypeFlag == "oci" {
// write model as yaml temporarily
modelDir := filepath.Join(outLocationFlag, modelName)
err = model.WriteModelDefinition(filepath.Join(modelDir, "model.yaml"), "yaml")
// build oci image for the model
img, err := oci.BuildImage(modelDir)
if err != nil {
utils.Log.Error(err)
return err
}
oci.SaveOCIArtifact(img, outLocationFlag+modelName+".tar", modelName)
os.RemoveAll(modelDir)
}
if err != nil {
utils.Log.Error(err)
return err
}
return nil
}
4 changes: 2 additions & 2 deletions mesheryctl/internal/cli/root/registry/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ var generateCmd = &cobra.Command{
Short: "Generate Models",
Long: "Prerequisite: Excecute this command from the root of a meshery/meshery repo fork.\n\nGiven a Google Sheet with a list of model names and source locations, generate models and components any Registrant (e.g. GitHub, Artifact Hub) repositories.\n\nGenerated Model files are written to local filesystem under `/server/models/<model-name>`.",
Example: `
// Generate Meshery Models from a Google Spreadsheet (i.e. "Meshery Integrations" spreadsheet).
// Generate Meshery Models from a Google Spreadsheet (i.e. "Meshery Integrations" spreadsheet).
mesheryctl registry generate --spreadsheet-id "1DZHnzxYWOlJ69Oguz4LkRVTFM79kC2tuvdwizOJmeMw" --spreadsheet-cred
// Directly generate models from one of the supported registrants by using Registrant Connection Definition and (optional) Registrant Credential Definition
mesheryctl registry generate --registrant-def [path to connection definition] --registrant-cred [path to credential definition]
Expand Down Expand Up @@ -408,7 +408,7 @@ func createVersionedDirectoryForModelAndComp(version, modelName string) (string,

func writeModelDefToFileSystem(model *utils.ModelCSV, version, modelDefPath string) (*v1beta1.Model, error) {
modelDef := model.CreateModelDefinition(version, defVersion)
err := modelDef.WriteModelDefinition(modelDefPath, "json")
err := modelDef.WriteModelDefinition(modelDefPath+"/model.json", "json")
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion mesheryctl/internal/cli/root/registry/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ func init() {
func WriteModelDefToFileSystem(model *utils.ModelCSV, version string, location string) (string, *v1beta1.Model, error) {
modelDef := model.CreateModelDefinition(version, defVersion)
modelDefPath := filepath.Join(location, modelDef.Name)
err := modelDef.WriteModelDefinition(modelDefPath, "json")
err := modelDef.WriteModelDefinition(modelDefPath+"/model.json", "json")
if err != nil {
return "", nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion server/handlers/meshery_pattern_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2074,4 +2074,4 @@ func createArtifactHubPkg(pattern *models.MesheryPattern, user string) ([]byte,
}

return data, nil
}
}

0 comments on commit 263e1c6

Please sign in to comment.