From e8944c54be117d47977e79e8b3035243a99a04f6 Mon Sep 17 00:00:00 2001 From: Gustavo Bazan Date: Fri, 27 Aug 2021 17:30:50 +0100 Subject: [PATCH] feat: mcli integration (#536) --- mongodbatlas/config.go | 28 ++++++------ mongodbatlas/provider.go | 54 ++++++++++++----------- website/docs/index.html.markdown | 74 ++++++++++++++++++-------------- 3 files changed, 85 insertions(+), 71 deletions(-) diff --git a/mongodbatlas/config.go b/mongodbatlas/config.go index 8a2dfe9f91..dcf7ad0900 100644 --- a/mongodbatlas/config.go +++ b/mongodbatlas/config.go @@ -2,24 +2,24 @@ package mongodbatlas import ( "context" - "fmt" + "errors" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/logging" + "github.com/mongodb-forks/digest" "github.com/mongodb/terraform-provider-mongodbatlas/version" "github.com/spf13/cast" - realmAuth "go.mongodb.org/realm/auth" - - "github.com/mongodb-forks/digest" matlasClient "go.mongodb.org/atlas/mongodbatlas" + realmAuth "go.mongodb.org/realm/auth" "go.mongodb.org/realm/realm" ) // Config struct ... type Config struct { - PublicKey string - PrivateKey string - BaseURL string + PublicKey string + PrivateKey string + BaseURL string + RealmBaseURL string } // MongoDBClient client @@ -28,6 +28,8 @@ type MongoDBClient struct { Config *Config } +var ua = "terraform-provider-mongodbatlas/" + version.ProviderVersion + // NewClient func... func (c *Config) NewClient(ctx context.Context) (interface{}, diag.Diagnostics) { // setup a transport to handle digest @@ -41,8 +43,8 @@ func (c *Config) NewClient(ctx context.Context) (interface{}, diag.Diagnostics) client.Transport = logging.NewTransport("MongoDB Atlas", transport) - optsAtlas := []matlasClient.ClientOpt{matlasClient.SetUserAgent("terraform-provider-mongodbatlas/" + version.ProviderVersion)} - if len(c.BaseURL) > 0 { + optsAtlas := []matlasClient.ClientOpt{matlasClient.SetUserAgent(ua)} + if c.BaseURL != "" { optsAtlas = append(optsAtlas, matlasClient.SetBaseURL(c.BaseURL)) } @@ -63,12 +65,12 @@ func (c *Config) NewClient(ctx context.Context) (interface{}, diag.Diagnostics) func (c *MongoDBClient) GetRealmClient(ctx context.Context) (*realm.Client, error) { // Realm if c.Config.PublicKey == "" && c.Config.PrivateKey == "" { - return nil, fmt.Errorf("please set `public_key` and `private_key` in order to use the realm client") + return nil, errors.New("please set `public_key` and `private_key` in order to use the realm client") } - optsRealm := []realm.ClientOpt{realm.SetUserAgent("terraform-provider-mongodbatlas/" + version.ProviderVersion)} - if len(c.Config.BaseURL) > 0 { - optsRealm = append(optsRealm, realm.SetBaseURL(c.Config.BaseURL)) + optsRealm := []realm.ClientOpt{realm.SetUserAgent(ua)} + if c.Config.BaseURL != "" && c.Config.RealmBaseURL != "" { + optsRealm = append(optsRealm, realm.SetBaseURL(c.Config.RealmBaseURL)) } authConfig := realmAuth.NewConfig(nil) token, err := authConfig.NewTokenFromCredentials(ctx, c.Config.PublicKey, c.Config.PrivateKey) diff --git a/mongodbatlas/provider.go b/mongodbatlas/provider.go index b235653512..6f65ec65ea 100644 --- a/mongodbatlas/provider.go +++ b/mongodbatlas/provider.go @@ -1,7 +1,6 @@ package mongodbatlas import ( - "bytes" "context" "encoding/base64" "fmt" @@ -22,22 +21,38 @@ func Provider() *schema.Provider { return &schema.Provider{ Schema: map[string]*schema.Schema{ "public_key": { - Type: schema.TypeString, - Required: true, - DefaultFunc: schema.EnvDefaultFunc("MONGODB_ATLAS_PUBLIC_KEY", ""), + Type: schema.TypeString, + Required: true, + DefaultFunc: schema.MultiEnvDefaultFunc([]string{ + "MONGODB_ATLAS_PUBLIC_KEY", + "MCLI_PUBLIC_API_KEY", + }, ""), Description: "MongoDB Atlas Programmatic Public Key", }, "private_key": { - Type: schema.TypeString, - Required: true, - DefaultFunc: schema.EnvDefaultFunc("MONGODB_ATLAS_PRIVATE_KEY", ""), + Type: schema.TypeString, + Required: true, + DefaultFunc: schema.MultiEnvDefaultFunc([]string{ + "MONGODB_ATLAS_PRIVATE_KEY", + "MCLI_PRIVATE_API_KEY", + }, ""), Description: "MongoDB Atlas Programmatic Private Key", + Sensitive: true, }, "base_url": { + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.MultiEnvDefaultFunc([]string{ + "MONGODB_ATLAS_BASE_URL", + "MCLI_OPS_MANAGER_URL", + }, ""), + Description: "MongoDB Atlas Base URL", + }, + "realm_base_url": { Type: schema.TypeString, Optional: true, - DefaultFunc: schema.EnvDefaultFunc("MONGODB_ATLAS_BASE_URL", ""), - Description: "MongoDB Atlas Base URL", + DefaultFunc: schema.EnvDefaultFunc("MONGODB_REALM_BASE_URL", ""), + Description: "MongoDB Realm Base URL", }, }, @@ -129,12 +144,10 @@ func Provider() *schema.Provider { func providerConfigure(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) { config := Config{ - PublicKey: d.Get("public_key").(string), - PrivateKey: d.Get("private_key").(string), - } - - if baseURL, ok := d.GetOk("base_url"); ok { - config.BaseURL = baseURL.(string) + PublicKey: d.Get("public_key").(string), + PrivateKey: d.Get("private_key").(string), + BaseURL: d.Get("base_url").(string), + RealmBaseURL: d.Get("realm_base_url").(string), } return config.NewClient(ctx) @@ -302,14 +315,3 @@ func HashCodeString(s string) int { // v == MinInt return 0 } - -// HashCodeStrings hashes a list of strings to a unique hashcode. -func HashCodeStrings(hashStrings []string) string { - var buf bytes.Buffer - - for _, s := range hashStrings { - buf.WriteString(fmt.Sprintf("%s-", s)) - } - - return fmt.Sprintf("%d", HashCodeString(buf.String())) -} diff --git a/website/docs/index.html.markdown b/website/docs/index.html.markdown index 90d0616ed1..37720d0196 100644 --- a/website/docs/index.html.markdown +++ b/website/docs/index.html.markdown @@ -8,11 +8,13 @@ description: |- # MongoDB Atlas Provider -The MongoDB Atlas provider is used to interact with the resources supported by [MongoDB Atlas](https://www.mongodb.com/cloud/atlas). The provider needs to be configured with the proper credentials before it can be used. +You can use the MongoDB Atlas provider to interact with the resources supported by [MongoDB Atlas](https://www.mongodb.com/cloud/atlas). +The provider needs to be configured with the proper credentials before it can be used. Use the navigation to the left to read about the available provider resources and data sources. -You may want to consider pinning the [provider version](https://www.terraform.io/docs/configuration/providers.html#provider-versions) to ensure you have a chance to review and prepare for changes. Speaking of changes, see [CHANGELOG](https://github.com/mongodb/terraform-provider-mongodbatlas/blob/master/CHANGELOG.md) for current version information. +You may want to consider pinning the [provider version](https://www.terraform.io/docs/configuration/providers.html#provider-versions) to ensure you have a chance to review and prepare for changes. +Speaking of changes, see [CHANGELOG](https://github.com/mongodb/terraform-provider-mongodbatlas/blob/master/CHANGELOG.md) for current version information. ## Example Usage @@ -22,37 +24,25 @@ provider "mongodbatlas" { public_key = var.mongodbatlas_public_key private_key = var.mongodbatlas_private_key } - -#Create the resources -... +# Create the resources ``` ## Configure Atlas Programmatic Access -In order to setup authentication with the MongoDB Atlas provider a programmatic API key must be generated for MongoDB Atlas with the appropriate permissions and IP access list entries. The [MongoDB Atlas documentation](https://docs.atlas.mongodb.com/tutorial/manage-programmatic-access/index.html) contains the most up-to-date instructions for creating and managing your key(s) and IP access. Be aware, not all API resources require an IP access list by default, but one can set Atlas to require IP access entries for all API resources, see the [organization settings documentation](https://docs.atlas.mongodb.com/tutorial/manage-organization-settings/#require-ip-access-list-for-public-api) for more info. +In order to set up authentication with the MongoDB Atlas provider a programmatic API key must be generated for MongoDB Atlas with the appropriate permissions and IP access list entries. +The [MongoDB Atlas documentation](https://docs.atlas.mongodb.com/tutorial/manage-programmatic-access/index.html) contains the most up-to-date instructions for creating and managing your key(s) and IP access. +Be aware, not all API resources require an IP access list by default, but one can set Atlas to require IP access entries for all API resources, see the [organization settings documentation](https://docs.atlas.mongodb.com/tutorial/manage-organization-settings/#require-ip-access-list-for-public-api) for more info. ## Authenticate the Provider -The MongoDB Atlas provider offers a flexible means of providing credentials for authentication. The following methods are supported and explained below: - -### Static credentials - -Static credentials can be provided by adding the following attributes in-line in the MongoDB Atlas provider block, either directly or via input variable/local value: - -Usage: - -```hcl -provider "mongodbatlas" { - public_key = "atlas_public_api_key" #required - private_key = "atlas_private_api_key" #required -} -``` - -~> *IMPORTANT* Hard-coding your MongoDB Atlas programmatic API key pair into a Terraform configuration is not recommended. Consider the risks, especially the inadvertent submission of a configuration file containing secrets to a public repository. +The MongoDB Atlas provider offers a flexible means of providing credentials for authentication. +You can use any the following methods: -### Environment variables +### Environment Variables -You can also provide your credentials via the environment variables, MONGODB_ATLAS_PUBLIC_KEY and MONGODB_ATLAS_PRIVATE_KEY, for your public and private MongoDB Atlas programmatic API key pair respectively: +You can also provide your credentials via the environment variables, +`MONGODB_ATLAS_PUBLIC_KEY` and `MONGODB_ATLAS_PRIVATE_KEY`, +for your public and private MongoDB Atlas programmatic API key pair respectively: ```hcl provider "mongodbatlas" {} @@ -66,19 +56,36 @@ $ export MONGODB_ATLAS_PRIVATE_KEY="xxxx" $ terraform plan ``` +As an alternative to `MONGODB_ATLAS_PUBLIC_KEY` and `MONGODB_ATLAS_PRIVATE_KEY` +if you are using [MongoDB CLI](https://docs.mongodb.com/mongocli/stable/) +then `MCLI_PUBLIC_API_KEY` and `MCLI_PRIVATE_API_KEY` are also supported. + +### Static Credentials + +Static credentials can be provided by adding the following attributes in-line in the MongoDB Atlas provider block, +either directly or via input variable/local value: + +```hcl +provider "mongodbatlas" { + public_key = "atlas_public_api_key" #required + private_key = "atlas_private_api_key" #required +} +``` + +~> *IMPORTANT* Hard-coding your MongoDB Atlas programmatic API key pair into a Terraform configuration is not recommended. +Consider the risks, especially the inadvertent submission of a configuration file containing secrets to a public repository. + ## Argument Reference -In addition to [generic `provider` -arguments](https://www.terraform.io/docs/configuration/providers.html) (e.g. -`alias` and `version`), the following arguments are supported in the MongoDB -Atlas `provider` block: +In addition to [generic `provider` arguments](https://www.terraform.io/docs/configuration/providers.html) +(e.g. `alias` and `version`), the MongoDB Atlas `provider` supports the following arguments: * `public_key` - (Optional) This is the public key of your MongoDB Atlas API key pair. It must be - provided, but it can also be sourced from the `MONGODB_ATLAS_PUBLIC_KEY` + provided, but it can also be sourced from the `MONGODB_ATLAS_PUBLIC_KEY` or `MCLI_PUBLIC_API_KEY` environment variable. * `private_key` - (Optional) This is the private key of your MongoDB Atlas key pair. It must be - provided, but it can also be sourced from the `MONGODB_ATLAS_PRIVATE_KEY` + provided, but it can also be sourced from the `MONGODB_ATLAS_PRIVATE_KEY` or `MCLI_PRIVATE_API_KEY` environment variable. For more information on configuring and managing programmatic API Keys see the [MongoDB Atlas Documentation](https://docs.atlas.mongodb.com/tutorial/manage-programmatic-access/index.html). @@ -97,7 +104,10 @@ For more information on configuring and managing programmatic API Keys see the [ ## Examples from MongoDB and the Community -We have [example configurations](https://github.com/mongodb/terraform-provider-mongodbatlas/tree/master/examples) in our GitHub repo that will help both beginner and more advanced users. +We have [example configurations](https://github.com/mongodb/terraform-provider-mongodbatlas/tree/master/examples) +in our GitHub repo that will help both beginner and more advanced users. -Have a good example you've created and want to share? Let us know the details via an [issue](https://github.com/mongodb/terraform-provider-mongodbatlas/issues) or submit a PR of your work to add it to the examples directory in our [GitHub repo](https://github.com/mongodb/terraform-provider-mongodbatlas/). +Have a good example you've created and want to share? +Let us know the details via an [issue](https://github.com/mongodb/terraform-provider-mongodbatlas/issues) +or submit a PR of your work to add it to the `examples` directory in our [GitHub repo](https://github.com/mongodb/terraform-provider-mongodbatlas/).