docs/static/v0.6/project/contributing/contributing-cli/index.html
mesheryctl is written in Golang or the Go Programming Language. For development use Go version 1.19+.
mesheryctl commands.Fill-in a community member form to gain access to community resources.
Building mesheryctl
The /mesheryctl folder contains the complete code for mesheryctl. Fork and clone the Meshery repo. cd mesheryctl to change directory mesheryctl’s source.
After making changes, run make in the mesheryctl folder to build the binary. You can then use the binary by, say, ./mesheryctl system start.
Framework
mesheryctl uses the Cobra framework. A good first-step towards contributing to mesheryctl would be to familiarise yourself with the Cobra concepts. For manipulating config files, mesheryctl uses Viper.
Model and Configuration Data
A central struct is maintained in the mesheryctl/internal/cli/root/config/config.go file. These are updated and should be used for getting the Meshery configuration.
Updates to this central struct is made through updates in Context with setter functions. The changes made in this central struct are reflected back in the Meshery configuration file (.meshery/config.yaml).
Logging
For logs, mesheryctl uses Logrus. Going through the docs and understanding the different log-levels will help a lot.
Linting
mesheryctl uses golangci-lint. See the .github/workflow/ci.yaml for syntax used during Meshery’s build process.
Unit Tests
Unit test code coverage reports can be found in the CodeCov logs. Note: GitHub login may be required for access.
Documentation
The documentation pages for mesheryctl reference are made with the help of the Cobra Golang framework and use of GitHub Actions. Refer to Contributing to mesheryctl documentation for details.
These guidelines are a collection of principles and conventions that need to be followed while designing mesheryctl commands. mesheryctl might be the interface that the users first have with Meshery. As such, mesheryctl needs to provide a great UX.
The following principles should be taken in mind while designing mesheryctl commands-
1. Consistency is quality.
2. Intuitive user experiences feel natural to users.
3. Design for brevity.
4. Design with automated testing in mind.
Part of delivering a great user experience is providing intuitive interfaces. In the case of mesheryctl takes inspiration from and delivers similar user experiences as popular CLIs do in this ecosystem, like kubectl and docker. Here is relevant kubectl information to reference - Kubectl SIG CLI Community Meeting Minutes, contributing to kubectl, code.
Command structure and command behavior should be designed in such a way that they are intuitive. Users should ideally be able to understand what a command is used for without having to extensively go through the documentation. For example, mesheryctl pattern apply -f <pattern name> requires no further clarification as it is evident that the command will apply the pattern specified.
Consistency is key when designing intuitive interfaces. Although mesheryctl perf run -f <performance profile name> may sound more intuitive, users who are experienced in using the CLI will prefer the consistant verb apply over run. This will also ensure a consistent command language making memorizing easier.
Flags
Consistency should also be enforced when chaining commands and using flags. For example, if mesheryctl pattern has a list and view command and has an -all and --output flag, then, similar commands like mesheryctl perf should also support the same commands and flags and provide a consistent user experience.
Default behaviour should be optimised for what users will need to do most of the time.
These assumed defaults should be easily overriden by the user with flags.
For example, mesheryctl system context create <context name> assumes a default platform for the created context. But this can be easily overriden with the --platform flag.
Ideally, all functionaly provided in Meshery UI should be available to users via CLI (in mesheryctl). Meshery strives for parity of functionality between it’s two clients. For example, viewing a performance profile in the GUI and with mesheryctl system perf view <profile name> in the CLI should show the same data.
Command line interfaces offer less context to the user, which makes them inherently less intuitive compared to graphical user interfaces. Both of these user interfaces, however, are the same in that they are both clients of Meshery Server. Both clients are a user experience and as such, to be attended to in this way. The following considerations should be accounted for when designing mesheryctl experiences:
--verbose flag wherever needed.AskForConfirmation function which will prompt the user to type in “yes” or “no” to continue.mesheryctl system context create then the next action might be mesheryctl system start to start Meshery ot mesheryctl system context switch to switch context names.mesheryctl system satrt, using the inbuilt features with the cobra library, we can correct it to start and alert the user.If you are working on a new command or adding a new feature on an existing command, it is recommended to setup a design spec so that other contributors can weigh in on the design before you start to code.Broader features should have a design spec made in Google Doc. Check this Google Doc out, which has detailed information on creating a Design Specification. For small changes, communicating over the issue tracker or the discussions will be helpful.
When designing for the command line interface, ask and consider the following questions.
mesheryctl <command> <subcommand> [args] [flags] [value])You will need to provide a short and long description of the command for the help pages and also for the Meshery Documentation.
Unit tests and integration tests are essential to make each mesheryctl release robust and fault tolerant.
Below you will find guidelines to write unit tests and integration tests and examples of how they are implemented in mesheryctl.
Unit tests: Individual components are tested.
Integration tests: Individual components are combined and tested as a group.
The Meshery CLI Reference is autogenerated based on docs sections in each of mesheryctl’s Golang files. Meshery CLI Reference pages are updated each time a change to its respective mesheryctl Golang file is merged into the project’s master branch. This approach to documentation facilitates a single source of truth for CLI syntax and command behavior, which results in higher quality reference and a reduction in the toil involved in keeping documentation up-to-date. To contribute to the Meshery CLI Reference, follow these steps:
`var startCmd = &cobra.Command{
Use: "start",
Short: "Start Meshery",
Long: 'Start Meshery and each of its service mesh components.',
Args: cobra.NoArgs,
Example:```
// Start meshery
mesheryctl system start
// To create a new context for in-cluster Kubernetes deployments and set the new context as your current-context
mesheryctl system context create k8s -p kubernetes -s
```,
Annotations: linkScreenshot,
...`
The variables present in above sample will be used in creating the doc pages for the specific command
Also, if the screenshot is present in the command, an Annotation macro variable (of map[string]string type) containing the link and the caption has to be added at the bottom of the Examples field in the command file. The image file has to be included in the docs/assets folder in PNG format. The screenshot field is given for reference below
`var linkDocPatternApply = map[string]string{
"link": "",
"caption": "Usage of mesheryctl pattern apply",
}
...
Example:```
// apply a pattern file
mesheryctl pattern apply -f [file | URL]
// deploy a saved pattern
mesheryctl pattern apply [pattern-name]
```,
Annotations: linkDocPatternApply,
...
`
NOTE: It is advised not to modify the changes in docs folder, rather should be done in mesheryctl folder as the changes will get overwritten by the script.
Though the command page is generated automatically by the Cobra CLI library, there are chances where the command does not appear in the reference index page. In such cases, the command details must be manually added to the reference index YAML file. This is generally done by editing the below two files:
The following key principles should be taken to mind when writing tests:
Since there is no straightforward way to mark unit tests and integration tests differently. Here we use the --short flag while running tests to differentiate between unit tests and integration tests.
`func TestPreflightCmdIntegration(t *testing.T) {
// skipping this integration test with --short flag
if testing.Short() {
t.Skip("skipping integration test")
}
}`
In the above code sample, the test is marked with “Integration” in the title and if a --short flag is passed with the command, this test is skipped.
Unit tests:
`go test --short ./... -race -coverprofile=coverage.txt -covermode=atomic`
Integration tests:
`go test -run Integration ./... -race -coverprofile=coverage.txt -covermode=atomic`
To update golden files with the test output use the --update flag:
`var update = flag.Bool("update", false, "update golden files")`
To grab console logs - fmt.Println() (check mesheryctl/internal/cli/root/perf/view_test.go )
To grab Logrus logs - logrus.Info() (check mesheryctl/internal/cli/root/perf/apply_test.go )