diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 0000000..8068002 --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,33 @@ +before: + hooks: + - go mod tidy +builds: + - env: + - CGO_ENABLED=0 + - GO111MODULE=on + - GOPRIVATE=github.com/turbot + goos: + - linux + - darwin + + goarch: + - amd64 + - arm64 + + id: "steampipe" + binary: "{{ .ProjectName }}.plugin" + +archives: + - format: gz + name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}" + files: + - none* +checksum: + name_template: "{{ .ProjectName }}_{{ .Version }}_SHA256SUMS" + algorithm: sha256 +changelog: + sort: asc + filters: + exclude: + - "^docs:" + - "^test:" \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..8e6850d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,6 @@ +## v0.1.0 [2023-08-17] + +_What's new?_ + +- First version of the plugin + - Select a Terraform provider, then integrate its datasources with Steampipe \ No newline at end of file diff --git a/README.md b/README.md index 86a38a9..4579286 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,87 @@ -# `steampipe-plugin-tfbridge` +![image](https://hub.steampipe.io/images/plugins/jreyesr/tfbridge-social-graphic.png) -**WORK IN PROGRESS:** Don't use, the code is unstable! It may not do what it says, config values may behave strangely, parts may just print a message and do nothing. +# Terraform Bridge Plugin for Steampipe + +Use SQL to query data from the datasources of any Terraform provider. This repo contains a [Steampipe](https://steampipe.io/) plugin that lets the user call any (?) [data source that is exposed by a Terraform provider](https://developer.hashicorp.com/terraform/language/data-sources). This will expand the reach of Steampipe's plugins to also cover remote APIs that have a Terraform provider but no Steampipe plugin. This will also let users unify efforts: the Terraform provider can be used to manage resources, and querying on the current state of those resources can be done via Steampipe, using the same source code and provider. +- **[Get started →](https://hub.steampipe.io/plugins/jreyesr/tfbridge)** +- Documentation: [Table definitions & examples](https://hub.steampipe.io/plugins/jreyesr/tfbridge/tables) +- Community: [Join #steampipe on Slack →](https://turbot.com/community/join) +- Get involved: [Issues](https://github.com/jreyesr/steampipe-plugin-tfbridge/issues) + +## Quick start + +Install the plugin with [Steampipe](https://steampipe.io): + +```shell +steampipe plugin install jreyesr/tfbridge +``` + +Configure your [config file](https://hub.steampipe.io/plugins/jreyesr/tfbridge#configuration) to point to a Terraform provider+version. If the Terraform provider requires configuration values, provide them too. + +Run steampipe: + +```shell +steampipe query +``` + +Run a query for whatever data source the Terraform provider exposes: + +```sql +select + attr1, + attr2 +from + datasource_name; +``` + +## Developing + +Prerequisites: + +- [Steampipe](https://steampipe.io/downloads) +- [Golang](https://golang.org/doc/install) + +Clone: + +```sh +git clone https://github.com/jreyesr/steampipe-plugin-tfbridge.git +cd steampipe-plugin-tfbridge +``` + +Build, which automatically installs the new version to your `~/.steampipe/plugins` directory: + +``` +make +``` + +Configure the plugin: + +``` +cp config/* ~/.steampipe/config +vi ~/.steampipe/config/tfbridge.spc +``` + +Try it! + +``` +steampipe query +> .inspect tfbridge +``` + +Further reading: + +- [Writing plugins](https://steampipe.io/docs/develop/writing-plugins) +- [Writing your first table](https://steampipe.io/docs/develop/writing-your-first-table) + +## Contributing + +Please see the [contribution guidelines](https://github.com/turbot/steampipe/blob/main/CONTRIBUTING.md) and our [code of conduct](https://github.com/turbot/steampipe/blob/main/CODE_OF_CONDUCT.md). All contributions are subject to the [Mozilla Public License 2.0 open source license](https://github.com/jreyesr/steampipe-plugin-tfbridge/blob/main/LICENSE). + + ## Old proof of concept Previously (see [the `poc` tag](https://github.com/jreyesr/steampipe-plugin-tfbridge/tree/poc)), the repo only contained a proof of concept Go program that was used to test ways of driving a Terraform plugin. This wasn't too documented before, with [Terraform's docs](https://developer.hashicorp.com/terraform/plugin/best-practices/interacting-with-providers#using-the-rpc-protocol) merely stating that diff --git a/config/tfbridge.spc b/config/tfbridge.spc index f419e50..615ad62 100644 --- a/config/tfbridge.spc +++ b/config/tfbridge.spc @@ -1,9 +1,21 @@ connection "tfbridge" { plugin = "jreyesr/tfbridge" - provider = "hashicorp/dns" - version = "3.2.4" + # Write the name of a Terraform provider, in the same way that you'd write it + # in the required_providers block in the Terraform main file + # Examples: "hashicorp/aws", "TimDurward/slack", "hashicorp/random" + # If using a private Terraform registry, also include the hostname: "registry.acme.com/acme/supercloud" + provider = "integrations/github" + # Write a single version for a Terraform provider, in the same way that you'd write it + # in the required_providers block in the Terraform main file + # Note that, unlike in the Terraform file, you can't use a version constraint, such as "~> 1.0" or ">= 1.2.0, < 2.0.0", + # only explicit versions are allowed + version = "5.33.0" + + # If the Terraform provider would require some configuration in its provider {...} block, + # copy it here directly (just the _contents_ of the provider {} block, not the entire block!) provider_config = < 1.0" or ">= 1.2.0, < 2.0.0", + # only explicit versions are allowed + version = "5.33.0" + + # If the Terraform provider would require some configuration in its provider {...} block, + # copy it here directly (just the _contents_ of the provider {} block, not the entire block!) + provider_config = < +| query | id | include_repo_id | results_per_page | sort | full_names > ++------------+------------+-----------------+------------------+-------+-------------------------------------------------------------------------------------------------------> +| org:turbot | org:turbot | false | 100 | stars | ["turbot/steampipe","turbot/steampipe-mod-aws-compliance","turbot/steampipe-plugin-aws","turbot/steamp> +| | | | | | plugin-whois","turbot/steampipe-plugin-prometheus","turbot/steampipe-plugin-csv","turbot/steampipe-plu> +| | | | | | urbot/terraform-provider-turbot","turbot/terraform-provider-steampipecloud","turbot/steampipe-plugin-a> +| | | | | | eampipe-mod-digitalocean-thrifty","turbot/steampipe-plugin-crtsh","turbot/steampipe-plugin-abuseipdb",> +| | | | | | ","turbot/steampipe-plugin-hcloud","turbot/steampipe-plugin-fly","turbot/steampipe-plugin-equinix","tu> +| | | | | | pipe-plugin-workos","turbot/steampipe-mod-oci-insights","turbot/steampipe-mod-digitalocean-insights","> +| | | | | | hrifty","turbot/steampipe-mod-jira-sherlock","turbot/steampipe-plugin-ansible","turbot/steampipe-plugi> +| | | | | | teampipe-plugin-chaosratelimit","turbot/steampipe-mod-googleworkspace-compliance","turbot/steampipe-mo> ++------------+------------+-----------------+------------------+-------+-------------------------------------------------------------------------------------------------------> +``` + +### Getting details of an Algolia index + +Assume that you're using the `k-yomo/algolia` Terraform provider at version `0.5.7`. + + +```sql +select + * +from + algolia_index +where + name='indexname' +``` + +``` ++-----------+-----------+-------------------------------------------------------------------------------------------------------------------------------------+ +| name | id | advanced_config | ++-----------+-----------+-------------------------------------------------------------------------------------------------------------------------------------+ +| yourindex | yourindex | [{"attribute_criteria_computed_by_min_proximity": true, "attribute_for_distinct": "url", "distinct": 1, "max_facet_hits": 10, ...}] | ++-----------+-----------+-------------------------------------------------------------------------------------------------------------------------------------+ +``` + + +### Getting information about your public IP + +Assume that you're using the `dewhurstwill/whatsmyip` Terraform provider at version `1.0.3`. + +```sql +select + * +from + whatsmyip +``` + +``` ++----+---------------+---------+---------+ +| cc | country | id | ip | ++----+---------------+---------+---------+ +| US | United States | 1.1.1.1 | 1.1.1.1 | ++----+---------------+---------+---------+ +``` + +## General translation rules + +The following rules are followed to translate from Terraform data sources to Steampipe/SQL tables: + +* Every Terraform data source becomes a SQL table + * The name and description of the table are taken directly from the Terraform schema +* Every attribute in the Terraform data source becomes a column in the table + * Data types are translated in a best-effort basis: strings, numbers and booleans will become their corresponding Postgres types, and more complex Terraform types will become JSONB columns +* Required attributes in the Terraform data source (such as resource IDs if the data source returns data about a single object) _must_ be provided via `WHERE` clauses + * This requires that the Terraform provider has actually marked the attributes as required +* Other/more complex `WHERE` conditions may also be expressed, but those won't be passed to the Terraform provider. + * For example, `LIKE` conditions on text fields, or numerical comparisons (such as greater-than or is-even), or comparisons between columns + * If you use such conditions, be aware that the Terraform provider will receive a request to list _all_ data, and thus may incur on large API usage, even if most of that data will be discarded by a later condition +* It's up to the Terraform provider to implement "singular" and "plural" data sources (i.e. data sources that return information about a single item or about a list of items). If the Terraform data source is singular (i.e. you must provide a unique ID for the item that you wish to look up), this plugin won't be able to list all items, since it would need to somehow invent the IDs of the items + * For a provider that does implement singular and plural data sources, see [the Grafana provider](https://registry.terraform.io/providers/grafana/grafana/latest/docs/data-sources/dashboard), in particular see the `dashboard`/`dashboards`, `folder`/`folders` and `user`/`users` pairs of data sources + * However, if you somehow have a list of item IDs to query, you can use a `WHERE unique_id IN('id1', 'id2', ...)` condition, and it _will_ work as expected on a singular data source (since such queries are internally expanded into many parallel queries with `WHERE unique_id='id1'` and so on, which can be satisfied by a singular data source) \ No newline at end of file diff --git a/go.mod b/go.mod index 3e7e5ac..01d7e0e 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/jreyesr/steampipe-plugin-tfbridge -go 1.20 +go 1.19 require ( github.com/hashicorp/errwrap v1.1.0 diff --git a/tfbridge/plugin.go b/tfbridge/plugin.go index aeb370b..8d57910 100644 --- a/tfbridge/plugin.go +++ b/tfbridge/plugin.go @@ -17,9 +17,6 @@ func Plugin(ctx context.Context) *plugin.Plugin { }, SchemaMode: plugin.SchemaModeDynamic, TableMapFunc: PluginTables, - // TableMap: map[string]*plugin.Table{ - // "tfbridge_ds_1": tableTFBridgeZone(), - // }, } return p }