Giter Club home page Giter Club logo

terraform-provider-restapi's Introduction

Build Status Coverage Status Go Report Card

Terraform provider for generic REST APIs

Maintenance Note

This provider is largely feature-complete and in maintenance mode.

  • It's not dead - it's just slow moving and updates must be done very carefully
  • We encourage community participation with open issues for usage and remain welcoming of pull requests
  • Code updates happen sporadically throughout the year, driven primarily by security fixes and PRs
  • Because of the many API variations and flexibility of this provider, detailed per-API troubleshooting cannot be guaranteed

 

About This Provider

This terraform provider allows you to interact with APIs that may not yet have a first-class provider available by implementing a "dumb" REST API client.

This provider is essentially created to be a terraform-wrapped cURL client. Because of this, you need to know quite a bit about the API you are interacting with as opposed to full-featured terraform providers written with a specific API in mind.

There are a few requirements about how the API must work for this provider to be able to do its thing:

  • The API is expected to support the following HTTP methods:
    • POST: create an object
    • GET: read an object
    • PUT: update an object
    • DELETE: remove an object
  • An "object" in the API has a unique identifier the API will return
  • Objects live under a distinct path such that for the path /api/v1/things...
    • POST on /api/v1/things creates a new object
    • GET, PUT and DELETE on /api/v1/things/{id} manages an existing object

Have a look at the examples directory for some use cases.

 

Provider Documentation

This provider has only a few moving components, but LOTS of configurable parameters:

 

Usage

  • Try to set as few parameters as possible to begin with. The more complicated the configuration gets, the more difficult troubleshooting can become.
  • Play with the fakeserver cli tool (included in releases) to get a feel for how this API client is expected to work. Also see the examples directory directory for some working use cases with fakeserver.
  • By default, data isn't considered sensitive. If you want to hide the data this provider submits as well as the data returned by the API, you would need to set environment variable API_DATA_IS_SENSITIVE=true.
  • The *_path elements are for very specific use cases where one might initially create an object in one location, but read/update/delete it on another path. For this reason, they allow for substitution to be done by the provider internally by injecting the id somewhere along the path. This is similar to terraform's substitution syntax in the form of ${variable.name}, but must be done within the provider due to structure. The only substitution available is to replace the string {id} with the internal (terraform) id of the object as learned by the id_attribute.

 

Troubleshooting

Because this provider is just a terraform-wrapped cURL, the API details and the go implementation of this client are often leaked to you. This means you, as the user, will have a bit more troubleshooting on your hands than would typically be required of a full-fledged provider if you experience issues.

Here are some tips for troubleshooting that may be helpful...

 

Debug log

Rely heavily on the debug log. The debug log, enabled by setting the environment variable TF_LOG=1 and enabling the debug parameter on the provider, is the best way to figure out what is happening.

If an unexpected error occurs, enable debug log and review the output:

  • Does the API return an odd HTTP response code? This is common for bad requests to the API. Look closely at the HTTP request details.
  • Does an unexpected golang 'unmarshaling' error occur? Take a look at the debug log and see if anything other than a hash (for resources) or an array (for the datasource) is being returned. For example, the provider cannot cope with cases where a JSON object is requested, but an array of JSON objects is returned.

 

Importing existing resources

This provider supports importing existing resources into the terraform state. Import is done according to the various provider/resource configuation settings to contact the API server and obtain data. That is: if a custom read method, path, or id attribute is defined, the provider will honor those settings to pull data in.

To import data: terraform import restapi.Name /path/to/resource.

See a concrete example here.

 

Installation

There are two standard methods of installing this provider detailed in Terraform's documentation. You can place the file in the directory of your .tf file in terraform.d/plugins/{OS}_{ARCH}/ or place it in your home directory at ~/.terraform.d/plugins/{OS}_{ARCH}/.

The released binaries are named terraform-provider-restapi_vX.Y.Z-{OS}-{ARCH} so you know which binary to install. You may need to rename the binary you use during installation to just terraform-provider-restapi_vX.Y.Z.

Once downloaded, be sure to make the plugin executable by running chmod +x terraform-provider-restapi_vX.Y.Z-{OS}-{ARCH}.

 

Contributing

Pull requests are always welcome! Please be sure the following things are taken care of with your pull request:

  • go fmt is run before pushing
  • Be sure to add a test case for new functionality (or explain why this cannot be done)
  • Run the scripts/test.sh script to be sure everything works
  • Ensure new attributes can also be set by environment variables

Development environment requirements:

  • Golang v1.11 or newer is installed and go is in your path
  • Terraform is installed and terraform is in your path

To make development easy, you can use the Docker image druggeri/tdk as a development environment:

docker run -it --name tdk --rm -v "$HOME/go":/root/go druggeri/tdk
go get github.com/Mastercard/terraform-provider-restapi
cd ~/go/src/github.com/Mastercard/terraform-provider-restapi
#Hack hack hack

terraform-provider-restapi's People

Contributors

breml avatar burbon avatar danielris avatar dependabot[bot] avatar detvdl avatar douernesto avatar druggeri avatar duanshiqiang avatar fgouteroux avatar gazoakley avatar glitchcrab avatar ipleten avatar jgrumboe avatar landorg avatar martina-majova avatar mgw6 avatar namrathag avatar nicok avatar nitinnbisht avatar orgads avatar paultyng avatar placydo avatar ppaci avatar rberlind avatar sirlatrom avatar svenhamers avatar tmayad avatar vladdoster avatar vmarlier avatar yi2020 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

terraform-provider-restapi's Issues

It would be helpful if allow arbitrary headers and content types

It would be helpful if arbitrary headers and could be added and other content types could be specified.

In particular, the authorization_header of the provider is too restrictive as currently implemented without the ability to add other headers. In particular, it hard-codes "Authorization: Bearer " in the header it creates. In the case of HashiCorp's Vault, one needs to add a header like "X-Vault-Token: f3b09679-3001-009d-2b80-9c306ab81aa6" and setting that as the value of authorization_header does not work since one ends up with "Authorization: Bearer X-Vault-Token: f3b09679-3001-009d-2b80-9c306ab81aa6" which does not work.

With regard to the Terraform Enterprise API, the insertion of "Authorization: Bearer " is fine, but the hard-coded content type of "application/json" causes problems since the TFE API expects content-type of "application/vnd.api+json". This is why being able to specify the content-type would be helpful.

Allow custom path to ID field in restapi_object resource

Hi. I have an API, the request body for CREATE looks similar to this:

{
    "metadata": {
       ...,
    },
    "resources": [
        {
            "name": "Test Key",
            "type": "root"
        }
    ]
}

The response body looks like this:

{
    "metadata": {
        ...,
    },
    "resources": [
        {
            "id": "bc17d646-f9ac-46a9-9bff-afcdb5bae888",
            "name": "Test Key",
            "state": 1,
            "type": "root"
        }
    ]
}

The provider is able to create the object but since id isn't a top-level attribute, it cannot effectively set the Object ID:

Error: Error applying plan:

1 error(s) occurred:

* restapi_object.kmskey: 1 error(s) occurred:

* restapi_object.kmskey: Internal validation failed. Object ID is not set, but *may* have been created. This should never happen!

Can an attribute be added to support non top-level ID attributes? Similar to results_key in the datasource where:

resource "restapi_object" "kmskey" {
  path = "keys"
  data = "{...}"
  id_key = "resources[0]/id"
}

I understand that this is more of a complex example and may not be the intended purpose of a generic restapi provider.

data restapi_object causes panic on returned data

I'm running into an issue where the provider is bombing out on the data restapi_object returned values. I've validated that the returned payload is valid json.

Thoughts?

data "restapi_object" "account_uuid" {
  path         = "/Accounts"
  search_key   = "name"
  search_value = "${var.account_name}"
  results_key  = "id"
  debug        = true
}
2018-08-31T18:57:41.615-0400 [DEBUG] plugin.terraform-provider-restapi_v1.2.1-darwin-amd64: panic: interface conversion: interface {} is []interface {}, not map[string]interface {}
2018-08-31T18:57:41.615-0400 [DEBUG] plugin.terraform-provider-restapi_v1.2.1-darwin-amd64: 
2018-08-31T18:57:41.615-0400 [DEBUG] plugin.terraform-provider-restapi_v1.2.1-darwin-amd64: goroutine 38 [running]:
2018-08-31T18:57:41.615-0400 [DEBUG] plugin.terraform-provider-restapi_v1.2.1-darwin-amd64: github.com/Mastercard/terraform-provider-restapi/restapi.dataSourceRestApiRead(0xc420343490, 0x185a9e0, 0xc420372090, 0xc420343490, 0x0)
2018-08-31T18:57:41.615-0400 [DEBUG] plugin.terraform-provider-restapi_v1.2.1-darwin-amd64: 	/root/go/src/github.com/Mastercard/terraform-provider-restapi/restapi/datasource_api_object.go:106 +0xe96
2018-08-31T18:57:41.615-0400 [DEBUG] plugin.terraform-provider-restapi_v1.2.1-darwin-amd64: github.com/hashicorp/terraform/helper/schema.(*Resource).ReadDataApply(0xc420450af0, 0xc42033b0c0, 0x185a9e0, 0xc420372090, 0xc4203c6e58, 0x10b9b01, 0x17ef5e0)
2018-08-31T18:57:41.615-0400 [DEBUG] plugin.terraform-provider-restapi_v1.2.1-darwin-amd64: 	/root/go/src/github.com/hashicorp/terraform/helper/schema/resource.go:292 +0x88
2018-08-31T18:57:41.615-0400 [DEBUG] plugin.terraform-provider-restapi_v1.2.1-darwin-amd64: github.com/hashicorp/terraform/helper/schema.(*Provider).ReadDataApply(0xc420450b60, 0xc420332780, 0xc42033b0c0, 0x18, 0x18, 0xc42033b100)
2018-08-31T18:57:41.615-0400 [DEBUG] plugin.terraform-provider-restapi_v1.2.1-darwin-amd64: 	/root/go/src/github.com/hashicorp/terraform/helper/schema/provider.go:426 +0x9a
2018-08-31T18:57:41.615-0400 [DEBUG] plugin.terraform-provider-restapi_v1.2.1-darwin-amd64: github.com/hashicorp/terraform/plugin.(*ResourceProviderServer).ReadDataApply(0xc4203b7660, 0xc42032b710, 0xc42032b880, 0x0, 0x0)
2018-08-31T18:57:41.615-0400 [DEBUG] plugin.terraform-provider-restapi_v1.2.1-darwin-amd64: 	/root/go/src/github.com/hashicorp/terraform/plugin/resource_provider.go:604 +0x4e
2018-08-31T18:57:41.615-0400 [DEBUG] plugin.terraform-provider-restapi_v1.2.1-darwin-amd64: reflect.Value.call(0xc42013b320, 0xc4203340e8, 0x13, 0x197a629, 0x4, 0xc4203adf18, 0x3, 0x3, 0xc4203362c0, 0x20002, ...)
2018-08-31T18:57:41.615-0400 [DEBUG] plugin.terraform-provider-restapi_v1.2.1-darwin-amd64: 	/usr/local/go/src/reflect/value.go:447 +0x969
2018-08-31T18:57:41.615-0400 [DEBUG] plugin.terraform-provider-restapi_v1.2.1-darwin-amd64: reflect.Value.Call(0xc42013b320, 0xc4203340e8, 0x13, 0xc420051718, 0x3, 0x3, 0xc42045e240, 0x13dcc1b, 0x1)
2018-08-31T18:57:41.615-0400 [DEBUG] plugin.terraform-provider-restapi_v1.2.1-darwin-amd64: 	/usr/local/go/src/reflect/value.go:308 +0xa4
2018-08-31T18:57:41.616-0400 [DEBUG] plugin.terraform-provider-restapi_v1.2.1-darwin-amd64: net/rpc.(*service).call(0xc420336300, 0xc420332640, 0xc42032c340, 0xc42032c350, 0xc420366600, 0xc42033a320, 0x17ef5a0, 0xc42032b710, 0x16, 0x17ef5e0, ...)
2018-08-31T18:57:41.616-0400 [DEBUG] plugin.terraform-provider-restapi_v1.2.1-darwin-amd64: 	/usr/local/go/src/net/rpc/server.go:384 +0x14e
2018-08-31T18:57:41.616-0400 [DEBUG] plugin.terraform-provider-restapi_v1.2.1-darwin-amd64: created by net/rpc.(*Server).ServeCodec
2018-08-31T18:57:41.616-0400 [DEBUG] plugin.terraform-provider-restapi_v1.2.1-darwin-amd64: 	/usr/local/go/src/net/rpc/server.go:480 +0x43a
2018/08/31 18:57:41 [ERROR] root: eval: *terraform.EvalReadDataApply, err: data.restapi_object.account_uuid: unexpected EOF
2018/08/31 18:57:41 [ERROR] root: eval: *terraform.EvalSequence, err: data.restapi_object.account_uuid: unexpected EOF
2018/08/31 18:57:41 [TRACE] [walkRefresh] Exiting eval tree: data.restapi_object.account_uuid
2018/08/31 18:57:41 [TRACE] dag/walk: upstream errored, not walking "provider.restapi (close)"

Allow data to be empty

Some APIs don't actually need any data sent to them to create objects. It would be good to allow the data attribute on the resource to be empty or "".

Batch GET Requests

Hello,

I am trying to use this module to create a data source which polls our internal API to get a collection of services owned by a specific team. I am struggling to do this with the current GET data source as it expects specific Search keys, values and id attributes.

Is this module able to:

  1. Call an endpoint like example.com/team-name/services which returns a list of all services owned by the specific team
  2. Loop through this data source to perform further logic

Add more flexibility for specification of object ID

When invoking Terraform Enterprise API endpoints, one typically gets back a response that looks like:

{
  "data": {
        "id": "4111797",
        "type": ...
        ...
   }
}

While I can create TFE objects with this provider, since the id is nested under data, the ID of the object is not set correctly in the Terraform state and it therefore cannot be destroyed.

Would it be possible to handle the ID deeper in the api_data structure?

Possibilities that occur to me include:

  1. search for the id_attribute deeper in the structure returned by the API.
  2. Let user specify full path to the ID, giving something like "data.id" or "employee.personal.ssn".
  3. Convert id_attribute to an array and handle as many entries as user provides up to 3 or some other N.
  4. Replace id_attribute with id_attribute_1, id_attribute_2, id_attribute_3.

Additionally, it would also be useful to allow the user to specify that the id_attribute is actually the last segment of the resource path. This would be useful for APIs like Vault's API in which the object created such are often specified at the end of the URL rather than in the body of the request. For more on this, see #5

Would it make sense to move id_attribute from provider to resource?

It occurs to me that if you moved id_attribute from the provider to the resource, then multiple resources with different values of this setting could be created against a single instance of the provider. Would that make sense? Or is there some reason it needs to be on the provider itself?

Access REST Endpoint thru Proxy

Hi

I am trying to access a REST API Endpoint from my internal network thru Proxy. It is giving the below error

1 error(s) occurred:

When I submit a Curl request from the same server, it is working fine. So the proxy is working fine, it is only when I try to connect using Mastercard Provider it is not able to utilize the Proxy setting defined in the Environment.

How to utilize the http_proxy and https_proxy in this Mastercard Provider.

Doesn't work inside alpine based docker image

This plugin doesn't work with alpine based terrraform docker image (which the official terraform docker image is the case).

When trying to use the plugin, it will give errors like below:

Error: Failed to instantiate provider "restapi" to obtain schema: fork/exec /workspace/terraform.d/plugins/linux_amd64/terraform-provider-restapi_v1.9.3: no such file or directory

After some google search, it seems to be a known issue with CGO and Alpine Linux. When doing go build, CGO_ENABLED=0 needs to be set.

attribute of api_data not found until resource is created

I am creating a resource using

resource "restapi_object" "server_name" {
  path = "/servernames/application"
  data = "{\"appcode\": \"${var.requestor_appcode}\",\"requestor\": \"${var.requestor_id}\"}"
}

and then accessing it via

name             = "${restapi_object.server_name.api_data.name}"

however, when running I get the error

* vsphere_virtual_machine.vm: Resource 'restapi_object.server_name' does not have attribute 'api_data.name' for variable 'restapi_object.server_name.api_data.name'

I was able to work around this by creating the restapi_object resource first (commenting out the vm resource) and applying and then uncommenting the rest and applying again. I've also tried adding a depends_on = ["restapi_object.server_name"] but that also doesn't seem to help.

Any ideas?

Unable to find provider binary

Hi,

Thanks for creating this. I would use this provider however after cloning the repo, I can't seem to identify the binaries or create then with a "make build"

Any help would be greatly appreciated.

Object ID is not set, but *may* have been created. This should never happen

Hi

I was trying to create Host record in infoblox using the provider. The Host record gets created but my terraform apply fails.

restapi_object.allocate_ip: Creating...
api_data.%: "" => ""
create_path: "" => "/record:host"
data: "" => "{"ipv4addrs":[{"ipv4addr":"10.7.8.7"}],"name":"tfhosttest.fisdev.local"}\n"
path: "" => "/record:host"

Error: Error applying plan:

1 error(s) occurred:

  • restapi_object.allocate_ip: 1 error(s) occurred:

  • restapi_object.allocate_ip: Internal validation failed. Object ID is not set, but may have been created. This should never happen!

Terraform does not automatically rollback in the face of errors.
Instead, your Terraform state file has been partially updated with
any resources that successfully completed. Please address the error
above and apply again to incrementally change your infrastructure.

tf config

resource "restapi_object" "allocate_ip" {
path = "/record:host"
create_path = "/record:host"
data = "${file("add_host_record.json")}"
}

add_host_record.json

{"ipv4addrs":[{"ipv4addr":"10.7.8.7"}],"name":"tfhosttest.fisdev.local"}

provider.tf

provider "restapi" {
uri = "https://myinfoblox.dev.local/wapi/v2.6/"
insecure = true
username = "admin"
password = "xxxxxxxxxxxx"
write_returns_object = true
create_method = "POST"
update_method = "POST"
create_returns_object = true
debug = true
}

Please let me know what I need to do to fix this problem.

Support For PUT Requests

Hi All

I am trying to use the restapi_object to fire a put request to my elastic search url, I am trying to create a new watcher as per api https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-put-watch.html

There is always a POST request getting sent, which is not supported as creating a new watcher only supports PUT request, i am not sure how can i import something from the apis as there is no id or parmater present.

below is my config

provider "restapi" {
  uri                  = "elastic.co"
  insecure = true
  write_returns_object = true
  debug                = true

  headers {
    Content-Type = "application/json"
  }
  username = "watcher"
  password = "watcher"
}

resource "restapi_object" "api" {
  path = "/_xpack/watcher/watch"
  object_id = "alert-1"
  update_path = "alert-1"
  data = "${data.template_file.alert.rendered}"
}

binaries created in releases are not named correctly

I believe that the provider binaries that have been generated under releases are not named correctly. In particular, when I added the v0.2.0 binary, terraform-provider-restapi-darwin-amd64, to my repository under terraform.d/plugins/darwin_amd64, I got errors when I ran terraform init.

I was able to successfully initiailize my Terraform code after changing the name of the binary in that directory to "terraform-provider-restapi_v0.2.0-darwin-amd64" in which I have added the version between the name of the provider and the platform.

Referencing nested IDs

Just need a little help wrapping my head around this:
but say I have an API with nested IDs, how would I reference this in terraform?
For example, a URL of a customer object is https://api.website.com/v1/customers
and the customer object has multiple nested objects that have ID fields. For example https://api.website.com/v1/customers/<customer_id>/products/<product_id>
I need to create/set products that are attached to a customer using TF.

I'm still a bit new to TF.

Allow application/x-www-form-urlencoded Body for Write Operations

This is a proposal to add support for write operations to send the request body as application/x-www-form-urlencoded data. Currently the request body is limited to application/json data. If this proposal is implemented, then it will allow this provider to interact with a greater subset of REST APIs, such as Pingdom's REST API.

From a user's perspective, the restapi_object could gain an additional argument write_content_type. This new argument's values would be restricted to json (default) and x-www-form-urlencoded. Alternatively, a new argument write_request_body could be added that overrides the request body generated from the data argument, allowing the request body for write operations to be formatted arbitrarily. The latter alternative would open up this provider to interact with even more content types than application/json and application/x-www-form-urlencoded.

how to pass apikey and secretkey through headers ?

Hello There,

In my case i do not have username and password to access api ! Can anyone please let me know if it is possible to pass api_key and secret_key through headers ? if yes please help here! how to pass api_key and secret_key through headers ?

Thanks in advance,
Antonynixson I

data restapi_object return: Failed to find an object with the key

We try to query Smartsheet API with this code:
data "restapi_object" "data_webhook1" { provider = "restapi.get" path = "/webhooks" search_key = "scopeObjectId" search_value = "${var.sheet1}" results_key = "data" id_attribute = "id" }

It is working if there is a match otherwise it will throw Failed to find an object with the scopeObjectId key. Is there a better way to handle/bypass this error? Could it return null if it doesnot exist?

Our goal is to try to check whether this data exists, then we can create/update this record accordingly.

ID Incorrectly Expressed In Scientific "E" Notation

The ID attribute of my API object is being expressed in scientific "E" notation instead of decimal notation.

Here is the output from my Terraform state.

resource "restapi_object" "check" {
    api_data    = {
        "check" = "map[id:5.3502e+06 name:mydomain.com]"
    }
    create_path = "/checks?encryption=true&host=mydomain.com&name=mydomain.com&notifyagainevery=0&paused=false&port=443&resolution=1&sendnotificationwhendown=3&teamids=&type=http&url=%2Fhealth_check.php&userids="
    id          = "5.3502e+06"
    path        = "/checks"
    update_path = "/checks{id}?encryption=true&host=mydomain.com&name=mydomain.com&notifyagainevery=0&paused=false&port=443&resolution=1&sendnotificationwhendown=3&teamids=&type=http&url=%2Fhealth_check.php&userids="
}

Comparing the Terraform state with the actual response suggests the notation problem is originating from within the provider and not the REST API.

{
    "check": {
        "id": 5350200,
        "name": "mydomain.com"
    }
}

Since the ID is expressed as 5.3502e+06 instead of 5350200 the terraform destroy operation is failing to refresh the object's state using the API as the Terraform debug log shows.

2019-07-23T12:17:03.717-0700 [DEBUG] plugin.terraform-provider-restapi_v1.9.2: 2019/07/23 12:17:03 api_client.go: method='GET', path='/checks/5.3502e+06', full uri (derived)='https://api.pingdom.com/api/2.1/checks/5.3502e+06', data=''
2019-07-23T12:17:03.717-0700 [DEBUG] plugin.terraform-provider-restapi_v1.9.2: 2019/07/23 12:17:03 api_client.go: Sending HTTP request to https://api.pingdom.com/api/2.1/checks/5.3502e+06...
...
Error: Unexpected response code '403': {"error":{"statuscode":403,"statusdesc":"Forbidden","errormessage":"Invalid check identifier"}}

FWIW I believe I configured the provider to properly extract the ID using the argument id_attribute = "check/id".

getting 404 error

I am using the latest release and configured a data source.

data "restapi_object" "ttt-dns-map" {
path = "/api/objects/network/dns_host"
search_key = "name"
search_value = "testing"
}

terraform plan is giving the 404 error. Please see the error below. Please let me know what i need to do to fix this issue.

2018-10-24T18:37:37.181-0700 [DEBUG] plugin.terraform-provider-restapi_v1.5.0-linux-amd64: "interface": "",
2018-10-24T18:37:37.181-0700 [DEBUG] plugin.terraform-provider-restapi_v1.5.0-linux-amd64: "name": "testing",
2018-10-24T18:37:37.181-0700 [DEBUG] plugin.terraform-provider-restapi_v1.5.0-linux-amd64: "resolved": true,
2018-10-24T18:37:37.181-0700 [DEBUG] plugin.terraform-provider-restapi_v1.5.0-linux-amd64: "resolved6": false,
2018-10-24T18:37:37.181-0700 [DEBUG] plugin.terraform-provider-restapi_v1.5.0-linux-amd64: "timeout": 0
2018-10-24T18:37:37.181-0700 [DEBUG] plugin.terraform-provider-restapi_v1.5.0-linux-amd64: }
2018-10-24T18:37:37.181-0700 [DEBUG] plugin.terraform-provider-restapi_v1.5.0-linux-amd64: ]
2018-10-24T18:37:37.187-0700 [DEBUG] plugin.terraform-provider-restapi_v1.5.0-linux-amd64: 2018/10/24 18:37:37 api_client.go: method='GET', path='/api/objects/network/dns_host/', full uri (derived)='https://test.com:4444/api/objects/network/dns_host/', data=''
2018-10-24T18:37:37.187-0700 [DEBUG] plugin.terraform-provider-restapi_v1.5.0-linux-amd64: 2018/10/24 18:37:37 api_client.go: Sending HTTP request to https://test.com:4444/api/objects/network/dns_host/%3Cnil%3E...
2018-10-24T18:37:37.187-0700 [DEBUG] plugin.terraform-provider-restapi_v1.5.0-linux-amd64: 2018/10/24 18:37:37 api_client.go: Request headers:
2018-10-24T18:37:37.187-0700 [DEBUG] plugin.terraform-provider-restapi_v1.5.0-linux-amd64: 2018/10/24 18:37:37 api_client.go: Authorization: Basic REDACTED
2018-10-24T18:37:37.187-0700 [DEBUG] plugin.terraform-provider-restapi_v1.5.0-linux-amd64: 2018/10/24 18:37:37 api_client.go: BODY:
2018-10-24T18:37:37.187-0700 [DEBUG] plugin.terraform-provider-restapi_v1.5.0-linux-amd64: 2018/10/24 18:37:37
2018/10/24 18:37:37 [ERROR] root: eval: *terraform.EvalReadDataApply, err: data.restapi_object.ttt-dns-map: Unexpected response code '404': 404 page not found
2018/10/24 18:37:37 [ERROR] root: eval: *terraform.EvalSequence, err: data.restapi_object.ttt-dns-map: Unexpected response code '404': 404 page not found
2018/10/24 18:37:37 [TRACE] [walkRefresh] Exiting eval tree: data.restapi_object.ttt-dns-map
2018/10/24 18:37:37 [TRACE] dag/walk: upstream errored, not walking "provider.restapi (close)"
2018/10/24 18:37:37 [TRACE] dag/walk: upstream errored, not walking "root"

Support for MIME

Is there any plan to support MIME (Content-Type: multipart/form-data)?

Use case with authentication

Hello, I'm trying to use this provider with HPE OneView API which uses user authentication to generate a token.
Using postman, I post json data in the body with username, password, and authLoginDomain to get the token which I then use in the header using "Auth" for subsequent requests which use json in the body.
My attempts to get this working are not yet successful. I'm wondering if this provider is appropriate for this API?
I have tried hard coding the token and making the config match the API documentation.
Perhaps I'm missing something in my setup for this provider... here is my .tf.

provider "restapi" {
uri = "https://10.0.0.3/rest/"
insecure = true
debug = true
write_returns_object = true
headers {
"Content-Type" = "application/json"
"x-api-version" = 1000
"Auth" = "randomstringofcharacters1234567"
}
}

resource "restapi_object" "authenticate" {
path = "login-sessions"
data = "{ "userName": "${var.apiusername}", "password": "${var.apipassword}", "authLoginDomain": "local"}"

terraform plan gives me this error with or without the resource "restapi_object" block.

  • provider.oneview: Post /rest/login-sessions: unsupported protocol scheme ""

Example

Hi,
Is it possible to add an example.tf with some basic use case?
Thank you

Ignore read response

I am doing a PUT/POST on an api which does not return anything in response body. In that case terraform always throw the following error since the response body is empty.

I am using terraform-provider-restapi to place a PUT/POST call to slack. Here is my provider config.

provider "restapi" { update_method = "PUT" id_attribute = "username" write_returns_object = false uri = "https://hooks.slack.com/services" headers = { "Accept" = "text/plain" "Content-Type" = "application/json" } }

Since slack rest call doesn't return anything, and terraform-provider-restapi is trying to read the response, which ends up throwing the following error.

unexpected end of JSON input

Is there any option available?

exec format error

Trying to use the provider but get

  • module.test_nodeping.provider.restapi: fork/exec /Users/kody/.terraform.d/plugins/darwin_amd64/terraform-provider-restapi_v1.9.0: exec format error

Tried versions 1.7.0-1.9.0 - I am using terraform 0.11

Reuse API call with different data (templates)

Hi,

On issue #43 I mentioned that I'm creating some LB's with an API calls, and I generate a template with some data, and to create a new LB I just need to update a few parameters of my template.
Instead of having template1, template2,..., templateN, and restapi_object1, restapi_object2, etc there is a process to reuse the same API call using diferent data/template each time??

Thanks in advance

windows-amd64 Provider "restapi" not available for installation.

Hello!

I have terraform installed on my notebook with Windows 10 Pro
Plugin located here %AppData%\terraform.d\plugins\windows-amd64\terraform-provider-restapi_v1.6.0-windows-amd64

c:\git\tf_api>terraform init

Initializing provider plugins...

Provider "restapi" not available for installation.

A provider named "restapi" could not be found in the official repository.

This may result from mistyping the provider name, or the given provider may
be a third-party provider that cannot be installed automatically.

In the latter case, the plugin must be installed manually by locating and
downloading a suitable distribution package and placing the plugin's executable
file in the following directory:
terraform.d/plugins/windows_amd64

Terraform detects necessary plugins by inspecting the configuration and state.
To view the provider versions requested by each module, run
"terraform providers".

c:\git\tf_api>terraform providers
.
└── provider.restapi

RestAPI Provider

Where/how do I download the binaries for this does not work directly with Terraform v0.12.6 ?

The installation guide talks about downloading Binaries ?

Support for GET returning array of objects rather than specific object

Thanks for this provider - been using for a day or so now and it's nicely thought out.

I'm working with the gitea API, and trying to add a user to a team. The only related API methods for this are:
PUT /team/0/members/robertgates55 - to add a user object to team 0
DELETE /team/0/members/robertgates55 - to remove user object from team 0
GET /team/0/members - returns an array of the user objects in that team

Is there any way I can work with this API? I've already set create_method = "PUT" in the provider, and am setting the object_id manually (as the PUT doesn't return the object it creates); but since theres no GET /team/0/members/robertgates55 method available, we obviously can't work out whether my object_id is a member of the team.

Any ideas?

Allow empty uri in provider configuration

Hi,

We are using restapi provider to configure elasticsearch, which is created in the same terraform apply. It is not possible to set the uri parameter to the output of newly created resource (hashicorp/terraform#2430). It will be great to have a possibility to leave provider's uri parameter empty.

For now we are using "clever" workaround:

provider "restapi" {
  uri = "https:"
}

And in the resource:

resource "restapi_object" "elasticsearch_template_others" {
  path        = "//${aws_elasticsearch_domain.es.endpoint}/_template"

  object_id   = "template_2"
  create_path = "//${aws_elasticsearch_domain.es.endpoint}/_template/{id}"

  data        = <<EOF
{
    "index_patterns": [
        "*"
    ],
    "settings": {
        "number_of_shards": "1",
        "number_of_replicas": "1"
    }
}
EOF
}

update_method and create_method must be set to PUT in order to create PUT provider

  • In v1.9.2:

  • When I use update_method: PUT in the provider and update_path in the resource. It returns 404 status.

  • However, if i use update_method:PUT and create_method:PUT in provider and create_path in the resource, it will work for the first run. On the second run it returns 404.

  • What am I missing on this PUT request?

case 1: provider: PUT and resource : update_path
update_path_on_put

case 2:
create_pathon_2 puts

Originally posted by @cnguyenp in #46 (comment)

Support URLs that identify created object at end of URL

Some APIs such as the Vault API require the user to specify the ID of an object being created as the last part of the URL. While this provider can actually create a Vault secret, it gets an error when trying to read the secret back during terraform apply. So, if I set id_attribute to "id", my resource path to "/secret/restapi/test" and data to "{"foo":"bar","id":"test"}", the provider successfully writes the secret to <vault_url>:8200/v1/secret/restapi/test, but then tries to read it back from <vault_url>:8200/v1/secret/restapi/test/test which does not exist.

Additionally, one would not normally include the final part of the Vault path as a key in the body as I have done. I only did that so I could get the provider to write the secret. Normally, my data would have just been "{"foo":"bar"}"

So, I think it would be useful to somehow support URLs like these. Note that these URLs each effectively only manage a single object.

The key to making the provider work with these paths is to make it use the same URL for POSTs that it uses for GETs, PUTs, and DELETEs. Somehow, the user would be able to indicate that the ID for their object actually is the last segment of the resource path.

See #4 in which I requested more flexibility for specifying object IDs and included the possibility of specifying that the ID is the last segment of the resource path.

Rest API terraform script

Can you provide me sample terraform template for update, create and delete using JSON payload?
in this provider, I am seeing only for adding.

Help wanted: Developing terraform-specific test cases

The test coverage for the "guts" of the API interaction is... OK. We instantiate an HTTP API server that verifies GET, PUT, POST and DELETE , but we lack test coverage for the creation and usage of the terraform provider itself. As the provider matures, this is likely to result in gaps/blind spots.

It would be super awesome to have a fakeserver-backed provider test suite.

Some examples of things to test:

  • The same GET, PUT, POST and DELETE operations as the test suite
  • Import of an object
  • Use of the data resource

More complicated test cases:

  • Importing or data for "deeply nested" objects

Access to Rest Endpoint thru Proxy

Hi,

I have created a new issue since my previous issue was closed and problem is not yet resolved.

Hi

I set the Env variables to Uppercase and ran the terraform script but still getting the same issue.

env | grep PROXY
HTTPS_PROXY=http://10.8.225.113:3128
HTTP_PROXY=http://10.8.225.113:3128

terraform apply
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:

create
Terraform will perform the following actions:

restapi_object.create-request
id:
api_data.%:
data: "{"Description": "Venkat request from TF RestAPI","AdditionalInformation": "Testing create req Terraform RestAPI", "ApplicationProfileId": 35, "Requestor": "Venkatraman Ramakrishnan"}\n"
path: "/NetworkAutomation/rest/v1/ChangeRequest"
Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.

Enter a value: yes

restapi_object.create-request: Creating...
api_data.%: "" => ""
data: "" => "{"Description": "Venkat request from TF RestAPI","AdditionalInformation": "Testing create req Terraform RestAPI", "ApplicationProfileId": 35, "Requestor": "Venkatraman Ramakrishnan"}\n"
path: "" => "/NetworkAutomation/rest/v1/ChangeRequest"
restapi_object.create-request: Still creating... (10s elapsed)
restapi_object.create-request: Still creating... (20s elapsed)
restapi_object.create-request: Still creating... (30s elapsed)
restapi_object.create-request: Still creating... (40s elapsed)
restapi_object.create-request: Still creating... (50s elapsed)
restapi_object.create-request: Still creating... (1m0s elapsed)
restapi_object.create-request: Still creating... (1m10s elapsed)
restapi_object.create-request: Still creating... (1m20s elapsed)
restapi_object.create-request: Still creating... (1m30s elapsed)
restapi_object.create-request: Still creating... (1m40s elapsed)
restapi_object.create-request: Still creating... (1m50s elapsed)
restapi_object.create-request: Still creating... (2m0s elapsed)

Error: Error applying plan:

1 error(s) occurred:

restapi_object.create-request: 1 error(s) occurred:

restapi_object.create-request: Put https://console-d.dynecon.com/NetworkAutomation/rest/v1/ChangeRequest: dial tcp 34.96.75.80:443: connect: connection timed out

Terraform does not automatically rollback in the face of errors.
Instead, your Terraform state file has been partially updated with
any resources that successfully completed. Please address the error
above and apply again to incrementally change your infrastructure.

Please let me know if I am doing anything wrong. I am able to get the CURL request work in terraform script.

Thanks

support for asynchronous endpoints

The REST API provider will provision a resource via POST method and wait for a response (call it 'sync' mode) NetApp WFA accepts such a request, but starts the workflow in the background and only returns a job ID (call it 'async' mode) You have to query that job ID separately to get the current status and potential return values. I saw a similar behavior with VMware vRO.

Example:
POST /workflows/{workflow_uuid}/jobs -> creates object and returns job_id
GET /workflows/{workflow_uuid}/jobs/{job_id} -> query on a regular base to get return value (after the job finishes)

Could set_resource_state do deep copy of obj.api_data?

I was wondering if set_resource_state might be able to do a deep copy of obj.api_data so that the actual object in Terraform would have nested fields under api_data that would be accessible with outputs and references from other resources. Is this something you've investigated?

Would simply doing api_data[k] = v in set_resource_state() work?

If not, would one of the deepCopyJSON functions suggested under https://stackoverflow.com/questions/51459083/deep-copying-maps-in-golang work?

Some issues with datasource

I've noticed a significant issue with the datasource: the GET done by read_object near the end is being done against the same path as the first GET done on line 83. That means it returns all the objects returned by the first GET and stores data for all the objects in the object identified through the datasource search attributes. I recommend adding a line with obj.get_path = path + "/{id}" before line 142. The second GET will then use the ID returned by the search logic of the datasource code.

Additionally, it seems to me that the call to d.SetId(obj.id) on line 139 is not needed since the same call is made on line 146 which is where it is really needed. Even if you were going to keep the call on line 139, it seems to me that it should be done after the call to obj.id = id that is currently on line 140.

Additionally, the call to d.Id() in line 65 does not make sense to me. I don't think the d object will have any ID at that point in the execution of the code, at least not when the datasource is first added to the Terraform configuration. I suggest setting the id being passed to NewAPIObject to "0". This will avoid having to set create_returns_object to true in the provider configuration in order to use the datasource which is currently the case since if NewAPIObject sees a blank id (""), it checks to make sure that at least one of create_returns_object or write_returns_object is set to true. But the user should not be forced to set these to true if they don't need them set to true for their resources.

I've actually made these and some other modifications to the datasource code, but have avoided pushing my changes to Github since I would prefer those be handled on a separate branch in my fork and have not had time to do set that up yet. But I do hope to submit a pull request some time this week.

Make PUT request

Hello. I know this is not an issue but rather me misunderstanding how the module works, but please bear with me here.

I'm trying to make a PUT request to modify a CloudFlare resource via its API. However, for some reason, I cannot convince the restapi provider to send a PUT request. It always POSTs.

Here is my particular snippet:

resource "cloudflare_load_balancer_pool" "ext_api" {
  name  = "api-pool"

  origins {
    name    = "origin-1"
    address = "10.0.0.1"
  }

  origins {
    name    = "origin-2"
    address = "10.0.0.2"
  }

  minimum_origins    = "1"
}

provider "restapi" {
  uri                  = "https://api.cloudflare.com"
  write_returns_object = true
  debug                = true

  headers {
    X-Auth-Email = "${var.cloudflare_api["email"]}"
    X-Auth-Key   = "${var.cloudflare_api["token"]}"
    Content-Type = "application/json"
  }
}

resource "restapi_object" "ext_api_pool" {
  path         = "/client/v4/user/load_balancers/pools"
  object_id = "${cloudflare_load_balancer_pool.ext_api.id}"

  data = <<EOF
{
  "name": "api-pool",
  "minimum_origins": 1,
  "origins": [
    {
      "name": "origin-1",
      "address": "10.0.0.1",
      "enabled": true,
      "weight": "${var.origin1_weight}"
    },
    {
      "name": "origin-2",
      "address": "10.0.0.2",
      "enabled": true,
      "weight": "${var.origin2_weight}"
    }
    ]
  }EOF
}

On each run, the result is the following:

* restapi_object.ext_api_pool: Unexpected response code '409': {
  "result": null,
  "success": false,
  "errors": [
    {
      "code": 1003,
      "message": "value not unique"
    }
  ],
  "messages": []
}

This is due to restapi POSTing and trying to create the resource again, conflicting with the existing one created by the Cloudflare module. I want it to PUT that request so that the weights are modified.

What am I doing wrong here? I tried:

  • putting the ID in the path. No dice, it sends POST as well
  • using id_attribute. Still POST
  • putting "id" in the "data". Forever POST.

I may be missing something very subtle here, but please help.

Regards,
Claudiu

Requesting to elaborate with example for the listed config parameters

Hello There,

I'm very new to terraform restapi provider, Can anyone please help ?
could anyone please provide an example for the all config parameters,? It will be very very helpful for me

Provider configuration

uri
insecure
username
password
headers
use_cookies
timeout
id_attribute
create_method
read_method
update_method
delete_method
copy_keys
write_returns_object
create_returns_object
xssi_prefix
debug

Restapi resource configuration

path
create_path
read_path
update_path
destroy_path
id_attribute
object_id
data
force_new
debug

Restapi datasource configuration

path
query_string
search_key
search_value
results_key
id_attribute
debug

Thanks in advance,
Antonynixson I

Set expected response type

I am using the provider to post to an api that takes json and returns a string. The post works as expected but always returns 'Error json: cannot unmarshal string into Go value of type map[string]interface {}'. I would like to set the expected return type or ignore the response.

Parsing api_data output

Hi again,

As mentioned on #43, I'm creating some LB's using an API call, and once the API is made I'm trying to use the output on terraform.

Right now, when I use:

output "LB-IP" {
  value = ["${restapi_object.create_lb.api_data}"]
}

This is the output:

LB-IP = [
  {
    "loadBalancer" = "map[cluster:map[name:ztm-n17.iad3.lbaas.rackspace.net] httpsRedirect:false protocol:HTTP port:80 nodes:[map[type:PRIMARY port:80 status:ONLINE condition:ENABLED weight:1 address:10.176.160.39 id:964073] map[condition:ENABLED weight:1 address:10.176.160.34 id:964075 type:PRIMARY port:80 status:ONLINE] map[condition:ENABLED weight:1 address:10.176.160.56 id:964077 type:PRIMARY port:80 status:ONLINE]] contentCaching:map[enabled:false] name:terra-lb updated:map[time:2019-07-03T21:56:34Z] halfClosed:false sourceAddresses:map[ipv6Public:2001:4802:7903:100::5/64 ipv4Public:146.20.52.5 ipv4Servicenet:10.187.186.5] timeout:120 id:250983 connectionLogging:map[enabled:false] created:map[time:2019-07-03T21:56:34Z] virtualIps:[map[id:14393 type:PUBLIC ipVersion:IPV4 address:146.20.52.137] map[ipVersion:IPV6 address:2001:4802:7903:0100:18f8:8715:0000:001a id:9.086273e+06 type:PUBLIC]] algorithm:ROUND_ROBIN status:BUILD]"
  },
]

When I use:

output "LB-IP" {
  value = ["${restapi_object.create_lb.api_data.loadBalancer}"]
}

The output is:

  "map[nodes:[map[condition:ENABLED weight:1 address:10.176.160.56 id:964085 type:PRIMARY port:80 status:ONLINE] map[address:10.176.160.34 id:964087 type:PRIMARY port:80 status:ONLINE condition:ENABLED weight:1] map[type:PRIMARY port:80 status:ONLINE condition:ENABLED weight:1 address:10.176.160.39 id:964089]] contentCaching:map[enabled:false] connectionLogging:map[enabled:false] httpsRedirect:false sourceAddresses:map[ipv6Public:2001:4802:7901::8/64 ipv4Public:162.209.114.8 ipv4Servicenet:10.189.254.8] timeout:120 name:terra-lb port:80 virtualIps:[map[ipVersion:IPV4 address:23.253.147.48 id:4583 type:PUBLIC] map[ipVersion:IPV6 address:2001:4802:7901:0000:18f8:8715:0000:0012 id:9.086277e+06 type:PUBLIC]] updated:map[time:2019-07-03T22:53:15Z] id:250987 protocol:HTTP cluster:map[name:ztm-n05.iad3.lbaas.rackspace.net] created:map[time:2019-07-03T22:53:15Z] halfClosed:false status:BUILD algorithm:ROUND_ROBIN]",
]

And finally, when I use:

output "LB-IP" {
  value = ["${lookup(restapi_object.create_lb.api_data.loadBalancer, "ipv4Public}"]
}

Does not even run correctly, the output is:

Error: Invalid character

  on terraform/outputs.tf line 17, in output "LB-IP":
  17: #   value = "${formatlist(

Please help!!

default provider needed if using aliases

This is mostly for x-ref in case someone runs into this when using this provider.

If you are using multiple providers using Terraform's feature to alias providers, you will get an error on destroys

Error: Missing required argument

The argument "uri" is required, but was not set.

This is from hashicorp/terraform#21330

A workaround is to include a dummy default:

provider "restapi" {
  # Default provider for rest API to avoid error on destroy WRT uri argument
  # https://github.com/hashicorp/terraform/issues/21330
  uri                  = "dummy"
}

Float value in api_data return exponential format

We have data return from Smartsheet API with this format.
"data": [ { "id": 7243977842812804, "name": "Webhook Tube Life Estimate Listener", "scope": "sheet", "scopeObjectId": 8562070036735876, "events": [ "*.*" ], "callbackUrl": "https://api.bluecentral-test.io/webhook/sheets", "sharedSecret": "6es3m789ebor0ewabxivj1czw0", "enabled": true, "status": "ENABLED", "version": 1, "createdAt": "2019-07-01T18:05:24Z", "modifiedAt": "2019-07-08T22:31:43Z" }]

When we try to access id or scopeObjectId, value of these fields have been converted to 7.243977842812804e+15 and 8.562070036735876e+15. Is this an expected result?

Object creation/deletion it not working properly

Hi,

I'm using this provider to interact with the Rackspace Load Balancers API.
So far it is working to create a new LB's, but it is not deleting the one that was already created, only creates new LBs instead of deleting the one that was already created an create a new one.

I'm using this code:

nodes_json => Using this to generate a template with the nodes that I will attach to the LB.
data_json => Using this to put all my variables together
token => Generates my auth-token
create_lb => API call to create the LB, and I assume to delete it but seems like it is not working.

provider "restapi" {
  uri     = "https://iad.loadbalancers.api.rackspacecloud.com/v1.0/${var.openstack_tenant_name}/loadbalancers"
  debug   = true
  write_returns_object = true
  create_returns_object = true
  create_method = "POST"
  update_method = "POST"
  headers = {
    Content-Type = "application/json",
    X-Auth-Token = data.external.token.result["token"]
  }
}

data "template_file" "nodes_json" {
  template = "${file("${path.module}/templates/nodes_lb.json.tmpl")}"
  count       = "${var.openstack_count}"
  vars = {
    node_address = "${element(openstack_compute_instance_v2.nodes.*.network.1.fixed_ip_v4, count.index)}"
  }
}

data "template_file" "data_json" {
  template = "${file("${path.module}/templates/create_lb.json.tmpl")}"
  vars = {
    lb_name = "${var.openstack_lb_name}"
    lb_port = "${var.openstack_lb_exposed_port}"
    lb_protocol = "${var.openstack_lb_protocol}"
    lb_timeout = "${var.openstack_lb_timeout}"
    lb_algorithm = "${var.openstack_lb_algorithm}"
    lb_nodes = "${join(",", data.template_file.nodes_json.*.rendered)}"
  }
}

data "external" "token" {
  program = [
    "files/get_token.sh",
    "-e",
    "${var.openstack_auth_url}/tokens",
    "-u",
    "${var.openstack_username}",
    "-a",
    "${var.openstack_apikey}",
  ]
}
resource "restapi_object" "create_lb" {
  path = "/"
  create_path = "{id}"
  read_path = "{id}"
  update_path = "{id}"
  destroy_path = "{id}"
  id_attribute = "loadBalancer/id"
  debug = true
  data = "${data.template_file.data_json.rendered}"
}

create_lb.json.tmpl

{ 
  "loadBalancer": 
  { 
    "name"       : "${lb_name}",
    "port"       : "${lb_port}",
    "protocol"   : "${lb_protocol}",
    "timeout"    : "${lb_timeout}",
    "algorithm"  : "${lb_algorithm}",
    "virtualIps" : [ 
      { 
        "type": "PUBLIC" 
      } 
    ],
    "nodes"      : [
      ${lb_nodes}
    ] 
  }
}

get_token.sh

#!/bin/bash

#set -eux

function usage() {
  # NOTE: Keep sorted for easy git merges
  cat << E_O_F
Usage:
  -e Endpoint
  -u username
  -a API Key
E_O_F
}

function check_deps() {
  test -f $(which jq) || error_exit "jq command not detected in path, please install it"
}

# NOTE: Keep sorted for easy git merges
while getopts "a:e:u:h?" opt; do
    case "$opt" in
    e) ENDPOINT=${OPTARG}
    ;;
    u) USERNAME=${OPTARG}
    ;;
    a) API_KEY=${OPTARG}
    ;;
    h|\?)
        usage
        exit 0
        ;;
    esac
done

check_deps
TOKEN=$(curl -s -H "Content-Type: application/json" -X POST -d '{ "auth": { "RAX-KSKEY:apiKeyCredentials": { "username": "'$USERNAME'", "apiKey": "'$API_KEY'" } } }' $ENDPOINT | jq '.access.token.id' | tr -d "\"")
jq -n --arg token "$TOKEN" '{"token":$token}'

Any light is helpful.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.