UnicodeSnowman / realm-cli

MongoDB Realm CLI

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

MongoDB Realm CLI

Building the CLI

The CLI can be run many different ways. To install it globally on your machine, you can use npm to do so:

npm install -g mongodb-realm-cli

Running from Source

You may wish to run the CLI from source, in which case go provides a few different options.

Using go run

The entry point for the CLI is in main.go, so simply running go run main.go from the root of the project repo is equivalent to invoking the installed command realm-cli. It accepts commands and flags as normal.

The one caveat here is you may wish to be running the tool from a clean directory, so as not to write app configuration files to the project repo. However, for commands that do not interact with the local filesystem, this is often the quickest and easiest way to run from source.

Using go build

Another option would be to build your own executable for realm-cli, at which point you could either invoke directly or then place on your machine's path somewhere. To do so, simply run:

go build -o realm-cli main.go

The above will build an executable named realm-cli that can be run with calling ./realm-cli. It accepts commands and flags as normal.

You may wish to set other configuration details while creating a local build of the CLI. To do so, you'll need to leverage the -ldflags option of go build. Here is an example usage of that with some CLI configuration details set:

go build -ldflags "-X github.com/10gen/realm-cli/internal/cli.Version=0.0.0-local -o realm-cli main.go

This will create a CLI build that will print 0.0.0-local when --version is invoked. Other configurable build options include:

  • -X github.com/10gen/realm-cli/internal/cli.osArch=macos-amd64
  • -X github.com/10gen/realm-cli/internal/telemetry.segmentWriteKey=${segment_write_key}

NOTE: ${segment_write_key} is a dynamic value you would need to replace with something valid. If it is left blank, then events will simply not be sent to Segment.

Using go install

Lastly, you can use go install which will build the realm-cli executable and install it in $GOPATH/bin (making it readily accessible throughout your machine). To do so, run:

go install

Additionally, the same -ldflags apply for go install as they do go build should you wish to configure this build further.

Running the CLI Locally

To run the CLI locally, you will want to have Realm server locally and capable of communicating with an Atlas instance for authentication. The recommended way to do this would be run baas with the local_cloud_dev_config.json server config via:

go run -exec="env LD_LIBRARY_PATH=$LD_LIBRARY_PATH" cmd/server/main.go --configFile etc/configs/local_cloud_dev_config.json

At which point you will have the necessary environment to run CLI commands that talk to a local Realm server and the Cloud Dev Atlas instance.

Authentication

To run any meaningful commands, you'll need to have an Atlas programmatic API Key created in the Atlas environment you are targeting to run with. In tha above setup, that would be on https://cloud-dev.mongodb.com, so ensure you create you API Key from there.

Using the Profile

With an API Key ready to be used, it's time to configure your profile with these details so you can easily execute commands with these details configured. The first thing you'll need to do is login, so the recommended command would be:

realm-cli login --profile local --api-key ${api_key} --private-api-key ${private_api_key} --realm-url http://localhost:8080 --atlas-url https://cloud-dev.mongodb.com

NOTE: Feel free to omit the --api-key and --private-api-key flags if you wish to run the command interactively. However, you must still remember to set the url flags (and optionally profile name) in order to talk to the right instances of Realm and Atlas.

By running this command, you've now created a "local" profile that knows your API Key credentials and the base URLs of the servers you wish to talk with. This profile is now also responsible for managing your active session with Realm. You can view all of these details on your machine at ~/.config/realm-cli/${profile}.yaml (where ${profile} is the name you supplied to the --profile flag).

After you successfully login, you will then be able to execute further commands by just specifying the same profile:

realm-cli --profile local whoami

realm-cli --profile local apps list

The base urls (among other details like api key credentials and telemetry mode) can be considered as "sticky" flags. Whenever they are provided and set, that particular profile (or the default profile if none is specified) will remember the new values going forward (read: they only need to be provided/set once).

Linting

To lint the project, run:

golangci-lint run

Testing

Unit Testing

To run unit tests:

go test -v -tags debug github.com/10gen/realm-cli/internal/... -run 'Test'

No environment variables should be necessary for running the CLI unit tests. You should see skipped tests for any of the integration tests that do require environment variables set and/or other servers running to talk to.

Integration Tests with Realm Server

To run integration tests against a Realm server locally, run baas with the local_cloud_dev_config.json server config via:

go run -exec="env LD_LIBRARY_PATH=$LD_LIBRARY_PATH" cmd/server/main.go --configFile etc/configs/local_cloud_dev_config.json

Then, from the realm-cli project root, simply run:

BAAS_MONGODB_CLOUD_GROUP_ID=${cloud_group_id} BAAS_MONGODB_CLOUD_GROUP_NAME=${cloud_group_name} BAAS_MONGODB_CLOUD_USERNAME=${cloud_username} BAAS_MONGODB_CLOUD_API_KEY=${cloud_api_key} go test -v -tags debug github.com/10gen/realm-cli/internal/cloud/... -run 'Test'

NOTE: With the above, you'll need to substitute ${cloud_group_id}, ${cloud_group_name}, ${cloud_username}, and ${cloud_api_key} with valid credentials of your own from https://cloud-dev.mongodb.com. Various other integration tests may rely on further environment variables you may wish to set, refer to internal/utils/test/test.go for more details.

Debugging an Interactive Test

Have a test that relies on prompts to the user for input? The go-expect framework handles those interactions and relies on "expected" output to wait for until proceeding with further instruction. Often times, this can result in a test hanging indefinitely if the expected output doesn't match. Unfortunately, in this case only a Ctrl+C (or timeout) ends the test and you are left without any output to inspect in order to determine a root cause.

If you want to actually see the output headed to your "pseudo-terminal", you just have to use a different stdout than the *bytes.Buffer tests usually rely on. For example:

out, outErr := mock.FileWriter(t)
assert.Nil(t, outErr)
defer out.Close()

c, err := expect.NewConsole(expect.WithStdout(out))
assert.Nil(t, err)
defer c.Close()

E2E Tests

E2E testing is not yet implemented for the realm-cli repo. The below is a suggested route to do so, taken from the documentation of go-expect library we use to leverage a pseudo-terminal within tests.

To write an end-to-end test for the CLI, use exec.Command. An example usage is:

func TestWhoamiE2E(t *testing.T) {
	core.DisableColor = true
	defer func() { core.DisableColor = false }()

	out := new(bytes.Buffer)
	c, err := expect.NewConsole(expect.WithStdout(out))
	assert.Nil(t, err)
	defer c.Close()

	go func() {
		c.ExpectEOF()
	}()

	cmd := exec.Command("../../main", "whoami")
	cmd.Stdin = c.Tty()
	cmd.Stdout = c.Tty()
	cmd.Stderr = c.Tty()

	if err := cmd.Start(); err != nil {
		log.Fatal(err)
	}
	if err := cmd.Wait(); err != nil {
		log.Fatal(err)
	}

  c.ExpectString("No user is currently logged in.")
	c.Tty().Close()

	fmt.Println(out.String()) // prints the output from the command
}

About

MongoDB Realm CLI

License:Apache License 2.0


Languages

Language:Go 99.0%Language:JavaScript 1.0%