diff --git a/.editorconfig b/.editorconfig index 831bb8696cc..3701d80b453 100644 --- a/.editorconfig +++ b/.editorconfig @@ -2,7 +2,7 @@ root = true [*.go] -indent_style = tabs +indent_style = tab indent_size = 2 charset = utf-8 trim_trailing_whitespace = true diff --git a/.floo b/.floo new file mode 100644 index 00000000000..1c2038f98cc --- /dev/null +++ b/.floo @@ -0,0 +1,3 @@ +{ + "url": "https://floobits.com/raintank/grafana" +} diff --git a/.flooignore b/.flooignore new file mode 100644 index 00000000000..43cddf93bdf --- /dev/null +++ b/.flooignore @@ -0,0 +1,12 @@ +#* +*.o +*.pyc +*.pyo +*~ +extern/ +node_modules/ +tmp/ +data/ +vendor/ +public_gen/ +dist/ diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index e79741bbe6c..fe0a1d6c548 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -12,11 +12,11 @@ grunt karma:dev ### Run tests for backend assets before commit ``` -test -z "$(gofmt -s -l . | grep -v Godeps/_workspace/src/ | tee /dev/stderr)" +test -z "$(gofmt -s -l . | grep -v -E 'vendor/(github.com|golang.org|gopkg.in)' | tee /dev/stderr)" ``` ### Run tests for frontend assets before commit ``` -grunt test -godep go test -v ./pkg/... +npm test +go test -v ./pkg/... ``` diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 61f039fe615..98f6b6fe928 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,12 +1,18 @@ -Thank you! For helping us make Grafana even better. +Please prefix your title with [Bug] or [Feature request] +For question please check [Support Options](http://grafana.org/support/). **Do not** open a github issue -To help us respond to your issues faster, please make sure to add as much information as possible. +Please include this information: +- What Grafana version are you using? +- What datasource are you using? +- What OS are you running grafana on? +- What did you do? +- What was the expected result? +- What happened instead? -If this issue is about a plugin, please open the issue in that repository. +**IMPORTANT** +If it relates to *metric data viz*: +- An image or text representation of your metric query +- The raw query and response for the network request (check this in chrome dev tools network tab, here you can see metric requests and other request, please include the request body and request response) -Start your issues title with [Feature Request] / [Bug] / [Question] or no tag if your unsure. - -Ex -* What grafana version are you using? -* What datasource are you using? -* What OS are you running grafana on? +If it relates to *alerting* +- An image of the test execution data fully expanded. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 9eacff7c5de..4b4588eab21 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,2 +1,4 @@ * Link the PR to an issue for new features -* Rebase your PR if it gets out of sync with master \ No newline at end of file +* Rebase your PR if it gets out of sync with master + +**REMOVE THE TEXT ABOVE BEFORE CREATING THE PULL REQUEST** diff --git a/.gitignore b/.gitignore index 515c19e7e0b..721a2a71ad4 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ public/css/*.min.css *.swp .idea/ *.iml +.vscode/ /data/* /bin/* @@ -37,4 +38,4 @@ profile.cov .notouch /pkg/cmd/grafana-cli/grafana-cli /pkg/cmd/grafana-server/grafana-server -/examples/*/dist \ No newline at end of file +/examples/*/dist diff --git a/.hooks/pre-commit b/.hooks/pre-commit index 2519d4c44f4..0d7c6c9ee5f 100755 --- a/.hooks/pre-commit +++ b/.hooks/pre-commit @@ -1,6 +1,6 @@ #!/usr/bin/env bash -test -z "$(gofmt -s -l . | grep -v Godeps/_workspace/src/ | tee /dev/stderr)" +test -z "$(gofmt -s -l . | grep -v vendor/src/ | tee /dev/stderr)" if [ $? -gt 0 ]; then echo "Some files aren't formatted, please run 'go fmt ./pkg/...' to format your source code before committing" exit 1 diff --git a/.jscs.json b/.jscs.json index dcf694dcc63..8fdad332de5 100644 --- a/.jscs.json +++ b/.jscs.json @@ -10,4 +10,4 @@ "disallowSpacesInsideArrayBrackets": true, "disallowSpacesInsideParentheses": true, "validateIndentation": 2 -} \ No newline at end of file +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 9959767c087..1e9e7849c01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,307 @@ -# 3.0.0 (unrelased master branch) +# 4.2.0 (unreleased) + +## Enhancements +* **Alerting**: Added Telegram alert notifier [#7098](https://github.com/grafana/grafana/pull/7098), thx [@leonoff](https://github.com/leonoff) + +# 4.1.0 (unreleased) + +### Bugfixes +* **Server side PNG rendering**: Fixed issue with y-axis label rotation in phantomjs rendered images [#6924](https://github.com/grafana/grafana/issues/6924) +* **Graph**: Fixed centering of y-axis label [#7099](https://github.com/grafana/grafana/issues/7099) +* **Graph**: Fixed graph legend table mode and always visible scrollbar [#6828](https://github.com/grafana/grafana/issues/6828) +* **Templating**: Fixed template variable value groups/tags feature [#6752](https://github.com/grafana/grafana/issues/6752) + +## Enhancements +* **Elasticsearch**: Added support for all moving average options [#7154](https://github.com/grafana/grafana/pull/7154), thx [@vaibhavinbayarea](https://github.com/vaibhavinbayarea) + +# 4.1-beta1 (2016-12-21) + +### Enhancements +* **Postgres**: Add support for Certs for Postgres database [#6655](https://github.com/grafana/grafana/issues/6655) +* **Victorops**: Add VictorOps notification integration [#6411](https://github.com/grafana/grafana/issues/6411), thx [@ichekrygin](https://github.com/ichekrygin) +* **Opsgenie**: Add OpsGenie notification integratiion [#6687](https://github.com/grafana/grafana/issues/6687), thx [@kylemcc](https://github.com/kylemcc) +* **Singlestat**: New aggregation on singlestat panel [#6740](https://github.com/grafana/grafana/pull/6740), thx [@dirk-leroux](https://github.com/dirk-leroux) +* **Cloudwatch**: Make it possible to specify access and secret key on the data source config page [#6697](https://github.com/grafana/grafana/issues/6697) +* **Table**: Added Hidden Column Style for Table Panel [#5677](https://github.com/grafana/grafana/pull/5677), thx [@bmundt](https://github.com/bmundt) +* **Graph**: Shared crosshair option renamed to shared tooltip, shows tooltip on all graphs as you hover over one graph. [#1578](https://github.com/grafana/grafana/pull/1578), [#6274](https://github.com/grafana/grafana/pull/6274) +* **Elasticsearch**: Added support for Missing option (bucket) for terms aggregation [#4244](https://github.com/grafana/grafana/pull/4244), thx [@shanielh](https://github.com/shanielh) +* **Elasticsearch**: Added support for Elasticsearch 5.x [#5740](https://github.com/grafana/grafana/issues/5740), thx [@lpic10](https://github.com/lpic10) +* **CLI**: Make it possible to reset the admin password using the grafana-cli. [#5479](https://github.com/grafana/grafana/issues/5479) +* **Influxdb**: Support multiple tags in InfluxDB annotations. [#4550](https://github.com/grafana/grafana/pull/4550), thx [@adrianlzt](https://github.com/adrianlzt) +* **LDAP**: Basic Auth now supports LDAP username and password, [#6940](https://github.com/grafana/grafana/pull/6940), thx [@utkarshcmu](https://github.com/utkarshcmu) +* **LDAP**: Now works with Auth Proxy, role and organisation mapping & sync will regularly be performed. [#6895](https://github.com/grafana/grafana/pull/6895), thx [@Seuf](https://github.com/seuf) +* **Alerting**: Adds OK as no data option. [#6866](https://github.com/grafana/grafana/issues/6866) +* **Alert list**: Order alerts based on state. [#6676](https://github.com/grafana/grafana/issues/6676) +* **Alerting**: Add api endpoint for pausing all alerts. [#6589](https://github.com/grafana/grafana/issues/6589) +* **Panel**: Added help text for panels. [#4079](https://github.com/grafana/grafana/issues/4079), thx [@utkarshcmu](https://github.com/utkarshcmu) + +### Bugfixes +* **API**: HTTP API for deleting org returning incorrect message for a non-existing org [#6679](https://github.com/grafana/grafana/issues/6679) +* **Dashboard**: Posting empty dashboard result in corrupted dashboard [#5443](https://github.com/grafana/grafana/issues/5443) +* **Logging**: Fixed logging level confing issue [#6978](https://github.com/grafana/grafana/issues/6978) +* **Notifications**: Remove html escaping the email subject. [#6905](https://github.com/grafana/grafana/issues/6905) +* **Influxdb**: Fixes broken field dropdown when using template vars as measurement. [#6473](https://github.com/grafana/grafana/issues/6473) + +# 4.0.3 (unreleased) + +### Bugfixes +* **Influxdb**: Handles time(auto) the same way as time($interval) [#6997](https://github.com/grafana/grafana/issues/6997) + +# 4.0.2 (2016-12-08) + +### Enhancements +* **Playlist**: Add support for kiosk mode [#6727](https://github.com/grafana/grafana/issues/6727) + +### Bugfixes +* **Alerting**: Add alert message to webhook notifications [#6807](https://github.com/grafana/grafana/issues/6807) +* **Alerting**: Fixes a bug where avg() reducer treated null as zero. [#6879](https://github.com/grafana/grafana/issues/6879) +* **PNG Rendering**: Fix for server side rendering when using non default http addr bind and domain setting [#6813](https://github.com/grafana/grafana/issues/6813) +* **PNG Rendering**: Fix for server side rendering when setting enforce_domain to true [#6769](https://github.com/grafana/grafana/issues/6769) +* **Webhooks**: Add content type json to outgoing webhooks [#6822](https://github.com/grafana/grafana/issues/6822) +* **Keyboard shortcut**: Fixed zoom out shortcut [#6837](https://github.com/grafana/grafana/issues/6837) +* **Webdav**: Adds basic auth headers to webdav uploader [#6779](https://github.com/grafana/grafana/issues/6779) + +# 4.0.1 (2016-12-02) + +> **Notice** +4.0.0 had serious connection pooling issue when using a data source in proxy access. This bug caused lots of resource issues +due to too many connections/file handles on the data source backend. This problem is fixed in this release. + +### Bugfixes +* **Metrics**: Fixes nil pointer dereference on my arm build [#6749](https://github.com/grafana/grafana/issues/6749) +* **Data proxy**: Fixes a tcp pooling issue in the datasource reverse proxy [#6759](https://github.com/grafana/grafana/issues/6759) + +# 4.0-stable (2016-11-29) + +### Bugfixes +* **Server-side rendering**: Fixed address used when rendering panel via phantomjs and using non default http_addr config [#6660](https://github.com/grafana/grafana/issues/6660) +* **Graph panel**: Fixed graph panel tooltip sort order issue [#6648](https://github.com/grafana/grafana/issues/6648) +* **Unsaved changes**: You now navigate to the intended page after saving in the unsaved changes dialog [#6675](https://github.com/grafana/grafana/issues/6675) +* **TLS Client Auth**: Support for TLS client authentication for datasource proxies [#2316](https://github.com/grafana/grafana/issues/2316) +* **Alerts out of sync**: Saving dashboards with broken alerts causes sync problem[#6576](https://github.com/grafana/grafana/issues/6576) +* **Alerting**: Saving an alert with condition "HAS NO DATA" throws an error[#6701](https://github.com/grafana/grafana/issues/6701) +* **Config**: Improve error message when parsing broken config file [#6731](https://github.com/grafana/grafana/issues/6731) +* **Table**: Render empty dates as - instead of current date [#6728](https://github.com/grafana/grafana/issues/6728) + +# 4.0-beta2 (2016-11-21) + +### Bugfixes +* **Graph Panel**: Log base scale on right Y-axis had no effect, max value calc was not applied, [#6534](https://github.com/grafana/grafana/issues/6534) +* **Graph Panel**: Bar width if bars was only used in series override, [#6528](https://github.com/grafana/grafana/issues/6528) +* **UI/Browser**: Fixed issue with page/view header gradient border not showing in Safari, [#6530](https://github.com/grafana/grafana/issues/6530) +* **Cloudwatch**: Fixed cloudwatch datasource requesting to many datapoints, [#6544](https://github.com/grafana/grafana/issues/6544) +* **UX**: Panel Drop zone visible after duplicating panel, and when entering fullscreen/edit view, [#6598](https://github.com/grafana/grafana/issues/6598) +* **Templating**: Newly added variable was not visible directly only after dashboard reload, [#6622](https://github.com/grafana/grafana/issues/6622) + +### Enhancements +* **Singlestat**: Support repeated template variables in prefix/postfix [#6595](https://github.com/grafana/grafana/issues/6595) +* **Templating**: Don't persist variable options with refresh option [#6586](https://github.com/grafana/grafana/issues/6586) +* **Alerting**: Add ability to have OR conditions (and mixing AND & OR) [#6579](https://github.com/grafana/grafana/issues/6579) +* **InfluxDB**: Fix for Ad-Hoc Filters variable & changing dashboards [#6821](https://github.com/grafana/grafana/issues/6821) + +# 4.0-beta1 (2016-11-09) + +### Enhancements +* **Login**: Adds option to disable username/password logins, closes [#4674](https://github.com/grafana/grafana/issues/4674) +* **SingleStat**: Add seriename as option in singlestat panel, closes [#4740](https://github.com/grafana/grafana/issues/4740) +* **Localization**: Week start day now dependant on browser locale setting, closes [#3003](https://github.com/grafana/grafana/issues/3003) +* **Templating**: Update panel repeats for variables that change on time refresh, closes [#5021](https://github.com/grafana/grafana/issues/5021) +* **Templating**: Add support for numeric and alphabetical sorting of variable values, closes [#2839](https://github.com/grafana/grafana/issues/2839) +* **Elasticsearch**: Support to set Precision Threshold for Unique Count metric, closes [#4689](https://github.com/grafana/grafana/issues/4689) +* **Navigation**: Add search to org swithcer, closes [#2609](https://github.com/grafana/grafana/issues/2609) +* **Database**: Allow database config using one propertie, closes [#5456](https://github.com/grafana/grafana/pull/5456) +* **Graphite**: Add support for groupByNodes, closes [#5613](https://github.com/grafana/grafana/pull/5613) +* **Influxdb**: Add support for elapsed(), closes [#5827](https://github.com/grafana/grafana/pull/5827) +* **OpenTSDB**: Add support for explicitTags for OpenTSDB>=2.3, closes [#6360](https://github.com/grafana/grafana/pull/6361) +* **OAuth**: Add support for generic oauth, closes [#4718](https://github.com/grafana/grafana/pull/4718) +* **Cloudwatch**: Add support to expand multi select template variable, closes [#5003](https://github.com/grafana/grafana/pull/5003) +* **Background Tasks**: Now support automatic purging of old snapshots, closes [#4087](https://github.com/grafana/grafana/issues/4087) +* **Background Tasks**: Now support automatic purging of old rendered images, closes [#2172](https://github.com/grafana/grafana/issues/2172) +* **Dashboard**: After inactivity hide nav/row actions, fade to nice clean view, can be toggled with `d v`, also added kiosk mode, toggled via `d k` [#6476](https://github.com/grafana/grafana/issues/6476) +* **Dashboard**: Improved dashboard row menu & add panel UX [#6442](https://github.com/grafana/grafana/issues/6442) +* **Graph Panel**: Support for stacking null values [#2912](https://github.com/grafana/grafana/issues/2912), [#6287](https://github.com/grafana/grafana/issues/6287), thanks @benrubson! + +### Breaking changes +* **SystemD**: Change systemd description, closes [#5971](https://github.com/grafana/grafana/pull/5971) +* **lodash upgrade**: Upgraded lodash from 2.4.2 to 4.15.0, this contains a number of breaking changes that could effect plugins. closes [#6021](https://github.com/grafana/grafana/pull/6021) + +### Bug fixes +* **Table Panel**: Fixed problem when switching to Mixed datasource in metrics tab, fixes [#5999](https://github.com/grafana/grafana/pull/5999) +* **Playlist**: Fixed problem with play order not matching order defined in playlist, fixes [#5467](https://github.com/grafana/grafana/pull/5467) +* **Graph panel**: Fixed problem with auto decimals on y axis when datamin=datamax, fixes [#6070](https://github.com/grafana/grafana/pull/6070) +* **Snapshot**: Can view embedded panels/png rendered panels in snapshots without login, fixes [#3769](https://github.com/grafana/grafana/pull/3769) +* **Elasticsearch**: Fix for query template variable when looking up terms without query, no longer relies on elasticsearch default field, fixes [#3887](https://github.com/grafana/grafana/pull/3887) +* **Elasticsearch**: Fix for displaying IP address used in terms aggregations, fixes [#4393](https://github.com/grafana/grafana/pull/4393) +* **PNG Rendering**: Fix for server side rendering when using auth proxy, fixes [#5906](https://github.com/grafana/grafana/pull/5906) +* **OpenTSDB**: Fixed multi-value nested templating for opentsdb, fixes [#6455](https://github.com/grafana/grafana/pull/6455) +* **Playlist**: Remove playlist items when dashboard is removed, fixes [#6292](https://github.com/grafana/grafana/issues/6292) + +# 3.1.2 (unreleased) +* **Templating**: Fixed issue when combining row & panel repeats, fixes [#5790](https://github.com/grafana/grafana/issues/5790) +* **Drag&Drop**: Fixed issue with drag and drop in latest Chrome(51+), fixes [#5767](https://github.com/grafana/grafana/issues/5767) +* **Internal Metrics**: Fixed issue with dots in instance_name when sending internal metrics to Graphite, fixes [#5739](https://github.com/grafana/grafana/issues/5739) +* **Grafana-CLI**: Add default plugin path for MAC OS, fixes [#5806](https://github.com/grafana/grafana/issues/5806) +* **Grafana-CLI**: Improve error message for upgrade-all command, fixes [#5885](https://github.com/grafana/grafana/issues/5885) + +# 3.1.1 (2016-08-01) +* **IFrame embedding**: Fixed issue of using full iframe height, fixes [#5605](https://github.com/grafana/grafana/issues/5606) +* **Panel PNG rendering**: Fixed issue detecting render completion, fixes [#5605](https://github.com/grafana/grafana/issues/5606) +* **Elasticsearch**: Fixed issue with templating query and json parse error, fixes [#5615](https://github.com/grafana/grafana/issues/5615) +* **Tech**: Upgraded JQuery to 2.2.4 to fix Security vulnerabilitie in 2.1.4, fixes [#5627](https://github.com/grafana/grafana/issues/5627) +* **Graphite**: Fixed issue with mixed data sources and Graphite, fixes [#5617](https://github.com/grafana/grafana/issues/5617) +* **Templating**: Fixed issue with template variable query was issued multiple times during dashboard load, fixes [#5637](https://github.com/grafana/grafana/issues/5637) +* **Zoom**: Fixed issues with zoom in and out on embedded (iframed) panel, fixes [#4489](https://github.com/grafana/grafana/issues/4489), [#5666](https://github.com/grafana/grafana/issues/5666) + +# 3.1.0 stable (2016-07-12) + +### Bugfixes & Enhancements, +* **User Alert Notices**: Backend error alert popups did not show properly, fixes [#5435](https://github.com/grafana/grafana/issues/5435) +* **Table**: Added sanitize HTML option to allow links in table cells, fixes [#4596](https://github.com/grafana/grafana/issues/4596) +* **Apps**: App dashboards are automatically synced to DB at startup after plugin update, fixes [#5529](https://github.com/grafana/grafana/issues/5529) + +# 3.1.0-beta1 (2016-06-23) + +### Enhancements +* **Dashboard Export/Import**: Dashboard export now templetize data sources and constant variables, users pick these on import, closes [#5084](https://github.com/grafana/grafana/issues/5084) +* **Dashboard Url**: Time range changes updates url, closes [#458](https://github.com/grafana/grafana/issues/458) +* **Dashboard Url**: Template variable change updates url, closes [#5002](https://github.com/grafana/grafana/issues/5002) +* **Singlestat**: Add support for range to text mappings, closes [#1319](https://github.com/grafana/grafana/issues/1319) +* **Graph**: Adds sort order options for graph tooltip, closes [#1189](https://github.com/grafana/grafana/issues/1189) +* **Theme**: Add default theme to config file [#5011](https://github.com/grafana/grafana/pull/5011) +* **Page Footer**: Added page footer with links to docs, shows Grafana version and info if new version is available, closes [#4889](https://github.com/grafana/grafana/pull/4889) +* **InfluxDB**: Add spread function, closes [#5211](https://github.com/grafana/grafana/issues/5211) +* **Scripts**: Use restart instead of start for deb package script, closes [#5282](https://github.com/grafana/grafana/pull/5282) +* **Logging**: Moved to structured logging lib, and moved to component specific level filters via config file, closes [#4590](https://github.com/grafana/grafana/issues/4590) +* **OpenTSDB**: Support nested template variables in tag_values function, closes [#4398](https://github.com/grafana/grafana/issues/4398) +* **Datasource**: Pending data source requests are cancelled before new ones are issues (Graphite & Prometheus), closes [#5321](https://github.com/grafana/grafana/issues/5321) + +### Breaking changes +* **Logging** : Changed default logging output format (now structured into message, and key value pairs, with logger key acting as component). You can also no change in config to json log ouput. +* **Graphite** : The Graph panel no longer have a Graphite PNG option. closes [#5367](https://github.com/grafana/grafana/issues/5367) + +### Bug fixes +* **PNG rendering**: Fixed phantomjs rendering and y-axis label rotation. fixes [#5220](https://github.com/grafana/grafana/issues/5220) +* **CLI**: The cli tool now supports reading plugin.json from dist/plugin.json. fixes [#5410](https://github.com/grafana/grafana/issues/5410) + +# 3.0.4 Patch release (2016-05-25) +* **Panel**: Fixed blank dashboard issue when switching to other dashboard while in fullscreen edit mode, fixes [#5163](https://github.com/grafana/grafana/pull/5163) +* **Templating**: Fixed issue with nested multi select variables and cascading and updating child variable selection state, fixes [#4861](https://github.com/grafana/grafana/pull/4861) +* **Templating**: Fixed issue with using templated data source in another template variable query, fixes [#5165](https://github.com/grafana/grafana/pull/5165) +* **Singlestat gauge**: Fixed issue with gauge render position, fixes [#5143](https://github.com/grafana/grafana/pull/5143) +* **Home dashboard**: Fixes broken home dashboard api, fixes [#5167](https://github.com/grafana/grafana/issues/5167) + +# 3.0.3 Patch release (2016-05-23) +* **Annotations**: Annotations can now use a template variable as data source, closes [#5054](https://github.com/grafana/grafana/issues/5054) +* **Time picker**: Fixed issue timepicker and UTC when reading time from URL, fixes [#5078](https://github.com/grafana/grafana/issues/5078) +* **CloudWatch**: Support for Multiple Account by AssumeRole, closes [#3522](https://github.com/grafana/grafana/issues/3522) +* **Singlestat**: Fixed alignment and minium height issue, fixes [#5113](https://github.com/grafana/grafana/issues/5113), fixes [#4679](https://github.com/grafana/grafana/issues/4679) +* **Share modal**: Fixed link when using grafana under dashboard sub url, fixes [#5109](https://github.com/grafana/grafana/issues/5109) +* **Prometheus**: Fixed bug in query editor that caused it not to load when reloading page, fixes [#5107](https://github.com/grafana/grafana/issues/5107) +* **Elasticsearch**: Fixed bug when template variable query returns numeric values, fixes [#5097](https://github.com/grafana/grafana/issues/5097), fixes [#5088](https://github.com/grafana/grafana/issues/5088) +* **Logging**: Fixed issue with reading logging level value, fixes [#5079](https://github.com/grafana/grafana/issues/5079) +* **Timepicker**: Fixed issue with timepicker and UTC when reading time from URL, fixes [#5078](https://github.com/grafana/grafana/issues/5078) +* **Docs**: Added docs for org & user preferences HTTP API, closes [#5069](https://github.com/grafana/grafana/issues/5069) +* **Plugin list panel**: Now shows correct enable state for apps when not enabled, fixes [#5068](https://github.com/grafana/grafana/issues/5068) +* **Elasticsearch**: Templating & Annotation queries that use template variables are now formatted correctly, fixes [#5135](https://github.com/grafana/grafana/issues/5135) + +# 3.0.2 Patch release (2016-05-16) + +* **Templating**: Fixed issue mixing row repeat and panel repeats, fixes [#4988](https://github.com/grafana/grafana/issues/4988) +* **Templating**: Fixed issue detecting dependencies in nested variables, fixes [#4987](https://github.com/grafana/grafana/issues/4987), fixes [#4986](https://github.com/grafana/grafana/issues/4986) +* **Graph**: Fixed broken PNG rendering in graph panel, fixes [#5025](https://github.com/grafana/grafana/issues/5025) +* **Graph**: Fixed broken xaxis on graph panel, fixes [#5024](https://github.com/grafana/grafana/issues/5024) + +* **Influxdb**: Fixes crash when hiding middle serie, fixes [#5005](https://github.com/grafana/grafana/issues/5005) + +# 3.0.1 Stable (2016-05-11) + +### Bug fixes +* **Templating**: Fixed issue with new data source variable not persisting current selected value, fixes [#4934](https://github.com/grafana/grafana/issues/4934) + +# 3.0.0-beta7 (2016-05-02) + +### Bug fixes +* **Dashboard title**: Fixed max dashboard title width (media query) for large screens, fixes [#4859](https://github.com/grafana/grafana/issues/4859) +* **Annotations**: Fixed issue with entering annotation edit view, fixes [#4857](https://github.com/grafana/grafana/issues/4857) +* **Remove query**: Fixed issue with removing query for data sources without collapsable query editors, fixes [#4856](https://github.com/grafana/grafana/issues/4856) +* **Graphite PNG**: Fixed issue graphite png rendering option, fixes [#4864](https://github.com/grafana/grafana/issues/4864) +* **InfluxDB**: Fixed issue missing plus group by iconn, fixes [#4862](https://github.com/grafana/grafana/issues/4862) +* **Graph**: Fixes missing line mode for thresholds, fixes [#4902](https://github.com/grafana/grafana/pull/4902) + +### Enhancements +* **InfluxDB**: Added new functions moving_average and difference to query editor, closes [#4698](https://github.com/grafana/grafana/issues/4698) + +# 3.0.0-beta6 (2016-04-29) + +### Enhancements +* **Singlestat**: Support for gauges in singlestat panel. closes [#3688](https://github.com/grafana/grafana/pull/3688) +* **Templating**: Support for data source as variable, closes [#816](https://github.com/grafana/grafana/pull/816) + +### Bug fixes +* **InfluxDB 0.12**: Fixed issue templating and `show tag values` query only returning tags for first measurement, fixes [#4726](https://github.com/grafana/grafana/issues/4726) +* **Templating**: Fixed issue with regex formating when matching multiple values, fixes [#4755](https://github.com/grafana/grafana/issues/4755) +* **Templating**: Fixed issue with custom all value and escaping, fixes [#4736](https://github.com/grafana/grafana/issues/4736) +* **Dashlist**: Fixed issue dashboard list panel and caching tags, fixes [#4768](https://github.com/grafana/grafana/issues/4768) +* **Graph**: Fixed issue with unneeded scrollbar in legend for Firefox, fixes [#4760](https://github.com/grafana/grafana/issues/4760) +* **Table panel**: Fixed issue table panel formating string array properties, fixes [#4791](https://github.com/grafana/grafana/issues/4791) +* **grafana-cli**: Improve error message when failing to install plugins due to corrupt response, fixes [#4651](https://github.com/grafana/grafana/issues/4651) +* **Singlestat**: Fixes prefix an postfix for gauges, fixes [#4812](https://github.com/grafana/grafana/issues/4812) +* **Singlestat**: Fixes auto-refresh on change for some options, fixes [#4809](https://github.com/grafana/grafana/issues/4809) + +### Breaking changes +**Data Source Query Editors**: Issue [#3900](https://github.com/grafana/grafana/issues/3900) + +Query editors have been updated to use the new form styles. External data source plugins needs to be +updated to work. Sorry to introduce breaking change this late in beta phase. We wanted to get this change +in before 3.0 stable is released so we don't have to break data sources in next release (3.1). If you are +a data source plugin author and want help for how the new form styles work please ask for help in +slack channel (link to slack channel in readme). + +# 3.0.0-beta5 (2016-04-15) + +### Bug fixes +* **grafana-cli**: Fixed issue grafana-cli tool, did not detect the right plugin dir, fixes [#4723](https://github.com/grafana/grafana/issues/4723) +* **Graph**: Fixed issue with light theme text color issue in tooltip, fixes [#4702](https://github.com/grafana/grafana/issues/4702) +* **Snapshot**: Fixed issue with empty snapshots, fixes [#4706](https://github.com/grafana/grafana/issues/4706) + +# 3.0.0-beta4 (2016-04-13) + +### Bug fixes +* **Home dashboard**: Fixed issue with permission denied error on home dashboard, fixes [#4686](https://github.com/grafana/grafana/issues/4686) +* **Templating**: Fixed issue templating variables that use regex extraction, fixes [#4672](https://github.com/grafana/grafana/issues/4672) + +# 3.0.0-beta3 (2016-04-12) + +### Enhancements +* **InfluxDB**: Changed multi query encoding to work with InfluxDB 0.11 & 0.12, closes [#4533](https://github.com/grafana/grafana/issues/4533) +* **Timepicker**: Add arrows and shortcuts for moving back and forth in current dashboard, closes [#119](https://github.com/grafana/grafana/issues/119) + +### Bug fixes +* **Postgres**: Fixed page render crash when using postgres, fixes [#4558](https://github.com/grafana/grafana/issues/4558) +* **Table panel**: Fixed table panel bug when trying to show annotations in table panel, fixes [#4563](https://github.com/grafana/grafana/issues/4563) +* **App Config**: Fixed app config issue showing content of other app config, fixes [#4575](https://github.com/grafana/grafana/issues/4575) +* **Graph Panel**: Fixed legend option max not updating, fixes [#4601](https://github.com/grafana/grafana/issues/4601) +* **Graph Panel**: Fixed issue where newly added graph panels shared same axes config, fixes [#4582](https://github.com/grafana/grafana/issues/4582) +* **Graph Panel**: Fixed issue with axis labels overlapping Y-axis, fixes [#4626](https://github.com/grafana/grafana/issues/4626) +* **InfluxDB**: Fixed issue with templating query containing template variable, fixes [#4602](https://github.com/grafana/grafana/issues/4602) +* **Graph Panel**: Fixed issue with hiding series and stacking, fixes [#4557](https://github.com/grafana/grafana/issues/4557) +* **Graph Panel**: Fixed issue with legend height in table mode with few series, affected iframe embedding as well, fixes [#4640](https://github.com/grafana/grafana/issues/4640) + +# 3.0.0-beta2 (2016-04-04) + +### New Features (introduces since 3.0-beta1) +* **Preferences**: Set home dashboard on user and org level, closes [#1678](https://github.com/grafana/grafana/issues/1678) +* **Preferences**: Set timezone on user and org level, closes [#3214](https://github.com/grafana/grafana/issues/3214), [#1200](https://github.com/grafana/grafana/issues/1200) +* **Preferences**: Set theme on user and org level, closes [#3214](https://github.com/grafana/grafana/issues/3214), [#1917](https://github.com/grafana/grafana/issues/1917) + +### Bug fixes +* **Dashboard**: Fixed dashboard panel layout for mobile devices, fixes [#4529](https://github.com/grafana/grafana/issues/4529) +* **Table Panel**: Fixed issue with table panel sort, fixes [#4532](https://github.com/grafana/grafana/issues/4532) +* **Page Load Crash**: A Datasource with null jsonData would make Grafana fail to load page, fixes [#4536](https://github.com/grafana/grafana/issues/4536) +* **Metrics tab**: Fix for missing datasource name in datasource selector, fixes [#4541](https://github.com/grafana/grafana/issues/4540) +* **Graph**: Fix legend in table mode with series on right-y axis, fixes [#4551](https://github.com/grafana/grafana/issues/4551), [#1145](https://github.com/grafana/grafana/issues/1145) + +# 3.0.0-beta1 (2016-03-31) ### New Features * **Playlists**: Playlists can now be persisted and started from urls, closes [#3655](https://github.com/grafana/grafana/issues/3655) diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json deleted file mode 100644 index 76a9bbf0d18..00000000000 --- a/Godeps/Godeps.json +++ /dev/null @@ -1,351 +0,0 @@ -{ - "ImportPath": "github.com/grafana/grafana", - "GoVersion": "go1.5.1", - "GodepVersion": "v60", - "Packages": [ - "./pkg/..." - ], - "Deps": [ - { - "ImportPath": "github.com/BurntSushi/toml", - "Comment": "v0.1.0-21-g056c9bc", - "Rev": "056c9bc7be7190eaa7715723883caffa5f8fa3e4" - }, - { - "ImportPath": "github.com/Unknwon/com", - "Rev": "d9bcf409c8a368d06c9b347705c381e7c12d54df" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/awserr", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/awsutil", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/client", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/client/metadata", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/corehandlers", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/credentials", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/defaults", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/ec2metadata", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/request", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/session", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/private/endpoints", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/private/protocol/ec2query", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query/queryutil", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/private/protocol/rest", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/private/signer/v4", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/private/waiter", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/service/cloudwatch", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/service/ec2", - "Comment": "v1.0.0", - "Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f" - }, - { - "ImportPath": "github.com/bmizerany/assert", - "Comment": "release.r60-6-ge17e998", - "Rev": "e17e99893cb6509f428e1728281c2ad60a6b31e3" - }, - { - "ImportPath": "github.com/bradfitz/gomemcache/memcache", - "Comment": "release.r60-40-g72a6864", - "Rev": "72a68649ba712ee7c4b5b4a943a626bcd7d90eb8" - }, - { - "ImportPath": "github.com/codegangsta/cli", - "Comment": "1.2.0-187-gc31a797", - "Rev": "c31a7975863e7810c92e2e288a9ab074f9a88f29" - }, - { - "ImportPath": "github.com/davecgh/go-spew/spew", - "Rev": "2df174808ee097f90d259e432cc04442cf60be21" - }, - { - "ImportPath": "github.com/fatih/color", - "Comment": "v0.1-16-g4f7bcef", - "Rev": "4f7bcef27eec7925456d0c30c5e7b0408b3339be" - }, - { - "ImportPath": "github.com/franela/goreq", - "Rev": "3ddeded65be21dacb5a2e2d0b95af9ff6862a2b5" - }, - { - "ImportPath": "github.com/go-ini/ini", - "Comment": "v0-48-g060d7da", - "Rev": "060d7da055ba6ec5ea7a31f116332fe5efa04ce0" - }, - { - "ImportPath": "github.com/go-ldap/ldap", - "Comment": "v2.2.1", - "Rev": "07a7330929b9ee80495c88a4439657d89c7dbd87" - }, - { - "ImportPath": "github.com/go-macaron/binding", - "Rev": "2502aaf4bce3a4e6451b4610847bfb8dffdb6266" - }, - { - "ImportPath": "github.com/go-macaron/gzip", - "Rev": "4938e9be6b279d8426cb1c89a6bcf7af70b0c21d" - }, - { - "ImportPath": "github.com/go-macaron/inject", - "Rev": "c5ab7bf3a307593cd44cb272d1a5beea473dd072" - }, - { - "ImportPath": "github.com/go-macaron/session", - "Rev": "66031fcb37a0fff002a1f028eb0b3a815c78306b" - }, - { - "ImportPath": "github.com/go-macaron/session/memcache", - "Rev": "66031fcb37a0fff002a1f028eb0b3a815c78306b" - }, - { - "ImportPath": "github.com/go-macaron/session/mysql", - "Rev": "66031fcb37a0fff002a1f028eb0b3a815c78306b" - }, - { - "ImportPath": "github.com/go-macaron/session/postgres", - "Rev": "66031fcb37a0fff002a1f028eb0b3a815c78306b" - }, - { - "ImportPath": "github.com/go-macaron/session/redis", - "Rev": "66031fcb37a0fff002a1f028eb0b3a815c78306b" - }, - { - "ImportPath": "github.com/go-sql-driver/mysql", - "Comment": "v1.2-171-g267b128", - "Rev": "267b128680c46286b9ca13475c3cca5de8f79bd7" - }, - { - "ImportPath": "github.com/go-xorm/core", - "Comment": "v0.4.4-7-g9e608f7", - "Rev": "9e608f7330b9d16fe2818cfe731128b3f156cb9a" - }, - { - "ImportPath": "github.com/go-xorm/xorm", - "Comment": "v0.4.4-44-gf561133", - "Rev": "f56113384f2c63dfe4cd8e768e349f1c35122b58" - }, - { - "ImportPath": "github.com/gorilla/websocket", - "Rev": "c45a635370221f34fea2d5163fd156fcb4e38e8a" - }, - { - "ImportPath": "github.com/gosimple/slug", - "Rev": "8d258463b4459f161f51d6a357edacd3eef9d663" - }, - { - "ImportPath": "github.com/hashicorp/go-version", - "Rev": "7e3c02b30806fa5779d3bdfc152ce4c6f40e7b38" - }, - { - "ImportPath": "github.com/jmespath/go-jmespath", - "Comment": "0.2.2", - "Rev": "3433f3ea46d9f8019119e7dd41274e112a2359a9" - }, - { - "ImportPath": "github.com/jtolds/gls", - "Rev": "f1ac7f4f24f50328e6bc838ca4437d1612a0243c" - }, - { - "ImportPath": "github.com/klauspost/compress/flate", - "Rev": "7b02889a2005228347aef0e76beeaee564d82f8c" - }, - { - "ImportPath": "github.com/klauspost/compress/gzip", - "Rev": "7b02889a2005228347aef0e76beeaee564d82f8c" - }, - { - "ImportPath": "github.com/klauspost/cpuid", - "Rev": "349c675778172472f5e8f3a3e0fe187e302e5a10" - }, - { - "ImportPath": "github.com/klauspost/crc32", - "Rev": "6834731faf32e62a2dd809d99fb24d1e4ae5a92d" - }, - { - "ImportPath": "github.com/kr/pretty", - "Comment": "go.weekly.2011-12-22-27-ge6ac2fc", - "Rev": "e6ac2fc51e89a3249e82157fa0bb7a18ef9dd5bb" - }, - { - "ImportPath": "github.com/kr/text", - "Rev": "bb797dc4fb8320488f47bf11de07a733d7233e1f" - }, - { - "ImportPath": "github.com/lib/pq", - "Comment": "go1.0-cutoff-13-g19eeca3", - "Rev": "19eeca3e30d2577b1761db471ec130810e67f532" - }, - { - "ImportPath": "github.com/lib/pq/oid", - "Comment": "go1.0-cutoff-13-g19eeca3", - "Rev": "19eeca3e30d2577b1761db471ec130810e67f532" - }, - { - "ImportPath": "github.com/mattn/go-colorable", - "Rev": "9cbef7c35391cca05f15f8181dc0b18bc9736dbb" - }, - { - "ImportPath": "github.com/mattn/go-isatty", - "Rev": "56b76bdf51f7708750eac80fa38b952bb9f32639" - }, - { - "ImportPath": "github.com/mattn/go-sqlite3", - "Rev": "e28cd440fabdd39b9520344bc26829f61db40ece" - }, - { - "ImportPath": "github.com/rainycape/unidecode", - "Rev": "836ef0a715aedf08a12d595ed73ec8ed5b288cac" - }, - { - "ImportPath": "github.com/smartystreets/goconvey/convey", - "Comment": "1.5.0-356-gfbc0a1c", - "Rev": "fbc0a1c888f9f96263f9a559d1769905245f1123" - }, - { - "ImportPath": "github.com/smartystreets/goconvey/convey/assertions", - "Comment": "1.5.0-356-gfbc0a1c", - "Rev": "fbc0a1c888f9f96263f9a559d1769905245f1123" - }, - { - "ImportPath": "github.com/smartystreets/goconvey/convey/assertions/oglematchers", - "Comment": "1.5.0-356-gfbc0a1c", - "Rev": "fbc0a1c888f9f96263f9a559d1769905245f1123" - }, - { - "ImportPath": "github.com/smartystreets/goconvey/convey/gotest", - "Comment": "1.5.0-356-gfbc0a1c", - "Rev": "fbc0a1c888f9f96263f9a559d1769905245f1123" - }, - { - "ImportPath": "github.com/smartystreets/goconvey/convey/reporting", - "Comment": "1.5.0-356-gfbc0a1c", - "Rev": "fbc0a1c888f9f96263f9a559d1769905245f1123" - }, - { - "ImportPath": "github.com/streadway/amqp", - "Rev": "150b7f24d6ad507e6026c13d85ce1f1391ac7400" - }, - { - "ImportPath": "golang.org/x/net/context", - "Rev": "972f0c5fbe4ae29e666c3f78c3ed42ae7a448b0a" - }, - { - "ImportPath": "golang.org/x/oauth2", - "Rev": "c58fcf0ffc1c772aa2e1ee4894bc19f2649263b2" - }, - { - "ImportPath": "golang.org/x/sys/unix", - "Rev": "7a56174f0086b32866ebd746a794417edbc678a1" - }, - { - "ImportPath": "gopkg.in/asn1-ber.v1", - "Comment": "v1", - "Rev": "9eae18c3681ae3d3c677ac2b80a8fe57de45fc09" - }, - { - "ImportPath": "gopkg.in/bufio.v1", - "Comment": "v1", - "Rev": "567b2bfa514e796916c4747494d6ff5132a1dfce" - }, - { - "ImportPath": "gopkg.in/ini.v1", - "Comment": "v0-16-g1772191", - "Rev": "177219109c97e7920c933e21c9b25f874357b237" - }, - { - "ImportPath": "gopkg.in/macaron.v1", - "Rev": "1c6dd87797ae9319b4658cbd48d1d0420b279fd5" - }, - { - "ImportPath": "gopkg.in/redis.v2", - "Comment": "v2.3.2", - "Rev": "e6179049628164864e6e84e973cfb56335748dea" - } - ] -} diff --git a/Godeps/Readme b/Godeps/Readme deleted file mode 100644 index 4cdaa53d56d..00000000000 --- a/Godeps/Readme +++ /dev/null @@ -1,5 +0,0 @@ -This directory tree is generated automatically by godep. - -Please do not edit. - -See https://github.com/tools/godep for more information. diff --git a/Godeps/_workspace/.gitignore b/Godeps/_workspace/.gitignore deleted file mode 100644 index f037d684ef2..00000000000 --- a/Godeps/_workspace/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/pkg -/bin diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/copy_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/copy_test.go deleted file mode 100644 index 84b7e3f34aa..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/copy_test.go +++ /dev/null @@ -1,233 +0,0 @@ -package awsutil_test - -import ( - "bytes" - "fmt" - "io" - "io/ioutil" - "testing" - - "github.com/aws/aws-sdk-go/aws/awsutil" - "github.com/stretchr/testify/assert" -) - -func ExampleCopy() { - type Foo struct { - A int - B []*string - } - - // Create the initial value - str1 := "hello" - str2 := "bye bye" - f1 := &Foo{A: 1, B: []*string{&str1, &str2}} - - // Do the copy - var f2 Foo - awsutil.Copy(&f2, f1) - - // Print the result - fmt.Println(awsutil.Prettify(f2)) - - // Output: - // { - // A: 1, - // B: ["hello","bye bye"] - // } -} - -func TestCopy(t *testing.T) { - type Foo struct { - A int - B []*string - C map[string]*int - } - - // Create the initial value - str1 := "hello" - str2 := "bye bye" - int1 := 1 - int2 := 2 - f1 := &Foo{ - A: 1, - B: []*string{&str1, &str2}, - C: map[string]*int{ - "A": &int1, - "B": &int2, - }, - } - - // Do the copy - var f2 Foo - awsutil.Copy(&f2, f1) - - // Values are equal - assert.Equal(t, f2.A, f1.A) - assert.Equal(t, f2.B, f1.B) - assert.Equal(t, f2.C, f1.C) - - // But pointers are not! - str3 := "nothello" - int3 := 57 - f2.A = 100 - f2.B[0] = &str3 - f2.C["B"] = &int3 - assert.NotEqual(t, f2.A, f1.A) - assert.NotEqual(t, f2.B, f1.B) - assert.NotEqual(t, f2.C, f1.C) -} - -func TestCopyNestedWithUnexported(t *testing.T) { - type Bar struct { - a int - B int - } - type Foo struct { - A string - B Bar - } - - f1 := &Foo{A: "string", B: Bar{a: 1, B: 2}} - - var f2 Foo - awsutil.Copy(&f2, f1) - - // Values match - assert.Equal(t, f2.A, f1.A) - assert.NotEqual(t, f2.B, f1.B) - assert.NotEqual(t, f2.B.a, f1.B.a) - assert.Equal(t, f2.B.B, f2.B.B) -} - -func TestCopyIgnoreNilMembers(t *testing.T) { - type Foo struct { - A *string - B []string - C map[string]string - } - - f := &Foo{} - assert.Nil(t, f.A) - assert.Nil(t, f.B) - assert.Nil(t, f.C) - - var f2 Foo - awsutil.Copy(&f2, f) - assert.Nil(t, f2.A) - assert.Nil(t, f2.B) - assert.Nil(t, f2.C) - - fcopy := awsutil.CopyOf(f) - f3 := fcopy.(*Foo) - assert.Nil(t, f3.A) - assert.Nil(t, f3.B) - assert.Nil(t, f3.C) -} - -func TestCopyPrimitive(t *testing.T) { - str := "hello" - var s string - awsutil.Copy(&s, &str) - assert.Equal(t, "hello", s) -} - -func TestCopyNil(t *testing.T) { - var s string - awsutil.Copy(&s, nil) - assert.Equal(t, "", s) -} - -func TestCopyReader(t *testing.T) { - var buf io.Reader = bytes.NewReader([]byte("hello world")) - var r io.Reader - awsutil.Copy(&r, buf) - b, err := ioutil.ReadAll(r) - assert.NoError(t, err) - assert.Equal(t, []byte("hello world"), b) - - // empty bytes because this is not a deep copy - b, err = ioutil.ReadAll(buf) - assert.NoError(t, err) - assert.Equal(t, []byte(""), b) -} - -func TestCopyDifferentStructs(t *testing.T) { - type SrcFoo struct { - A int - B []*string - C map[string]*int - SrcUnique string - SameNameDiffType int - unexportedPtr *int - ExportedPtr *int - } - type DstFoo struct { - A int - B []*string - C map[string]*int - DstUnique int - SameNameDiffType string - unexportedPtr *int - ExportedPtr *int - } - - // Create the initial value - str1 := "hello" - str2 := "bye bye" - int1 := 1 - int2 := 2 - f1 := &SrcFoo{ - A: 1, - B: []*string{&str1, &str2}, - C: map[string]*int{ - "A": &int1, - "B": &int2, - }, - SrcUnique: "unique", - SameNameDiffType: 1, - unexportedPtr: &int1, - ExportedPtr: &int2, - } - - // Do the copy - var f2 DstFoo - awsutil.Copy(&f2, f1) - - // Values are equal - assert.Equal(t, f2.A, f1.A) - assert.Equal(t, f2.B, f1.B) - assert.Equal(t, f2.C, f1.C) - assert.Equal(t, "unique", f1.SrcUnique) - assert.Equal(t, 1, f1.SameNameDiffType) - assert.Equal(t, 0, f2.DstUnique) - assert.Equal(t, "", f2.SameNameDiffType) - assert.Equal(t, int1, *f1.unexportedPtr) - assert.Nil(t, f2.unexportedPtr) - assert.Equal(t, int2, *f1.ExportedPtr) - assert.Equal(t, int2, *f2.ExportedPtr) -} - -func ExampleCopyOf() { - type Foo struct { - A int - B []*string - } - - // Create the initial value - str1 := "hello" - str2 := "bye bye" - f1 := &Foo{A: 1, B: []*string{&str1, &str2}} - - // Do the copy - v := awsutil.CopyOf(f1) - var f2 *Foo = v.(*Foo) - - // Print the result - fmt.Println(awsutil.Prettify(f2)) - - // Output: - // { - // A: 1, - // B: ["hello","bye bye"] - // } -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/equal_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/equal_test.go deleted file mode 100644 index 7a5db6e49bc..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/equal_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package awsutil_test - -import ( - "testing" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awsutil" - "github.com/stretchr/testify/assert" -) - -func TestDeepEqual(t *testing.T) { - cases := []struct { - a, b interface{} - equal bool - }{ - {"a", "a", true}, - {"a", "b", false}, - {"a", aws.String(""), false}, - {"a", nil, false}, - {"a", aws.String("a"), true}, - {(*bool)(nil), (*bool)(nil), true}, - {(*bool)(nil), (*string)(nil), false}, - {nil, nil, true}, - } - - for i, c := range cases { - assert.Equal(t, c.equal, awsutil.DeepEqual(c.a, c.b), "%d, a:%v b:%v, %t", i, c.a, c.b, c.equal) - } -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/path_value_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/path_value_test.go deleted file mode 100644 index b2225566fa3..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/path_value_test.go +++ /dev/null @@ -1,142 +0,0 @@ -package awsutil_test - -import ( - "testing" - - "github.com/aws/aws-sdk-go/aws/awsutil" - "github.com/stretchr/testify/assert" -) - -type Struct struct { - A []Struct - z []Struct - B *Struct - D *Struct - C string - E map[string]string -} - -var data = Struct{ - A: []Struct{{C: "value1"}, {C: "value2"}, {C: "value3"}}, - z: []Struct{{C: "value1"}, {C: "value2"}, {C: "value3"}}, - B: &Struct{B: &Struct{C: "terminal"}, D: &Struct{C: "terminal2"}}, - C: "initial", -} -var data2 = Struct{A: []Struct{ - {A: []Struct{{C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}}}, - {A: []Struct{{C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}}}, -}} - -func TestValueAtPathSuccess(t *testing.T) { - var testCases = []struct { - expect []interface{} - data interface{} - path string - }{ - {[]interface{}{"initial"}, data, "C"}, - {[]interface{}{"value1"}, data, "A[0].C"}, - {[]interface{}{"value2"}, data, "A[1].C"}, - {[]interface{}{"value3"}, data, "A[2].C"}, - {[]interface{}{"value3"}, data, "a[2].c"}, - {[]interface{}{"value3"}, data, "A[-1].C"}, - {[]interface{}{"value1", "value2", "value3"}, data, "A[].C"}, - {[]interface{}{"terminal"}, data, "B . B . C"}, - {[]interface{}{"initial"}, data, "A.D.X || C"}, - {[]interface{}{"initial"}, data, "A[0].B || C"}, - {[]interface{}{ - Struct{A: []Struct{{C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}}}, - Struct{A: []Struct{{C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}}}, - }, data2, "A"}, - } - for i, c := range testCases { - v, err := awsutil.ValuesAtPath(c.data, c.path) - assert.NoError(t, err, "case %d, expected no error, %s", i, c.path) - assert.Equal(t, c.expect, v, "case %d, %s", i, c.path) - } -} - -func TestValueAtPathFailure(t *testing.T) { - var testCases = []struct { - expect []interface{} - errContains string - data interface{} - path string - }{ - {nil, "", data, "C.x"}, - {nil, "SyntaxError: Invalid token: tDot", data, ".x"}, - {nil, "", data, "X.Y.Z"}, - {nil, "", data, "A[100].C"}, - {nil, "", data, "A[3].C"}, - {nil, "", data, "B.B.C.Z"}, - {nil, "", data, "z[-1].C"}, - {nil, "", nil, "A.B.C"}, - {[]interface{}{}, "", Struct{}, "A"}, - {nil, "", data, "A[0].B.C"}, - {nil, "", data, "D"}, - } - - for i, c := range testCases { - v, err := awsutil.ValuesAtPath(c.data, c.path) - if c.errContains != "" { - assert.Contains(t, err.Error(), c.errContains, "case %d, expected error, %s", i, c.path) - continue - } else { - assert.NoError(t, err, "case %d, expected no error, %s", i, c.path) - } - assert.Equal(t, c.expect, v, "case %d, %s", i, c.path) - } -} - -func TestSetValueAtPathSuccess(t *testing.T) { - var s Struct - awsutil.SetValueAtPath(&s, "C", "test1") - awsutil.SetValueAtPath(&s, "B.B.C", "test2") - awsutil.SetValueAtPath(&s, "B.D.C", "test3") - assert.Equal(t, "test1", s.C) - assert.Equal(t, "test2", s.B.B.C) - assert.Equal(t, "test3", s.B.D.C) - - awsutil.SetValueAtPath(&s, "B.*.C", "test0") - assert.Equal(t, "test0", s.B.B.C) - assert.Equal(t, "test0", s.B.D.C) - - var s2 Struct - awsutil.SetValueAtPath(&s2, "b.b.c", "test0") - assert.Equal(t, "test0", s2.B.B.C) - awsutil.SetValueAtPath(&s2, "A", []Struct{{}}) - assert.Equal(t, []Struct{{}}, s2.A) - - str := "foo" - - s3 := Struct{} - awsutil.SetValueAtPath(&s3, "b.b.c", str) - assert.Equal(t, "foo", s3.B.B.C) - - s3 = Struct{B: &Struct{B: &Struct{C: str}}} - awsutil.SetValueAtPath(&s3, "b.b.c", nil) - assert.Equal(t, "", s3.B.B.C) - - s3 = Struct{} - awsutil.SetValueAtPath(&s3, "b.b.c", nil) - assert.Equal(t, "", s3.B.B.C) - - s3 = Struct{} - awsutil.SetValueAtPath(&s3, "b.b.c", &str) - assert.Equal(t, "foo", s3.B.B.C) - - var s4 struct{ Name *string } - awsutil.SetValueAtPath(&s4, "Name", str) - assert.Equal(t, str, *s4.Name) - - s4 = struct{ Name *string }{} - awsutil.SetValueAtPath(&s4, "Name", nil) - assert.Equal(t, (*string)(nil), s4.Name) - - s4 = struct{ Name *string }{Name: &str} - awsutil.SetValueAtPath(&s4, "Name", nil) - assert.Equal(t, (*string)(nil), s4.Name) - - s4 = struct{ Name *string }{} - awsutil.SetValueAtPath(&s4, "Name", &str) - assert.Equal(t, str, *s4.Name) -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/client/default_retryer.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/client/default_retryer.go deleted file mode 100644 index 24d39ce5641..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/client/default_retryer.go +++ /dev/null @@ -1,45 +0,0 @@ -package client - -import ( - "math" - "math/rand" - "time" - - "github.com/aws/aws-sdk-go/aws/request" -) - -// DefaultRetryer implements basic retry logic using exponential backoff for -// most services. If you want to implement custom retry logic, implement the -// request.Retryer interface or create a structure type that composes this -// struct and override the specific methods. For example, to override only -// the MaxRetries method: -// -// type retryer struct { -// service.DefaultRetryer -// } -// -// // This implementation always has 100 max retries -// func (d retryer) MaxRetries() uint { return 100 } -type DefaultRetryer struct { - NumMaxRetries int -} - -// MaxRetries returns the number of maximum returns the service will use to make -// an individual API request. -func (d DefaultRetryer) MaxRetries() int { - return d.NumMaxRetries -} - -// RetryRules returns the delay duration before retrying this request again -func (d DefaultRetryer) RetryRules(r *request.Request) time.Duration { - delay := int(math.Pow(2, float64(r.RetryCount))) * (rand.Intn(30) + 30) - return time.Duration(delay) * time.Millisecond -} - -// ShouldRetry returns if the request should be retried. -func (d DefaultRetryer) ShouldRetry(r *request.Request) bool { - if r.HTTPResponse.StatusCode >= 500 { - return true - } - return r.IsErrorRetryable() -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/config_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/config_test.go deleted file mode 100644 index fe97a31fc76..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/config_test.go +++ /dev/null @@ -1,86 +0,0 @@ -package aws - -import ( - "net/http" - "reflect" - "testing" - - "github.com/aws/aws-sdk-go/aws/credentials" -) - -var testCredentials = credentials.NewStaticCredentials("AKID", "SECRET", "SESSION") - -var copyTestConfig = Config{ - Credentials: testCredentials, - Endpoint: String("CopyTestEndpoint"), - Region: String("COPY_TEST_AWS_REGION"), - DisableSSL: Bool(true), - HTTPClient: http.DefaultClient, - LogLevel: LogLevel(LogDebug), - Logger: NewDefaultLogger(), - MaxRetries: Int(3), - DisableParamValidation: Bool(true), - DisableComputeChecksums: Bool(true), - S3ForcePathStyle: Bool(true), -} - -func TestCopy(t *testing.T) { - want := copyTestConfig - got := copyTestConfig.Copy() - if !reflect.DeepEqual(*got, want) { - t.Errorf("Copy() = %+v", got) - t.Errorf(" want %+v", want) - } - - got.Region = String("other") - if got.Region == want.Region { - t.Errorf("Expect setting copy values not not reflect in source") - } -} - -func TestCopyReturnsNewInstance(t *testing.T) { - want := copyTestConfig - got := copyTestConfig.Copy() - if got == &want { - t.Errorf("Copy() = %p; want different instance as source %p", got, &want) - } -} - -var mergeTestZeroValueConfig = Config{} - -var mergeTestConfig = Config{ - Credentials: testCredentials, - Endpoint: String("MergeTestEndpoint"), - Region: String("MERGE_TEST_AWS_REGION"), - DisableSSL: Bool(true), - HTTPClient: http.DefaultClient, - LogLevel: LogLevel(LogDebug), - Logger: NewDefaultLogger(), - MaxRetries: Int(10), - DisableParamValidation: Bool(true), - DisableComputeChecksums: Bool(true), - S3ForcePathStyle: Bool(true), -} - -var mergeTests = []struct { - cfg *Config - in *Config - want *Config -}{ - {&Config{}, nil, &Config{}}, - {&Config{}, &mergeTestZeroValueConfig, &Config{}}, - {&Config{}, &mergeTestConfig, &mergeTestConfig}, -} - -func TestMerge(t *testing.T) { - for i, tt := range mergeTests { - got := tt.cfg.Copy() - got.MergeIn(tt.in) - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("Config %d %+v", i, tt.cfg) - t.Errorf(" Merge(%+v)", tt.in) - t.Errorf(" got %+v", got) - t.Errorf(" want %+v", tt.want) - } - } -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/convert_types_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/convert_types_test.go deleted file mode 100644 index df7a3e5d2de..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/convert_types_test.go +++ /dev/null @@ -1,437 +0,0 @@ -package aws - -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -var testCasesStringSlice = [][]string{ - {"a", "b", "c", "d", "e"}, - {"a", "b", "", "", "e"}, -} - -func TestStringSlice(t *testing.T) { - for idx, in := range testCasesStringSlice { - if in == nil { - continue - } - out := StringSlice(in) - assert.Len(t, out, len(in), "Unexpected len at idx %d", idx) - for i := range out { - assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx) - } - - out2 := StringValueSlice(out) - assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx) - assert.Equal(t, in, out2, "Unexpected value at idx %d", idx) - } -} - -var testCasesStringValueSlice = [][]*string{ - {String("a"), String("b"), nil, String("c")}, -} - -func TestStringValueSlice(t *testing.T) { - for idx, in := range testCasesStringValueSlice { - if in == nil { - continue - } - out := StringValueSlice(in) - assert.Len(t, out, len(in), "Unexpected len at idx %d", idx) - for i := range out { - if in[i] == nil { - assert.Empty(t, out[i], "Unexpected value at idx %d", idx) - } else { - assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx) - } - } - - out2 := StringSlice(out) - assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx) - for i := range out2 { - if in[i] == nil { - assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx) - } else { - assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx) - } - } - } -} - -var testCasesStringMap = []map[string]string{ - {"a": "1", "b": "2", "c": "3"}, -} - -func TestStringMap(t *testing.T) { - for idx, in := range testCasesStringMap { - if in == nil { - continue - } - out := StringMap(in) - assert.Len(t, out, len(in), "Unexpected len at idx %d", idx) - for i := range out { - assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx) - } - - out2 := StringValueMap(out) - assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx) - assert.Equal(t, in, out2, "Unexpected value at idx %d", idx) - } -} - -var testCasesBoolSlice = [][]bool{ - {true, true, false, false}, -} - -func TestBoolSlice(t *testing.T) { - for idx, in := range testCasesBoolSlice { - if in == nil { - continue - } - out := BoolSlice(in) - assert.Len(t, out, len(in), "Unexpected len at idx %d", idx) - for i := range out { - assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx) - } - - out2 := BoolValueSlice(out) - assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx) - assert.Equal(t, in, out2, "Unexpected value at idx %d", idx) - } -} - -var testCasesBoolValueSlice = [][]*bool{} - -func TestBoolValueSlice(t *testing.T) { - for idx, in := range testCasesBoolValueSlice { - if in == nil { - continue - } - out := BoolValueSlice(in) - assert.Len(t, out, len(in), "Unexpected len at idx %d", idx) - for i := range out { - if in[i] == nil { - assert.Empty(t, out[i], "Unexpected value at idx %d", idx) - } else { - assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx) - } - } - - out2 := BoolSlice(out) - assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx) - for i := range out2 { - if in[i] == nil { - assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx) - } else { - assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx) - } - } - } -} - -var testCasesBoolMap = []map[string]bool{ - {"a": true, "b": false, "c": true}, -} - -func TestBoolMap(t *testing.T) { - for idx, in := range testCasesBoolMap { - if in == nil { - continue - } - out := BoolMap(in) - assert.Len(t, out, len(in), "Unexpected len at idx %d", idx) - for i := range out { - assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx) - } - - out2 := BoolValueMap(out) - assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx) - assert.Equal(t, in, out2, "Unexpected value at idx %d", idx) - } -} - -var testCasesIntSlice = [][]int{ - {1, 2, 3, 4}, -} - -func TestIntSlice(t *testing.T) { - for idx, in := range testCasesIntSlice { - if in == nil { - continue - } - out := IntSlice(in) - assert.Len(t, out, len(in), "Unexpected len at idx %d", idx) - for i := range out { - assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx) - } - - out2 := IntValueSlice(out) - assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx) - assert.Equal(t, in, out2, "Unexpected value at idx %d", idx) - } -} - -var testCasesIntValueSlice = [][]*int{} - -func TestIntValueSlice(t *testing.T) { - for idx, in := range testCasesIntValueSlice { - if in == nil { - continue - } - out := IntValueSlice(in) - assert.Len(t, out, len(in), "Unexpected len at idx %d", idx) - for i := range out { - if in[i] == nil { - assert.Empty(t, out[i], "Unexpected value at idx %d", idx) - } else { - assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx) - } - } - - out2 := IntSlice(out) - assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx) - for i := range out2 { - if in[i] == nil { - assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx) - } else { - assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx) - } - } - } -} - -var testCasesIntMap = []map[string]int{ - {"a": 3, "b": 2, "c": 1}, -} - -func TestIntMap(t *testing.T) { - for idx, in := range testCasesIntMap { - if in == nil { - continue - } - out := IntMap(in) - assert.Len(t, out, len(in), "Unexpected len at idx %d", idx) - for i := range out { - assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx) - } - - out2 := IntValueMap(out) - assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx) - assert.Equal(t, in, out2, "Unexpected value at idx %d", idx) - } -} - -var testCasesInt64Slice = [][]int64{ - {1, 2, 3, 4}, -} - -func TestInt64Slice(t *testing.T) { - for idx, in := range testCasesInt64Slice { - if in == nil { - continue - } - out := Int64Slice(in) - assert.Len(t, out, len(in), "Unexpected len at idx %d", idx) - for i := range out { - assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx) - } - - out2 := Int64ValueSlice(out) - assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx) - assert.Equal(t, in, out2, "Unexpected value at idx %d", idx) - } -} - -var testCasesInt64ValueSlice = [][]*int64{} - -func TestInt64ValueSlice(t *testing.T) { - for idx, in := range testCasesInt64ValueSlice { - if in == nil { - continue - } - out := Int64ValueSlice(in) - assert.Len(t, out, len(in), "Unexpected len at idx %d", idx) - for i := range out { - if in[i] == nil { - assert.Empty(t, out[i], "Unexpected value at idx %d", idx) - } else { - assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx) - } - } - - out2 := Int64Slice(out) - assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx) - for i := range out2 { - if in[i] == nil { - assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx) - } else { - assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx) - } - } - } -} - -var testCasesInt64Map = []map[string]int64{ - {"a": 3, "b": 2, "c": 1}, -} - -func TestInt64Map(t *testing.T) { - for idx, in := range testCasesInt64Map { - if in == nil { - continue - } - out := Int64Map(in) - assert.Len(t, out, len(in), "Unexpected len at idx %d", idx) - for i := range out { - assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx) - } - - out2 := Int64ValueMap(out) - assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx) - assert.Equal(t, in, out2, "Unexpected value at idx %d", idx) - } -} - -var testCasesFloat64Slice = [][]float64{ - {1, 2, 3, 4}, -} - -func TestFloat64Slice(t *testing.T) { - for idx, in := range testCasesFloat64Slice { - if in == nil { - continue - } - out := Float64Slice(in) - assert.Len(t, out, len(in), "Unexpected len at idx %d", idx) - for i := range out { - assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx) - } - - out2 := Float64ValueSlice(out) - assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx) - assert.Equal(t, in, out2, "Unexpected value at idx %d", idx) - } -} - -var testCasesFloat64ValueSlice = [][]*float64{} - -func TestFloat64ValueSlice(t *testing.T) { - for idx, in := range testCasesFloat64ValueSlice { - if in == nil { - continue - } - out := Float64ValueSlice(in) - assert.Len(t, out, len(in), "Unexpected len at idx %d", idx) - for i := range out { - if in[i] == nil { - assert.Empty(t, out[i], "Unexpected value at idx %d", idx) - } else { - assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx) - } - } - - out2 := Float64Slice(out) - assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx) - for i := range out2 { - if in[i] == nil { - assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx) - } else { - assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx) - } - } - } -} - -var testCasesFloat64Map = []map[string]float64{ - {"a": 3, "b": 2, "c": 1}, -} - -func TestFloat64Map(t *testing.T) { - for idx, in := range testCasesFloat64Map { - if in == nil { - continue - } - out := Float64Map(in) - assert.Len(t, out, len(in), "Unexpected len at idx %d", idx) - for i := range out { - assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx) - } - - out2 := Float64ValueMap(out) - assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx) - assert.Equal(t, in, out2, "Unexpected value at idx %d", idx) - } -} - -var testCasesTimeSlice = [][]time.Time{ - {time.Now(), time.Now().AddDate(100, 0, 0)}, -} - -func TestTimeSlice(t *testing.T) { - for idx, in := range testCasesTimeSlice { - if in == nil { - continue - } - out := TimeSlice(in) - assert.Len(t, out, len(in), "Unexpected len at idx %d", idx) - for i := range out { - assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx) - } - - out2 := TimeValueSlice(out) - assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx) - assert.Equal(t, in, out2, "Unexpected value at idx %d", idx) - } -} - -var testCasesTimeValueSlice = [][]*time.Time{} - -func TestTimeValueSlice(t *testing.T) { - for idx, in := range testCasesTimeValueSlice { - if in == nil { - continue - } - out := TimeValueSlice(in) - assert.Len(t, out, len(in), "Unexpected len at idx %d", idx) - for i := range out { - if in[i] == nil { - assert.Empty(t, out[i], "Unexpected value at idx %d", idx) - } else { - assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx) - } - } - - out2 := TimeSlice(out) - assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx) - for i := range out2 { - if in[i] == nil { - assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx) - } else { - assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx) - } - } - } -} - -var testCasesTimeMap = []map[string]time.Time{ - {"a": time.Now().AddDate(-100, 0, 0), "b": time.Now()}, -} - -func TestTimeMap(t *testing.T) { - for idx, in := range testCasesTimeMap { - if in == nil { - continue - } - out := TimeMap(in) - assert.Len(t, out, len(in), "Unexpected len at idx %d", idx) - for i := range out { - assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx) - } - - out2 := TimeValueMap(out) - assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx) - assert.Equal(t, in, out2, "Unexpected value at idx %d", idx) - } -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/handlers_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/handlers_test.go deleted file mode 100644 index 632ea8d4ea1..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/handlers_test.go +++ /dev/null @@ -1,113 +0,0 @@ -package corehandlers_test - -import ( - "fmt" - "net/http" - "os" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/aws/corehandlers" - "github.com/aws/aws-sdk-go/aws/credentials" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/awstesting" -) - -func TestValidateEndpointHandler(t *testing.T) { - os.Clearenv() - - svc := awstesting.NewClient(aws.NewConfig().WithRegion("us-west-2")) - svc.Handlers.Clear() - svc.Handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler) - - req := svc.NewRequest(&request.Operation{Name: "Operation"}, nil, nil) - err := req.Build() - - assert.NoError(t, err) -} - -func TestValidateEndpointHandlerErrorRegion(t *testing.T) { - os.Clearenv() - - svc := awstesting.NewClient() - svc.Handlers.Clear() - svc.Handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler) - - req := svc.NewRequest(&request.Operation{Name: "Operation"}, nil, nil) - err := req.Build() - - assert.Error(t, err) - assert.Equal(t, aws.ErrMissingRegion, err) -} - -type mockCredsProvider struct { - expired bool - retrieveCalled bool -} - -func (m *mockCredsProvider) Retrieve() (credentials.Value, error) { - m.retrieveCalled = true - return credentials.Value{}, nil -} - -func (m *mockCredsProvider) IsExpired() bool { - return m.expired -} - -func TestAfterRetryRefreshCreds(t *testing.T) { - os.Clearenv() - credProvider := &mockCredsProvider{} - - svc := awstesting.NewClient(&aws.Config{ - Credentials: credentials.NewCredentials(credProvider), - MaxRetries: aws.Int(1), - }) - - svc.Handlers.Clear() - svc.Handlers.ValidateResponse.PushBack(func(r *request.Request) { - r.Error = awserr.New("UnknownError", "", nil) - r.HTTPResponse = &http.Response{StatusCode: 400} - }) - svc.Handlers.UnmarshalError.PushBack(func(r *request.Request) { - r.Error = awserr.New("ExpiredTokenException", "", nil) - }) - svc.Handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler) - - assert.True(t, svc.Config.Credentials.IsExpired(), "Expect to start out expired") - assert.False(t, credProvider.retrieveCalled) - - req := svc.NewRequest(&request.Operation{Name: "Operation"}, nil, nil) - req.Send() - - assert.True(t, svc.Config.Credentials.IsExpired()) - assert.False(t, credProvider.retrieveCalled) - - _, err := svc.Config.Credentials.Get() - assert.NoError(t, err) - assert.True(t, credProvider.retrieveCalled) -} - -type testSendHandlerTransport struct{} - -func (t *testSendHandlerTransport) RoundTrip(r *http.Request) (*http.Response, error) { - return nil, fmt.Errorf("mock error") -} - -func TestSendHandlerError(t *testing.T) { - svc := awstesting.NewClient(&aws.Config{ - HTTPClient: &http.Client{ - Transport: &testSendHandlerTransport{}, - }, - }) - svc.Handlers.Clear() - svc.Handlers.Send.PushBackNamed(corehandlers.SendHandler) - r := svc.NewRequest(&request.Operation{Name: "Operation"}, nil, nil) - - r.Send() - - assert.Error(t, r.Error) - assert.NotNil(t, r.HTTPResponse) -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go deleted file mode 100644 index 3b53f5e026a..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go +++ /dev/null @@ -1,144 +0,0 @@ -package corehandlers - -import ( - "fmt" - "reflect" - "strconv" - "strings" - - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/aws/request" -) - -// ValidateParametersHandler is a request handler to validate the input parameters. -// Validating parameters only has meaning if done prior to the request being sent. -var ValidateParametersHandler = request.NamedHandler{Name: "core.ValidateParametersHandler", Fn: func(r *request.Request) { - if r.ParamsFilled() { - v := validator{errors: []string{}} - v.validateAny(reflect.ValueOf(r.Params), "") - - if count := len(v.errors); count > 0 { - format := "%d validation errors:\n- %s" - msg := fmt.Sprintf(format, count, strings.Join(v.errors, "\n- ")) - r.Error = awserr.New("InvalidParameter", msg, nil) - } - } -}} - -// A validator validates values. Collects validations errors which occurs. -type validator struct { - errors []string -} - -// validateAny will validate any struct, slice or map type. All validations -// are also performed recursively for nested types. -func (v *validator) validateAny(value reflect.Value, path string) { - value = reflect.Indirect(value) - if !value.IsValid() { - return - } - - switch value.Kind() { - case reflect.Struct: - v.validateStruct(value, path) - case reflect.Slice: - for i := 0; i < value.Len(); i++ { - v.validateAny(value.Index(i), path+fmt.Sprintf("[%d]", i)) - } - case reflect.Map: - for _, n := range value.MapKeys() { - v.validateAny(value.MapIndex(n), path+fmt.Sprintf("[%q]", n.String())) - } - } -} - -// validateStruct will validate the struct value's fields. If the structure has -// nested types those types will be validated also. -func (v *validator) validateStruct(value reflect.Value, path string) { - prefix := "." - if path == "" { - prefix = "" - } - - for i := 0; i < value.Type().NumField(); i++ { - f := value.Type().Field(i) - if strings.ToLower(f.Name[0:1]) == f.Name[0:1] { - continue - } - fvalue := value.FieldByName(f.Name) - - err := validateField(f, fvalue, validateFieldRequired, validateFieldMin) - if err != nil { - v.errors = append(v.errors, fmt.Sprintf("%s: %s", err.Error(), path+prefix+f.Name)) - continue - } - - v.validateAny(fvalue, path+prefix+f.Name) - } -} - -type validatorFunc func(f reflect.StructField, fvalue reflect.Value) error - -func validateField(f reflect.StructField, fvalue reflect.Value, funcs ...validatorFunc) error { - for _, fn := range funcs { - if err := fn(f, fvalue); err != nil { - return err - } - } - return nil -} - -// Validates that a field has a valid value provided for required fields. -func validateFieldRequired(f reflect.StructField, fvalue reflect.Value) error { - if f.Tag.Get("required") == "" { - return nil - } - - switch fvalue.Kind() { - case reflect.Ptr, reflect.Slice, reflect.Map: - if fvalue.IsNil() { - return fmt.Errorf("missing required parameter") - } - default: - if !fvalue.IsValid() { - return fmt.Errorf("missing required parameter") - } - } - return nil -} - -// Validates that if a value is provided for a field, that value must be at -// least a minimum length. -func validateFieldMin(f reflect.StructField, fvalue reflect.Value) error { - minStr := f.Tag.Get("min") - if minStr == "" { - return nil - } - min, _ := strconv.ParseInt(minStr, 10, 64) - - kind := fvalue.Kind() - if kind == reflect.Ptr { - if fvalue.IsNil() { - return nil - } - fvalue = fvalue.Elem() - } - - switch fvalue.Kind() { - case reflect.String: - if int64(fvalue.Len()) < min { - return fmt.Errorf("field too short, minimum length %d", min) - } - case reflect.Slice, reflect.Map: - if fvalue.IsNil() { - return nil - } - if int64(fvalue.Len()) < min { - return fmt.Errorf("field too short, minimum length %d", min) - } - - // TODO min can also apply to number minimum value. - - } - return nil -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator_test.go deleted file mode 100644 index 96bfc0e6720..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator_test.go +++ /dev/null @@ -1,134 +0,0 @@ -package corehandlers_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/aws/client" - "github.com/aws/aws-sdk-go/aws/client/metadata" - "github.com/aws/aws-sdk-go/aws/corehandlers" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/stretchr/testify/require" -) - -var testSvc = func() *client.Client { - s := &client.Client{ - Config: aws.Config{}, - ClientInfo: metadata.ClientInfo{ - ServiceName: "mock-service", - APIVersion: "2015-01-01", - }, - } - return s -}() - -type StructShape struct { - RequiredList []*ConditionalStructShape `required:"true"` - RequiredMap map[string]*ConditionalStructShape `required:"true"` - RequiredBool *bool `required:"true"` - OptionalStruct *ConditionalStructShape - - hiddenParameter *string - - metadataStructureShape -} - -type metadataStructureShape struct { - SDKShapeTraits bool -} - -type ConditionalStructShape struct { - Name *string `required:"true"` - SDKShapeTraits bool -} - -func TestNoErrors(t *testing.T) { - input := &StructShape{ - RequiredList: []*ConditionalStructShape{}, - RequiredMap: map[string]*ConditionalStructShape{ - "key1": {Name: aws.String("Name")}, - "key2": {Name: aws.String("Name")}, - }, - RequiredBool: aws.Bool(true), - OptionalStruct: &ConditionalStructShape{Name: aws.String("Name")}, - } - - req := testSvc.NewRequest(&request.Operation{}, input, nil) - corehandlers.ValidateParametersHandler.Fn(req) - require.NoError(t, req.Error) -} - -func TestMissingRequiredParameters(t *testing.T) { - input := &StructShape{} - req := testSvc.NewRequest(&request.Operation{}, input, nil) - corehandlers.ValidateParametersHandler.Fn(req) - - require.Error(t, req.Error) - assert.Equal(t, "InvalidParameter", req.Error.(awserr.Error).Code()) - assert.Equal(t, "3 validation errors:\n- missing required parameter: RequiredList\n- missing required parameter: RequiredMap\n- missing required parameter: RequiredBool", req.Error.(awserr.Error).Message()) -} - -func TestNestedMissingRequiredParameters(t *testing.T) { - input := &StructShape{ - RequiredList: []*ConditionalStructShape{{}}, - RequiredMap: map[string]*ConditionalStructShape{ - "key1": {Name: aws.String("Name")}, - "key2": {}, - }, - RequiredBool: aws.Bool(true), - OptionalStruct: &ConditionalStructShape{}, - } - - req := testSvc.NewRequest(&request.Operation{}, input, nil) - corehandlers.ValidateParametersHandler.Fn(req) - - require.Error(t, req.Error) - assert.Equal(t, "InvalidParameter", req.Error.(awserr.Error).Code()) - assert.Equal(t, "3 validation errors:\n- missing required parameter: RequiredList[0].Name\n- missing required parameter: RequiredMap[\"key2\"].Name\n- missing required parameter: OptionalStruct.Name", req.Error.(awserr.Error).Message()) -} - -type testInput struct { - StringField string `min:"5"` - PtrStrField *string `min:"2"` - ListField []string `min:"3"` - MapField map[string]string `min:"4"` -} - -var testsFieldMin = []struct { - err awserr.Error - in testInput -}{ - { - err: awserr.New("InvalidParameter", "1 validation errors:\n- field too short, minimum length 5: StringField", nil), - in: testInput{StringField: "abcd"}, - }, - { - err: awserr.New("InvalidParameter", "2 validation errors:\n- field too short, minimum length 5: StringField\n- field too short, minimum length 3: ListField", nil), - in: testInput{StringField: "abcd", ListField: []string{"a", "b"}}, - }, - { - err: awserr.New("InvalidParameter", "3 validation errors:\n- field too short, minimum length 5: StringField\n- field too short, minimum length 3: ListField\n- field too short, minimum length 4: MapField", nil), - in: testInput{StringField: "abcd", ListField: []string{"a", "b"}, MapField: map[string]string{"a": "a", "b": "b"}}, - }, - { - err: awserr.New("InvalidParameter", "1 validation errors:\n- field too short, minimum length 2: PtrStrField", nil), - in: testInput{StringField: "abcde", PtrStrField: aws.String("v")}, - }, - { - err: nil, - in: testInput{StringField: "abcde", PtrStrField: aws.String("value"), - ListField: []string{"a", "b", "c"}, MapField: map[string]string{"a": "a", "b": "b", "c": "c", "d": "d"}}, - }, -} - -func TestValidateFieldMinParameter(t *testing.T) { - for i, c := range testsFieldMin { - req := testSvc.NewRequest(&request.Operation{}, &c.in, nil) - corehandlers.ValidateParametersHandler.Fn(req) - - require.Equal(t, c.err, req.Error, "%d case failed", i) - } -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/chain_provider_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/chain_provider_test.go deleted file mode 100644 index 4fba22f29f4..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/chain_provider_test.go +++ /dev/null @@ -1,73 +0,0 @@ -package credentials - -import ( - "testing" - - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/stretchr/testify/assert" -) - -func TestChainProviderGet(t *testing.T) { - p := &ChainProvider{ - Providers: []Provider{ - &stubProvider{err: awserr.New("FirstError", "first provider error", nil)}, - &stubProvider{err: awserr.New("SecondError", "second provider error", nil)}, - &stubProvider{ - creds: Value{ - AccessKeyID: "AKID", - SecretAccessKey: "SECRET", - SessionToken: "", - }, - }, - }, - } - - creds, err := p.Retrieve() - assert.Nil(t, err, "Expect no error") - assert.Equal(t, "AKID", creds.AccessKeyID, "Expect access key ID to match") - assert.Equal(t, "SECRET", creds.SecretAccessKey, "Expect secret access key to match") - assert.Empty(t, creds.SessionToken, "Expect session token to be empty") -} - -func TestChainProviderIsExpired(t *testing.T) { - stubProvider := &stubProvider{expired: true} - p := &ChainProvider{ - Providers: []Provider{ - stubProvider, - }, - } - - assert.True(t, p.IsExpired(), "Expect expired to be true before any Retrieve") - _, err := p.Retrieve() - assert.Nil(t, err, "Expect no error") - assert.False(t, p.IsExpired(), "Expect not expired after retrieve") - - stubProvider.expired = true - assert.True(t, p.IsExpired(), "Expect return of expired provider") - - _, err = p.Retrieve() - assert.False(t, p.IsExpired(), "Expect not expired after retrieve") -} - -func TestChainProviderWithNoProvider(t *testing.T) { - p := &ChainProvider{ - Providers: []Provider{}, - } - - assert.True(t, p.IsExpired(), "Expect expired with no providers") - _, err := p.Retrieve() - assert.Equal(t, ErrNoValidProvidersFoundInChain, err, "Expect no providers error returned") -} - -func TestChainProviderWithNoValidProvider(t *testing.T) { - p := &ChainProvider{ - Providers: []Provider{ - &stubProvider{err: awserr.New("FirstError", "first provider error", nil)}, - &stubProvider{err: awserr.New("SecondError", "second provider error", nil)}, - }, - } - - assert.True(t, p.IsExpired(), "Expect expired with no providers") - _, err := p.Retrieve() - assert.Equal(t, ErrNoValidProvidersFoundInChain, err, "Expect no providers error returned") -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/credentials_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/credentials_test.go deleted file mode 100644 index 99c2b47742e..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/credentials_test.go +++ /dev/null @@ -1,62 +0,0 @@ -package credentials - -import ( - "testing" - - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/stretchr/testify/assert" -) - -type stubProvider struct { - creds Value - expired bool - err error -} - -func (s *stubProvider) Retrieve() (Value, error) { - s.expired = false - return s.creds, s.err -} -func (s *stubProvider) IsExpired() bool { - return s.expired -} - -func TestCredentialsGet(t *testing.T) { - c := NewCredentials(&stubProvider{ - creds: Value{ - AccessKeyID: "AKID", - SecretAccessKey: "SECRET", - SessionToken: "", - }, - expired: true, - }) - - creds, err := c.Get() - assert.Nil(t, err, "Expected no error") - assert.Equal(t, "AKID", creds.AccessKeyID, "Expect access key ID to match") - assert.Equal(t, "SECRET", creds.SecretAccessKey, "Expect secret access key to match") - assert.Empty(t, creds.SessionToken, "Expect session token to be empty") -} - -func TestCredentialsGetWithError(t *testing.T) { - c := NewCredentials(&stubProvider{err: awserr.New("provider error", "", nil), expired: true}) - - _, err := c.Get() - assert.Equal(t, "provider error", err.(awserr.Error).Code(), "Expected provider error") -} - -func TestCredentialsExpire(t *testing.T) { - stub := &stubProvider{} - c := NewCredentials(stub) - - stub.expired = false - assert.True(t, c.IsExpired(), "Expected to start out expired") - c.Expire() - assert.True(t, c.IsExpired(), "Expected to be expired") - - c.forceRefresh = false - assert.False(t, c.IsExpired(), "Expected not to be expired") - - stub.expired = true - assert.True(t, c.IsExpired(), "Expected to be expired") -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider_test.go deleted file mode 100644 index da3d8ed3ec1..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider_test.go +++ /dev/null @@ -1,159 +0,0 @@ -package ec2rolecreds_test - -import ( - "fmt" - "net/http" - "net/http/httptest" - "testing" - "time" - - "github.com/stretchr/testify/assert" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds" - "github.com/aws/aws-sdk-go/aws/ec2metadata" - "github.com/aws/aws-sdk-go/aws/session" -) - -const credsRespTmpl = `{ - "Code": "Success", - "Type": "AWS-HMAC", - "AccessKeyId" : "accessKey", - "SecretAccessKey" : "secret", - "Token" : "token", - "Expiration" : "%s", - "LastUpdated" : "2009-11-23T0:00:00Z" -}` - -const credsFailRespTmpl = `{ - "Code": "ErrorCode", - "Message": "ErrorMsg", - "LastUpdated": "2009-11-23T0:00:00Z" -}` - -func initTestServer(expireOn string, failAssume bool) *httptest.Server { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.URL.Path == "/latest/meta-data/iam/security-credentials" { - fmt.Fprintln(w, "RoleName") - } else if r.URL.Path == "/latest/meta-data/iam/security-credentials/RoleName" { - if failAssume { - fmt.Fprintf(w, credsFailRespTmpl) - } else { - fmt.Fprintf(w, credsRespTmpl, expireOn) - } - } else { - http.Error(w, "bad request", http.StatusBadRequest) - } - })) - - return server -} - -func TestEC2RoleProvider(t *testing.T) { - server := initTestServer("2014-12-16T01:51:37Z", false) - defer server.Close() - - p := &ec2rolecreds.EC2RoleProvider{ - Client: ec2metadata.New(session.New(), &aws.Config{Endpoint: aws.String(server.URL + "/latest")}), - } - - creds, err := p.Retrieve() - assert.Nil(t, err, "Expect no error, %v", err) - - assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match") - assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match") - assert.Equal(t, "token", creds.SessionToken, "Expect session token to match") -} - -func TestEC2RoleProviderFailAssume(t *testing.T) { - server := initTestServer("2014-12-16T01:51:37Z", true) - defer server.Close() - - p := &ec2rolecreds.EC2RoleProvider{ - Client: ec2metadata.New(session.New(), &aws.Config{Endpoint: aws.String(server.URL + "/latest")}), - } - - creds, err := p.Retrieve() - assert.Error(t, err, "Expect error") - - e := err.(awserr.Error) - assert.Equal(t, "ErrorCode", e.Code()) - assert.Equal(t, "ErrorMsg", e.Message()) - assert.Nil(t, e.OrigErr()) - - assert.Equal(t, "", creds.AccessKeyID, "Expect access key ID to match") - assert.Equal(t, "", creds.SecretAccessKey, "Expect secret access key to match") - assert.Equal(t, "", creds.SessionToken, "Expect session token to match") -} - -func TestEC2RoleProviderIsExpired(t *testing.T) { - server := initTestServer("2014-12-16T01:51:37Z", false) - defer server.Close() - - p := &ec2rolecreds.EC2RoleProvider{ - Client: ec2metadata.New(session.New(), &aws.Config{Endpoint: aws.String(server.URL + "/latest")}), - } - p.CurrentTime = func() time.Time { - return time.Date(2014, 12, 15, 21, 26, 0, 0, time.UTC) - } - - assert.True(t, p.IsExpired(), "Expect creds to be expired before retrieve.") - - _, err := p.Retrieve() - assert.Nil(t, err, "Expect no error, %v", err) - - assert.False(t, p.IsExpired(), "Expect creds to not be expired after retrieve.") - - p.CurrentTime = func() time.Time { - return time.Date(3014, 12, 15, 21, 26, 0, 0, time.UTC) - } - - assert.True(t, p.IsExpired(), "Expect creds to be expired.") -} - -func TestEC2RoleProviderExpiryWindowIsExpired(t *testing.T) { - server := initTestServer("2014-12-16T01:51:37Z", false) - defer server.Close() - - p := &ec2rolecreds.EC2RoleProvider{ - Client: ec2metadata.New(session.New(), &aws.Config{Endpoint: aws.String(server.URL + "/latest")}), - ExpiryWindow: time.Hour * 1, - } - p.CurrentTime = func() time.Time { - return time.Date(2014, 12, 15, 0, 51, 37, 0, time.UTC) - } - - assert.True(t, p.IsExpired(), "Expect creds to be expired before retrieve.") - - _, err := p.Retrieve() - assert.Nil(t, err, "Expect no error, %v", err) - - assert.False(t, p.IsExpired(), "Expect creds to not be expired after retrieve.") - - p.CurrentTime = func() time.Time { - return time.Date(2014, 12, 16, 0, 55, 37, 0, time.UTC) - } - - assert.True(t, p.IsExpired(), "Expect creds to be expired.") -} - -func BenchmarkEC3RoleProvider(b *testing.B) { - server := initTestServer("2014-12-16T01:51:37Z", false) - defer server.Close() - - p := &ec2rolecreds.EC2RoleProvider{ - Client: ec2metadata.New(session.New(), &aws.Config{Endpoint: aws.String(server.URL + "/latest")}), - } - _, err := p.Retrieve() - if err != nil { - b.Fatal(err) - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - if _, err := p.Retrieve(); err != nil { - b.Fatal(err) - } - } -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/env_provider_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/env_provider_test.go deleted file mode 100644 index 53f6ce256eb..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/env_provider_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package credentials - -import ( - "github.com/stretchr/testify/assert" - "os" - "testing" -) - -func TestEnvProviderRetrieve(t *testing.T) { - os.Clearenv() - os.Setenv("AWS_ACCESS_KEY_ID", "access") - os.Setenv("AWS_SECRET_ACCESS_KEY", "secret") - os.Setenv("AWS_SESSION_TOKEN", "token") - - e := EnvProvider{} - creds, err := e.Retrieve() - assert.Nil(t, err, "Expect no error") - - assert.Equal(t, "access", creds.AccessKeyID, "Expect access key ID to match") - assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match") - assert.Equal(t, "token", creds.SessionToken, "Expect session token to match") -} - -func TestEnvProviderIsExpired(t *testing.T) { - os.Clearenv() - os.Setenv("AWS_ACCESS_KEY_ID", "access") - os.Setenv("AWS_SECRET_ACCESS_KEY", "secret") - os.Setenv("AWS_SESSION_TOKEN", "token") - - e := EnvProvider{} - - assert.True(t, e.IsExpired(), "Expect creds to be expired before retrieve.") - - _, err := e.Retrieve() - assert.Nil(t, err, "Expect no error") - - assert.False(t, e.IsExpired(), "Expect creds to not be expired after retrieve.") -} - -func TestEnvProviderNoAccessKeyID(t *testing.T) { - os.Clearenv() - os.Setenv("AWS_SECRET_ACCESS_KEY", "secret") - - e := EnvProvider{} - creds, err := e.Retrieve() - assert.Equal(t, ErrAccessKeyIDNotFound, err, "ErrAccessKeyIDNotFound expected, but was %#v error: %#v", creds, err) -} - -func TestEnvProviderNoSecretAccessKey(t *testing.T) { - os.Clearenv() - os.Setenv("AWS_ACCESS_KEY_ID", "access") - - e := EnvProvider{} - creds, err := e.Retrieve() - assert.Equal(t, ErrSecretAccessKeyNotFound, err, "ErrSecretAccessKeyNotFound expected, but was %#v error: %#v", creds, err) -} - -func TestEnvProviderAlternateNames(t *testing.T) { - os.Clearenv() - os.Setenv("AWS_ACCESS_KEY", "access") - os.Setenv("AWS_SECRET_KEY", "secret") - - e := EnvProvider{} - creds, err := e.Retrieve() - assert.Nil(t, err, "Expect no error") - - assert.Equal(t, "access", creds.AccessKeyID, "Expected access key ID") - assert.Equal(t, "secret", creds.SecretAccessKey, "Expected secret access key") - assert.Empty(t, creds.SessionToken, "Expected no token") -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider_test.go deleted file mode 100644 index 2e26da2634b..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider_test.go +++ /dev/null @@ -1,100 +0,0 @@ -package credentials - -import ( - "github.com/stretchr/testify/assert" - "os" - "testing" -) - -func TestSharedCredentialsProvider(t *testing.T) { - os.Clearenv() - - p := SharedCredentialsProvider{Filename: "example.ini", Profile: ""} - creds, err := p.Retrieve() - assert.Nil(t, err, "Expect no error") - - assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match") - assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match") - assert.Equal(t, "token", creds.SessionToken, "Expect session token to match") -} - -func TestSharedCredentialsProviderIsExpired(t *testing.T) { - os.Clearenv() - - p := SharedCredentialsProvider{Filename: "example.ini", Profile: ""} - - assert.True(t, p.IsExpired(), "Expect creds to be expired before retrieve") - - _, err := p.Retrieve() - assert.Nil(t, err, "Expect no error") - - assert.False(t, p.IsExpired(), "Expect creds to not be expired after retrieve") -} - -func TestSharedCredentialsProviderWithAWS_SHARED_CREDENTIALS_FILE(t *testing.T) { - os.Clearenv() - os.Setenv("AWS_SHARED_CREDENTIALS_FILE", "example.ini") - p := SharedCredentialsProvider{} - creds, err := p.Retrieve() - - assert.Nil(t, err, "Expect no error") - - assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match") - assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match") - assert.Equal(t, "token", creds.SessionToken, "Expect session token to match") -} - -func TestSharedCredentialsProviderWithAWS_PROFILE(t *testing.T) { - os.Clearenv() - os.Setenv("AWS_PROFILE", "no_token") - - p := SharedCredentialsProvider{Filename: "example.ini", Profile: ""} - creds, err := p.Retrieve() - assert.Nil(t, err, "Expect no error") - - assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match") - assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match") - assert.Empty(t, creds.SessionToken, "Expect no token") -} - -func TestSharedCredentialsProviderWithoutTokenFromProfile(t *testing.T) { - os.Clearenv() - - p := SharedCredentialsProvider{Filename: "example.ini", Profile: "no_token"} - creds, err := p.Retrieve() - assert.Nil(t, err, "Expect no error") - - assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match") - assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match") - assert.Empty(t, creds.SessionToken, "Expect no token") -} - -func TestSharedCredentialsProviderColonInCredFile(t *testing.T) { - os.Clearenv() - - p := SharedCredentialsProvider{Filename: "example.ini", Profile: "with_colon"} - creds, err := p.Retrieve() - assert.Nil(t, err, "Expect no error") - - assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match") - assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match") - assert.Empty(t, creds.SessionToken, "Expect no token") -} - -func BenchmarkSharedCredentialsProvider(b *testing.B) { - os.Clearenv() - - p := SharedCredentialsProvider{Filename: "example.ini", Profile: ""} - _, err := p.Retrieve() - if err != nil { - b.Fatal(err) - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, err := p.Retrieve() - if err != nil { - b.Fatal(err) - } - } -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/static_provider_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/static_provider_test.go deleted file mode 100644 index ea012369624..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/static_provider_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package credentials - -import ( - "github.com/stretchr/testify/assert" - "testing" -) - -func TestStaticProviderGet(t *testing.T) { - s := StaticProvider{ - Value: Value{ - AccessKeyID: "AKID", - SecretAccessKey: "SECRET", - SessionToken: "", - }, - } - - creds, err := s.Retrieve() - assert.Nil(t, err, "Expect no error") - assert.Equal(t, "AKID", creds.AccessKeyID, "Expect access key ID to match") - assert.Equal(t, "SECRET", creds.SecretAccessKey, "Expect secret access key to match") - assert.Empty(t, creds.SessionToken, "Expect no session token") -} - -func TestStaticProviderIsExpired(t *testing.T) { - s := StaticProvider{ - Value: Value{ - AccessKeyID: "AKID", - SecretAccessKey: "SECRET", - SessionToken: "", - }, - } - - assert.False(t, s.IsExpired(), "Expect static credentials to never expire") -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider_test.go deleted file mode 100644 index 6bd6e91973e..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider_test.go +++ /dev/null @@ -1,56 +0,0 @@ -package stscreds - -import ( - "testing" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/sts" - "github.com/stretchr/testify/assert" -) - -type stubSTS struct { -} - -func (s *stubSTS) AssumeRole(input *sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error) { - expiry := time.Now().Add(60 * time.Minute) - return &sts.AssumeRoleOutput{ - Credentials: &sts.Credentials{ - // Just reflect the role arn to the provider. - AccessKeyId: input.RoleArn, - SecretAccessKey: aws.String("assumedSecretAccessKey"), - SessionToken: aws.String("assumedSessionToken"), - Expiration: &expiry, - }, - }, nil -} - -func TestAssumeRoleProvider(t *testing.T) { - stub := &stubSTS{} - p := &AssumeRoleProvider{ - Client: stub, - RoleARN: "roleARN", - } - - creds, err := p.Retrieve() - assert.Nil(t, err, "Expect no error") - - assert.Equal(t, "roleARN", creds.AccessKeyID, "Expect access key ID to be reflected role ARN") - assert.Equal(t, "assumedSecretAccessKey", creds.SecretAccessKey, "Expect secret access key to match") - assert.Equal(t, "assumedSessionToken", creds.SessionToken, "Expect session token to match") -} - -func BenchmarkAssumeRoleProvider(b *testing.B) { - stub := &stubSTS{} - p := &AssumeRoleProvider{ - Client: stub, - RoleARN: "roleARN", - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - if _, err := p.Retrieve(); err != nil { - b.Fatal(err) - } - } -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/defaults/defaults.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/defaults/defaults.go deleted file mode 100644 index b746783beca..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/defaults/defaults.go +++ /dev/null @@ -1,76 +0,0 @@ -// Package defaults is a collection of helpers to retrieve the SDK's default -// configuration and handlers. -package defaults - -import ( - "net/http" - "os" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/corehandlers" - "github.com/aws/aws-sdk-go/aws/credentials" - "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds" - "github.com/aws/aws-sdk-go/aws/ec2metadata" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/private/endpoints" -) - -// A Defaults provides a collection of default values for SDK clients. -type Defaults struct { - Config *aws.Config - Handlers request.Handlers -} - -// Get returns the SDK's default values with Config and handlers pre-configured. -func Get() Defaults { - cfg := Config() - handlers := Handlers() - cfg.Credentials = CredChain(cfg, handlers) - - return Defaults{ - Config: cfg, - Handlers: handlers, - } -} - -// Config returns the default configuration. -func Config() *aws.Config { - return aws.NewConfig(). - WithCredentials(credentials.AnonymousCredentials). - WithRegion(os.Getenv("AWS_REGION")). - WithHTTPClient(http.DefaultClient). - WithMaxRetries(aws.UseServiceDefaultRetries). - WithLogger(aws.NewDefaultLogger()). - WithLogLevel(aws.LogOff). - WithSleepDelay(time.Sleep) -} - -// Handlers returns the default request handlers. -func Handlers() request.Handlers { - var handlers request.Handlers - - handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler) - handlers.Build.PushBackNamed(corehandlers.SDKVersionUserAgentHandler) - handlers.Sign.PushBackNamed(corehandlers.BuildContentLengthHandler) - handlers.Send.PushBackNamed(corehandlers.SendHandler) - handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler) - handlers.ValidateResponse.PushBackNamed(corehandlers.ValidateResponseHandler) - - return handlers -} - -// CredChain returns the default credential chain. -func CredChain(cfg *aws.Config, handlers request.Handlers) *credentials.Credentials { - endpoint, signingRegion := endpoints.EndpointForRegion(ec2metadata.ServiceName, *cfg.Region, true) - - return credentials.NewChainCredentials( - []credentials.Provider{ - &credentials.EnvProvider{}, - &credentials.SharedCredentialsProvider{Filename: "", Profile: ""}, - &ec2rolecreds.EC2RoleProvider{ - Client: ec2metadata.NewClient(*cfg, handlers, endpoint, signingRegion), - ExpiryWindow: 5 * time.Minute, - }, - }) -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go deleted file mode 100644 index e5137ca17da..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go +++ /dev/null @@ -1,43 +0,0 @@ -package ec2metadata - -import ( - "path" - - "github.com/aws/aws-sdk-go/aws/request" -) - -// GetMetadata uses the path provided to request -func (c *EC2Metadata) GetMetadata(p string) (string, error) { - op := &request.Operation{ - Name: "GetMetadata", - HTTPMethod: "GET", - HTTPPath: path.Join("/", "meta-data", p), - } - - output := &metadataOutput{} - req := c.NewRequest(op, nil, output) - - return output.Content, req.Send() -} - -// Region returns the region the instance is running in. -func (c *EC2Metadata) Region() (string, error) { - resp, err := c.GetMetadata("placement/availability-zone") - if err != nil { - return "", err - } - - // returns region without the suffix. Eg: us-west-2a becomes us-west-2 - return resp[:len(resp)-1], nil -} - -// Available returns if the application has access to the EC2 Metadata service. -// Can be used to determine if application is running within an EC2 Instance and -// the metadata service is available. -func (c *EC2Metadata) Available() bool { - if _, err := c.GetMetadata("instance-id"); err != nil { - return false - } - - return true -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/ec2metadata/api_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/ec2metadata/api_test.go deleted file mode 100644 index c3c92972b7c..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/ec2metadata/api_test.go +++ /dev/null @@ -1,101 +0,0 @@ -package ec2metadata_test - -import ( - "bytes" - "io/ioutil" - "net/http" - "net/http/httptest" - "path" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/aws/ec2metadata" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/aws/session" -) - -func initTestServer(path string, resp string) *httptest.Server { - return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.RequestURI != path { - http.Error(w, "not found", http.StatusNotFound) - return - } - - w.Write([]byte(resp)) - })) -} - -func TestEndpoint(t *testing.T) { - c := ec2metadata.New(session.New()) - op := &request.Operation{ - Name: "GetMetadata", - HTTPMethod: "GET", - HTTPPath: path.Join("/", "meta-data", "testpath"), - } - - req := c.NewRequest(op, nil, nil) - assert.Equal(t, "http://169.254.169.254/latest", req.ClientInfo.Endpoint) - assert.Equal(t, "http://169.254.169.254/latest/meta-data/testpath", req.HTTPRequest.URL.String()) -} - -func TestGetMetadata(t *testing.T) { - server := initTestServer( - "/latest/meta-data/some/path", - "success", // real response includes suffix - ) - defer server.Close() - c := ec2metadata.New(session.New(), &aws.Config{Endpoint: aws.String(server.URL + "/latest")}) - - resp, err := c.GetMetadata("some/path") - - assert.NoError(t, err) - assert.Equal(t, "success", resp) -} - -func TestGetRegion(t *testing.T) { - server := initTestServer( - "/latest/meta-data/placement/availability-zone", - "us-west-2a", // real response includes suffix - ) - defer server.Close() - c := ec2metadata.New(session.New(), &aws.Config{Endpoint: aws.String(server.URL + "/latest")}) - - region, err := c.Region() - - assert.NoError(t, err) - assert.Equal(t, "us-west-2", region) -} - -func TestMetadataAvailable(t *testing.T) { - server := initTestServer( - "/latest/meta-data/instance-id", - "instance-id", - ) - defer server.Close() - c := ec2metadata.New(session.New(), &aws.Config{Endpoint: aws.String(server.URL + "/latest")}) - - available := c.Available() - - assert.True(t, available) -} - -func TestMetadataNotAvailable(t *testing.T) { - c := ec2metadata.New(session.New()) - c.Handlers.Send.Clear() - c.Handlers.Send.PushBack(func(r *request.Request) { - r.HTTPResponse = &http.Response{ - StatusCode: int(0), - Status: http.StatusText(int(0)), - Body: ioutil.NopCloser(bytes.NewReader([]byte{})), - } - r.Error = awserr.New("RequestError", "send request failed", nil) - r.Retryable = aws.Bool(true) // network errors are retryable - }) - - available := c.Available() - - assert.False(t, available) -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/handlers_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/handlers_test.go deleted file mode 100644 index 16a1418283b..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/handlers_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package request_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/request" -) - -func TestHandlerList(t *testing.T) { - s := "" - r := &request.Request{} - l := request.HandlerList{} - l.PushBack(func(r *request.Request) { - s += "a" - r.Data = s - }) - l.Run(r) - assert.Equal(t, "a", s) - assert.Equal(t, "a", r.Data) -} - -func TestMultipleHandlers(t *testing.T) { - r := &request.Request{} - l := request.HandlerList{} - l.PushBack(func(r *request.Request) { r.Data = nil }) - l.PushFront(func(r *request.Request) { r.Data = aws.Bool(true) }) - l.Run(r) - if r.Data != nil { - t.Error("Expected handler to execute") - } -} - -func TestNamedHandlers(t *testing.T) { - l := request.HandlerList{} - named := request.NamedHandler{Name: "Name", Fn: func(r *request.Request) {}} - named2 := request.NamedHandler{Name: "NotName", Fn: func(r *request.Request) {}} - l.PushBackNamed(named) - l.PushBackNamed(named) - l.PushBackNamed(named2) - l.PushBack(func(r *request.Request) {}) - assert.Equal(t, 4, l.Len()) - l.Remove(named) - assert.Equal(t, 2, l.Len()) -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/request_pagination_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/request_pagination_test.go deleted file mode 100644 index 95a8d99fbe6..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/request_pagination_test.go +++ /dev/null @@ -1,455 +0,0 @@ -package request_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/awstesting/unit" - "github.com/aws/aws-sdk-go/service/dynamodb" - "github.com/aws/aws-sdk-go/service/route53" - "github.com/aws/aws-sdk-go/service/s3" -) - -// Use DynamoDB methods for simplicity -func TestPaginationQueryPage(t *testing.T) { - db := dynamodb.New(unit.Session) - tokens, pages, numPages, gotToEnd := []map[string]*dynamodb.AttributeValue{}, []map[string]*dynamodb.AttributeValue{}, 0, false - - reqNum := 0 - resps := []*dynamodb.QueryOutput{ - { - LastEvaluatedKey: map[string]*dynamodb.AttributeValue{"key": {S: aws.String("key1")}}, - Count: aws.Int64(1), - Items: []map[string]*dynamodb.AttributeValue{ - map[string]*dynamodb.AttributeValue{ - "key": {S: aws.String("key1")}, - }, - }, - }, - { - LastEvaluatedKey: map[string]*dynamodb.AttributeValue{"key": {S: aws.String("key2")}}, - Count: aws.Int64(1), - Items: []map[string]*dynamodb.AttributeValue{ - map[string]*dynamodb.AttributeValue{ - "key": {S: aws.String("key2")}, - }, - }, - }, - { - LastEvaluatedKey: map[string]*dynamodb.AttributeValue{}, - Count: aws.Int64(1), - Items: []map[string]*dynamodb.AttributeValue{ - map[string]*dynamodb.AttributeValue{ - "key": {S: aws.String("key3")}, - }, - }, - }, - } - - db.Handlers.Send.Clear() // mock sending - db.Handlers.Unmarshal.Clear() - db.Handlers.UnmarshalMeta.Clear() - db.Handlers.ValidateResponse.Clear() - db.Handlers.Build.PushBack(func(r *request.Request) { - in := r.Params.(*dynamodb.QueryInput) - if in == nil { - tokens = append(tokens, nil) - } else if len(in.ExclusiveStartKey) != 0 { - tokens = append(tokens, in.ExclusiveStartKey) - } - }) - db.Handlers.Unmarshal.PushBack(func(r *request.Request) { - r.Data = resps[reqNum] - reqNum++ - }) - - params := &dynamodb.QueryInput{ - Limit: aws.Int64(2), - TableName: aws.String("tablename"), - } - err := db.QueryPages(params, func(p *dynamodb.QueryOutput, last bool) bool { - numPages++ - for _, item := range p.Items { - pages = append(pages, item) - } - if last { - if gotToEnd { - assert.Fail(t, "last=true happened twice") - } - gotToEnd = true - } - return true - }) - assert.Nil(t, err) - - assert.Equal(t, - []map[string]*dynamodb.AttributeValue{ - map[string]*dynamodb.AttributeValue{"key": {S: aws.String("key1")}}, - map[string]*dynamodb.AttributeValue{"key": {S: aws.String("key2")}}, - }, tokens) - assert.Equal(t, - []map[string]*dynamodb.AttributeValue{ - map[string]*dynamodb.AttributeValue{"key": {S: aws.String("key1")}}, - map[string]*dynamodb.AttributeValue{"key": {S: aws.String("key2")}}, - map[string]*dynamodb.AttributeValue{"key": {S: aws.String("key3")}}, - }, pages) - assert.Equal(t, 3, numPages) - assert.True(t, gotToEnd) - assert.Nil(t, params.ExclusiveStartKey) -} - -// Use DynamoDB methods for simplicity -func TestPagination(t *testing.T) { - db := dynamodb.New(unit.Session) - tokens, pages, numPages, gotToEnd := []string{}, []string{}, 0, false - - reqNum := 0 - resps := []*dynamodb.ListTablesOutput{ - {TableNames: []*string{aws.String("Table1"), aws.String("Table2")}, LastEvaluatedTableName: aws.String("Table2")}, - {TableNames: []*string{aws.String("Table3"), aws.String("Table4")}, LastEvaluatedTableName: aws.String("Table4")}, - {TableNames: []*string{aws.String("Table5")}}, - } - - db.Handlers.Send.Clear() // mock sending - db.Handlers.Unmarshal.Clear() - db.Handlers.UnmarshalMeta.Clear() - db.Handlers.ValidateResponse.Clear() - db.Handlers.Build.PushBack(func(r *request.Request) { - in := r.Params.(*dynamodb.ListTablesInput) - if in == nil { - tokens = append(tokens, "") - } else if in.ExclusiveStartTableName != nil { - tokens = append(tokens, *in.ExclusiveStartTableName) - } - }) - db.Handlers.Unmarshal.PushBack(func(r *request.Request) { - r.Data = resps[reqNum] - reqNum++ - }) - - params := &dynamodb.ListTablesInput{Limit: aws.Int64(2)} - err := db.ListTablesPages(params, func(p *dynamodb.ListTablesOutput, last bool) bool { - numPages++ - for _, t := range p.TableNames { - pages = append(pages, *t) - } - if last { - if gotToEnd { - assert.Fail(t, "last=true happened twice") - } - gotToEnd = true - } - return true - }) - - assert.Equal(t, []string{"Table2", "Table4"}, tokens) - assert.Equal(t, []string{"Table1", "Table2", "Table3", "Table4", "Table5"}, pages) - assert.Equal(t, 3, numPages) - assert.True(t, gotToEnd) - assert.Nil(t, err) - assert.Nil(t, params.ExclusiveStartTableName) -} - -// Use DynamoDB methods for simplicity -func TestPaginationEachPage(t *testing.T) { - db := dynamodb.New(unit.Session) - tokens, pages, numPages, gotToEnd := []string{}, []string{}, 0, false - - reqNum := 0 - resps := []*dynamodb.ListTablesOutput{ - {TableNames: []*string{aws.String("Table1"), aws.String("Table2")}, LastEvaluatedTableName: aws.String("Table2")}, - {TableNames: []*string{aws.String("Table3"), aws.String("Table4")}, LastEvaluatedTableName: aws.String("Table4")}, - {TableNames: []*string{aws.String("Table5")}}, - } - - db.Handlers.Send.Clear() // mock sending - db.Handlers.Unmarshal.Clear() - db.Handlers.UnmarshalMeta.Clear() - db.Handlers.ValidateResponse.Clear() - db.Handlers.Build.PushBack(func(r *request.Request) { - in := r.Params.(*dynamodb.ListTablesInput) - if in == nil { - tokens = append(tokens, "") - } else if in.ExclusiveStartTableName != nil { - tokens = append(tokens, *in.ExclusiveStartTableName) - } - }) - db.Handlers.Unmarshal.PushBack(func(r *request.Request) { - r.Data = resps[reqNum] - reqNum++ - }) - - params := &dynamodb.ListTablesInput{Limit: aws.Int64(2)} - req, _ := db.ListTablesRequest(params) - err := req.EachPage(func(p interface{}, last bool) bool { - numPages++ - for _, t := range p.(*dynamodb.ListTablesOutput).TableNames { - pages = append(pages, *t) - } - if last { - if gotToEnd { - assert.Fail(t, "last=true happened twice") - } - gotToEnd = true - } - - return true - }) - - assert.Equal(t, []string{"Table2", "Table4"}, tokens) - assert.Equal(t, []string{"Table1", "Table2", "Table3", "Table4", "Table5"}, pages) - assert.Equal(t, 3, numPages) - assert.True(t, gotToEnd) - assert.Nil(t, err) -} - -// Use DynamoDB methods for simplicity -func TestPaginationEarlyExit(t *testing.T) { - db := dynamodb.New(unit.Session) - numPages, gotToEnd := 0, false - - reqNum := 0 - resps := []*dynamodb.ListTablesOutput{ - {TableNames: []*string{aws.String("Table1"), aws.String("Table2")}, LastEvaluatedTableName: aws.String("Table2")}, - {TableNames: []*string{aws.String("Table3"), aws.String("Table4")}, LastEvaluatedTableName: aws.String("Table4")}, - {TableNames: []*string{aws.String("Table5")}}, - } - - db.Handlers.Send.Clear() // mock sending - db.Handlers.Unmarshal.Clear() - db.Handlers.UnmarshalMeta.Clear() - db.Handlers.ValidateResponse.Clear() - db.Handlers.Unmarshal.PushBack(func(r *request.Request) { - r.Data = resps[reqNum] - reqNum++ - }) - - params := &dynamodb.ListTablesInput{Limit: aws.Int64(2)} - err := db.ListTablesPages(params, func(p *dynamodb.ListTablesOutput, last bool) bool { - numPages++ - if numPages == 2 { - return false - } - if last { - if gotToEnd { - assert.Fail(t, "last=true happened twice") - } - gotToEnd = true - } - return true - }) - - assert.Equal(t, 2, numPages) - assert.False(t, gotToEnd) - assert.Nil(t, err) -} - -func TestSkipPagination(t *testing.T) { - client := s3.New(unit.Session) - client.Handlers.Send.Clear() // mock sending - client.Handlers.Unmarshal.Clear() - client.Handlers.UnmarshalMeta.Clear() - client.Handlers.ValidateResponse.Clear() - client.Handlers.Unmarshal.PushBack(func(r *request.Request) { - r.Data = &s3.HeadBucketOutput{} - }) - - req, _ := client.HeadBucketRequest(&s3.HeadBucketInput{Bucket: aws.String("bucket")}) - - numPages, gotToEnd := 0, false - req.EachPage(func(p interface{}, last bool) bool { - numPages++ - if last { - gotToEnd = true - } - return true - }) - assert.Equal(t, 1, numPages) - assert.True(t, gotToEnd) -} - -// Use S3 for simplicity -func TestPaginationTruncation(t *testing.T) { - client := s3.New(unit.Session) - - reqNum := 0 - resps := []*s3.ListObjectsOutput{ - {IsTruncated: aws.Bool(true), Contents: []*s3.Object{{Key: aws.String("Key1")}}}, - {IsTruncated: aws.Bool(true), Contents: []*s3.Object{{Key: aws.String("Key2")}}}, - {IsTruncated: aws.Bool(false), Contents: []*s3.Object{{Key: aws.String("Key3")}}}, - {IsTruncated: aws.Bool(true), Contents: []*s3.Object{{Key: aws.String("Key4")}}}, - } - - client.Handlers.Send.Clear() // mock sending - client.Handlers.Unmarshal.Clear() - client.Handlers.UnmarshalMeta.Clear() - client.Handlers.ValidateResponse.Clear() - client.Handlers.Unmarshal.PushBack(func(r *request.Request) { - r.Data = resps[reqNum] - reqNum++ - }) - - params := &s3.ListObjectsInput{Bucket: aws.String("bucket")} - - results := []string{} - err := client.ListObjectsPages(params, func(p *s3.ListObjectsOutput, last bool) bool { - results = append(results, *p.Contents[0].Key) - return true - }) - - assert.Equal(t, []string{"Key1", "Key2", "Key3"}, results) - assert.Nil(t, err) - - // Try again without truncation token at all - reqNum = 0 - resps[1].IsTruncated = nil - resps[2].IsTruncated = aws.Bool(true) - results = []string{} - err = client.ListObjectsPages(params, func(p *s3.ListObjectsOutput, last bool) bool { - results = append(results, *p.Contents[0].Key) - return true - }) - - assert.Equal(t, []string{"Key1", "Key2"}, results) - assert.Nil(t, err) -} - -func TestPaginationNilToken(t *testing.T) { - client := route53.New(unit.Session) - - reqNum := 0 - resps := []*route53.ListResourceRecordSetsOutput{ - { - ResourceRecordSets: []*route53.ResourceRecordSet{ - {Name: aws.String("first.example.com.")}, - }, - IsTruncated: aws.Bool(true), - NextRecordName: aws.String("second.example.com."), - NextRecordType: aws.String("MX"), - NextRecordIdentifier: aws.String("second"), - MaxItems: aws.String("1"), - }, - { - ResourceRecordSets: []*route53.ResourceRecordSet{ - {Name: aws.String("second.example.com.")}, - }, - IsTruncated: aws.Bool(true), - NextRecordName: aws.String("third.example.com."), - NextRecordType: aws.String("MX"), - MaxItems: aws.String("1"), - }, - { - ResourceRecordSets: []*route53.ResourceRecordSet{ - {Name: aws.String("third.example.com.")}, - }, - IsTruncated: aws.Bool(false), - MaxItems: aws.String("1"), - }, - } - client.Handlers.Send.Clear() // mock sending - client.Handlers.Unmarshal.Clear() - client.Handlers.UnmarshalMeta.Clear() - client.Handlers.ValidateResponse.Clear() - - idents := []string{} - client.Handlers.Build.PushBack(func(r *request.Request) { - p := r.Params.(*route53.ListResourceRecordSetsInput) - idents = append(idents, aws.StringValue(p.StartRecordIdentifier)) - - }) - client.Handlers.Unmarshal.PushBack(func(r *request.Request) { - r.Data = resps[reqNum] - reqNum++ - }) - - params := &route53.ListResourceRecordSetsInput{ - HostedZoneId: aws.String("id-zone"), - } - - results := []string{} - err := client.ListResourceRecordSetsPages(params, func(p *route53.ListResourceRecordSetsOutput, last bool) bool { - results = append(results, *p.ResourceRecordSets[0].Name) - return true - }) - - assert.NoError(t, err) - assert.Equal(t, []string{"", "second", ""}, idents) - assert.Equal(t, []string{"first.example.com.", "second.example.com.", "third.example.com."}, results) -} - -// Benchmarks -var benchResps = []*dynamodb.ListTablesOutput{ - {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, - {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, - {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, - {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, - {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, - {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, - {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, - {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, - {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, - {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, - {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, - {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, - {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, - {TableNames: []*string{aws.String("TABLE")}}, -} - -var benchDb = func() *dynamodb.DynamoDB { - db := dynamodb.New(unit.Session) - db.Handlers.Send.Clear() // mock sending - db.Handlers.Unmarshal.Clear() - db.Handlers.UnmarshalMeta.Clear() - db.Handlers.ValidateResponse.Clear() - return db -} - -func BenchmarkCodegenIterator(b *testing.B) { - reqNum := 0 - db := benchDb() - db.Handlers.Unmarshal.PushBack(func(r *request.Request) { - r.Data = benchResps[reqNum] - reqNum++ - }) - - input := &dynamodb.ListTablesInput{Limit: aws.Int64(2)} - iter := func(fn func(*dynamodb.ListTablesOutput, bool) bool) error { - page, _ := db.ListTablesRequest(input) - for ; page != nil; page = page.NextPage() { - page.Send() - out := page.Data.(*dynamodb.ListTablesOutput) - if result := fn(out, !page.HasNextPage()); page.Error != nil || !result { - return page.Error - } - } - return nil - } - - for i := 0; i < b.N; i++ { - reqNum = 0 - iter(func(p *dynamodb.ListTablesOutput, last bool) bool { - return true - }) - } -} - -func BenchmarkEachPageIterator(b *testing.B) { - reqNum := 0 - db := benchDb() - db.Handlers.Unmarshal.PushBack(func(r *request.Request) { - r.Data = benchResps[reqNum] - reqNum++ - }) - - input := &dynamodb.ListTablesInput{Limit: aws.Int64(2)} - for i := 0; i < b.N; i++ { - reqNum = 0 - req, _ := db.ListTablesRequest(input) - req.EachPage(func(p interface{}, last bool) bool { - return true - }) - } -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/request_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/request_test.go deleted file mode 100644 index 4828dff7fda..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/request_test.go +++ /dev/null @@ -1,261 +0,0 @@ -package request_test - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "net/http" - "runtime" - "testing" - "time" - - "github.com/stretchr/testify/assert" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/aws/credentials" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/awstesting" -) - -type testData struct { - Data string -} - -func body(str string) io.ReadCloser { - return ioutil.NopCloser(bytes.NewReader([]byte(str))) -} - -func unmarshal(req *request.Request) { - defer req.HTTPResponse.Body.Close() - if req.Data != nil { - json.NewDecoder(req.HTTPResponse.Body).Decode(req.Data) - } - return -} - -func unmarshalError(req *request.Request) { - bodyBytes, err := ioutil.ReadAll(req.HTTPResponse.Body) - if err != nil { - req.Error = awserr.New("UnmarshaleError", req.HTTPResponse.Status, err) - return - } - if len(bodyBytes) == 0 { - req.Error = awserr.NewRequestFailure( - awserr.New("UnmarshaleError", req.HTTPResponse.Status, fmt.Errorf("empty body")), - req.HTTPResponse.StatusCode, - "", - ) - return - } - var jsonErr jsonErrorResponse - if err := json.Unmarshal(bodyBytes, &jsonErr); err != nil { - req.Error = awserr.New("UnmarshaleError", "JSON unmarshal", err) - return - } - req.Error = awserr.NewRequestFailure( - awserr.New(jsonErr.Code, jsonErr.Message, nil), - req.HTTPResponse.StatusCode, - "", - ) -} - -type jsonErrorResponse struct { - Code string `json:"__type"` - Message string `json:"message"` -} - -// test that retries occur for 5xx status codes -func TestRequestRecoverRetry5xx(t *testing.T) { - reqNum := 0 - reqs := []http.Response{ - {StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, - {StatusCode: 501, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, - {StatusCode: 200, Body: body(`{"data":"valid"}`)}, - } - - s := awstesting.NewClient(aws.NewConfig().WithMaxRetries(10)) - s.Handlers.Validate.Clear() - s.Handlers.Unmarshal.PushBack(unmarshal) - s.Handlers.UnmarshalError.PushBack(unmarshalError) - s.Handlers.Send.Clear() // mock sending - s.Handlers.Send.PushBack(func(r *request.Request) { - r.HTTPResponse = &reqs[reqNum] - reqNum++ - }) - out := &testData{} - r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, out) - err := r.Send() - assert.Nil(t, err) - assert.Equal(t, 2, int(r.RetryCount)) - assert.Equal(t, "valid", out.Data) -} - -// test that retries occur for 4xx status codes with a response type that can be retried - see `shouldRetry` -func TestRequestRecoverRetry4xxRetryable(t *testing.T) { - reqNum := 0 - reqs := []http.Response{ - {StatusCode: 400, Body: body(`{"__type":"Throttling","message":"Rate exceeded."}`)}, - {StatusCode: 429, Body: body(`{"__type":"ProvisionedThroughputExceededException","message":"Rate exceeded."}`)}, - {StatusCode: 200, Body: body(`{"data":"valid"}`)}, - } - - s := awstesting.NewClient(aws.NewConfig().WithMaxRetries(10)) - s.Handlers.Validate.Clear() - s.Handlers.Unmarshal.PushBack(unmarshal) - s.Handlers.UnmarshalError.PushBack(unmarshalError) - s.Handlers.Send.Clear() // mock sending - s.Handlers.Send.PushBack(func(r *request.Request) { - r.HTTPResponse = &reqs[reqNum] - reqNum++ - }) - out := &testData{} - r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, out) - err := r.Send() - assert.Nil(t, err) - assert.Equal(t, 2, int(r.RetryCount)) - assert.Equal(t, "valid", out.Data) -} - -// test that retries don't occur for 4xx status codes with a response type that can't be retried -func TestRequest4xxUnretryable(t *testing.T) { - s := awstesting.NewClient(aws.NewConfig().WithMaxRetries(10)) - s.Handlers.Validate.Clear() - s.Handlers.Unmarshal.PushBack(unmarshal) - s.Handlers.UnmarshalError.PushBack(unmarshalError) - s.Handlers.Send.Clear() // mock sending - s.Handlers.Send.PushBack(func(r *request.Request) { - r.HTTPResponse = &http.Response{StatusCode: 401, Body: body(`{"__type":"SignatureDoesNotMatch","message":"Signature does not match."}`)} - }) - out := &testData{} - r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, out) - err := r.Send() - assert.NotNil(t, err) - if e, ok := err.(awserr.RequestFailure); ok { - assert.Equal(t, 401, e.StatusCode()) - } else { - assert.Fail(t, "Expected error to be a service failure") - } - assert.Equal(t, "SignatureDoesNotMatch", err.(awserr.Error).Code()) - assert.Equal(t, "Signature does not match.", err.(awserr.Error).Message()) - assert.Equal(t, 0, int(r.RetryCount)) -} - -func TestRequestExhaustRetries(t *testing.T) { - delays := []time.Duration{} - sleepDelay := func(delay time.Duration) { - delays = append(delays, delay) - } - - reqNum := 0 - reqs := []http.Response{ - {StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, - {StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, - {StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, - {StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, - } - - s := awstesting.NewClient(aws.NewConfig().WithSleepDelay(sleepDelay)) - s.Handlers.Validate.Clear() - s.Handlers.Unmarshal.PushBack(unmarshal) - s.Handlers.UnmarshalError.PushBack(unmarshalError) - s.Handlers.Send.Clear() // mock sending - s.Handlers.Send.PushBack(func(r *request.Request) { - r.HTTPResponse = &reqs[reqNum] - reqNum++ - }) - r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, nil) - err := r.Send() - assert.NotNil(t, err) - if e, ok := err.(awserr.RequestFailure); ok { - assert.Equal(t, 500, e.StatusCode()) - } else { - assert.Fail(t, "Expected error to be a service failure") - } - assert.Equal(t, "UnknownError", err.(awserr.Error).Code()) - assert.Equal(t, "An error occurred.", err.(awserr.Error).Message()) - assert.Equal(t, 3, int(r.RetryCount)) - - expectDelays := []struct{ min, max time.Duration }{{30, 59}, {60, 118}, {120, 236}} - for i, v := range delays { - min := expectDelays[i].min * time.Millisecond - max := expectDelays[i].max * time.Millisecond - assert.True(t, min <= v && v <= max, - "Expect delay to be within range, i:%d, v:%s, min:%s, max:%s", i, v, min, max) - } -} - -// test that the request is retried after the credentials are expired. -func TestRequestRecoverExpiredCreds(t *testing.T) { - reqNum := 0 - reqs := []http.Response{ - {StatusCode: 400, Body: body(`{"__type":"ExpiredTokenException","message":"expired token"}`)}, - {StatusCode: 200, Body: body(`{"data":"valid"}`)}, - } - - s := awstesting.NewClient(&aws.Config{MaxRetries: aws.Int(10), Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "")}) - s.Handlers.Validate.Clear() - s.Handlers.Unmarshal.PushBack(unmarshal) - s.Handlers.UnmarshalError.PushBack(unmarshalError) - - credExpiredBeforeRetry := false - credExpiredAfterRetry := false - - s.Handlers.AfterRetry.PushBack(func(r *request.Request) { - credExpiredAfterRetry = r.Config.Credentials.IsExpired() - }) - - s.Handlers.Sign.Clear() - s.Handlers.Sign.PushBack(func(r *request.Request) { - r.Config.Credentials.Get() - }) - s.Handlers.Send.Clear() // mock sending - s.Handlers.Send.PushBack(func(r *request.Request) { - r.HTTPResponse = &reqs[reqNum] - reqNum++ - }) - out := &testData{} - r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, out) - err := r.Send() - assert.Nil(t, err) - - assert.False(t, credExpiredBeforeRetry, "Expect valid creds before retry check") - assert.True(t, credExpiredAfterRetry, "Expect expired creds after retry check") - assert.False(t, s.Config.Credentials.IsExpired(), "Expect valid creds after cred expired recovery") - - assert.Equal(t, 1, int(r.RetryCount)) - assert.Equal(t, "valid", out.Data) -} - -func TestMakeAddtoUserAgentHandler(t *testing.T) { - fn := request.MakeAddToUserAgentHandler("name", "version", "extra1", "extra2") - r := &request.Request{HTTPRequest: &http.Request{Header: http.Header{}}} - r.HTTPRequest.Header.Set("User-Agent", "foo/bar") - fn(r) - - assert.Equal(t, "foo/bar name/version (extra1; extra2)", r.HTTPRequest.Header.Get("User-Agent")) -} - -func TestMakeAddtoUserAgentFreeFormHandler(t *testing.T) { - fn := request.MakeAddToUserAgentFreeFormHandler("name/version (extra1; extra2)") - r := &request.Request{HTTPRequest: &http.Request{Header: http.Header{}}} - r.HTTPRequest.Header.Set("User-Agent", "foo/bar") - fn(r) - - assert.Equal(t, "foo/bar name/version (extra1; extra2)", r.HTTPRequest.Header.Get("User-Agent")) -} - -func TestRequestUserAgent(t *testing.T) { - s := awstesting.NewClient(&aws.Config{Region: aws.String("us-east-1")}) - // s.Handlers.Validate.Clear() - - req := s.NewRequest(&request.Operation{Name: "Operation"}, nil, &testData{}) - req.HTTPRequest.Header.Set("User-Agent", "foo/bar") - assert.NoError(t, req.Build()) - - expectUA := fmt.Sprintf("foo/bar %s/%s (%s; %s; %s)", - aws.SDKName, aws.SDKVersion, runtime.Version(), runtime.GOOS, runtime.GOARCH) - assert.Equal(t, expectUA, req.HTTPRequest.Header.Get("User-Agent")) -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/session/session.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/session/session.go deleted file mode 100644 index eb7fc2052f1..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/session/session.go +++ /dev/null @@ -1,105 +0,0 @@ -// Package session provides a way to create service clients with shared configuration -// and handlers. -package session - -import ( - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/client" - "github.com/aws/aws-sdk-go/aws/corehandlers" - "github.com/aws/aws-sdk-go/aws/defaults" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/private/endpoints" -) - -// A Session provides a central location to create service clients from and -// store configurations and request handlers for those services. -// -// Sessions are safe to create service clients concurrently, but it is not safe -// to mutate the session concurrently. -type Session struct { - Config *aws.Config - Handlers request.Handlers -} - -// New creates a new instance of the handlers merging in the provided Configs -// on top of the SDK's default configurations. Once the session is created it -// can be mutated to modify Configs or Handlers. The session is safe to be read -// concurrently, but it should not be written to concurrently. -// -// Example: -// // Create a session with the default config and request handlers. -// sess := session.New() -// -// // Create a session with a custom region -// sess := session.New(&aws.Config{Region: aws.String("us-east-1")}) -// -// // Create a session, and add additional handlers for all service -// // clients created with the session to inherit. Adds logging handler. -// sess := session.New() -// sess.Handlers.Send.PushFront(func(r *request.Request) { -// // Log every request made and its payload -// logger.Println("Request: %s/%s, Payload: %s", r.ClientInfo.ServiceName, r.Operation, r.Params) -// }) -// -// // Create a S3 client instance from a session -// sess := session.New() -// svc := s3.New(sess) -func New(cfgs ...*aws.Config) *Session { - def := defaults.Get() - s := &Session{ - Config: def.Config, - Handlers: def.Handlers, - } - s.Config.MergeIn(cfgs...) - - initHandlers(s) - - return s -} - -func initHandlers(s *Session) { - // Add the Validate parameter handler if it is not disabled. - s.Handlers.Validate.Remove(corehandlers.ValidateParametersHandler) - if !aws.BoolValue(s.Config.DisableParamValidation) { - s.Handlers.Validate.PushBackNamed(corehandlers.ValidateParametersHandler) - } -} - -// Copy creates and returns a copy of the current session, coping the config -// and handlers. If any additional configs are provided they will be merged -// on top of the session's copied config. -// -// Example: -// // Create a copy of the current session, configured for the us-west-2 region. -// sess.Copy(&aws.Config{Region: aws.String("us-west-2"}) -func (s *Session) Copy(cfgs ...*aws.Config) *Session { - newSession := &Session{ - Config: s.Config.Copy(cfgs...), - Handlers: s.Handlers.Copy(), - } - - initHandlers(newSession) - - return newSession -} - -// ClientConfig satisfies the client.ConfigProvider interface and is used to -// configure the service client instances. Passing the Session to the service -// client's constructor (New) will use this method to configure the client. -// -// Example: -// sess := session.New() -// s3.New(sess) -func (s *Session) ClientConfig(serviceName string, cfgs ...*aws.Config) client.Config { - s = s.Copy(cfgs...) - endpoint, signingRegion := endpoints.NormalizeEndpoint( - aws.StringValue(s.Config.Endpoint), serviceName, - aws.StringValue(s.Config.Region), aws.BoolValue(s.Config.DisableSSL)) - - return client.Config{ - Config: s.Config, - Handlers: s.Handlers, - Endpoint: endpoint, - SigningRegion: signingRegion, - } -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/session/session_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/session/session_test.go deleted file mode 100644 index e56c02fc661..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/session/session_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package session_test - -import ( - "net/http" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" -) - -func TestNewDefaultSession(t *testing.T) { - s := session.New(&aws.Config{Region: aws.String("region")}) - - assert.Equal(t, "region", *s.Config.Region) - assert.Equal(t, http.DefaultClient, s.Config.HTTPClient) - assert.NotNil(t, s.Config.Logger) - assert.Equal(t, aws.LogOff, *s.Config.LogLevel) -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/types_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/types_test.go deleted file mode 100644 index a4ed20e7d22..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/types_test.go +++ /dev/null @@ -1,56 +0,0 @@ -package aws - -import ( - "math/rand" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestWriteAtBuffer(t *testing.T) { - b := &WriteAtBuffer{} - - n, err := b.WriteAt([]byte{1}, 0) - assert.NoError(t, err) - assert.Equal(t, 1, n) - - n, err = b.WriteAt([]byte{1, 1, 1}, 5) - assert.NoError(t, err) - assert.Equal(t, 3, n) - - n, err = b.WriteAt([]byte{2}, 1) - assert.NoError(t, err) - assert.Equal(t, 1, n) - - n, err = b.WriteAt([]byte{3}, 2) - assert.NoError(t, err) - assert.Equal(t, 1, n) - - assert.Equal(t, []byte{1, 2, 3, 0, 0, 1, 1, 1}, b.Bytes()) -} - -func BenchmarkWriteAtBuffer(b *testing.B) { - buf := &WriteAtBuffer{} - r := rand.New(rand.NewSource(1)) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - to := r.Intn(10) * 4096 - bs := make([]byte, to) - buf.WriteAt(bs, r.Int63n(10)*4096) - } -} - -func BenchmarkWriteAtBufferParallel(b *testing.B) { - buf := &WriteAtBuffer{} - r := rand.New(rand.NewSource(1)) - - b.ResetTimer() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - to := r.Intn(10) * 4096 - bs := make([]byte, to) - buf.WriteAt(bs, r.Int63n(10)*4096) - } - }) -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/endpoints/endpoints.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/endpoints/endpoints.go deleted file mode 100644 index d040cccd57d..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/endpoints/endpoints.go +++ /dev/null @@ -1,31 +0,0 @@ -// Package endpoints validates regional endpoints for services. -package endpoints - -//go:generate go run ../model/cli/gen-endpoints/main.go endpoints.json endpoints_map.go -//go:generate gofmt -s -w endpoints_map.go - -import "strings" - -// EndpointForRegion returns an endpoint and its signing region for a service and region. -// if the service and region pair are not found endpoint and signingRegion will be empty. -func EndpointForRegion(svcName, region string) (endpoint, signingRegion string) { - derivedKeys := []string{ - region + "/" + svcName, - region + "/*", - "*/" + svcName, - "*/*", - } - - for _, key := range derivedKeys { - if val, ok := endpointsMap.Endpoints[key]; ok { - ep := val.Endpoint - ep = strings.Replace(ep, "{region}", region, -1) - ep = strings.Replace(ep, "{service}", svcName, -1) - - endpoint = ep - signingRegion = val.SigningRegion - return - } - } - return -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/endpoints/endpoints.json b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/endpoints/endpoints.json deleted file mode 100644 index 4c588090a9c..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/endpoints/endpoints.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "version": 2, - "endpoints": { - "*/*": { - "endpoint": "{service}.{region}.amazonaws.com" - }, - "cn-north-1/*": { - "endpoint": "{service}.{region}.amazonaws.com.cn", - "signatureVersion": "v4" - }, - "us-gov-west-1/iam": { - "endpoint": "iam.us-gov.amazonaws.com" - }, - "us-gov-west-1/sts": { - "endpoint": "sts.us-gov-west-1.amazonaws.com" - }, - "us-gov-west-1/s3": { - "endpoint": "s3-{region}.amazonaws.com" - }, - "*/cloudfront": { - "endpoint": "cloudfront.amazonaws.com", - "signingRegion": "us-east-1" - }, - "*/cloudsearchdomain": { - "endpoint": "", - "signingRegion": "us-east-1" - }, - "*/iam": { - "endpoint": "iam.amazonaws.com", - "signingRegion": "us-east-1" - }, - "*/importexport": { - "endpoint": "importexport.amazonaws.com", - "signingRegion": "us-east-1" - }, - "*/route53": { - "endpoint": "route53.amazonaws.com", - "signingRegion": "us-east-1" - }, - "*/sts": { - "endpoint": "sts.amazonaws.com", - "signingRegion": "us-east-1" - }, - "us-east-1/sdb": { - "endpoint": "sdb.amazonaws.com", - "signingRegion": "us-east-1" - }, - "us-east-1/s3": { - "endpoint": "s3.amazonaws.com" - }, - "us-west-1/s3": { - "endpoint": "s3-{region}.amazonaws.com" - }, - "us-west-2/s3": { - "endpoint": "s3-{region}.amazonaws.com" - }, - "eu-west-1/s3": { - "endpoint": "s3-{region}.amazonaws.com" - }, - "ap-southeast-1/s3": { - "endpoint": "s3-{region}.amazonaws.com" - }, - "ap-southeast-2/s3": { - "endpoint": "s3-{region}.amazonaws.com" - }, - "ap-northeast-1/s3": { - "endpoint": "s3-{region}.amazonaws.com" - }, - "sa-east-1/s3": { - "endpoint": "s3-{region}.amazonaws.com" - }, - "eu-central-1/s3": { - "endpoint": "{service}.{region}.amazonaws.com", - "signatureVersion": "v4" - } - } -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/endpoints/endpoints_map.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/endpoints/endpoints_map.go deleted file mode 100644 index 894c1a64341..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/endpoints/endpoints_map.go +++ /dev/null @@ -1,89 +0,0 @@ -package endpoints - -// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. - -type endpointStruct struct { - Version int - Endpoints map[string]endpointEntry -} - -type endpointEntry struct { - Endpoint string - SigningRegion string -} - -var endpointsMap = endpointStruct{ - Version: 2, - Endpoints: map[string]endpointEntry{ - "*/*": { - Endpoint: "{service}.{region}.amazonaws.com", - }, - "*/cloudfront": { - Endpoint: "cloudfront.amazonaws.com", - SigningRegion: "us-east-1", - }, - "*/cloudsearchdomain": { - Endpoint: "", - SigningRegion: "us-east-1", - }, - "*/iam": { - Endpoint: "iam.amazonaws.com", - SigningRegion: "us-east-1", - }, - "*/importexport": { - Endpoint: "importexport.amazonaws.com", - SigningRegion: "us-east-1", - }, - "*/route53": { - Endpoint: "route53.amazonaws.com", - SigningRegion: "us-east-1", - }, - "*/sts": { - Endpoint: "sts.amazonaws.com", - SigningRegion: "us-east-1", - }, - "ap-northeast-1/s3": { - Endpoint: "s3-{region}.amazonaws.com", - }, - "ap-southeast-1/s3": { - Endpoint: "s3-{region}.amazonaws.com", - }, - "ap-southeast-2/s3": { - Endpoint: "s3-{region}.amazonaws.com", - }, - "cn-north-1/*": { - Endpoint: "{service}.{region}.amazonaws.com.cn", - }, - "eu-central-1/s3": { - Endpoint: "{service}.{region}.amazonaws.com", - }, - "eu-west-1/s3": { - Endpoint: "s3-{region}.amazonaws.com", - }, - "sa-east-1/s3": { - Endpoint: "s3-{region}.amazonaws.com", - }, - "us-east-1/s3": { - Endpoint: "s3.amazonaws.com", - }, - "us-east-1/sdb": { - Endpoint: "sdb.amazonaws.com", - SigningRegion: "us-east-1", - }, - "us-gov-west-1/iam": { - Endpoint: "iam.us-gov.amazonaws.com", - }, - "us-gov-west-1/s3": { - Endpoint: "s3-{region}.amazonaws.com", - }, - "us-gov-west-1/sts": { - Endpoint: "sts.us-gov-west-1.amazonaws.com", - }, - "us-west-1/s3": { - Endpoint: "s3-{region}.amazonaws.com", - }, - "us-west-2/s3": { - Endpoint: "s3-{region}.amazonaws.com", - }, - }, -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/endpoints/endpoints_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/endpoints/endpoints_test.go deleted file mode 100644 index 8af65879d40..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/endpoints/endpoints_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package endpoints - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestGlobalEndpoints(t *testing.T) { - region := "mock-region-1" - svcs := []string{"cloudfront", "iam", "importexport", "route53", "sts"} - - for _, name := range svcs { - ep, sr := EndpointForRegion(name, region) - assert.Equal(t, name+".amazonaws.com", ep) - assert.Equal(t, "us-east-1", sr) - } -} - -func TestServicesInCN(t *testing.T) { - region := "cn-north-1" - svcs := []string{"cloudfront", "iam", "importexport", "route53", "sts", "s3"} - - for _, name := range svcs { - ep, _ := EndpointForRegion(name, region) - assert.Equal(t, name+"."+region+".amazonaws.com.cn", ep) - } -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/ec2query/build.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/ec2query/build.go deleted file mode 100644 index e3d4147ee33..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/ec2query/build.go +++ /dev/null @@ -1,32 +0,0 @@ -// Package ec2query provides serialisation of AWS EC2 requests and responses. -package ec2query - -//go:generate go run ../../fixtures/protocol/generate.go ../../fixtures/protocol/input/ec2.json build_test.go - -import ( - "net/url" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/internal/protocol/query/queryutil" -) - -// Build builds a request for the EC2 protocol. -func Build(r *aws.Request) { - body := url.Values{ - "Action": {r.Operation.Name}, - "Version": {r.Service.APIVersion}, - } - if err := queryutil.Parse(body, r.Params, true); err != nil { - r.Error = awserr.New("SerializationError", "failed encoding EC2 Query request", err) - } - - if r.ExpireTime == 0 { - r.HTTPRequest.Method = "POST" - r.HTTPRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8") - r.SetBufferBody([]byte(body.Encode())) - } else { // This is a pre-signed request - r.HTTPRequest.Method = "GET" - r.HTTPRequest.URL.RawQuery = body.Encode() - } -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/ec2query/build_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/ec2query/build_test.go deleted file mode 100644 index 7973dd3baec..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/ec2query/build_test.go +++ /dev/null @@ -1,860 +0,0 @@ -package ec2query_test - -import ( - "bytes" - "encoding/json" - "encoding/xml" - "io" - "io/ioutil" - "net/http" - "net/url" - "testing" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/internal/protocol/ec2query" - "github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil" - "github.com/aws/aws-sdk-go/internal/signer/v4" - "github.com/aws/aws-sdk-go/internal/util" - "github.com/stretchr/testify/assert" -) - -var _ bytes.Buffer // always import bytes -var _ http.Request -var _ json.Marshaler -var _ time.Time -var _ xmlutil.XMLNode -var _ xml.Attr -var _ = ioutil.Discard -var _ = util.Trim("") -var _ = url.Values{} -var _ = io.EOF - -type InputService1ProtocolTest struct { - *aws.Service -} - -// New returns a new InputService1ProtocolTest client. -func NewInputService1ProtocolTest(config *aws.Config) *InputService1ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "inputservice1protocoltest", - APIVersion: "2014-01-01", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(ec2query.Build) - service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return &InputService1ProtocolTest{service} -} - -// newRequest creates a new request for a InputService1ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService1ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opInputService1TestCaseOperation1 = "OperationName" - -// InputService1TestCaseOperation1Request generates a request for the InputService1TestCaseOperation1 operation. -func (c *InputService1ProtocolTest) InputService1TestCaseOperation1Request(input *InputService1TestShapeInputShape) (req *aws.Request, output *InputService1TestShapeInputService1TestCaseOperation1Output) { - op := &aws.Operation{ - Name: opInputService1TestCaseOperation1, - } - - if input == nil { - input = &InputService1TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService1TestShapeInputService1TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService1ProtocolTest) InputService1TestCaseOperation1(input *InputService1TestShapeInputShape) (*InputService1TestShapeInputService1TestCaseOperation1Output, error) { - req, out := c.InputService1TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService1TestShapeInputService1TestCaseOperation1Output struct { - metadataInputService1TestShapeInputService1TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService1TestShapeInputService1TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService1TestShapeInputShape struct { - Bar *string `type:"string"` - - Foo *string `type:"string"` - - metadataInputService1TestShapeInputShape `json:"-" xml:"-"` -} - -type metadataInputService1TestShapeInputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService2ProtocolTest struct { - *aws.Service -} - -// New returns a new InputService2ProtocolTest client. -func NewInputService2ProtocolTest(config *aws.Config) *InputService2ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "inputservice2protocoltest", - APIVersion: "2014-01-01", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(ec2query.Build) - service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return &InputService2ProtocolTest{service} -} - -// newRequest creates a new request for a InputService2ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService2ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opInputService2TestCaseOperation1 = "OperationName" - -// InputService2TestCaseOperation1Request generates a request for the InputService2TestCaseOperation1 operation. -func (c *InputService2ProtocolTest) InputService2TestCaseOperation1Request(input *InputService2TestShapeInputShape) (req *aws.Request, output *InputService2TestShapeInputService2TestCaseOperation1Output) { - op := &aws.Operation{ - Name: opInputService2TestCaseOperation1, - } - - if input == nil { - input = &InputService2TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService2TestShapeInputService2TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService2ProtocolTest) InputService2TestCaseOperation1(input *InputService2TestShapeInputShape) (*InputService2TestShapeInputService2TestCaseOperation1Output, error) { - req, out := c.InputService2TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService2TestShapeInputService2TestCaseOperation1Output struct { - metadataInputService2TestShapeInputService2TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService2TestShapeInputService2TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService2TestShapeInputShape struct { - Bar *string `locationName:"barLocationName" type:"string"` - - Foo *string `type:"string"` - - Yuck *string `locationName:"yuckLocationName" queryName:"yuckQueryName" type:"string"` - - metadataInputService2TestShapeInputShape `json:"-" xml:"-"` -} - -type metadataInputService2TestShapeInputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService3ProtocolTest struct { - *aws.Service -} - -// New returns a new InputService3ProtocolTest client. -func NewInputService3ProtocolTest(config *aws.Config) *InputService3ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "inputservice3protocoltest", - APIVersion: "2014-01-01", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(ec2query.Build) - service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return &InputService3ProtocolTest{service} -} - -// newRequest creates a new request for a InputService3ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService3ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opInputService3TestCaseOperation1 = "OperationName" - -// InputService3TestCaseOperation1Request generates a request for the InputService3TestCaseOperation1 operation. -func (c *InputService3ProtocolTest) InputService3TestCaseOperation1Request(input *InputService3TestShapeInputShape) (req *aws.Request, output *InputService3TestShapeInputService3TestCaseOperation1Output) { - op := &aws.Operation{ - Name: opInputService3TestCaseOperation1, - } - - if input == nil { - input = &InputService3TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService3TestShapeInputService3TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService3ProtocolTest) InputService3TestCaseOperation1(input *InputService3TestShapeInputShape) (*InputService3TestShapeInputService3TestCaseOperation1Output, error) { - req, out := c.InputService3TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService3TestShapeInputService3TestCaseOperation1Output struct { - metadataInputService3TestShapeInputService3TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService3TestShapeInputService3TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService3TestShapeInputShape struct { - StructArg *InputService3TestShapeStructType `locationName:"Struct" type:"structure"` - - metadataInputService3TestShapeInputShape `json:"-" xml:"-"` -} - -type metadataInputService3TestShapeInputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService3TestShapeStructType struct { - ScalarArg *string `locationName:"Scalar" type:"string"` - - metadataInputService3TestShapeStructType `json:"-" xml:"-"` -} - -type metadataInputService3TestShapeStructType struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService4ProtocolTest struct { - *aws.Service -} - -// New returns a new InputService4ProtocolTest client. -func NewInputService4ProtocolTest(config *aws.Config) *InputService4ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "inputservice4protocoltest", - APIVersion: "2014-01-01", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(ec2query.Build) - service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return &InputService4ProtocolTest{service} -} - -// newRequest creates a new request for a InputService4ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService4ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opInputService4TestCaseOperation1 = "OperationName" - -// InputService4TestCaseOperation1Request generates a request for the InputService4TestCaseOperation1 operation. -func (c *InputService4ProtocolTest) InputService4TestCaseOperation1Request(input *InputService4TestShapeInputShape) (req *aws.Request, output *InputService4TestShapeInputService4TestCaseOperation1Output) { - op := &aws.Operation{ - Name: opInputService4TestCaseOperation1, - } - - if input == nil { - input = &InputService4TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService4TestShapeInputService4TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService4ProtocolTest) InputService4TestCaseOperation1(input *InputService4TestShapeInputShape) (*InputService4TestShapeInputService4TestCaseOperation1Output, error) { - req, out := c.InputService4TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService4TestShapeInputService4TestCaseOperation1Output struct { - metadataInputService4TestShapeInputService4TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService4TestShapeInputService4TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService4TestShapeInputShape struct { - ListArg []*string `type:"list"` - - metadataInputService4TestShapeInputShape `json:"-" xml:"-"` -} - -type metadataInputService4TestShapeInputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService5ProtocolTest struct { - *aws.Service -} - -// New returns a new InputService5ProtocolTest client. -func NewInputService5ProtocolTest(config *aws.Config) *InputService5ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "inputservice5protocoltest", - APIVersion: "2014-01-01", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(ec2query.Build) - service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return &InputService5ProtocolTest{service} -} - -// newRequest creates a new request for a InputService5ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService5ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opInputService5TestCaseOperation1 = "OperationName" - -// InputService5TestCaseOperation1Request generates a request for the InputService5TestCaseOperation1 operation. -func (c *InputService5ProtocolTest) InputService5TestCaseOperation1Request(input *InputService5TestShapeInputShape) (req *aws.Request, output *InputService5TestShapeInputService5TestCaseOperation1Output) { - op := &aws.Operation{ - Name: opInputService5TestCaseOperation1, - } - - if input == nil { - input = &InputService5TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService5TestShapeInputService5TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService5ProtocolTest) InputService5TestCaseOperation1(input *InputService5TestShapeInputShape) (*InputService5TestShapeInputService5TestCaseOperation1Output, error) { - req, out := c.InputService5TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService5TestShapeInputService5TestCaseOperation1Output struct { - metadataInputService5TestShapeInputService5TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService5TestShapeInputService5TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService5TestShapeInputShape struct { - ListArg []*string `locationName:"ListMemberName" locationNameList:"item" type:"list"` - - metadataInputService5TestShapeInputShape `json:"-" xml:"-"` -} - -type metadataInputService5TestShapeInputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService6ProtocolTest struct { - *aws.Service -} - -// New returns a new InputService6ProtocolTest client. -func NewInputService6ProtocolTest(config *aws.Config) *InputService6ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "inputservice6protocoltest", - APIVersion: "2014-01-01", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(ec2query.Build) - service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return &InputService6ProtocolTest{service} -} - -// newRequest creates a new request for a InputService6ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService6ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opInputService6TestCaseOperation1 = "OperationName" - -// InputService6TestCaseOperation1Request generates a request for the InputService6TestCaseOperation1 operation. -func (c *InputService6ProtocolTest) InputService6TestCaseOperation1Request(input *InputService6TestShapeInputShape) (req *aws.Request, output *InputService6TestShapeInputService6TestCaseOperation1Output) { - op := &aws.Operation{ - Name: opInputService6TestCaseOperation1, - } - - if input == nil { - input = &InputService6TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService6TestShapeInputService6TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService6ProtocolTest) InputService6TestCaseOperation1(input *InputService6TestShapeInputShape) (*InputService6TestShapeInputService6TestCaseOperation1Output, error) { - req, out := c.InputService6TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService6TestShapeInputService6TestCaseOperation1Output struct { - metadataInputService6TestShapeInputService6TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService6TestShapeInputService6TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService6TestShapeInputShape struct { - ListArg []*string `locationName:"ListMemberName" queryName:"ListQueryName" locationNameList:"item" type:"list"` - - metadataInputService6TestShapeInputShape `json:"-" xml:"-"` -} - -type metadataInputService6TestShapeInputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService7ProtocolTest struct { - *aws.Service -} - -// New returns a new InputService7ProtocolTest client. -func NewInputService7ProtocolTest(config *aws.Config) *InputService7ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "inputservice7protocoltest", - APIVersion: "2014-01-01", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(ec2query.Build) - service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return &InputService7ProtocolTest{service} -} - -// newRequest creates a new request for a InputService7ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService7ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opInputService7TestCaseOperation1 = "OperationName" - -// InputService7TestCaseOperation1Request generates a request for the InputService7TestCaseOperation1 operation. -func (c *InputService7ProtocolTest) InputService7TestCaseOperation1Request(input *InputService7TestShapeInputShape) (req *aws.Request, output *InputService7TestShapeInputService7TestCaseOperation1Output) { - op := &aws.Operation{ - Name: opInputService7TestCaseOperation1, - } - - if input == nil { - input = &InputService7TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService7TestShapeInputService7TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService7ProtocolTest) InputService7TestCaseOperation1(input *InputService7TestShapeInputShape) (*InputService7TestShapeInputService7TestCaseOperation1Output, error) { - req, out := c.InputService7TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService7TestShapeInputService7TestCaseOperation1Output struct { - metadataInputService7TestShapeInputService7TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService7TestShapeInputService7TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService7TestShapeInputShape struct { - BlobArg []byte `type:"blob"` - - metadataInputService7TestShapeInputShape `json:"-" xml:"-"` -} - -type metadataInputService7TestShapeInputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService8ProtocolTest struct { - *aws.Service -} - -// New returns a new InputService8ProtocolTest client. -func NewInputService8ProtocolTest(config *aws.Config) *InputService8ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "inputservice8protocoltest", - APIVersion: "2014-01-01", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(ec2query.Build) - service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return &InputService8ProtocolTest{service} -} - -// newRequest creates a new request for a InputService8ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService8ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opInputService8TestCaseOperation1 = "OperationName" - -// InputService8TestCaseOperation1Request generates a request for the InputService8TestCaseOperation1 operation. -func (c *InputService8ProtocolTest) InputService8TestCaseOperation1Request(input *InputService8TestShapeInputShape) (req *aws.Request, output *InputService8TestShapeInputService8TestCaseOperation1Output) { - op := &aws.Operation{ - Name: opInputService8TestCaseOperation1, - } - - if input == nil { - input = &InputService8TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService8TestShapeInputService8TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService8ProtocolTest) InputService8TestCaseOperation1(input *InputService8TestShapeInputShape) (*InputService8TestShapeInputService8TestCaseOperation1Output, error) { - req, out := c.InputService8TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService8TestShapeInputService8TestCaseOperation1Output struct { - metadataInputService8TestShapeInputService8TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService8TestShapeInputService8TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService8TestShapeInputShape struct { - TimeArg *time.Time `type:"timestamp" timestampFormat:"iso8601"` - - metadataInputService8TestShapeInputShape `json:"-" xml:"-"` -} - -type metadataInputService8TestShapeInputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -// -// Tests begin here -// - -func TestInputService1ProtocolTestScalarMembersCase1(t *testing.T) { - svc := NewInputService1ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService1TestShapeInputShape{ - Bar: aws.String("val2"), - Foo: aws.String("val1"), - } - req, _ := svc.InputService1TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - ec2query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&Bar=val2&Foo=val1&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService2ProtocolTestStructureWithLocationNameAndQueryNameAppliedToMembersCase1(t *testing.T) { - svc := NewInputService2ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService2TestShapeInputShape{ - Bar: aws.String("val2"), - Foo: aws.String("val1"), - Yuck: aws.String("val3"), - } - req, _ := svc.InputService2TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - ec2query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&BarLocationName=val2&Foo=val1&Version=2014-01-01&yuckQueryName=val3`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService3ProtocolTestNestedStructureMembersCase1(t *testing.T) { - svc := NewInputService3ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService3TestShapeInputShape{ - StructArg: &InputService3TestShapeStructType{ - ScalarArg: aws.String("foo"), - }, - } - req, _ := svc.InputService3TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - ec2query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&Struct.Scalar=foo&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService4ProtocolTestListTypesCase1(t *testing.T) { - svc := NewInputService4ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService4TestShapeInputShape{ - ListArg: []*string{ - aws.String("foo"), - aws.String("bar"), - aws.String("baz"), - }, - } - req, _ := svc.InputService4TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - ec2query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&ListArg.1=foo&ListArg.2=bar&ListArg.3=baz&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService5ProtocolTestListWithLocationNameAppliedToMemberCase1(t *testing.T) { - svc := NewInputService5ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService5TestShapeInputShape{ - ListArg: []*string{ - aws.String("a"), - aws.String("b"), - aws.String("c"), - }, - } - req, _ := svc.InputService5TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - ec2query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&ListMemberName.1=a&ListMemberName.2=b&ListMemberName.3=c&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService6ProtocolTestListWithLocationNameAndQueryNameCase1(t *testing.T) { - svc := NewInputService6ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService6TestShapeInputShape{ - ListArg: []*string{ - aws.String("a"), - aws.String("b"), - aws.String("c"), - }, - } - req, _ := svc.InputService6TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - ec2query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&ListQueryName.1=a&ListQueryName.2=b&ListQueryName.3=c&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService7ProtocolTestBase64EncodedBlobsCase1(t *testing.T) { - svc := NewInputService7ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService7TestShapeInputShape{ - BlobArg: []byte("foo"), - } - req, _ := svc.InputService7TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - ec2query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&BlobArg=Zm9v&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService8ProtocolTestTimestampValuesCase1(t *testing.T) { - svc := NewInputService8ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService8TestShapeInputShape{ - TimeArg: aws.Time(time.Unix(1422172800, 0)), - } - req, _ := svc.InputService8TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - ec2query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&TimeArg=2015-01-25T08%3A00%3A00Z&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/ec2query/unmarshal.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/ec2query/unmarshal.go deleted file mode 100644 index e59b2bbac3e..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/ec2query/unmarshal.go +++ /dev/null @@ -1,54 +0,0 @@ -package ec2query - -//go:generate go run ../../fixtures/protocol/generate.go ../../fixtures/protocol/output/ec2.json unmarshal_test.go - -import ( - "encoding/xml" - "io" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil" -) - -// Unmarshal unmarshals a response body for the EC2 protocol. -func Unmarshal(r *aws.Request) { - defer r.HTTPResponse.Body.Close() - if r.DataFilled() { - decoder := xml.NewDecoder(r.HTTPResponse.Body) - err := xmlutil.UnmarshalXML(r.Data, decoder, "") - if err != nil { - r.Error = awserr.New("SerializationError", "failed decoding EC2 Query response", err) - return - } - } -} - -// UnmarshalMeta unmarshals response headers for the EC2 protocol. -func UnmarshalMeta(r *aws.Request) { - // TODO implement unmarshaling of request IDs -} - -type xmlErrorResponse struct { - XMLName xml.Name `xml:"Response"` - Code string `xml:"Errors>Error>Code"` - Message string `xml:"Errors>Error>Message"` - RequestID string `xml:"RequestId"` -} - -// UnmarshalError unmarshals a response error for the EC2 protocol. -func UnmarshalError(r *aws.Request) { - defer r.HTTPResponse.Body.Close() - - resp := &xmlErrorResponse{} - err := xml.NewDecoder(r.HTTPResponse.Body).Decode(resp) - if err != nil && err != io.EOF { - r.Error = awserr.New("SerializationError", "failed decoding EC2 Query error response", err) - } else { - r.Error = awserr.NewRequestFailure( - awserr.New(resp.Code, resp.Message, nil), - r.HTTPResponse.StatusCode, - resp.RequestID, - ) - } -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/ec2query/unmarshal_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/ec2query/unmarshal_test.go deleted file mode 100644 index a4527c14e7e..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/ec2query/unmarshal_test.go +++ /dev/null @@ -1,816 +0,0 @@ -package ec2query_test - -import ( - "bytes" - "encoding/json" - "encoding/xml" - "io" - "io/ioutil" - "net/http" - "net/url" - "testing" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/internal/protocol/ec2query" - "github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil" - "github.com/aws/aws-sdk-go/internal/signer/v4" - "github.com/aws/aws-sdk-go/internal/util" - "github.com/stretchr/testify/assert" -) - -var _ bytes.Buffer // always import bytes -var _ http.Request -var _ json.Marshaler -var _ time.Time -var _ xmlutil.XMLNode -var _ xml.Attr -var _ = ioutil.Discard -var _ = util.Trim("") -var _ = url.Values{} -var _ = io.EOF - -type OutputService1ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService1ProtocolTest client. -func NewOutputService1ProtocolTest(config *aws.Config) *OutputService1ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice1protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(ec2query.Build) - service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return &OutputService1ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService1ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService1ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService1TestCaseOperation1 = "OperationName" - -// OutputService1TestCaseOperation1Request generates a request for the OutputService1TestCaseOperation1 operation. -func (c *OutputService1ProtocolTest) OutputService1TestCaseOperation1Request(input *OutputService1TestShapeOutputService1TestCaseOperation1Input) (req *aws.Request, output *OutputService1TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService1TestCaseOperation1, - } - - if input == nil { - input = &OutputService1TestShapeOutputService1TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService1TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService1ProtocolTest) OutputService1TestCaseOperation1(input *OutputService1TestShapeOutputService1TestCaseOperation1Input) (*OutputService1TestShapeOutputShape, error) { - req, out := c.OutputService1TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService1TestShapeOutputService1TestCaseOperation1Input struct { - metadataOutputService1TestShapeOutputService1TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService1TestShapeOutputService1TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService1TestShapeOutputShape struct { - Char *string `type:"character"` - - Double *float64 `type:"double"` - - FalseBool *bool `type:"boolean"` - - Float *float64 `type:"float"` - - Long *int64 `type:"long"` - - Num *int64 `locationName:"FooNum" type:"integer"` - - Str *string `type:"string"` - - TrueBool *bool `type:"boolean"` - - metadataOutputService1TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService1TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService2ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService2ProtocolTest client. -func NewOutputService2ProtocolTest(config *aws.Config) *OutputService2ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice2protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(ec2query.Build) - service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return &OutputService2ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService2ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService2ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService2TestCaseOperation1 = "OperationName" - -// OutputService2TestCaseOperation1Request generates a request for the OutputService2TestCaseOperation1 operation. -func (c *OutputService2ProtocolTest) OutputService2TestCaseOperation1Request(input *OutputService2TestShapeOutputService2TestCaseOperation1Input) (req *aws.Request, output *OutputService2TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService2TestCaseOperation1, - } - - if input == nil { - input = &OutputService2TestShapeOutputService2TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService2TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService2ProtocolTest) OutputService2TestCaseOperation1(input *OutputService2TestShapeOutputService2TestCaseOperation1Input) (*OutputService2TestShapeOutputShape, error) { - req, out := c.OutputService2TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService2TestShapeOutputService2TestCaseOperation1Input struct { - metadataOutputService2TestShapeOutputService2TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService2TestShapeOutputService2TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService2TestShapeOutputShape struct { - Blob []byte `type:"blob"` - - metadataOutputService2TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService2TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService3ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService3ProtocolTest client. -func NewOutputService3ProtocolTest(config *aws.Config) *OutputService3ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice3protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(ec2query.Build) - service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return &OutputService3ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService3ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService3ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService3TestCaseOperation1 = "OperationName" - -// OutputService3TestCaseOperation1Request generates a request for the OutputService3TestCaseOperation1 operation. -func (c *OutputService3ProtocolTest) OutputService3TestCaseOperation1Request(input *OutputService3TestShapeOutputService3TestCaseOperation1Input) (req *aws.Request, output *OutputService3TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService3TestCaseOperation1, - } - - if input == nil { - input = &OutputService3TestShapeOutputService3TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService3TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService3ProtocolTest) OutputService3TestCaseOperation1(input *OutputService3TestShapeOutputService3TestCaseOperation1Input) (*OutputService3TestShapeOutputShape, error) { - req, out := c.OutputService3TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService3TestShapeOutputService3TestCaseOperation1Input struct { - metadataOutputService3TestShapeOutputService3TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService3TestShapeOutputService3TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService3TestShapeOutputShape struct { - ListMember []*string `type:"list"` - - metadataOutputService3TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService3TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService4ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService4ProtocolTest client. -func NewOutputService4ProtocolTest(config *aws.Config) *OutputService4ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice4protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(ec2query.Build) - service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return &OutputService4ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService4ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService4ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService4TestCaseOperation1 = "OperationName" - -// OutputService4TestCaseOperation1Request generates a request for the OutputService4TestCaseOperation1 operation. -func (c *OutputService4ProtocolTest) OutputService4TestCaseOperation1Request(input *OutputService4TestShapeOutputService4TestCaseOperation1Input) (req *aws.Request, output *OutputService4TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService4TestCaseOperation1, - } - - if input == nil { - input = &OutputService4TestShapeOutputService4TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService4TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService4ProtocolTest) OutputService4TestCaseOperation1(input *OutputService4TestShapeOutputService4TestCaseOperation1Input) (*OutputService4TestShapeOutputShape, error) { - req, out := c.OutputService4TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService4TestShapeOutputService4TestCaseOperation1Input struct { - metadataOutputService4TestShapeOutputService4TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService4TestShapeOutputService4TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService4TestShapeOutputShape struct { - ListMember []*string `locationNameList:"item" type:"list"` - - metadataOutputService4TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService4TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService5ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService5ProtocolTest client. -func NewOutputService5ProtocolTest(config *aws.Config) *OutputService5ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice5protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(ec2query.Build) - service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return &OutputService5ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService5ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService5ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService5TestCaseOperation1 = "OperationName" - -// OutputService5TestCaseOperation1Request generates a request for the OutputService5TestCaseOperation1 operation. -func (c *OutputService5ProtocolTest) OutputService5TestCaseOperation1Request(input *OutputService5TestShapeOutputService5TestCaseOperation1Input) (req *aws.Request, output *OutputService5TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService5TestCaseOperation1, - } - - if input == nil { - input = &OutputService5TestShapeOutputService5TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService5TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService5ProtocolTest) OutputService5TestCaseOperation1(input *OutputService5TestShapeOutputService5TestCaseOperation1Input) (*OutputService5TestShapeOutputShape, error) { - req, out := c.OutputService5TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService5TestShapeOutputService5TestCaseOperation1Input struct { - metadataOutputService5TestShapeOutputService5TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService5TestShapeOutputService5TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService5TestShapeOutputShape struct { - ListMember []*string `type:"list" flattened:"true"` - - metadataOutputService5TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService5TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService6ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService6ProtocolTest client. -func NewOutputService6ProtocolTest(config *aws.Config) *OutputService6ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice6protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(ec2query.Build) - service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return &OutputService6ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService6ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService6ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService6TestCaseOperation1 = "OperationName" - -// OutputService6TestCaseOperation1Request generates a request for the OutputService6TestCaseOperation1 operation. -func (c *OutputService6ProtocolTest) OutputService6TestCaseOperation1Request(input *OutputService6TestShapeOutputService6TestCaseOperation1Input) (req *aws.Request, output *OutputService6TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService6TestCaseOperation1, - } - - if input == nil { - input = &OutputService6TestShapeOutputService6TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService6TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService6ProtocolTest) OutputService6TestCaseOperation1(input *OutputService6TestShapeOutputService6TestCaseOperation1Input) (*OutputService6TestShapeOutputShape, error) { - req, out := c.OutputService6TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService6TestShapeOutputService6TestCaseOperation1Input struct { - metadataOutputService6TestShapeOutputService6TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService6TestShapeOutputService6TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService6TestShapeOutputShape struct { - Map map[string]*OutputService6TestShapeStructureType `type:"map"` - - metadataOutputService6TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService6TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService6TestShapeStructureType struct { - Foo *string `locationName:"foo" type:"string"` - - metadataOutputService6TestShapeStructureType `json:"-" xml:"-"` -} - -type metadataOutputService6TestShapeStructureType struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService7ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService7ProtocolTest client. -func NewOutputService7ProtocolTest(config *aws.Config) *OutputService7ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice7protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(ec2query.Build) - service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return &OutputService7ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService7ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService7ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService7TestCaseOperation1 = "OperationName" - -// OutputService7TestCaseOperation1Request generates a request for the OutputService7TestCaseOperation1 operation. -func (c *OutputService7ProtocolTest) OutputService7TestCaseOperation1Request(input *OutputService7TestShapeOutputService7TestCaseOperation1Input) (req *aws.Request, output *OutputService7TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService7TestCaseOperation1, - } - - if input == nil { - input = &OutputService7TestShapeOutputService7TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService7TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService7ProtocolTest) OutputService7TestCaseOperation1(input *OutputService7TestShapeOutputService7TestCaseOperation1Input) (*OutputService7TestShapeOutputShape, error) { - req, out := c.OutputService7TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService7TestShapeOutputService7TestCaseOperation1Input struct { - metadataOutputService7TestShapeOutputService7TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService7TestShapeOutputService7TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService7TestShapeOutputShape struct { - Map map[string]*string `type:"map" flattened:"true"` - - metadataOutputService7TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService7TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService8ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService8ProtocolTest client. -func NewOutputService8ProtocolTest(config *aws.Config) *OutputService8ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice8protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(ec2query.Build) - service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return &OutputService8ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService8ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService8ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService8TestCaseOperation1 = "OperationName" - -// OutputService8TestCaseOperation1Request generates a request for the OutputService8TestCaseOperation1 operation. -func (c *OutputService8ProtocolTest) OutputService8TestCaseOperation1Request(input *OutputService8TestShapeOutputService8TestCaseOperation1Input) (req *aws.Request, output *OutputService8TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService8TestCaseOperation1, - } - - if input == nil { - input = &OutputService8TestShapeOutputService8TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService8TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService8ProtocolTest) OutputService8TestCaseOperation1(input *OutputService8TestShapeOutputService8TestCaseOperation1Input) (*OutputService8TestShapeOutputShape, error) { - req, out := c.OutputService8TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService8TestShapeOutputService8TestCaseOperation1Input struct { - metadataOutputService8TestShapeOutputService8TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService8TestShapeOutputService8TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService8TestShapeOutputShape struct { - Map map[string]*string `locationNameKey:"foo" locationNameValue:"bar" type:"map" flattened:"true"` - - metadataOutputService8TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService8TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -// -// Tests begin here -// - -func TestOutputService1ProtocolTestScalarMembersCase1(t *testing.T) { - svc := NewOutputService1ProtocolTest(nil) - - buf := bytes.NewReader([]byte("myname123falsetrue1.21.3200arequest-id")) - req, out := svc.OutputService1TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - ec2query.UnmarshalMeta(req) - ec2query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "a", *out.Char) - assert.Equal(t, 1.3, *out.Double) - assert.Equal(t, false, *out.FalseBool) - assert.Equal(t, 1.2, *out.Float) - assert.Equal(t, int64(200), *out.Long) - assert.Equal(t, int64(123), *out.Num) - assert.Equal(t, "myname", *out.Str) - assert.Equal(t, true, *out.TrueBool) - -} - -func TestOutputService2ProtocolTestBlobCase1(t *testing.T) { - svc := NewOutputService2ProtocolTest(nil) - - buf := bytes.NewReader([]byte("dmFsdWU=requestid")) - req, out := svc.OutputService2TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - ec2query.UnmarshalMeta(req) - ec2query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "value", string(out.Blob)) - -} - -func TestOutputService3ProtocolTestListsCase1(t *testing.T) { - svc := NewOutputService3ProtocolTest(nil) - - buf := bytes.NewReader([]byte("abc123requestid")) - req, out := svc.OutputService3TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - ec2query.UnmarshalMeta(req) - ec2query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "abc", *out.ListMember[0]) - assert.Equal(t, "123", *out.ListMember[1]) - -} - -func TestOutputService4ProtocolTestListWithCustomMemberNameCase1(t *testing.T) { - svc := NewOutputService4ProtocolTest(nil) - - buf := bytes.NewReader([]byte("abc123requestid")) - req, out := svc.OutputService4TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - ec2query.UnmarshalMeta(req) - ec2query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "abc", *out.ListMember[0]) - assert.Equal(t, "123", *out.ListMember[1]) - -} - -func TestOutputService5ProtocolTestFlattenedListCase1(t *testing.T) { - svc := NewOutputService5ProtocolTest(nil) - - buf := bytes.NewReader([]byte("abc123requestid")) - req, out := svc.OutputService5TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - ec2query.UnmarshalMeta(req) - ec2query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "abc", *out.ListMember[0]) - assert.Equal(t, "123", *out.ListMember[1]) - -} - -func TestOutputService6ProtocolTestNormalMapCase1(t *testing.T) { - svc := NewOutputService6ProtocolTest(nil) - - buf := bytes.NewReader([]byte("quxbarbazbamrequestid")) - req, out := svc.OutputService6TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - ec2query.UnmarshalMeta(req) - ec2query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "bam", *out.Map["baz"].Foo) - assert.Equal(t, "bar", *out.Map["qux"].Foo) - -} - -func TestOutputService7ProtocolTestFlattenedMapCase1(t *testing.T) { - svc := NewOutputService7ProtocolTest(nil) - - buf := bytes.NewReader([]byte("quxbarbazbamrequestid")) - req, out := svc.OutputService7TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - ec2query.UnmarshalMeta(req) - ec2query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "bam", *out.Map["baz"]) - assert.Equal(t, "bar", *out.Map["qux"]) - -} - -func TestOutputService8ProtocolTestNamedMapCase1(t *testing.T) { - svc := NewOutputService8ProtocolTest(nil) - - buf := bytes.NewReader([]byte("quxbarbazbamrequestid")) - req, out := svc.OutputService8TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - ec2query.UnmarshalMeta(req) - ec2query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "bam", *out.Map["baz"]) - assert.Equal(t, "bar", *out.Map["qux"]) - -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/query/build.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/query/build.go deleted file mode 100644 index c4d8dd2635a..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/query/build.go +++ /dev/null @@ -1,33 +0,0 @@ -// Package query provides serialisation of AWS query requests, and responses. -package query - -//go:generate go run ../../fixtures/protocol/generate.go ../../fixtures/protocol/input/query.json build_test.go - -import ( - "net/url" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/internal/protocol/query/queryutil" -) - -// Build builds a request for an AWS Query service. -func Build(r *aws.Request) { - body := url.Values{ - "Action": {r.Operation.Name}, - "Version": {r.Service.APIVersion}, - } - if err := queryutil.Parse(body, r.Params, false); err != nil { - r.Error = awserr.New("SerializationError", "failed encoding Query request", err) - return - } - - if r.ExpireTime == 0 { - r.HTTPRequest.Method = "POST" - r.HTTPRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8") - r.SetBufferBody([]byte(body.Encode())) - } else { // This is a pre-signed request - r.HTTPRequest.Method = "GET" - r.HTTPRequest.URL.RawQuery = body.Encode() - } -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/query/build_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/query/build_test.go deleted file mode 100644 index 52bbf7e1c87..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/query/build_test.go +++ /dev/null @@ -1,1482 +0,0 @@ -package query_test - -import ( - "bytes" - "encoding/json" - "encoding/xml" - "io" - "io/ioutil" - "net/http" - "net/url" - "testing" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/internal/protocol/query" - "github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil" - "github.com/aws/aws-sdk-go/internal/signer/v4" - "github.com/aws/aws-sdk-go/internal/util" - "github.com/stretchr/testify/assert" -) - -var _ bytes.Buffer // always import bytes -var _ http.Request -var _ json.Marshaler -var _ time.Time -var _ xmlutil.XMLNode -var _ xml.Attr -var _ = ioutil.Discard -var _ = util.Trim("") -var _ = url.Values{} -var _ = io.EOF - -type InputService1ProtocolTest struct { - *aws.Service -} - -// New returns a new InputService1ProtocolTest client. -func NewInputService1ProtocolTest(config *aws.Config) *InputService1ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "inputservice1protocoltest", - APIVersion: "2014-01-01", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &InputService1ProtocolTest{service} -} - -// newRequest creates a new request for a InputService1ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService1ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opInputService1TestCaseOperation1 = "OperationName" - -// InputService1TestCaseOperation1Request generates a request for the InputService1TestCaseOperation1 operation. -func (c *InputService1ProtocolTest) InputService1TestCaseOperation1Request(input *InputService1TestShapeInputShape) (req *aws.Request, output *InputService1TestShapeInputService1TestCaseOperation1Output) { - op := &aws.Operation{ - Name: opInputService1TestCaseOperation1, - } - - if input == nil { - input = &InputService1TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService1TestShapeInputService1TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService1ProtocolTest) InputService1TestCaseOperation1(input *InputService1TestShapeInputShape) (*InputService1TestShapeInputService1TestCaseOperation1Output, error) { - req, out := c.InputService1TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService1TestShapeInputService1TestCaseOperation1Output struct { - metadataInputService1TestShapeInputService1TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService1TestShapeInputService1TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService1TestShapeInputShape struct { - Bar *string `type:"string"` - - Foo *string `type:"string"` - - metadataInputService1TestShapeInputShape `json:"-" xml:"-"` -} - -type metadataInputService1TestShapeInputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService2ProtocolTest struct { - *aws.Service -} - -// New returns a new InputService2ProtocolTest client. -func NewInputService2ProtocolTest(config *aws.Config) *InputService2ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "inputservice2protocoltest", - APIVersion: "2014-01-01", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &InputService2ProtocolTest{service} -} - -// newRequest creates a new request for a InputService2ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService2ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opInputService2TestCaseOperation1 = "OperationName" - -// InputService2TestCaseOperation1Request generates a request for the InputService2TestCaseOperation1 operation. -func (c *InputService2ProtocolTest) InputService2TestCaseOperation1Request(input *InputService2TestShapeInputShape) (req *aws.Request, output *InputService2TestShapeInputService2TestCaseOperation1Output) { - op := &aws.Operation{ - Name: opInputService2TestCaseOperation1, - } - - if input == nil { - input = &InputService2TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService2TestShapeInputService2TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService2ProtocolTest) InputService2TestCaseOperation1(input *InputService2TestShapeInputShape) (*InputService2TestShapeInputService2TestCaseOperation1Output, error) { - req, out := c.InputService2TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService2TestShapeInputService2TestCaseOperation1Output struct { - metadataInputService2TestShapeInputService2TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService2TestShapeInputService2TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService2TestShapeInputShape struct { - StructArg *InputService2TestShapeStructType `type:"structure"` - - metadataInputService2TestShapeInputShape `json:"-" xml:"-"` -} - -type metadataInputService2TestShapeInputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService2TestShapeStructType struct { - ScalarArg *string `type:"string"` - - metadataInputService2TestShapeStructType `json:"-" xml:"-"` -} - -type metadataInputService2TestShapeStructType struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService3ProtocolTest struct { - *aws.Service -} - -// New returns a new InputService3ProtocolTest client. -func NewInputService3ProtocolTest(config *aws.Config) *InputService3ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "inputservice3protocoltest", - APIVersion: "2014-01-01", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &InputService3ProtocolTest{service} -} - -// newRequest creates a new request for a InputService3ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService3ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opInputService3TestCaseOperation1 = "OperationName" - -// InputService3TestCaseOperation1Request generates a request for the InputService3TestCaseOperation1 operation. -func (c *InputService3ProtocolTest) InputService3TestCaseOperation1Request(input *InputService3TestShapeInputShape) (req *aws.Request, output *InputService3TestShapeInputService3TestCaseOperation1Output) { - op := &aws.Operation{ - Name: opInputService3TestCaseOperation1, - } - - if input == nil { - input = &InputService3TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService3TestShapeInputService3TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService3ProtocolTest) InputService3TestCaseOperation1(input *InputService3TestShapeInputShape) (*InputService3TestShapeInputService3TestCaseOperation1Output, error) { - req, out := c.InputService3TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -const opInputService3TestCaseOperation2 = "OperationName" - -// InputService3TestCaseOperation2Request generates a request for the InputService3TestCaseOperation2 operation. -func (c *InputService3ProtocolTest) InputService3TestCaseOperation2Request(input *InputService3TestShapeInputShape) (req *aws.Request, output *InputService3TestShapeInputService3TestCaseOperation2Output) { - op := &aws.Operation{ - Name: opInputService3TestCaseOperation2, - } - - if input == nil { - input = &InputService3TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService3TestShapeInputService3TestCaseOperation2Output{} - req.Data = output - return -} - -func (c *InputService3ProtocolTest) InputService3TestCaseOperation2(input *InputService3TestShapeInputShape) (*InputService3TestShapeInputService3TestCaseOperation2Output, error) { - req, out := c.InputService3TestCaseOperation2Request(input) - err := req.Send() - return out, err -} - -type InputService3TestShapeInputService3TestCaseOperation1Output struct { - metadataInputService3TestShapeInputService3TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService3TestShapeInputService3TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService3TestShapeInputService3TestCaseOperation2Output struct { - metadataInputService3TestShapeInputService3TestCaseOperation2Output `json:"-" xml:"-"` -} - -type metadataInputService3TestShapeInputService3TestCaseOperation2Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService3TestShapeInputShape struct { - ListArg []*string `type:"list"` - - metadataInputService3TestShapeInputShape `json:"-" xml:"-"` -} - -type metadataInputService3TestShapeInputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService4ProtocolTest struct { - *aws.Service -} - -// New returns a new InputService4ProtocolTest client. -func NewInputService4ProtocolTest(config *aws.Config) *InputService4ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "inputservice4protocoltest", - APIVersion: "2014-01-01", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &InputService4ProtocolTest{service} -} - -// newRequest creates a new request for a InputService4ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService4ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opInputService4TestCaseOperation1 = "OperationName" - -// InputService4TestCaseOperation1Request generates a request for the InputService4TestCaseOperation1 operation. -func (c *InputService4ProtocolTest) InputService4TestCaseOperation1Request(input *InputService4TestShapeInputShape) (req *aws.Request, output *InputService4TestShapeInputService4TestCaseOperation1Output) { - op := &aws.Operation{ - Name: opInputService4TestCaseOperation1, - } - - if input == nil { - input = &InputService4TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService4TestShapeInputService4TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService4ProtocolTest) InputService4TestCaseOperation1(input *InputService4TestShapeInputShape) (*InputService4TestShapeInputService4TestCaseOperation1Output, error) { - req, out := c.InputService4TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -const opInputService4TestCaseOperation2 = "OperationName" - -// InputService4TestCaseOperation2Request generates a request for the InputService4TestCaseOperation2 operation. -func (c *InputService4ProtocolTest) InputService4TestCaseOperation2Request(input *InputService4TestShapeInputShape) (req *aws.Request, output *InputService4TestShapeInputService4TestCaseOperation2Output) { - op := &aws.Operation{ - Name: opInputService4TestCaseOperation2, - } - - if input == nil { - input = &InputService4TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService4TestShapeInputService4TestCaseOperation2Output{} - req.Data = output - return -} - -func (c *InputService4ProtocolTest) InputService4TestCaseOperation2(input *InputService4TestShapeInputShape) (*InputService4TestShapeInputService4TestCaseOperation2Output, error) { - req, out := c.InputService4TestCaseOperation2Request(input) - err := req.Send() - return out, err -} - -type InputService4TestShapeInputService4TestCaseOperation1Output struct { - metadataInputService4TestShapeInputService4TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService4TestShapeInputService4TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService4TestShapeInputService4TestCaseOperation2Output struct { - metadataInputService4TestShapeInputService4TestCaseOperation2Output `json:"-" xml:"-"` -} - -type metadataInputService4TestShapeInputService4TestCaseOperation2Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService4TestShapeInputShape struct { - ListArg []*string `type:"list" flattened:"true"` - - ScalarArg *string `type:"string"` - - metadataInputService4TestShapeInputShape `json:"-" xml:"-"` -} - -type metadataInputService4TestShapeInputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService5ProtocolTest struct { - *aws.Service -} - -// New returns a new InputService5ProtocolTest client. -func NewInputService5ProtocolTest(config *aws.Config) *InputService5ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "inputservice5protocoltest", - APIVersion: "2014-01-01", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &InputService5ProtocolTest{service} -} - -// newRequest creates a new request for a InputService5ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService5ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opInputService5TestCaseOperation1 = "OperationName" - -// InputService5TestCaseOperation1Request generates a request for the InputService5TestCaseOperation1 operation. -func (c *InputService5ProtocolTest) InputService5TestCaseOperation1Request(input *InputService5TestShapeInputShape) (req *aws.Request, output *InputService5TestShapeInputService5TestCaseOperation1Output) { - op := &aws.Operation{ - Name: opInputService5TestCaseOperation1, - } - - if input == nil { - input = &InputService5TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService5TestShapeInputService5TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService5ProtocolTest) InputService5TestCaseOperation1(input *InputService5TestShapeInputShape) (*InputService5TestShapeInputService5TestCaseOperation1Output, error) { - req, out := c.InputService5TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -const opInputService5TestCaseOperation2 = "OperationName" - -// InputService5TestCaseOperation2Request generates a request for the InputService5TestCaseOperation2 operation. -func (c *InputService5ProtocolTest) InputService5TestCaseOperation2Request(input *InputService5TestShapeInputShape) (req *aws.Request, output *InputService5TestShapeInputService5TestCaseOperation2Output) { - op := &aws.Operation{ - Name: opInputService5TestCaseOperation2, - } - - if input == nil { - input = &InputService5TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService5TestShapeInputService5TestCaseOperation2Output{} - req.Data = output - return -} - -func (c *InputService5ProtocolTest) InputService5TestCaseOperation2(input *InputService5TestShapeInputShape) (*InputService5TestShapeInputService5TestCaseOperation2Output, error) { - req, out := c.InputService5TestCaseOperation2Request(input) - err := req.Send() - return out, err -} - -type InputService5TestShapeInputService5TestCaseOperation1Output struct { - metadataInputService5TestShapeInputService5TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService5TestShapeInputService5TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService5TestShapeInputService5TestCaseOperation2Output struct { - metadataInputService5TestShapeInputService5TestCaseOperation2Output `json:"-" xml:"-"` -} - -type metadataInputService5TestShapeInputService5TestCaseOperation2Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService5TestShapeInputShape struct { - MapArg map[string]*string `type:"map"` - - metadataInputService5TestShapeInputShape `json:"-" xml:"-"` -} - -type metadataInputService5TestShapeInputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService6ProtocolTest struct { - *aws.Service -} - -// New returns a new InputService6ProtocolTest client. -func NewInputService6ProtocolTest(config *aws.Config) *InputService6ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "inputservice6protocoltest", - APIVersion: "2014-01-01", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &InputService6ProtocolTest{service} -} - -// newRequest creates a new request for a InputService6ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService6ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opInputService6TestCaseOperation1 = "OperationName" - -// InputService6TestCaseOperation1Request generates a request for the InputService6TestCaseOperation1 operation. -func (c *InputService6ProtocolTest) InputService6TestCaseOperation1Request(input *InputService6TestShapeInputShape) (req *aws.Request, output *InputService6TestShapeInputService6TestCaseOperation1Output) { - op := &aws.Operation{ - Name: opInputService6TestCaseOperation1, - } - - if input == nil { - input = &InputService6TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService6TestShapeInputService6TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService6ProtocolTest) InputService6TestCaseOperation1(input *InputService6TestShapeInputShape) (*InputService6TestShapeInputService6TestCaseOperation1Output, error) { - req, out := c.InputService6TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService6TestShapeInputService6TestCaseOperation1Output struct { - metadataInputService6TestShapeInputService6TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService6TestShapeInputService6TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService6TestShapeInputShape struct { - MapArg map[string]*string `locationNameKey:"TheKey" locationNameValue:"TheValue" type:"map"` - - metadataInputService6TestShapeInputShape `json:"-" xml:"-"` -} - -type metadataInputService6TestShapeInputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService7ProtocolTest struct { - *aws.Service -} - -// New returns a new InputService7ProtocolTest client. -func NewInputService7ProtocolTest(config *aws.Config) *InputService7ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "inputservice7protocoltest", - APIVersion: "2014-01-01", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &InputService7ProtocolTest{service} -} - -// newRequest creates a new request for a InputService7ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService7ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opInputService7TestCaseOperation1 = "OperationName" - -// InputService7TestCaseOperation1Request generates a request for the InputService7TestCaseOperation1 operation. -func (c *InputService7ProtocolTest) InputService7TestCaseOperation1Request(input *InputService7TestShapeInputShape) (req *aws.Request, output *InputService7TestShapeInputService7TestCaseOperation1Output) { - op := &aws.Operation{ - Name: opInputService7TestCaseOperation1, - } - - if input == nil { - input = &InputService7TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService7TestShapeInputService7TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService7ProtocolTest) InputService7TestCaseOperation1(input *InputService7TestShapeInputShape) (*InputService7TestShapeInputService7TestCaseOperation1Output, error) { - req, out := c.InputService7TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService7TestShapeInputService7TestCaseOperation1Output struct { - metadataInputService7TestShapeInputService7TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService7TestShapeInputService7TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService7TestShapeInputShape struct { - BlobArg []byte `type:"blob"` - - metadataInputService7TestShapeInputShape `json:"-" xml:"-"` -} - -type metadataInputService7TestShapeInputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService8ProtocolTest struct { - *aws.Service -} - -// New returns a new InputService8ProtocolTest client. -func NewInputService8ProtocolTest(config *aws.Config) *InputService8ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "inputservice8protocoltest", - APIVersion: "2014-01-01", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &InputService8ProtocolTest{service} -} - -// newRequest creates a new request for a InputService8ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService8ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opInputService8TestCaseOperation1 = "OperationName" - -// InputService8TestCaseOperation1Request generates a request for the InputService8TestCaseOperation1 operation. -func (c *InputService8ProtocolTest) InputService8TestCaseOperation1Request(input *InputService8TestShapeInputShape) (req *aws.Request, output *InputService8TestShapeInputService8TestCaseOperation1Output) { - op := &aws.Operation{ - Name: opInputService8TestCaseOperation1, - } - - if input == nil { - input = &InputService8TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService8TestShapeInputService8TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService8ProtocolTest) InputService8TestCaseOperation1(input *InputService8TestShapeInputShape) (*InputService8TestShapeInputService8TestCaseOperation1Output, error) { - req, out := c.InputService8TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService8TestShapeInputService8TestCaseOperation1Output struct { - metadataInputService8TestShapeInputService8TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService8TestShapeInputService8TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService8TestShapeInputShape struct { - TimeArg *time.Time `type:"timestamp" timestampFormat:"iso8601"` - - metadataInputService8TestShapeInputShape `json:"-" xml:"-"` -} - -type metadataInputService8TestShapeInputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService9ProtocolTest struct { - *aws.Service -} - -// New returns a new InputService9ProtocolTest client. -func NewInputService9ProtocolTest(config *aws.Config) *InputService9ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "inputservice9protocoltest", - APIVersion: "2014-01-01", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &InputService9ProtocolTest{service} -} - -// newRequest creates a new request for a InputService9ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService9ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opInputService9TestCaseOperation1 = "OperationName" - -// InputService9TestCaseOperation1Request generates a request for the InputService9TestCaseOperation1 operation. -func (c *InputService9ProtocolTest) InputService9TestCaseOperation1Request(input *InputService9TestShapeInputShape) (req *aws.Request, output *InputService9TestShapeInputService9TestCaseOperation1Output) { - op := &aws.Operation{ - Name: opInputService9TestCaseOperation1, - } - - if input == nil { - input = &InputService9TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService9TestShapeInputService9TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService9ProtocolTest) InputService9TestCaseOperation1(input *InputService9TestShapeInputShape) (*InputService9TestShapeInputService9TestCaseOperation1Output, error) { - req, out := c.InputService9TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -const opInputService9TestCaseOperation2 = "OperationName" - -// InputService9TestCaseOperation2Request generates a request for the InputService9TestCaseOperation2 operation. -func (c *InputService9ProtocolTest) InputService9TestCaseOperation2Request(input *InputService9TestShapeInputShape) (req *aws.Request, output *InputService9TestShapeInputService9TestCaseOperation2Output) { - op := &aws.Operation{ - Name: opInputService9TestCaseOperation2, - } - - if input == nil { - input = &InputService9TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService9TestShapeInputService9TestCaseOperation2Output{} - req.Data = output - return -} - -func (c *InputService9ProtocolTest) InputService9TestCaseOperation2(input *InputService9TestShapeInputShape) (*InputService9TestShapeInputService9TestCaseOperation2Output, error) { - req, out := c.InputService9TestCaseOperation2Request(input) - err := req.Send() - return out, err -} - -const opInputService9TestCaseOperation3 = "OperationName" - -// InputService9TestCaseOperation3Request generates a request for the InputService9TestCaseOperation3 operation. -func (c *InputService9ProtocolTest) InputService9TestCaseOperation3Request(input *InputService9TestShapeInputShape) (req *aws.Request, output *InputService9TestShapeInputService9TestCaseOperation3Output) { - op := &aws.Operation{ - Name: opInputService9TestCaseOperation3, - } - - if input == nil { - input = &InputService9TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService9TestShapeInputService9TestCaseOperation3Output{} - req.Data = output - return -} - -func (c *InputService9ProtocolTest) InputService9TestCaseOperation3(input *InputService9TestShapeInputShape) (*InputService9TestShapeInputService9TestCaseOperation3Output, error) { - req, out := c.InputService9TestCaseOperation3Request(input) - err := req.Send() - return out, err -} - -const opInputService9TestCaseOperation4 = "OperationName" - -// InputService9TestCaseOperation4Request generates a request for the InputService9TestCaseOperation4 operation. -func (c *InputService9ProtocolTest) InputService9TestCaseOperation4Request(input *InputService9TestShapeInputShape) (req *aws.Request, output *InputService9TestShapeInputService9TestCaseOperation4Output) { - op := &aws.Operation{ - Name: opInputService9TestCaseOperation4, - } - - if input == nil { - input = &InputService9TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService9TestShapeInputService9TestCaseOperation4Output{} - req.Data = output - return -} - -func (c *InputService9ProtocolTest) InputService9TestCaseOperation4(input *InputService9TestShapeInputShape) (*InputService9TestShapeInputService9TestCaseOperation4Output, error) { - req, out := c.InputService9TestCaseOperation4Request(input) - err := req.Send() - return out, err -} - -const opInputService9TestCaseOperation5 = "OperationName" - -// InputService9TestCaseOperation5Request generates a request for the InputService9TestCaseOperation5 operation. -func (c *InputService9ProtocolTest) InputService9TestCaseOperation5Request(input *InputService9TestShapeInputShape) (req *aws.Request, output *InputService9TestShapeInputService9TestCaseOperation5Output) { - op := &aws.Operation{ - Name: opInputService9TestCaseOperation5, - } - - if input == nil { - input = &InputService9TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService9TestShapeInputService9TestCaseOperation5Output{} - req.Data = output - return -} - -func (c *InputService9ProtocolTest) InputService9TestCaseOperation5(input *InputService9TestShapeInputShape) (*InputService9TestShapeInputService9TestCaseOperation5Output, error) { - req, out := c.InputService9TestCaseOperation5Request(input) - err := req.Send() - return out, err -} - -const opInputService9TestCaseOperation6 = "OperationName" - -// InputService9TestCaseOperation6Request generates a request for the InputService9TestCaseOperation6 operation. -func (c *InputService9ProtocolTest) InputService9TestCaseOperation6Request(input *InputService9TestShapeInputShape) (req *aws.Request, output *InputService9TestShapeInputService9TestCaseOperation6Output) { - op := &aws.Operation{ - Name: opInputService9TestCaseOperation6, - } - - if input == nil { - input = &InputService9TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService9TestShapeInputService9TestCaseOperation6Output{} - req.Data = output - return -} - -func (c *InputService9ProtocolTest) InputService9TestCaseOperation6(input *InputService9TestShapeInputShape) (*InputService9TestShapeInputService9TestCaseOperation6Output, error) { - req, out := c.InputService9TestCaseOperation6Request(input) - err := req.Send() - return out, err -} - -type InputService9TestShapeInputService9TestCaseOperation1Output struct { - metadataInputService9TestShapeInputService9TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService9TestShapeInputService9TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService9TestShapeInputService9TestCaseOperation2Output struct { - metadataInputService9TestShapeInputService9TestCaseOperation2Output `json:"-" xml:"-"` -} - -type metadataInputService9TestShapeInputService9TestCaseOperation2Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService9TestShapeInputService9TestCaseOperation3Output struct { - metadataInputService9TestShapeInputService9TestCaseOperation3Output `json:"-" xml:"-"` -} - -type metadataInputService9TestShapeInputService9TestCaseOperation3Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService9TestShapeInputService9TestCaseOperation4Output struct { - metadataInputService9TestShapeInputService9TestCaseOperation4Output `json:"-" xml:"-"` -} - -type metadataInputService9TestShapeInputService9TestCaseOperation4Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService9TestShapeInputService9TestCaseOperation5Output struct { - metadataInputService9TestShapeInputService9TestCaseOperation5Output `json:"-" xml:"-"` -} - -type metadataInputService9TestShapeInputService9TestCaseOperation5Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService9TestShapeInputService9TestCaseOperation6Output struct { - metadataInputService9TestShapeInputService9TestCaseOperation6Output `json:"-" xml:"-"` -} - -type metadataInputService9TestShapeInputService9TestCaseOperation6Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService9TestShapeInputShape struct { - RecursiveStruct *InputService9TestShapeRecursiveStructType `type:"structure"` - - metadataInputService9TestShapeInputShape `json:"-" xml:"-"` -} - -type metadataInputService9TestShapeInputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService9TestShapeRecursiveStructType struct { - NoRecurse *string `type:"string"` - - RecursiveList []*InputService9TestShapeRecursiveStructType `type:"list"` - - RecursiveMap map[string]*InputService9TestShapeRecursiveStructType `type:"map"` - - RecursiveStruct *InputService9TestShapeRecursiveStructType `type:"structure"` - - metadataInputService9TestShapeRecursiveStructType `json:"-" xml:"-"` -} - -type metadataInputService9TestShapeRecursiveStructType struct { - SDKShapeTraits bool `type:"structure"` -} - -// -// Tests begin here -// - -func TestInputService1ProtocolTestScalarMembersCase1(t *testing.T) { - svc := NewInputService1ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService1TestShapeInputShape{ - Bar: aws.String("val2"), - Foo: aws.String("val1"), - } - req, _ := svc.InputService1TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&Bar=val2&Foo=val1&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService2ProtocolTestNestedStructureMembersCase1(t *testing.T) { - svc := NewInputService2ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService2TestShapeInputShape{ - StructArg: &InputService2TestShapeStructType{ - ScalarArg: aws.String("foo"), - }, - } - req, _ := svc.InputService2TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&StructArg.ScalarArg=foo&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService3ProtocolTestListTypesCase1(t *testing.T) { - svc := NewInputService3ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService3TestShapeInputShape{ - ListArg: []*string{ - aws.String("foo"), - aws.String("bar"), - aws.String("baz"), - }, - } - req, _ := svc.InputService3TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&ListArg.member.1=foo&ListArg.member.2=bar&ListArg.member.3=baz&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService3ProtocolTestListTypesCase2(t *testing.T) { - svc := NewInputService3ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService3TestShapeInputShape{ - ListArg: []*string{}, - } - req, _ := svc.InputService3TestCaseOperation2Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&ListArg=&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService4ProtocolTestFlattenedListCase1(t *testing.T) { - svc := NewInputService4ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService4TestShapeInputShape{ - ListArg: []*string{ - aws.String("a"), - aws.String("b"), - aws.String("c"), - }, - ScalarArg: aws.String("foo"), - } - req, _ := svc.InputService4TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&ListArg.1=a&ListArg.2=b&ListArg.3=c&ScalarArg=foo&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService4ProtocolTestFlattenedListCase2(t *testing.T) { - svc := NewInputService4ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService4TestShapeInputShape{ - ListArg: []*string{}, - ScalarArg: aws.String("foo"), - } - req, _ := svc.InputService4TestCaseOperation2Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&ListArg=&ScalarArg=foo&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService5ProtocolTestSerializeMapTypeCase1(t *testing.T) { - svc := NewInputService5ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService5TestShapeInputShape{ - MapArg: map[string]*string{ - "key1": aws.String("val1"), - "key2": aws.String("val2"), - }, - } - req, _ := svc.InputService5TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&MapArg.entry.1.key=key1&MapArg.entry.1.value=val1&MapArg.entry.2.key=key2&MapArg.entry.2.value=val2&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService5ProtocolTestSerializeMapTypeCase2(t *testing.T) { - svc := NewInputService5ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService5TestShapeInputShape{ - MapArg: map[string]*string{}, - } - req, _ := svc.InputService5TestCaseOperation2Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&MapArg=&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService6ProtocolTestSerializeMapTypeWithLocationNameCase1(t *testing.T) { - svc := NewInputService6ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService6TestShapeInputShape{ - MapArg: map[string]*string{ - "key1": aws.String("val1"), - "key2": aws.String("val2"), - }, - } - req, _ := svc.InputService6TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&MapArg.entry.1.TheKey=key1&MapArg.entry.1.TheValue=val1&MapArg.entry.2.TheKey=key2&MapArg.entry.2.TheValue=val2&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService7ProtocolTestBase64EncodedBlobsCase1(t *testing.T) { - svc := NewInputService7ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService7TestShapeInputShape{ - BlobArg: []byte("foo"), - } - req, _ := svc.InputService7TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&BlobArg=Zm9v&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService8ProtocolTestTimestampValuesCase1(t *testing.T) { - svc := NewInputService8ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService8TestShapeInputShape{ - TimeArg: aws.Time(time.Unix(1422172800, 0)), - } - req, _ := svc.InputService8TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&TimeArg=2015-01-25T08%3A00%3A00Z&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService9ProtocolTestRecursiveShapesCase1(t *testing.T) { - svc := NewInputService9ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService9TestShapeInputShape{ - RecursiveStruct: &InputService9TestShapeRecursiveStructType{ - NoRecurse: aws.String("foo"), - }, - } - req, _ := svc.InputService9TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&RecursiveStruct.NoRecurse=foo&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService9ProtocolTestRecursiveShapesCase2(t *testing.T) { - svc := NewInputService9ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService9TestShapeInputShape{ - RecursiveStruct: &InputService9TestShapeRecursiveStructType{ - RecursiveStruct: &InputService9TestShapeRecursiveStructType{ - NoRecurse: aws.String("foo"), - }, - }, - } - req, _ := svc.InputService9TestCaseOperation2Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&RecursiveStruct.RecursiveStruct.NoRecurse=foo&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService9ProtocolTestRecursiveShapesCase3(t *testing.T) { - svc := NewInputService9ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService9TestShapeInputShape{ - RecursiveStruct: &InputService9TestShapeRecursiveStructType{ - RecursiveStruct: &InputService9TestShapeRecursiveStructType{ - RecursiveStruct: &InputService9TestShapeRecursiveStructType{ - RecursiveStruct: &InputService9TestShapeRecursiveStructType{ - NoRecurse: aws.String("foo"), - }, - }, - }, - }, - } - req, _ := svc.InputService9TestCaseOperation3Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&RecursiveStruct.RecursiveStruct.RecursiveStruct.RecursiveStruct.NoRecurse=foo&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService9ProtocolTestRecursiveShapesCase4(t *testing.T) { - svc := NewInputService9ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService9TestShapeInputShape{ - RecursiveStruct: &InputService9TestShapeRecursiveStructType{ - RecursiveList: []*InputService9TestShapeRecursiveStructType{ - { - NoRecurse: aws.String("foo"), - }, - { - NoRecurse: aws.String("bar"), - }, - }, - }, - } - req, _ := svc.InputService9TestCaseOperation4Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&RecursiveStruct.RecursiveList.member.1.NoRecurse=foo&RecursiveStruct.RecursiveList.member.2.NoRecurse=bar&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService9ProtocolTestRecursiveShapesCase5(t *testing.T) { - svc := NewInputService9ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService9TestShapeInputShape{ - RecursiveStruct: &InputService9TestShapeRecursiveStructType{ - RecursiveList: []*InputService9TestShapeRecursiveStructType{ - { - NoRecurse: aws.String("foo"), - }, - { - RecursiveStruct: &InputService9TestShapeRecursiveStructType{ - NoRecurse: aws.String("bar"), - }, - }, - }, - }, - } - req, _ := svc.InputService9TestCaseOperation5Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&RecursiveStruct.RecursiveList.member.1.NoRecurse=foo&RecursiveStruct.RecursiveList.member.2.RecursiveStruct.NoRecurse=bar&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService9ProtocolTestRecursiveShapesCase6(t *testing.T) { - svc := NewInputService9ProtocolTest(nil) - svc.Endpoint = "https://test" - - input := &InputService9TestShapeInputShape{ - RecursiveStruct: &InputService9TestShapeRecursiveStructType{ - RecursiveMap: map[string]*InputService9TestShapeRecursiveStructType{ - "bar": { - NoRecurse: aws.String("bar"), - }, - "foo": { - NoRecurse: aws.String("foo"), - }, - }, - }, - } - req, _ := svc.InputService9TestCaseOperation6Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - assert.Equal(t, util.Trim(`Action=OperationName&RecursiveStruct.RecursiveMap.entry.1.key=bar&RecursiveStruct.RecursiveMap.entry.1.value.NoRecurse=bar&RecursiveStruct.RecursiveMap.entry.2.key=foo&RecursiveStruct.RecursiveMap.entry.2.value.NoRecurse=foo&Version=2014-01-01`), util.Trim(string(body))) - - // assert URL - assert.Equal(t, "https://test/", r.URL.String()) - - // assert headers - -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/query/queryutil/queryutil.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/query/queryutil/queryutil.go deleted file mode 100644 index 3b417a89f71..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/query/queryutil/queryutil.go +++ /dev/null @@ -1,223 +0,0 @@ -package queryutil - -import ( - "encoding/base64" - "fmt" - "net/url" - "reflect" - "sort" - "strconv" - "strings" - "time" -) - -// Parse parses an object i and fills a url.Values object. The isEC2 flag -// indicates if this is the EC2 Query sub-protocol. -func Parse(body url.Values, i interface{}, isEC2 bool) error { - q := queryParser{isEC2: isEC2} - return q.parseValue(body, reflect.ValueOf(i), "", "") -} - -func elemOf(value reflect.Value) reflect.Value { - for value.Kind() == reflect.Ptr { - value = value.Elem() - } - return value -} - -type queryParser struct { - isEC2 bool -} - -func (q *queryParser) parseValue(v url.Values, value reflect.Value, prefix string, tag reflect.StructTag) error { - value = elemOf(value) - - // no need to handle zero values - if !value.IsValid() { - return nil - } - - t := tag.Get("type") - if t == "" { - switch value.Kind() { - case reflect.Struct: - t = "structure" - case reflect.Slice: - t = "list" - case reflect.Map: - t = "map" - } - } - - switch t { - case "structure": - return q.parseStruct(v, value, prefix) - case "list": - return q.parseList(v, value, prefix, tag) - case "map": - return q.parseMap(v, value, prefix, tag) - default: - return q.parseScalar(v, value, prefix, tag) - } -} - -func (q *queryParser) parseStruct(v url.Values, value reflect.Value, prefix string) error { - if !value.IsValid() { - return nil - } - - t := value.Type() - for i := 0; i < value.NumField(); i++ { - if c := t.Field(i).Name[0:1]; strings.ToLower(c) == c { - continue // ignore unexported fields - } - - value := elemOf(value.Field(i)) - field := t.Field(i) - var name string - - if q.isEC2 { - name = field.Tag.Get("queryName") - } - if name == "" { - if field.Tag.Get("flattened") != "" && field.Tag.Get("locationNameList") != "" { - name = field.Tag.Get("locationNameList") - } else if locName := field.Tag.Get("locationName"); locName != "" { - name = locName - } - if name != "" && q.isEC2 { - name = strings.ToUpper(name[0:1]) + name[1:] - } - } - if name == "" { - name = field.Name - } - - if prefix != "" { - name = prefix + "." + name - } - - if err := q.parseValue(v, value, name, field.Tag); err != nil { - return err - } - } - return nil -} - -func (q *queryParser) parseList(v url.Values, value reflect.Value, prefix string, tag reflect.StructTag) error { - // If it's empty, generate an empty value - if !value.IsNil() && value.Len() == 0 { - v.Set(prefix, "") - return nil - } - - // check for unflattened list member - if !q.isEC2 && tag.Get("flattened") == "" { - prefix += ".member" - } - - for i := 0; i < value.Len(); i++ { - slicePrefix := prefix - if slicePrefix == "" { - slicePrefix = strconv.Itoa(i + 1) - } else { - slicePrefix = slicePrefix + "." + strconv.Itoa(i+1) - } - if err := q.parseValue(v, value.Index(i), slicePrefix, ""); err != nil { - return err - } - } - return nil -} - -func (q *queryParser) parseMap(v url.Values, value reflect.Value, prefix string, tag reflect.StructTag) error { - // If it's empty, generate an empty value - if !value.IsNil() && value.Len() == 0 { - v.Set(prefix, "") - return nil - } - - // check for unflattened list member - if !q.isEC2 && tag.Get("flattened") == "" { - prefix += ".entry" - } - - // sort keys for improved serialization consistency. - // this is not strictly necessary for protocol support. - mapKeyValues := value.MapKeys() - mapKeys := map[string]reflect.Value{} - mapKeyNames := make([]string, len(mapKeyValues)) - for i, mapKey := range mapKeyValues { - name := mapKey.String() - mapKeys[name] = mapKey - mapKeyNames[i] = name - } - sort.Strings(mapKeyNames) - - for i, mapKeyName := range mapKeyNames { - mapKey := mapKeys[mapKeyName] - mapValue := value.MapIndex(mapKey) - - kname := tag.Get("locationNameKey") - if kname == "" { - kname = "key" - } - vname := tag.Get("locationNameValue") - if vname == "" { - vname = "value" - } - - // serialize key - var keyName string - if prefix == "" { - keyName = strconv.Itoa(i+1) + "." + kname - } else { - keyName = prefix + "." + strconv.Itoa(i+1) + "." + kname - } - - if err := q.parseValue(v, mapKey, keyName, ""); err != nil { - return err - } - - // serialize value - var valueName string - if prefix == "" { - valueName = strconv.Itoa(i+1) + "." + vname - } else { - valueName = prefix + "." + strconv.Itoa(i+1) + "." + vname - } - - if err := q.parseValue(v, mapValue, valueName, ""); err != nil { - return err - } - } - - return nil -} - -func (q *queryParser) parseScalar(v url.Values, r reflect.Value, name string, tag reflect.StructTag) error { - switch value := r.Interface().(type) { - case string: - v.Set(name, value) - case []byte: - if !r.IsNil() { - v.Set(name, base64.StdEncoding.EncodeToString(value)) - } - case bool: - v.Set(name, strconv.FormatBool(value)) - case int64: - v.Set(name, strconv.FormatInt(value, 10)) - case int: - v.Set(name, strconv.Itoa(value)) - case float64: - v.Set(name, strconv.FormatFloat(value, 'f', -1, 64)) - case float32: - v.Set(name, strconv.FormatFloat(float64(value), 'f', -1, 32)) - case time.Time: - const ISO8601UTC = "2006-01-02T15:04:05Z" - v.Set(name, value.UTC().Format(ISO8601UTC)) - default: - return fmt.Errorf("unsupported value for param %s: %v (%s)", name, r.Interface(), r.Type().Name()) - } - return nil -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/query/unmarshal.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/query/unmarshal.go deleted file mode 100644 index e8cfa926b65..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/query/unmarshal.go +++ /dev/null @@ -1,29 +0,0 @@ -package query - -//go:generate go run ../../fixtures/protocol/generate.go ../../fixtures/protocol/output/query.json unmarshal_test.go - -import ( - "encoding/xml" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil" -) - -// Unmarshal unmarshals a response for an AWS Query service. -func Unmarshal(r *aws.Request) { - defer r.HTTPResponse.Body.Close() - if r.DataFilled() { - decoder := xml.NewDecoder(r.HTTPResponse.Body) - err := xmlutil.UnmarshalXML(r.Data, decoder, r.Operation.Name+"Result") - if err != nil { - r.Error = awserr.New("SerializationError", "failed decoding Query response", err) - return - } - } -} - -// UnmarshalMeta unmarshals header response values for an AWS Query service. -func UnmarshalMeta(r *aws.Request) { - // TODO implement unmarshaling of request IDs -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/query/unmarshal_error.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/query/unmarshal_error.go deleted file mode 100644 index d88ee335805..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/query/unmarshal_error.go +++ /dev/null @@ -1,33 +0,0 @@ -package query - -import ( - "encoding/xml" - "io" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" -) - -type xmlErrorResponse struct { - XMLName xml.Name `xml:"ErrorResponse"` - Code string `xml:"Error>Code"` - Message string `xml:"Error>Message"` - RequestID string `xml:"RequestId"` -} - -// UnmarshalError unmarshals an error response for an AWS Query service. -func UnmarshalError(r *aws.Request) { - defer r.HTTPResponse.Body.Close() - - resp := &xmlErrorResponse{} - err := xml.NewDecoder(r.HTTPResponse.Body).Decode(resp) - if err != nil && err != io.EOF { - r.Error = awserr.New("SerializationError", "failed to decode query XML error response", err) - } else { - r.Error = awserr.NewRequestFailure( - awserr.New(resp.Code, resp.Message, nil), - r.HTTPResponse.StatusCode, - resp.RequestID, - ) - } -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/query/unmarshal_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/query/unmarshal_test.go deleted file mode 100644 index a44060ce8fe..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/query/unmarshal_test.go +++ /dev/null @@ -1,1418 +0,0 @@ -package query_test - -import ( - "bytes" - "encoding/json" - "encoding/xml" - "io" - "io/ioutil" - "net/http" - "net/url" - "testing" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/internal/protocol/query" - "github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil" - "github.com/aws/aws-sdk-go/internal/signer/v4" - "github.com/aws/aws-sdk-go/internal/util" - "github.com/stretchr/testify/assert" -) - -var _ bytes.Buffer // always import bytes -var _ http.Request -var _ json.Marshaler -var _ time.Time -var _ xmlutil.XMLNode -var _ xml.Attr -var _ = ioutil.Discard -var _ = util.Trim("") -var _ = url.Values{} -var _ = io.EOF - -type OutputService1ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService1ProtocolTest client. -func NewOutputService1ProtocolTest(config *aws.Config) *OutputService1ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice1protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &OutputService1ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService1ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService1ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService1TestCaseOperation1 = "OperationName" - -// OutputService1TestCaseOperation1Request generates a request for the OutputService1TestCaseOperation1 operation. -func (c *OutputService1ProtocolTest) OutputService1TestCaseOperation1Request(input *OutputService1TestShapeOutputService1TestCaseOperation1Input) (req *aws.Request, output *OutputService1TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService1TestCaseOperation1, - } - - if input == nil { - input = &OutputService1TestShapeOutputService1TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService1TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService1ProtocolTest) OutputService1TestCaseOperation1(input *OutputService1TestShapeOutputService1TestCaseOperation1Input) (*OutputService1TestShapeOutputShape, error) { - req, out := c.OutputService1TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService1TestShapeOutputService1TestCaseOperation1Input struct { - metadataOutputService1TestShapeOutputService1TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService1TestShapeOutputService1TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService1TestShapeOutputShape struct { - Char *string `type:"character"` - - Double *float64 `type:"double"` - - FalseBool *bool `type:"boolean"` - - Float *float64 `type:"float"` - - Long *int64 `type:"long"` - - Num *int64 `locationName:"FooNum" type:"integer"` - - Str *string `type:"string"` - - Timestamp *time.Time `type:"timestamp" timestampFormat:"iso8601"` - - TrueBool *bool `type:"boolean"` - - metadataOutputService1TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService1TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService2ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService2ProtocolTest client. -func NewOutputService2ProtocolTest(config *aws.Config) *OutputService2ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice2protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &OutputService2ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService2ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService2ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService2TestCaseOperation1 = "OperationName" - -// OutputService2TestCaseOperation1Request generates a request for the OutputService2TestCaseOperation1 operation. -func (c *OutputService2ProtocolTest) OutputService2TestCaseOperation1Request(input *OutputService2TestShapeOutputService2TestCaseOperation1Input) (req *aws.Request, output *OutputService2TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService2TestCaseOperation1, - } - - if input == nil { - input = &OutputService2TestShapeOutputService2TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService2TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService2ProtocolTest) OutputService2TestCaseOperation1(input *OutputService2TestShapeOutputService2TestCaseOperation1Input) (*OutputService2TestShapeOutputShape, error) { - req, out := c.OutputService2TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService2TestShapeOutputService2TestCaseOperation1Input struct { - metadataOutputService2TestShapeOutputService2TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService2TestShapeOutputService2TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService2TestShapeOutputShape struct { - Num *int64 `type:"integer"` - - Str *string `type:"string"` - - metadataOutputService2TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService2TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService3ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService3ProtocolTest client. -func NewOutputService3ProtocolTest(config *aws.Config) *OutputService3ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice3protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &OutputService3ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService3ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService3ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService3TestCaseOperation1 = "OperationName" - -// OutputService3TestCaseOperation1Request generates a request for the OutputService3TestCaseOperation1 operation. -func (c *OutputService3ProtocolTest) OutputService3TestCaseOperation1Request(input *OutputService3TestShapeOutputService3TestCaseOperation1Input) (req *aws.Request, output *OutputService3TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService3TestCaseOperation1, - } - - if input == nil { - input = &OutputService3TestShapeOutputService3TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService3TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService3ProtocolTest) OutputService3TestCaseOperation1(input *OutputService3TestShapeOutputService3TestCaseOperation1Input) (*OutputService3TestShapeOutputShape, error) { - req, out := c.OutputService3TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService3TestShapeOutputService3TestCaseOperation1Input struct { - metadataOutputService3TestShapeOutputService3TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService3TestShapeOutputService3TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService3TestShapeOutputShape struct { - Blob []byte `type:"blob"` - - metadataOutputService3TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService3TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService4ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService4ProtocolTest client. -func NewOutputService4ProtocolTest(config *aws.Config) *OutputService4ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice4protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &OutputService4ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService4ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService4ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService4TestCaseOperation1 = "OperationName" - -// OutputService4TestCaseOperation1Request generates a request for the OutputService4TestCaseOperation1 operation. -func (c *OutputService4ProtocolTest) OutputService4TestCaseOperation1Request(input *OutputService4TestShapeOutputService4TestCaseOperation1Input) (req *aws.Request, output *OutputService4TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService4TestCaseOperation1, - } - - if input == nil { - input = &OutputService4TestShapeOutputService4TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService4TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService4ProtocolTest) OutputService4TestCaseOperation1(input *OutputService4TestShapeOutputService4TestCaseOperation1Input) (*OutputService4TestShapeOutputShape, error) { - req, out := c.OutputService4TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService4TestShapeOutputService4TestCaseOperation1Input struct { - metadataOutputService4TestShapeOutputService4TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService4TestShapeOutputService4TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService4TestShapeOutputShape struct { - ListMember []*string `type:"list"` - - metadataOutputService4TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService4TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService5ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService5ProtocolTest client. -func NewOutputService5ProtocolTest(config *aws.Config) *OutputService5ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice5protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &OutputService5ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService5ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService5ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService5TestCaseOperation1 = "OperationName" - -// OutputService5TestCaseOperation1Request generates a request for the OutputService5TestCaseOperation1 operation. -func (c *OutputService5ProtocolTest) OutputService5TestCaseOperation1Request(input *OutputService5TestShapeOutputService5TestCaseOperation1Input) (req *aws.Request, output *OutputService5TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService5TestCaseOperation1, - } - - if input == nil { - input = &OutputService5TestShapeOutputService5TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService5TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService5ProtocolTest) OutputService5TestCaseOperation1(input *OutputService5TestShapeOutputService5TestCaseOperation1Input) (*OutputService5TestShapeOutputShape, error) { - req, out := c.OutputService5TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService5TestShapeOutputService5TestCaseOperation1Input struct { - metadataOutputService5TestShapeOutputService5TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService5TestShapeOutputService5TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService5TestShapeOutputShape struct { - ListMember []*string `locationNameList:"item" type:"list"` - - metadataOutputService5TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService5TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService6ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService6ProtocolTest client. -func NewOutputService6ProtocolTest(config *aws.Config) *OutputService6ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice6protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &OutputService6ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService6ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService6ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService6TestCaseOperation1 = "OperationName" - -// OutputService6TestCaseOperation1Request generates a request for the OutputService6TestCaseOperation1 operation. -func (c *OutputService6ProtocolTest) OutputService6TestCaseOperation1Request(input *OutputService6TestShapeOutputService6TestCaseOperation1Input) (req *aws.Request, output *OutputService6TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService6TestCaseOperation1, - } - - if input == nil { - input = &OutputService6TestShapeOutputService6TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService6TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService6ProtocolTest) OutputService6TestCaseOperation1(input *OutputService6TestShapeOutputService6TestCaseOperation1Input) (*OutputService6TestShapeOutputShape, error) { - req, out := c.OutputService6TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService6TestShapeOutputService6TestCaseOperation1Input struct { - metadataOutputService6TestShapeOutputService6TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService6TestShapeOutputService6TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService6TestShapeOutputShape struct { - ListMember []*string `type:"list" flattened:"true"` - - metadataOutputService6TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService6TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService7ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService7ProtocolTest client. -func NewOutputService7ProtocolTest(config *aws.Config) *OutputService7ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice7protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &OutputService7ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService7ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService7ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService7TestCaseOperation1 = "OperationName" - -// OutputService7TestCaseOperation1Request generates a request for the OutputService7TestCaseOperation1 operation. -func (c *OutputService7ProtocolTest) OutputService7TestCaseOperation1Request(input *OutputService7TestShapeOutputService7TestCaseOperation1Input) (req *aws.Request, output *OutputService7TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService7TestCaseOperation1, - } - - if input == nil { - input = &OutputService7TestShapeOutputService7TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService7TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService7ProtocolTest) OutputService7TestCaseOperation1(input *OutputService7TestShapeOutputService7TestCaseOperation1Input) (*OutputService7TestShapeOutputShape, error) { - req, out := c.OutputService7TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService7TestShapeOutputService7TestCaseOperation1Input struct { - metadataOutputService7TestShapeOutputService7TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService7TestShapeOutputService7TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService7TestShapeOutputShape struct { - ListMember []*string `type:"list" flattened:"true"` - - metadataOutputService7TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService7TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService8ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService8ProtocolTest client. -func NewOutputService8ProtocolTest(config *aws.Config) *OutputService8ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice8protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &OutputService8ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService8ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService8ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService8TestCaseOperation1 = "OperationName" - -// OutputService8TestCaseOperation1Request generates a request for the OutputService8TestCaseOperation1 operation. -func (c *OutputService8ProtocolTest) OutputService8TestCaseOperation1Request(input *OutputService8TestShapeOutputService8TestCaseOperation1Input) (req *aws.Request, output *OutputService8TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService8TestCaseOperation1, - } - - if input == nil { - input = &OutputService8TestShapeOutputService8TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService8TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService8ProtocolTest) OutputService8TestCaseOperation1(input *OutputService8TestShapeOutputService8TestCaseOperation1Input) (*OutputService8TestShapeOutputShape, error) { - req, out := c.OutputService8TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService8TestShapeOutputService8TestCaseOperation1Input struct { - metadataOutputService8TestShapeOutputService8TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService8TestShapeOutputService8TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService8TestShapeOutputShape struct { - List []*OutputService8TestShapeStructureShape `type:"list"` - - metadataOutputService8TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService8TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService8TestShapeStructureShape struct { - Bar *string `type:"string"` - - Baz *string `type:"string"` - - Foo *string `type:"string"` - - metadataOutputService8TestShapeStructureShape `json:"-" xml:"-"` -} - -type metadataOutputService8TestShapeStructureShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService9ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService9ProtocolTest client. -func NewOutputService9ProtocolTest(config *aws.Config) *OutputService9ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice9protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &OutputService9ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService9ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService9ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService9TestCaseOperation1 = "OperationName" - -// OutputService9TestCaseOperation1Request generates a request for the OutputService9TestCaseOperation1 operation. -func (c *OutputService9ProtocolTest) OutputService9TestCaseOperation1Request(input *OutputService9TestShapeOutputService9TestCaseOperation1Input) (req *aws.Request, output *OutputService9TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService9TestCaseOperation1, - } - - if input == nil { - input = &OutputService9TestShapeOutputService9TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService9TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService9ProtocolTest) OutputService9TestCaseOperation1(input *OutputService9TestShapeOutputService9TestCaseOperation1Input) (*OutputService9TestShapeOutputShape, error) { - req, out := c.OutputService9TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService9TestShapeOutputService9TestCaseOperation1Input struct { - metadataOutputService9TestShapeOutputService9TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService9TestShapeOutputService9TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService9TestShapeOutputShape struct { - List []*OutputService9TestShapeStructureShape `type:"list" flattened:"true"` - - metadataOutputService9TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService9TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService9TestShapeStructureShape struct { - Bar *string `type:"string"` - - Baz *string `type:"string"` - - Foo *string `type:"string"` - - metadataOutputService9TestShapeStructureShape `json:"-" xml:"-"` -} - -type metadataOutputService9TestShapeStructureShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService10ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService10ProtocolTest client. -func NewOutputService10ProtocolTest(config *aws.Config) *OutputService10ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice10protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &OutputService10ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService10ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService10ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService10TestCaseOperation1 = "OperationName" - -// OutputService10TestCaseOperation1Request generates a request for the OutputService10TestCaseOperation1 operation. -func (c *OutputService10ProtocolTest) OutputService10TestCaseOperation1Request(input *OutputService10TestShapeOutputService10TestCaseOperation1Input) (req *aws.Request, output *OutputService10TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService10TestCaseOperation1, - } - - if input == nil { - input = &OutputService10TestShapeOutputService10TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService10TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService10ProtocolTest) OutputService10TestCaseOperation1(input *OutputService10TestShapeOutputService10TestCaseOperation1Input) (*OutputService10TestShapeOutputShape, error) { - req, out := c.OutputService10TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService10TestShapeOutputService10TestCaseOperation1Input struct { - metadataOutputService10TestShapeOutputService10TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService10TestShapeOutputService10TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService10TestShapeOutputShape struct { - List []*string `locationNameList:"NamedList" type:"list" flattened:"true"` - - metadataOutputService10TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService10TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService11ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService11ProtocolTest client. -func NewOutputService11ProtocolTest(config *aws.Config) *OutputService11ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice11protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &OutputService11ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService11ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService11ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService11TestCaseOperation1 = "OperationName" - -// OutputService11TestCaseOperation1Request generates a request for the OutputService11TestCaseOperation1 operation. -func (c *OutputService11ProtocolTest) OutputService11TestCaseOperation1Request(input *OutputService11TestShapeOutputService11TestCaseOperation1Input) (req *aws.Request, output *OutputService11TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService11TestCaseOperation1, - } - - if input == nil { - input = &OutputService11TestShapeOutputService11TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService11TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService11ProtocolTest) OutputService11TestCaseOperation1(input *OutputService11TestShapeOutputService11TestCaseOperation1Input) (*OutputService11TestShapeOutputShape, error) { - req, out := c.OutputService11TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService11TestShapeOutputService11TestCaseOperation1Input struct { - metadataOutputService11TestShapeOutputService11TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService11TestShapeOutputService11TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService11TestShapeOutputShape struct { - Map map[string]*OutputService11TestShapeStructType `type:"map"` - - metadataOutputService11TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService11TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService11TestShapeStructType struct { - Foo *string `locationName:"foo" type:"string"` - - metadataOutputService11TestShapeStructType `json:"-" xml:"-"` -} - -type metadataOutputService11TestShapeStructType struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService12ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService12ProtocolTest client. -func NewOutputService12ProtocolTest(config *aws.Config) *OutputService12ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice12protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &OutputService12ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService12ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService12ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService12TestCaseOperation1 = "OperationName" - -// OutputService12TestCaseOperation1Request generates a request for the OutputService12TestCaseOperation1 operation. -func (c *OutputService12ProtocolTest) OutputService12TestCaseOperation1Request(input *OutputService12TestShapeOutputService12TestCaseOperation1Input) (req *aws.Request, output *OutputService12TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService12TestCaseOperation1, - } - - if input == nil { - input = &OutputService12TestShapeOutputService12TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService12TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService12ProtocolTest) OutputService12TestCaseOperation1(input *OutputService12TestShapeOutputService12TestCaseOperation1Input) (*OutputService12TestShapeOutputShape, error) { - req, out := c.OutputService12TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService12TestShapeOutputService12TestCaseOperation1Input struct { - metadataOutputService12TestShapeOutputService12TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService12TestShapeOutputService12TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService12TestShapeOutputShape struct { - Map map[string]*string `type:"map" flattened:"true"` - - metadataOutputService12TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService12TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService13ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService13ProtocolTest client. -func NewOutputService13ProtocolTest(config *aws.Config) *OutputService13ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice13protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &OutputService13ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService13ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService13ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService13TestCaseOperation1 = "OperationName" - -// OutputService13TestCaseOperation1Request generates a request for the OutputService13TestCaseOperation1 operation. -func (c *OutputService13ProtocolTest) OutputService13TestCaseOperation1Request(input *OutputService13TestShapeOutputService13TestCaseOperation1Input) (req *aws.Request, output *OutputService13TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService13TestCaseOperation1, - } - - if input == nil { - input = &OutputService13TestShapeOutputService13TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService13TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService13ProtocolTest) OutputService13TestCaseOperation1(input *OutputService13TestShapeOutputService13TestCaseOperation1Input) (*OutputService13TestShapeOutputShape, error) { - req, out := c.OutputService13TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService13TestShapeOutputService13TestCaseOperation1Input struct { - metadataOutputService13TestShapeOutputService13TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService13TestShapeOutputService13TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService13TestShapeOutputShape struct { - Map map[string]*string `locationName:"Attribute" locationNameKey:"Name" locationNameValue:"Value" type:"map" flattened:"true"` - - metadataOutputService13TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService13TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService14ProtocolTest struct { - *aws.Service -} - -// New returns a new OutputService14ProtocolTest client. -func NewOutputService14ProtocolTest(config *aws.Config) *OutputService14ProtocolTest { - service := &aws.Service{ - Config: aws.DefaultConfig.Merge(config), - ServiceName: "outputservice14protocoltest", - APIVersion: "", - } - service.Initialize() - - // Handlers - service.Handlers.Sign.PushBack(v4.Sign) - service.Handlers.Build.PushBack(query.Build) - service.Handlers.Unmarshal.PushBack(query.Unmarshal) - service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - service.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return &OutputService14ProtocolTest{service} -} - -// newRequest creates a new request for a OutputService14ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService14ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { - req := aws.NewRequest(c.Service, op, params, data) - - return req -} - -const opOutputService14TestCaseOperation1 = "OperationName" - -// OutputService14TestCaseOperation1Request generates a request for the OutputService14TestCaseOperation1 operation. -func (c *OutputService14ProtocolTest) OutputService14TestCaseOperation1Request(input *OutputService14TestShapeOutputService14TestCaseOperation1Input) (req *aws.Request, output *OutputService14TestShapeOutputShape) { - op := &aws.Operation{ - Name: opOutputService14TestCaseOperation1, - } - - if input == nil { - input = &OutputService14TestShapeOutputService14TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService14TestShapeOutputShape{} - req.Data = output - return -} - -func (c *OutputService14ProtocolTest) OutputService14TestCaseOperation1(input *OutputService14TestShapeOutputService14TestCaseOperation1Input) (*OutputService14TestShapeOutputShape, error) { - req, out := c.OutputService14TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService14TestShapeOutputService14TestCaseOperation1Input struct { - metadataOutputService14TestShapeOutputService14TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService14TestShapeOutputService14TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService14TestShapeOutputShape struct { - Map map[string]*string `locationNameKey:"foo" locationNameValue:"bar" type:"map" flattened:"true"` - - metadataOutputService14TestShapeOutputShape `json:"-" xml:"-"` -} - -type metadataOutputService14TestShapeOutputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -// -// Tests begin here -// - -func TestOutputService1ProtocolTestScalarMembersCase1(t *testing.T) { - svc := NewOutputService1ProtocolTest(nil) - - buf := bytes.NewReader([]byte("myname123falsetrue1.21.3200a2015-01-25T08:00:00Zrequest-id")) - req, out := svc.OutputService1TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "a", *out.Char) - assert.Equal(t, 1.3, *out.Double) - assert.Equal(t, false, *out.FalseBool) - assert.Equal(t, 1.2, *out.Float) - assert.Equal(t, int64(200), *out.Long) - assert.Equal(t, int64(123), *out.Num) - assert.Equal(t, "myname", *out.Str) - assert.Equal(t, time.Unix(1.4221728e+09, 0).UTC().String(), out.Timestamp.String()) - assert.Equal(t, true, *out.TrueBool) - -} - -func TestOutputService2ProtocolTestNotAllMembersInResponseCase1(t *testing.T) { - svc := NewOutputService2ProtocolTest(nil) - - buf := bytes.NewReader([]byte("mynamerequest-id")) - req, out := svc.OutputService2TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "myname", *out.Str) - -} - -func TestOutputService3ProtocolTestBlobCase1(t *testing.T) { - svc := NewOutputService3ProtocolTest(nil) - - buf := bytes.NewReader([]byte("dmFsdWU=requestid")) - req, out := svc.OutputService3TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "value", string(out.Blob)) - -} - -func TestOutputService4ProtocolTestListsCase1(t *testing.T) { - svc := NewOutputService4ProtocolTest(nil) - - buf := bytes.NewReader([]byte("abc123requestid")) - req, out := svc.OutputService4TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "abc", *out.ListMember[0]) - assert.Equal(t, "123", *out.ListMember[1]) - -} - -func TestOutputService5ProtocolTestListWithCustomMemberNameCase1(t *testing.T) { - svc := NewOutputService5ProtocolTest(nil) - - buf := bytes.NewReader([]byte("abc123requestid")) - req, out := svc.OutputService5TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "abc", *out.ListMember[0]) - assert.Equal(t, "123", *out.ListMember[1]) - -} - -func TestOutputService6ProtocolTestFlattenedListCase1(t *testing.T) { - svc := NewOutputService6ProtocolTest(nil) - - buf := bytes.NewReader([]byte("abc123requestid")) - req, out := svc.OutputService6TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "abc", *out.ListMember[0]) - assert.Equal(t, "123", *out.ListMember[1]) - -} - -func TestOutputService7ProtocolTestFlattenedSingleElementListCase1(t *testing.T) { - svc := NewOutputService7ProtocolTest(nil) - - buf := bytes.NewReader([]byte("abcrequestid")) - req, out := svc.OutputService7TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "abc", *out.ListMember[0]) - -} - -func TestOutputService8ProtocolTestListOfStructuresCase1(t *testing.T) { - svc := NewOutputService8ProtocolTest(nil) - - buf := bytes.NewReader([]byte("firstfoofirstbarfirstbazsecondfoosecondbarsecondbazrequestid")) - req, out := svc.OutputService8TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "firstbar", *out.List[0].Bar) - assert.Equal(t, "firstbaz", *out.List[0].Baz) - assert.Equal(t, "firstfoo", *out.List[0].Foo) - assert.Equal(t, "secondbar", *out.List[1].Bar) - assert.Equal(t, "secondbaz", *out.List[1].Baz) - assert.Equal(t, "secondfoo", *out.List[1].Foo) - -} - -func TestOutputService9ProtocolTestFlattenedListOfStructuresCase1(t *testing.T) { - svc := NewOutputService9ProtocolTest(nil) - - buf := bytes.NewReader([]byte("firstfoofirstbarfirstbazsecondfoosecondbarsecondbazrequestid")) - req, out := svc.OutputService9TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "firstbar", *out.List[0].Bar) - assert.Equal(t, "firstbaz", *out.List[0].Baz) - assert.Equal(t, "firstfoo", *out.List[0].Foo) - assert.Equal(t, "secondbar", *out.List[1].Bar) - assert.Equal(t, "secondbaz", *out.List[1].Baz) - assert.Equal(t, "secondfoo", *out.List[1].Foo) - -} - -func TestOutputService10ProtocolTestFlattenedListWithLocationNameCase1(t *testing.T) { - svc := NewOutputService10ProtocolTest(nil) - - buf := bytes.NewReader([]byte("abrequestid")) - req, out := svc.OutputService10TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "a", *out.List[0]) - assert.Equal(t, "b", *out.List[1]) - -} - -func TestOutputService11ProtocolTestNormalMapCase1(t *testing.T) { - svc := NewOutputService11ProtocolTest(nil) - - buf := bytes.NewReader([]byte("quxbarbazbamrequestid")) - req, out := svc.OutputService11TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "bam", *out.Map["baz"].Foo) - assert.Equal(t, "bar", *out.Map["qux"].Foo) - -} - -func TestOutputService12ProtocolTestFlattenedMapCase1(t *testing.T) { - svc := NewOutputService12ProtocolTest(nil) - - buf := bytes.NewReader([]byte("quxbarbazbamrequestid")) - req, out := svc.OutputService12TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "bam", *out.Map["baz"]) - assert.Equal(t, "bar", *out.Map["qux"]) - -} - -func TestOutputService13ProtocolTestFlattenedMapInShapeDefinitionCase1(t *testing.T) { - svc := NewOutputService13ProtocolTest(nil) - - buf := bytes.NewReader([]byte("quxbarrequestid")) - req, out := svc.OutputService13TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "bar", *out.Map["qux"]) - -} - -func TestOutputService14ProtocolTestNamedMapCase1(t *testing.T) { - svc := NewOutputService14ProtocolTest(nil) - - buf := bytes.NewReader([]byte("quxbarbazbamrequestid")) - req, out := svc.OutputService14TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "bam", *out.Map["baz"]) - assert.Equal(t, "bar", *out.Map["qux"]) - -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/rest/build.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/rest/build.go deleted file mode 100644 index 8917ad7a9bc..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/rest/build.go +++ /dev/null @@ -1,217 +0,0 @@ -// Package rest provides RESTful serialisation of AWS requests and responses. -package rest - -import ( - "bytes" - "encoding/base64" - "fmt" - "io" - "net/url" - "path" - "reflect" - "strconv" - "strings" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" -) - -// RFC822 returns an RFC822 formatted timestamp for AWS protocols -const RFC822 = "Mon, 2 Jan 2006 15:04:05 GMT" - -// Whether the byte value can be sent without escaping in AWS URLs -var noEscape [256]bool - -func init() { - for i := 0; i < len(noEscape); i++ { - // AWS expects every character except these to be escaped - noEscape[i] = (i >= 'A' && i <= 'Z') || - (i >= 'a' && i <= 'z') || - (i >= '0' && i <= '9') || - i == '-' || - i == '.' || - i == '_' || - i == '~' - } -} - -// Build builds the REST component of a service request. -func Build(r *aws.Request) { - if r.ParamsFilled() { - v := reflect.ValueOf(r.Params).Elem() - buildLocationElements(r, v) - buildBody(r, v) - } -} - -func buildLocationElements(r *aws.Request, v reflect.Value) { - query := r.HTTPRequest.URL.Query() - - for i := 0; i < v.NumField(); i++ { - m := v.Field(i) - if n := v.Type().Field(i).Name; n[0:1] == strings.ToLower(n[0:1]) { - continue - } - - if m.IsValid() { - field := v.Type().Field(i) - name := field.Tag.Get("locationName") - if name == "" { - name = field.Name - } - if m.Kind() == reflect.Ptr { - m = m.Elem() - } - if !m.IsValid() { - continue - } - - switch field.Tag.Get("location") { - case "headers": // header maps - buildHeaderMap(r, m, field.Tag.Get("locationName")) - case "header": - buildHeader(r, m, name) - case "uri": - buildURI(r, m, name) - case "querystring": - buildQueryString(r, m, name, query) - } - } - if r.Error != nil { - return - } - } - - r.HTTPRequest.URL.RawQuery = query.Encode() - updatePath(r.HTTPRequest.URL, r.HTTPRequest.URL.Path) -} - -func buildBody(r *aws.Request, v reflect.Value) { - if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok { - if payloadName := field.Tag.Get("payload"); payloadName != "" { - pfield, _ := v.Type().FieldByName(payloadName) - if ptag := pfield.Tag.Get("type"); ptag != "" && ptag != "structure" { - payload := reflect.Indirect(v.FieldByName(payloadName)) - if payload.IsValid() && payload.Interface() != nil { - switch reader := payload.Interface().(type) { - case io.ReadSeeker: - r.SetReaderBody(reader) - case []byte: - r.SetBufferBody(reader) - case string: - r.SetStringBody(reader) - default: - r.Error = awserr.New("SerializationError", - "failed to encode REST request", - fmt.Errorf("unknown payload type %s", payload.Type())) - } - } - } - } - } -} - -func buildHeader(r *aws.Request, v reflect.Value, name string) { - str, err := convertType(v) - if err != nil { - r.Error = awserr.New("SerializationError", "failed to encode REST request", err) - } else if str != nil { - r.HTTPRequest.Header.Add(name, *str) - } -} - -func buildHeaderMap(r *aws.Request, v reflect.Value, prefix string) { - for _, key := range v.MapKeys() { - str, err := convertType(v.MapIndex(key)) - if err != nil { - r.Error = awserr.New("SerializationError", "failed to encode REST request", err) - } else if str != nil { - r.HTTPRequest.Header.Add(prefix+key.String(), *str) - } - } -} - -func buildURI(r *aws.Request, v reflect.Value, name string) { - value, err := convertType(v) - if err != nil { - r.Error = awserr.New("SerializationError", "failed to encode REST request", err) - } else if value != nil { - uri := r.HTTPRequest.URL.Path - uri = strings.Replace(uri, "{"+name+"}", EscapePath(*value, true), -1) - uri = strings.Replace(uri, "{"+name+"+}", EscapePath(*value, false), -1) - r.HTTPRequest.URL.Path = uri - } -} - -func buildQueryString(r *aws.Request, v reflect.Value, name string, query url.Values) { - str, err := convertType(v) - if err != nil { - r.Error = awserr.New("SerializationError", "failed to encode REST request", err) - } else if str != nil { - query.Set(name, *str) - } -} - -func updatePath(url *url.URL, urlPath string) { - scheme, query := url.Scheme, url.RawQuery - - hasSlash := strings.HasSuffix(urlPath, "/") - - // clean up path - urlPath = path.Clean(urlPath) - if hasSlash && !strings.HasSuffix(urlPath, "/") { - urlPath += "/" - } - - // get formatted URL minus scheme so we can build this into Opaque - url.Scheme, url.Path, url.RawQuery = "", "", "" - s := url.String() - url.Scheme = scheme - url.RawQuery = query - - // build opaque URI - url.Opaque = s + urlPath -} - -// EscapePath escapes part of a URL path in Amazon style -func EscapePath(path string, encodeSep bool) string { - var buf bytes.Buffer - for i := 0; i < len(path); i++ { - c := path[i] - if noEscape[c] || (c == '/' && !encodeSep) { - buf.WriteByte(c) - } else { - buf.WriteByte('%') - buf.WriteString(strings.ToUpper(strconv.FormatUint(uint64(c), 16))) - } - } - return buf.String() -} - -func convertType(v reflect.Value) (*string, error) { - v = reflect.Indirect(v) - if !v.IsValid() { - return nil, nil - } - - var str string - switch value := v.Interface().(type) { - case string: - str = value - case []byte: - str = base64.StdEncoding.EncodeToString(value) - case bool: - str = strconv.FormatBool(value) - case int64: - str = strconv.FormatInt(value, 10) - case float64: - str = strconv.FormatFloat(value, 'f', -1, 64) - case time.Time: - str = value.UTC().Format(RFC822) - default: - err := fmt.Errorf("Unsupported value for param %v (%s)", v.Interface(), v.Type()) - return nil, err - } - return &str, nil -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/rest/unmarshal.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/rest/unmarshal.go deleted file mode 100644 index a4155f16699..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/rest/unmarshal.go +++ /dev/null @@ -1,174 +0,0 @@ -package rest - -import ( - "encoding/base64" - "fmt" - "io/ioutil" - "net/http" - "reflect" - "strconv" - "strings" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" -) - -// Unmarshal unmarshals the REST component of a response in a REST service. -func Unmarshal(r *aws.Request) { - if r.DataFilled() { - v := reflect.Indirect(reflect.ValueOf(r.Data)) - unmarshalBody(r, v) - unmarshalLocationElements(r, v) - } -} - -func unmarshalBody(r *aws.Request, v reflect.Value) { - if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok { - if payloadName := field.Tag.Get("payload"); payloadName != "" { - pfield, _ := v.Type().FieldByName(payloadName) - if ptag := pfield.Tag.Get("type"); ptag != "" && ptag != "structure" { - payload := v.FieldByName(payloadName) - if payload.IsValid() { - switch payload.Interface().(type) { - case []byte: - b, err := ioutil.ReadAll(r.HTTPResponse.Body) - if err != nil { - r.Error = awserr.New("SerializationError", "failed to decode REST response", err) - } else { - payload.Set(reflect.ValueOf(b)) - } - case *string: - b, err := ioutil.ReadAll(r.HTTPResponse.Body) - if err != nil { - r.Error = awserr.New("SerializationError", "failed to decode REST response", err) - } else { - str := string(b) - payload.Set(reflect.ValueOf(&str)) - } - default: - switch payload.Type().String() { - case "io.ReadSeeker": - payload.Set(reflect.ValueOf(aws.ReadSeekCloser(r.HTTPResponse.Body))) - case "aws.ReadSeekCloser", "io.ReadCloser": - payload.Set(reflect.ValueOf(r.HTTPResponse.Body)) - default: - r.Error = awserr.New("SerializationError", - "failed to decode REST response", - fmt.Errorf("unknown payload type %s", payload.Type())) - } - } - } - } - } - } -} - -func unmarshalLocationElements(r *aws.Request, v reflect.Value) { - for i := 0; i < v.NumField(); i++ { - m, field := v.Field(i), v.Type().Field(i) - if n := field.Name; n[0:1] == strings.ToLower(n[0:1]) { - continue - } - - if m.IsValid() { - name := field.Tag.Get("locationName") - if name == "" { - name = field.Name - } - - switch field.Tag.Get("location") { - case "statusCode": - unmarshalStatusCode(m, r.HTTPResponse.StatusCode) - case "header": - err := unmarshalHeader(m, r.HTTPResponse.Header.Get(name)) - if err != nil { - r.Error = awserr.New("SerializationError", "failed to decode REST response", err) - break - } - case "headers": - prefix := field.Tag.Get("locationName") - err := unmarshalHeaderMap(m, r.HTTPResponse.Header, prefix) - if err != nil { - r.Error = awserr.New("SerializationError", "failed to decode REST response", err) - break - } - } - } - if r.Error != nil { - return - } - } -} - -func unmarshalStatusCode(v reflect.Value, statusCode int) { - if !v.IsValid() { - return - } - - switch v.Interface().(type) { - case *int64: - s := int64(statusCode) - v.Set(reflect.ValueOf(&s)) - } -} - -func unmarshalHeaderMap(r reflect.Value, headers http.Header, prefix string) error { - switch r.Interface().(type) { - case map[string]*string: // we only support string map value types - out := map[string]*string{} - for k, v := range headers { - k = http.CanonicalHeaderKey(k) - if strings.HasPrefix(strings.ToLower(k), strings.ToLower(prefix)) { - out[k[len(prefix):]] = &v[0] - } - } - r.Set(reflect.ValueOf(out)) - } - return nil -} - -func unmarshalHeader(v reflect.Value, header string) error { - if !v.IsValid() || (header == "" && v.Elem().Kind() != reflect.String) { - return nil - } - - switch v.Interface().(type) { - case *string: - v.Set(reflect.ValueOf(&header)) - case []byte: - b, err := base64.StdEncoding.DecodeString(header) - if err != nil { - return err - } - v.Set(reflect.ValueOf(&b)) - case *bool: - b, err := strconv.ParseBool(header) - if err != nil { - return err - } - v.Set(reflect.ValueOf(&b)) - case *int64: - i, err := strconv.ParseInt(header, 10, 64) - if err != nil { - return err - } - v.Set(reflect.ValueOf(&i)) - case *float64: - f, err := strconv.ParseFloat(header, 64) - if err != nil { - return err - } - v.Set(reflect.ValueOf(&f)) - case *time.Time: - t, err := time.Parse(RFC822, header) - if err != nil { - return err - } - v.Set(reflect.ValueOf(&t)) - default: - err := fmt.Errorf("Unsupported value for param %v (%s)", v.Interface(), v.Type()) - return err - } - return nil -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil/build.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil/build.go deleted file mode 100644 index d3db250231b..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil/build.go +++ /dev/null @@ -1,287 +0,0 @@ -// Package xmlutil provides XML serialisation of AWS requests and responses. -package xmlutil - -import ( - "encoding/base64" - "encoding/xml" - "fmt" - "reflect" - "sort" - "strconv" - "strings" - "time" -) - -// BuildXML will serialize params into an xml.Encoder. -// Error will be returned if the serialization of any of the params or nested values fails. -func BuildXML(params interface{}, e *xml.Encoder) error { - b := xmlBuilder{encoder: e, namespaces: map[string]string{}} - root := NewXMLElement(xml.Name{}) - if err := b.buildValue(reflect.ValueOf(params), root, ""); err != nil { - return err - } - for _, c := range root.Children { - for _, v := range c { - return StructToXML(e, v, false) - } - } - return nil -} - -// Returns the reflection element of a value, if it is a pointer. -func elemOf(value reflect.Value) reflect.Value { - for value.Kind() == reflect.Ptr { - value = value.Elem() - } - return value -} - -// A xmlBuilder serializes values from Go code to XML -type xmlBuilder struct { - encoder *xml.Encoder - namespaces map[string]string -} - -// buildValue generic XMLNode builder for any type. Will build value for their specific type -// struct, list, map, scalar. -// -// Also takes a "type" tag value to set what type a value should be converted to XMLNode as. If -// type is not provided reflect will be used to determine the value's type. -func (b *xmlBuilder) buildValue(value reflect.Value, current *XMLNode, tag reflect.StructTag) error { - value = elemOf(value) - if !value.IsValid() { // no need to handle zero values - return nil - } else if tag.Get("location") != "" { // don't handle non-body location values - return nil - } - - t := tag.Get("type") - if t == "" { - switch value.Kind() { - case reflect.Struct: - t = "structure" - case reflect.Slice: - t = "list" - case reflect.Map: - t = "map" - } - } - - switch t { - case "structure": - if field, ok := value.Type().FieldByName("SDKShapeTraits"); ok { - tag = tag + reflect.StructTag(" ") + field.Tag - } - return b.buildStruct(value, current, tag) - case "list": - return b.buildList(value, current, tag) - case "map": - return b.buildMap(value, current, tag) - default: - return b.buildScalar(value, current, tag) - } -} - -// buildStruct adds a struct and its fields to the current XMLNode. All fields any any nested -// types are converted to XMLNodes also. -func (b *xmlBuilder) buildStruct(value reflect.Value, current *XMLNode, tag reflect.StructTag) error { - if !value.IsValid() { - return nil - } - - fieldAdded := false - - // unwrap payloads - if payload := tag.Get("payload"); payload != "" { - field, _ := value.Type().FieldByName(payload) - tag = field.Tag - value = elemOf(value.FieldByName(payload)) - - if !value.IsValid() { - return nil - } - } - - child := NewXMLElement(xml.Name{Local: tag.Get("locationName")}) - - // there is an xmlNamespace associated with this struct - if prefix, uri := tag.Get("xmlPrefix"), tag.Get("xmlURI"); uri != "" { - ns := xml.Attr{ - Name: xml.Name{Local: "xmlns"}, - Value: uri, - } - if prefix != "" { - b.namespaces[prefix] = uri // register the namespace - ns.Name.Local = "xmlns:" + prefix - } - - child.Attr = append(child.Attr, ns) - } - - t := value.Type() - for i := 0; i < value.NumField(); i++ { - if c := t.Field(i).Name[0:1]; strings.ToLower(c) == c { - continue // ignore unexported fields - } - - member := elemOf(value.Field(i)) - field := t.Field(i) - mTag := field.Tag - - if mTag.Get("location") != "" { // skip non-body members - continue - } - - memberName := mTag.Get("locationName") - if memberName == "" { - memberName = field.Name - mTag = reflect.StructTag(string(mTag) + ` locationName:"` + memberName + `"`) - } - if err := b.buildValue(member, child, mTag); err != nil { - return err - } - - fieldAdded = true - } - - if fieldAdded { // only append this child if we have one ore more valid members - current.AddChild(child) - } - - return nil -} - -// buildList adds the value's list items to the current XMLNode as children nodes. All -// nested values in the list are converted to XMLNodes also. -func (b *xmlBuilder) buildList(value reflect.Value, current *XMLNode, tag reflect.StructTag) error { - if value.IsNil() { // don't build omitted lists - return nil - } - - // check for unflattened list member - flattened := tag.Get("flattened") != "" - - xname := xml.Name{Local: tag.Get("locationName")} - if flattened { - for i := 0; i < value.Len(); i++ { - child := NewXMLElement(xname) - current.AddChild(child) - if err := b.buildValue(value.Index(i), child, ""); err != nil { - return err - } - } - } else { - list := NewXMLElement(xname) - current.AddChild(list) - - for i := 0; i < value.Len(); i++ { - iname := tag.Get("locationNameList") - if iname == "" { - iname = "member" - } - - child := NewXMLElement(xml.Name{Local: iname}) - list.AddChild(child) - if err := b.buildValue(value.Index(i), child, ""); err != nil { - return err - } - } - } - - return nil -} - -// buildMap adds the value's key/value pairs to the current XMLNode as children nodes. All -// nested values in the map are converted to XMLNodes also. -// -// Error will be returned if it is unable to build the map's values into XMLNodes -func (b *xmlBuilder) buildMap(value reflect.Value, current *XMLNode, tag reflect.StructTag) error { - if value.IsNil() { // don't build omitted maps - return nil - } - - maproot := NewXMLElement(xml.Name{Local: tag.Get("locationName")}) - current.AddChild(maproot) - current = maproot - - kname, vname := "key", "value" - if n := tag.Get("locationNameKey"); n != "" { - kname = n - } - if n := tag.Get("locationNameValue"); n != "" { - vname = n - } - - // sorting is not required for compliance, but it makes testing easier - keys := make([]string, value.Len()) - for i, k := range value.MapKeys() { - keys[i] = k.String() - } - sort.Strings(keys) - - for _, k := range keys { - v := value.MapIndex(reflect.ValueOf(k)) - - mapcur := current - if tag.Get("flattened") == "" { // add "entry" tag to non-flat maps - child := NewXMLElement(xml.Name{Local: "entry"}) - mapcur.AddChild(child) - mapcur = child - } - - kchild := NewXMLElement(xml.Name{Local: kname}) - kchild.Text = k - vchild := NewXMLElement(xml.Name{Local: vname}) - mapcur.AddChild(kchild) - mapcur.AddChild(vchild) - - if err := b.buildValue(v, vchild, ""); err != nil { - return err - } - } - - return nil -} - -// buildScalar will convert the value into a string and append it as a attribute or child -// of the current XMLNode. -// -// The value will be added as an attribute if tag contains a "xmlAttribute" attribute value. -// -// Error will be returned if the value type is unsupported. -func (b *xmlBuilder) buildScalar(value reflect.Value, current *XMLNode, tag reflect.StructTag) error { - var str string - switch converted := value.Interface().(type) { - case string: - str = converted - case []byte: - if !value.IsNil() { - str = base64.StdEncoding.EncodeToString(converted) - } - case bool: - str = strconv.FormatBool(converted) - case int64: - str = strconv.FormatInt(converted, 10) - case int: - str = strconv.Itoa(converted) - case float64: - str = strconv.FormatFloat(converted, 'f', -1, 64) - case float32: - str = strconv.FormatFloat(float64(converted), 'f', -1, 32) - case time.Time: - const ISO8601UTC = "2006-01-02T15:04:05Z" - str = converted.UTC().Format(ISO8601UTC) - default: - return fmt.Errorf("unsupported value for param %s: %v (%s)", - tag.Get("locationName"), value.Interface(), value.Type().Name()) - } - - xname := xml.Name{Local: tag.Get("locationName")} - if tag.Get("xmlAttribute") != "" { // put into current node's attribute list - attr := xml.Attr{Name: xname, Value: str} - current.Attr = append(current.Attr, attr) - } else { // regular text node - current.AddChild(&XMLNode{Name: xname, Text: str}) - } - return nil -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/signer/v4/functional_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/signer/v4/functional_test.go deleted file mode 100644 index fbb0e41cdc1..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/signer/v4/functional_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package v4_test - -import ( - "net/url" - "testing" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/internal/test/unit" - "github.com/aws/aws-sdk-go/service/s3" - "github.com/stretchr/testify/assert" -) - -var _ = unit.Imported - -func TestPresignHandler(t *testing.T) { - svc := s3.New(nil) - req, _ := svc.PutObjectRequest(&s3.PutObjectInput{ - Bucket: aws.String("bucket"), - Key: aws.String("key"), - ContentDisposition: aws.String("a+b c$d"), - ACL: aws.String("public-read"), - }) - req.Time = time.Unix(0, 0) - urlstr, err := req.Presign(5 * time.Minute) - - assert.NoError(t, err) - - expectedDate := "19700101T000000Z" - expectedHeaders := "host;x-amz-acl" - expectedSig := "7edcb4e3a1bf12f4989018d75acbe3a7f03df24bd6f3112602d59fc551f0e4e2" - expectedCred := "AKID/19700101/mock-region/s3/aws4_request" - - u, _ := url.Parse(urlstr) - urlQ := u.Query() - assert.Equal(t, expectedSig, urlQ.Get("X-Amz-Signature")) - assert.Equal(t, expectedCred, urlQ.Get("X-Amz-Credential")) - assert.Equal(t, expectedHeaders, urlQ.Get("X-Amz-SignedHeaders")) - assert.Equal(t, expectedDate, urlQ.Get("X-Amz-Date")) - assert.Equal(t, "300", urlQ.Get("X-Amz-Expires")) - - assert.NotContains(t, urlstr, "+") // + encoded as %20 -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/signer/v4/v4.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/signer/v4/v4.go deleted file mode 100644 index 748c37f2e65..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/signer/v4/v4.go +++ /dev/null @@ -1,364 +0,0 @@ -// Package v4 implements signing for AWS V4 signer -package v4 - -import ( - "crypto/hmac" - "crypto/sha256" - "encoding/hex" - "fmt" - "io" - "net/http" - "net/url" - "sort" - "strconv" - "strings" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/credentials" - "github.com/aws/aws-sdk-go/internal/protocol/rest" -) - -const ( - authHeaderPrefix = "AWS4-HMAC-SHA256" - timeFormat = "20060102T150405Z" - shortTimeFormat = "20060102" -) - -var ignoredHeaders = map[string]bool{ - "Authorization": true, - "Content-Type": true, - "Content-Length": true, - "User-Agent": true, -} - -type signer struct { - Request *http.Request - Time time.Time - ExpireTime time.Duration - ServiceName string - Region string - CredValues credentials.Value - Credentials *credentials.Credentials - Query url.Values - Body io.ReadSeeker - Debug aws.LogLevelType - Logger aws.Logger - - isPresign bool - formattedTime string - formattedShortTime string - - signedHeaders string - canonicalHeaders string - canonicalString string - credentialString string - stringToSign string - signature string - authorization string -} - -// Sign requests with signature version 4. -// -// Will sign the requests with the service config's Credentials object -// Signing is skipped if the credentials is the credentials.AnonymousCredentials -// object. -func Sign(req *aws.Request) { - // If the request does not need to be signed ignore the signing of the - // request if the AnonymousCredentials object is used. - if req.Service.Config.Credentials == credentials.AnonymousCredentials { - return - } - - region := req.Service.SigningRegion - if region == "" { - region = aws.StringValue(req.Service.Config.Region) - } - - name := req.Service.SigningName - if name == "" { - name = req.Service.ServiceName - } - - s := signer{ - Request: req.HTTPRequest, - Time: req.Time, - ExpireTime: req.ExpireTime, - Query: req.HTTPRequest.URL.Query(), - Body: req.Body, - ServiceName: name, - Region: region, - Credentials: req.Service.Config.Credentials, - Debug: req.Service.Config.LogLevel.Value(), - Logger: req.Service.Config.Logger, - } - - req.Error = s.sign() -} - -func (v4 *signer) sign() error { - if v4.ExpireTime != 0 { - v4.isPresign = true - } - - if v4.isRequestSigned() { - if !v4.Credentials.IsExpired() { - // If the request is already signed, and the credentials have not - // expired yet ignore the signing request. - return nil - } - - // The credentials have expired for this request. The current signing - // is invalid, and needs to be request because the request will fail. - if v4.isPresign { - v4.removePresign() - // Update the request's query string to ensure the values stays in - // sync in the case retrieving the new credentials fails. - v4.Request.URL.RawQuery = v4.Query.Encode() - } - } - - var err error - v4.CredValues, err = v4.Credentials.Get() - if err != nil { - return err - } - - if v4.isPresign { - v4.Query.Set("X-Amz-Algorithm", authHeaderPrefix) - if v4.CredValues.SessionToken != "" { - v4.Query.Set("X-Amz-Security-Token", v4.CredValues.SessionToken) - } else { - v4.Query.Del("X-Amz-Security-Token") - } - } else if v4.CredValues.SessionToken != "" { - v4.Request.Header.Set("X-Amz-Security-Token", v4.CredValues.SessionToken) - } - - v4.build() - - if v4.Debug.Matches(aws.LogDebugWithSigning) { - v4.logSigningInfo() - } - - return nil -} - -const logSignInfoMsg = `DEBUG: Request Signiture: ----[ CANONICAL STRING ]----------------------------- -%s ----[ STRING TO SIGN ]-------------------------------- -%s%s ------------------------------------------------------` -const logSignedURLMsg = ` ----[ SIGNED URL ]------------------------------------ -%s` - -func (v4 *signer) logSigningInfo() { - signedURLMsg := "" - if v4.isPresign { - signedURLMsg = fmt.Sprintf(logSignedURLMsg, v4.Request.URL.String()) - } - msg := fmt.Sprintf(logSignInfoMsg, v4.canonicalString, v4.stringToSign, signedURLMsg) - v4.Logger.Log(msg) -} - -func (v4 *signer) build() { - v4.buildTime() // no depends - v4.buildCredentialString() // no depends - if v4.isPresign { - v4.buildQuery() // no depends - } - v4.buildCanonicalHeaders() // depends on cred string - v4.buildCanonicalString() // depends on canon headers / signed headers - v4.buildStringToSign() // depends on canon string - v4.buildSignature() // depends on string to sign - - if v4.isPresign { - v4.Request.URL.RawQuery += "&X-Amz-Signature=" + v4.signature - } else { - parts := []string{ - authHeaderPrefix + " Credential=" + v4.CredValues.AccessKeyID + "/" + v4.credentialString, - "SignedHeaders=" + v4.signedHeaders, - "Signature=" + v4.signature, - } - v4.Request.Header.Set("Authorization", strings.Join(parts, ", ")) - } -} - -func (v4 *signer) buildTime() { - v4.formattedTime = v4.Time.UTC().Format(timeFormat) - v4.formattedShortTime = v4.Time.UTC().Format(shortTimeFormat) - - if v4.isPresign { - duration := int64(v4.ExpireTime / time.Second) - v4.Query.Set("X-Amz-Date", v4.formattedTime) - v4.Query.Set("X-Amz-Expires", strconv.FormatInt(duration, 10)) - } else { - v4.Request.Header.Set("X-Amz-Date", v4.formattedTime) - } -} - -func (v4 *signer) buildCredentialString() { - v4.credentialString = strings.Join([]string{ - v4.formattedShortTime, - v4.Region, - v4.ServiceName, - "aws4_request", - }, "/") - - if v4.isPresign { - v4.Query.Set("X-Amz-Credential", v4.CredValues.AccessKeyID+"/"+v4.credentialString) - } -} - -func (v4 *signer) buildQuery() { - for k, h := range v4.Request.Header { - if strings.HasPrefix(http.CanonicalHeaderKey(k), "X-Amz-") { - continue // never hoist x-amz-* headers, they must be signed - } - if _, ok := ignoredHeaders[http.CanonicalHeaderKey(k)]; ok { - continue // never hoist ignored headers - } - - v4.Request.Header.Del(k) - v4.Query.Del(k) - for _, v := range h { - v4.Query.Add(k, v) - } - } -} - -func (v4 *signer) buildCanonicalHeaders() { - var headers []string - headers = append(headers, "host") - for k := range v4.Request.Header { - if _, ok := ignoredHeaders[http.CanonicalHeaderKey(k)]; ok { - continue // ignored header - } - headers = append(headers, strings.ToLower(k)) - } - sort.Strings(headers) - - v4.signedHeaders = strings.Join(headers, ";") - - if v4.isPresign { - v4.Query.Set("X-Amz-SignedHeaders", v4.signedHeaders) - } - - headerValues := make([]string, len(headers)) - for i, k := range headers { - if k == "host" { - headerValues[i] = "host:" + v4.Request.URL.Host - } else { - headerValues[i] = k + ":" + - strings.Join(v4.Request.Header[http.CanonicalHeaderKey(k)], ",") - } - } - - v4.canonicalHeaders = strings.Join(headerValues, "\n") -} - -func (v4 *signer) buildCanonicalString() { - v4.Request.URL.RawQuery = strings.Replace(v4.Query.Encode(), "+", "%20", -1) - uri := v4.Request.URL.Opaque - if uri != "" { - uri = "/" + strings.Join(strings.Split(uri, "/")[3:], "/") - } else { - uri = v4.Request.URL.Path - } - if uri == "" { - uri = "/" - } - - if v4.ServiceName != "s3" { - uri = rest.EscapePath(uri, false) - } - - v4.canonicalString = strings.Join([]string{ - v4.Request.Method, - uri, - v4.Request.URL.RawQuery, - v4.canonicalHeaders + "\n", - v4.signedHeaders, - v4.bodyDigest(), - }, "\n") -} - -func (v4 *signer) buildStringToSign() { - v4.stringToSign = strings.Join([]string{ - authHeaderPrefix, - v4.formattedTime, - v4.credentialString, - hex.EncodeToString(makeSha256([]byte(v4.canonicalString))), - }, "\n") -} - -func (v4 *signer) buildSignature() { - secret := v4.CredValues.SecretAccessKey - date := makeHmac([]byte("AWS4"+secret), []byte(v4.formattedShortTime)) - region := makeHmac(date, []byte(v4.Region)) - service := makeHmac(region, []byte(v4.ServiceName)) - credentials := makeHmac(service, []byte("aws4_request")) - signature := makeHmac(credentials, []byte(v4.stringToSign)) - v4.signature = hex.EncodeToString(signature) -} - -func (v4 *signer) bodyDigest() string { - hash := v4.Request.Header.Get("X-Amz-Content-Sha256") - if hash == "" { - if v4.isPresign && v4.ServiceName == "s3" { - hash = "UNSIGNED-PAYLOAD" - } else if v4.Body == nil { - hash = hex.EncodeToString(makeSha256([]byte{})) - } else { - hash = hex.EncodeToString(makeSha256Reader(v4.Body)) - } - v4.Request.Header.Add("X-Amz-Content-Sha256", hash) - } - return hash -} - -// isRequestSigned returns if the request is currently signed or presigned -func (v4 *signer) isRequestSigned() bool { - if v4.isPresign && v4.Query.Get("X-Amz-Signature") != "" { - return true - } - if v4.Request.Header.Get("Authorization") != "" { - return true - } - - return false -} - -// unsign removes signing flags for both signed and presigned requests. -func (v4 *signer) removePresign() { - v4.Query.Del("X-Amz-Algorithm") - v4.Query.Del("X-Amz-Signature") - v4.Query.Del("X-Amz-Security-Token") - v4.Query.Del("X-Amz-Date") - v4.Query.Del("X-Amz-Expires") - v4.Query.Del("X-Amz-Credential") - v4.Query.Del("X-Amz-SignedHeaders") -} - -func makeHmac(key []byte, data []byte) []byte { - hash := hmac.New(sha256.New, key) - hash.Write(data) - return hash.Sum(nil) -} - -func makeSha256(data []byte) []byte { - hash := sha256.New() - hash.Write(data) - return hash.Sum(nil) -} - -func makeSha256Reader(reader io.ReadSeeker) []byte { - hash := sha256.New() - start, _ := reader.Seek(0, 1) - defer reader.Seek(start, 0) - - io.Copy(hash, reader) - return hash.Sum(nil) -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/signer/v4/v4_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/signer/v4/v4_test.go deleted file mode 100644 index adf8e7bd89e..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/signer/v4/v4_test.go +++ /dev/null @@ -1,245 +0,0 @@ -package v4 - -import ( - "net/http" - "strings" - "testing" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/credentials" - "github.com/stretchr/testify/assert" -) - -func buildSigner(serviceName string, region string, signTime time.Time, expireTime time.Duration, body string) signer { - endpoint := "https://" + serviceName + "." + region + ".amazonaws.com" - reader := strings.NewReader(body) - req, _ := http.NewRequest("POST", endpoint, reader) - req.URL.Opaque = "//example.org/bucket/key-._~,!@#$%^&*()" - req.Header.Add("X-Amz-Target", "prefix.Operation") - req.Header.Add("Content-Type", "application/x-amz-json-1.0") - req.Header.Add("Content-Length", string(len(body))) - req.Header.Add("X-Amz-Meta-Other-Header", "some-value=!@#$%^&* (+)") - - return signer{ - Request: req, - Time: signTime, - ExpireTime: expireTime, - Query: req.URL.Query(), - Body: reader, - ServiceName: serviceName, - Region: region, - Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "SESSION"), - } -} - -func removeWS(text string) string { - text = strings.Replace(text, " ", "", -1) - text = strings.Replace(text, "\n", "", -1) - text = strings.Replace(text, "\t", "", -1) - return text -} - -func assertEqual(t *testing.T, expected, given string) { - if removeWS(expected) != removeWS(given) { - t.Errorf("\nExpected: %s\nGiven: %s", expected, given) - } -} - -func TestPresignRequest(t *testing.T) { - signer := buildSigner("dynamodb", "us-east-1", time.Unix(0, 0), 300*time.Second, "{}") - signer.sign() - - expectedDate := "19700101T000000Z" - expectedHeaders := "host;x-amz-meta-other-header;x-amz-target" - expectedSig := "5eeedebf6f995145ce56daa02902d10485246d3defb34f97b973c1f40ab82d36" - expectedCred := "AKID/19700101/us-east-1/dynamodb/aws4_request" - - q := signer.Request.URL.Query() - assert.Equal(t, expectedSig, q.Get("X-Amz-Signature")) - assert.Equal(t, expectedCred, q.Get("X-Amz-Credential")) - assert.Equal(t, expectedHeaders, q.Get("X-Amz-SignedHeaders")) - assert.Equal(t, expectedDate, q.Get("X-Amz-Date")) -} - -func TestSignRequest(t *testing.T) { - signer := buildSigner("dynamodb", "us-east-1", time.Unix(0, 0), 0, "{}") - signer.sign() - - expectedDate := "19700101T000000Z" - expectedSig := "AWS4-HMAC-SHA256 Credential=AKID/19700101/us-east-1/dynamodb/aws4_request, SignedHeaders=host;x-amz-date;x-amz-meta-other-header;x-amz-security-token;x-amz-target, Signature=69ada33fec48180dab153576e4dd80c4e04124f80dda3eccfed8a67c2b91ed5e" - - q := signer.Request.Header - assert.Equal(t, expectedSig, q.Get("Authorization")) - assert.Equal(t, expectedDate, q.Get("X-Amz-Date")) -} - -func TestSignEmptyBody(t *testing.T) { - signer := buildSigner("dynamodb", "us-east-1", time.Now(), 0, "") - signer.Body = nil - signer.sign() - hash := signer.Request.Header.Get("X-Amz-Content-Sha256") - assert.Equal(t, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", hash) -} - -func TestSignBody(t *testing.T) { - signer := buildSigner("dynamodb", "us-east-1", time.Now(), 0, "hello") - signer.sign() - hash := signer.Request.Header.Get("X-Amz-Content-Sha256") - assert.Equal(t, "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824", hash) -} - -func TestSignSeekedBody(t *testing.T) { - signer := buildSigner("dynamodb", "us-east-1", time.Now(), 0, " hello") - signer.Body.Read(make([]byte, 3)) // consume first 3 bytes so body is now "hello" - signer.sign() - hash := signer.Request.Header.Get("X-Amz-Content-Sha256") - assert.Equal(t, "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824", hash) - - start, _ := signer.Body.Seek(0, 1) - assert.Equal(t, int64(3), start) -} - -func TestPresignEmptyBodyS3(t *testing.T) { - signer := buildSigner("s3", "us-east-1", time.Now(), 5*time.Minute, "hello") - signer.sign() - hash := signer.Request.Header.Get("X-Amz-Content-Sha256") - assert.Equal(t, "UNSIGNED-PAYLOAD", hash) -} - -func TestSignPrecomputedBodyChecksum(t *testing.T) { - signer := buildSigner("dynamodb", "us-east-1", time.Now(), 0, "hello") - signer.Request.Header.Set("X-Amz-Content-Sha256", "PRECOMPUTED") - signer.sign() - hash := signer.Request.Header.Get("X-Amz-Content-Sha256") - assert.Equal(t, "PRECOMPUTED", hash) -} - -func TestAnonymousCredentials(t *testing.T) { - r := aws.NewRequest( - aws.NewService(&aws.Config{Credentials: credentials.AnonymousCredentials}), - &aws.Operation{ - Name: "BatchGetItem", - HTTPMethod: "POST", - HTTPPath: "/", - }, - nil, - nil, - ) - Sign(r) - - urlQ := r.HTTPRequest.URL.Query() - assert.Empty(t, urlQ.Get("X-Amz-Signature")) - assert.Empty(t, urlQ.Get("X-Amz-Credential")) - assert.Empty(t, urlQ.Get("X-Amz-SignedHeaders")) - assert.Empty(t, urlQ.Get("X-Amz-Date")) - - hQ := r.HTTPRequest.Header - assert.Empty(t, hQ.Get("Authorization")) - assert.Empty(t, hQ.Get("X-Amz-Date")) -} - -func TestIgnoreResignRequestWithValidCreds(t *testing.T) { - r := aws.NewRequest( - aws.NewService(&aws.Config{ - Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "SESSION"), - Region: aws.String("us-west-2"), - }), - &aws.Operation{ - Name: "BatchGetItem", - HTTPMethod: "POST", - HTTPPath: "/", - }, - nil, - nil, - ) - - Sign(r) - sig := r.HTTPRequest.Header.Get("Authorization") - - Sign(r) - assert.Equal(t, sig, r.HTTPRequest.Header.Get("Authorization")) -} - -func TestIgnorePreResignRequestWithValidCreds(t *testing.T) { - r := aws.NewRequest( - aws.NewService(&aws.Config{ - Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "SESSION"), - Region: aws.String("us-west-2"), - }), - &aws.Operation{ - Name: "BatchGetItem", - HTTPMethod: "POST", - HTTPPath: "/", - }, - nil, - nil, - ) - r.ExpireTime = time.Minute * 10 - - Sign(r) - sig := r.HTTPRequest.Header.Get("X-Amz-Signature") - - Sign(r) - assert.Equal(t, sig, r.HTTPRequest.Header.Get("X-Amz-Signature")) -} - -func TestResignRequestExpiredCreds(t *testing.T) { - creds := credentials.NewStaticCredentials("AKID", "SECRET", "SESSION") - r := aws.NewRequest( - aws.NewService(&aws.Config{Credentials: creds}), - &aws.Operation{ - Name: "BatchGetItem", - HTTPMethod: "POST", - HTTPPath: "/", - }, - nil, - nil, - ) - Sign(r) - querySig := r.HTTPRequest.Header.Get("Authorization") - - creds.Expire() - - Sign(r) - assert.NotEqual(t, querySig, r.HTTPRequest.Header.Get("Authorization")) -} - -func TestPreResignRequestExpiredCreds(t *testing.T) { - provider := &credentials.StaticProvider{credentials.Value{"AKID", "SECRET", "SESSION"}} - creds := credentials.NewCredentials(provider) - r := aws.NewRequest( - aws.NewService(&aws.Config{Credentials: creds}), - &aws.Operation{ - Name: "BatchGetItem", - HTTPMethod: "POST", - HTTPPath: "/", - }, - nil, - nil, - ) - r.ExpireTime = time.Minute * 10 - - Sign(r) - querySig := r.HTTPRequest.URL.Query().Get("X-Amz-Signature") - - creds.Expire() - r.Time = time.Now().Add(time.Hour * 48) - - Sign(r) - assert.NotEqual(t, querySig, r.HTTPRequest.URL.Query().Get("X-Amz-Signature")) -} - -func BenchmarkPresignRequest(b *testing.B) { - signer := buildSigner("dynamodb", "us-east-1", time.Now(), 300*time.Second, "{}") - for i := 0; i < b.N; i++ { - signer.sign() - } -} - -func BenchmarkSignRequest(b *testing.B) { - signer := buildSigner("dynamodb", "us-east-1", time.Now(), 0, "{}") - for i := 0; i < b.N; i++ { - signer.sign() - } -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/endpoints/endpoints_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/endpoints/endpoints_test.go deleted file mode 100644 index 2add48890b3..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/endpoints/endpoints_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package endpoints_test - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/aws/aws-sdk-go/private/endpoints" -) - -func TestGenericEndpoint(t *testing.T) { - name := "service" - region := "mock-region-1" - - ep, sr := endpoints.EndpointForRegion(name, region, false) - assert.Equal(t, fmt.Sprintf("https://%s.%s.amazonaws.com", name, region), ep) - assert.Empty(t, sr) -} - -func TestGlobalEndpoints(t *testing.T) { - region := "mock-region-1" - svcs := []string{"cloudfront", "iam", "importexport", "route53", "sts", "waf"} - - for _, name := range svcs { - ep, sr := endpoints.EndpointForRegion(name, region, false) - assert.Equal(t, fmt.Sprintf("https://%s.amazonaws.com", name), ep) - assert.Equal(t, "us-east-1", sr) - } -} - -func TestServicesInCN(t *testing.T) { - region := "cn-north-1" - svcs := []string{"cloudfront", "iam", "importexport", "route53", "sts", "s3", "waf"} - - for _, name := range svcs { - ep, sr := endpoints.EndpointForRegion(name, region, false) - assert.Equal(t, fmt.Sprintf("https://%s.%s.amazonaws.com.cn", name, region), ep) - assert.Empty(t, sr) - } -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/ec2query/build_bench_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/ec2query/build_bench_test.go deleted file mode 100644 index e135b93601d..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/ec2query/build_bench_test.go +++ /dev/null @@ -1,85 +0,0 @@ -// +build bench - -package ec2query_test - -import ( - "testing" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/awstesting" - "github.com/aws/aws-sdk-go/private/protocol/ec2query" - "github.com/aws/aws-sdk-go/service/ec2" -) - -func BenchmarkEC2QueryBuild_Complex_ec2AuthorizeSecurityGroupEgress(b *testing.B) { - params := &ec2.AuthorizeSecurityGroupEgressInput{ - GroupId: aws.String("String"), // Required - CidrIp: aws.String("String"), - DryRun: aws.Bool(true), - FromPort: aws.Int64(1), - IpPermissions: []*ec2.IpPermission{ - { // Required - FromPort: aws.Int64(1), - IpProtocol: aws.String("String"), - IpRanges: []*ec2.IpRange{ - { // Required - CidrIp: aws.String("String"), - }, - // More values... - }, - PrefixListIds: []*ec2.PrefixListId{ - { // Required - PrefixListId: aws.String("String"), - }, - // More values... - }, - ToPort: aws.Int64(1), - UserIdGroupPairs: []*ec2.UserIdGroupPair{ - { // Required - GroupId: aws.String("String"), - GroupName: aws.String("String"), - UserId: aws.String("String"), - }, - // More values... - }, - }, - // More values... - }, - IpProtocol: aws.String("String"), - SourceSecurityGroupName: aws.String("String"), - SourceSecurityGroupOwnerId: aws.String("String"), - ToPort: aws.Int64(1), - } - - benchEC2QueryBuild(b, "AuthorizeSecurityGroupEgress", params) -} - -func BenchmarkEC2QueryBuild_Simple_ec2AttachNetworkInterface(b *testing.B) { - params := &ec2.AttachNetworkInterfaceInput{ - DeviceIndex: aws.Int64(1), // Required - InstanceId: aws.String("String"), // Required - NetworkInterfaceId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - - benchEC2QueryBuild(b, "AttachNetworkInterface", params) -} - -func benchEC2QueryBuild(b *testing.B, opName string, params interface{}) { - svc := awstesting.NewClient() - svc.ServiceName = "ec2" - svc.APIVersion = "2015-04-15" - - for i := 0; i < b.N; i++ { - r := svc.NewRequest(&request.Operation{ - Name: opName, - HTTPMethod: "POST", - HTTPPath: "/", - }, params, nil) - ec2query.Build(r) - if r.Error != nil { - b.Fatal("Unexpected error", r.Error) - } - } -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/ec2query/build_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/ec2query/build_test.go deleted file mode 100644 index 887feeb1ea8..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/ec2query/build_test.go +++ /dev/null @@ -1,1051 +0,0 @@ -package ec2query_test - -import ( - "bytes" - "encoding/json" - "encoding/xml" - "io" - "io/ioutil" - "net/http" - "net/url" - "testing" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/client" - "github.com/aws/aws-sdk-go/aws/client/metadata" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/awstesting" - "github.com/aws/aws-sdk-go/private/protocol/ec2query" - "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil" - "github.com/aws/aws-sdk-go/private/signer/v4" - "github.com/aws/aws-sdk-go/private/util" - "github.com/stretchr/testify/assert" -) - -var _ bytes.Buffer // always import bytes -var _ http.Request -var _ json.Marshaler -var _ time.Time -var _ xmlutil.XMLNode -var _ xml.Attr -var _ = awstesting.GenerateAssertions -var _ = ioutil.Discard -var _ = util.Trim("") -var _ = url.Values{} -var _ = io.EOF -var _ = aws.String - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type InputService1ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the InputService1ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a InputService1ProtocolTest client from just a session. -// svc := inputservice1protocoltest.New(mySession) -// -// // Create a InputService1ProtocolTest client with additional configuration -// svc := inputservice1protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewInputService1ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService1ProtocolTest { - c := p.ClientConfig("inputservice1protocoltest", cfgs...) - return newInputService1ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newInputService1ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService1ProtocolTest { - svc := &InputService1ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "inputservice1protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "2014-01-01", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(ec2query.Build) - svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a InputService1ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService1ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opInputService1TestCaseOperation1 = "OperationName" - -// InputService1TestCaseOperation1Request generates a request for the InputService1TestCaseOperation1 operation. -func (c *InputService1ProtocolTest) InputService1TestCaseOperation1Request(input *InputService1TestShapeInputService1TestCaseOperation1Input) (req *request.Request, output *InputService1TestShapeInputService1TestCaseOperation1Output) { - op := &request.Operation{ - Name: opInputService1TestCaseOperation1, - } - - if input == nil { - input = &InputService1TestShapeInputService1TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &InputService1TestShapeInputService1TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService1ProtocolTest) InputService1TestCaseOperation1(input *InputService1TestShapeInputService1TestCaseOperation1Input) (*InputService1TestShapeInputService1TestCaseOperation1Output, error) { - req, out := c.InputService1TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService1TestShapeInputService1TestCaseOperation1Input struct { - Bar *string `type:"string"` - - Foo *string `type:"string"` - - metadataInputService1TestShapeInputService1TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataInputService1TestShapeInputService1TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService1TestShapeInputService1TestCaseOperation1Output struct { - metadataInputService1TestShapeInputService1TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService1TestShapeInputService1TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type InputService2ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the InputService2ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a InputService2ProtocolTest client from just a session. -// svc := inputservice2protocoltest.New(mySession) -// -// // Create a InputService2ProtocolTest client with additional configuration -// svc := inputservice2protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewInputService2ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService2ProtocolTest { - c := p.ClientConfig("inputservice2protocoltest", cfgs...) - return newInputService2ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newInputService2ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService2ProtocolTest { - svc := &InputService2ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "inputservice2protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "2014-01-01", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(ec2query.Build) - svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a InputService2ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService2ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opInputService2TestCaseOperation1 = "OperationName" - -// InputService2TestCaseOperation1Request generates a request for the InputService2TestCaseOperation1 operation. -func (c *InputService2ProtocolTest) InputService2TestCaseOperation1Request(input *InputService2TestShapeInputService2TestCaseOperation1Input) (req *request.Request, output *InputService2TestShapeInputService2TestCaseOperation1Output) { - op := &request.Operation{ - Name: opInputService2TestCaseOperation1, - } - - if input == nil { - input = &InputService2TestShapeInputService2TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &InputService2TestShapeInputService2TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService2ProtocolTest) InputService2TestCaseOperation1(input *InputService2TestShapeInputService2TestCaseOperation1Input) (*InputService2TestShapeInputService2TestCaseOperation1Output, error) { - req, out := c.InputService2TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService2TestShapeInputService2TestCaseOperation1Input struct { - Bar *string `locationName:"barLocationName" type:"string"` - - Foo *string `type:"string"` - - Yuck *string `locationName:"yuckLocationName" queryName:"yuckQueryName" type:"string"` - - metadataInputService2TestShapeInputService2TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataInputService2TestShapeInputService2TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService2TestShapeInputService2TestCaseOperation1Output struct { - metadataInputService2TestShapeInputService2TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService2TestShapeInputService2TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type InputService3ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the InputService3ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a InputService3ProtocolTest client from just a session. -// svc := inputservice3protocoltest.New(mySession) -// -// // Create a InputService3ProtocolTest client with additional configuration -// svc := inputservice3protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewInputService3ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService3ProtocolTest { - c := p.ClientConfig("inputservice3protocoltest", cfgs...) - return newInputService3ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newInputService3ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService3ProtocolTest { - svc := &InputService3ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "inputservice3protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "2014-01-01", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(ec2query.Build) - svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a InputService3ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService3ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opInputService3TestCaseOperation1 = "OperationName" - -// InputService3TestCaseOperation1Request generates a request for the InputService3TestCaseOperation1 operation. -func (c *InputService3ProtocolTest) InputService3TestCaseOperation1Request(input *InputService3TestShapeInputService3TestCaseOperation1Input) (req *request.Request, output *InputService3TestShapeInputService3TestCaseOperation1Output) { - op := &request.Operation{ - Name: opInputService3TestCaseOperation1, - } - - if input == nil { - input = &InputService3TestShapeInputService3TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &InputService3TestShapeInputService3TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService3ProtocolTest) InputService3TestCaseOperation1(input *InputService3TestShapeInputService3TestCaseOperation1Input) (*InputService3TestShapeInputService3TestCaseOperation1Output, error) { - req, out := c.InputService3TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService3TestShapeInputService3TestCaseOperation1Input struct { - StructArg *InputService3TestShapeStructType `locationName:"Struct" type:"structure"` - - metadataInputService3TestShapeInputService3TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataInputService3TestShapeInputService3TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService3TestShapeInputService3TestCaseOperation1Output struct { - metadataInputService3TestShapeInputService3TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService3TestShapeInputService3TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService3TestShapeStructType struct { - ScalarArg *string `locationName:"Scalar" type:"string"` - - metadataInputService3TestShapeStructType `json:"-" xml:"-"` -} - -type metadataInputService3TestShapeStructType struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type InputService4ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the InputService4ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a InputService4ProtocolTest client from just a session. -// svc := inputservice4protocoltest.New(mySession) -// -// // Create a InputService4ProtocolTest client with additional configuration -// svc := inputservice4protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewInputService4ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService4ProtocolTest { - c := p.ClientConfig("inputservice4protocoltest", cfgs...) - return newInputService4ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newInputService4ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService4ProtocolTest { - svc := &InputService4ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "inputservice4protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "2014-01-01", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(ec2query.Build) - svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a InputService4ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService4ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opInputService4TestCaseOperation1 = "OperationName" - -// InputService4TestCaseOperation1Request generates a request for the InputService4TestCaseOperation1 operation. -func (c *InputService4ProtocolTest) InputService4TestCaseOperation1Request(input *InputService4TestShapeInputService4TestCaseOperation1Input) (req *request.Request, output *InputService4TestShapeInputService4TestCaseOperation1Output) { - op := &request.Operation{ - Name: opInputService4TestCaseOperation1, - } - - if input == nil { - input = &InputService4TestShapeInputService4TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &InputService4TestShapeInputService4TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService4ProtocolTest) InputService4TestCaseOperation1(input *InputService4TestShapeInputService4TestCaseOperation1Input) (*InputService4TestShapeInputService4TestCaseOperation1Output, error) { - req, out := c.InputService4TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService4TestShapeInputService4TestCaseOperation1Input struct { - ListArg []*string `type:"list"` - - metadataInputService4TestShapeInputService4TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataInputService4TestShapeInputService4TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService4TestShapeInputService4TestCaseOperation1Output struct { - metadataInputService4TestShapeInputService4TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService4TestShapeInputService4TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type InputService5ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the InputService5ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a InputService5ProtocolTest client from just a session. -// svc := inputservice5protocoltest.New(mySession) -// -// // Create a InputService5ProtocolTest client with additional configuration -// svc := inputservice5protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewInputService5ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService5ProtocolTest { - c := p.ClientConfig("inputservice5protocoltest", cfgs...) - return newInputService5ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newInputService5ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService5ProtocolTest { - svc := &InputService5ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "inputservice5protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "2014-01-01", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(ec2query.Build) - svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a InputService5ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService5ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opInputService5TestCaseOperation1 = "OperationName" - -// InputService5TestCaseOperation1Request generates a request for the InputService5TestCaseOperation1 operation. -func (c *InputService5ProtocolTest) InputService5TestCaseOperation1Request(input *InputService5TestShapeInputService5TestCaseOperation1Input) (req *request.Request, output *InputService5TestShapeInputService5TestCaseOperation1Output) { - op := &request.Operation{ - Name: opInputService5TestCaseOperation1, - } - - if input == nil { - input = &InputService5TestShapeInputService5TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &InputService5TestShapeInputService5TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService5ProtocolTest) InputService5TestCaseOperation1(input *InputService5TestShapeInputService5TestCaseOperation1Input) (*InputService5TestShapeInputService5TestCaseOperation1Output, error) { - req, out := c.InputService5TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService5TestShapeInputService5TestCaseOperation1Input struct { - ListArg []*string `locationName:"ListMemberName" locationNameList:"item" type:"list"` - - metadataInputService5TestShapeInputService5TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataInputService5TestShapeInputService5TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService5TestShapeInputService5TestCaseOperation1Output struct { - metadataInputService5TestShapeInputService5TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService5TestShapeInputService5TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type InputService6ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the InputService6ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a InputService6ProtocolTest client from just a session. -// svc := inputservice6protocoltest.New(mySession) -// -// // Create a InputService6ProtocolTest client with additional configuration -// svc := inputservice6protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewInputService6ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService6ProtocolTest { - c := p.ClientConfig("inputservice6protocoltest", cfgs...) - return newInputService6ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newInputService6ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService6ProtocolTest { - svc := &InputService6ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "inputservice6protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "2014-01-01", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(ec2query.Build) - svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a InputService6ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService6ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opInputService6TestCaseOperation1 = "OperationName" - -// InputService6TestCaseOperation1Request generates a request for the InputService6TestCaseOperation1 operation. -func (c *InputService6ProtocolTest) InputService6TestCaseOperation1Request(input *InputService6TestShapeInputService6TestCaseOperation1Input) (req *request.Request, output *InputService6TestShapeInputService6TestCaseOperation1Output) { - op := &request.Operation{ - Name: opInputService6TestCaseOperation1, - } - - if input == nil { - input = &InputService6TestShapeInputService6TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &InputService6TestShapeInputService6TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService6ProtocolTest) InputService6TestCaseOperation1(input *InputService6TestShapeInputService6TestCaseOperation1Input) (*InputService6TestShapeInputService6TestCaseOperation1Output, error) { - req, out := c.InputService6TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService6TestShapeInputService6TestCaseOperation1Input struct { - ListArg []*string `locationName:"ListMemberName" queryName:"ListQueryName" locationNameList:"item" type:"list"` - - metadataInputService6TestShapeInputService6TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataInputService6TestShapeInputService6TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService6TestShapeInputService6TestCaseOperation1Output struct { - metadataInputService6TestShapeInputService6TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService6TestShapeInputService6TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type InputService7ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the InputService7ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a InputService7ProtocolTest client from just a session. -// svc := inputservice7protocoltest.New(mySession) -// -// // Create a InputService7ProtocolTest client with additional configuration -// svc := inputservice7protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewInputService7ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService7ProtocolTest { - c := p.ClientConfig("inputservice7protocoltest", cfgs...) - return newInputService7ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newInputService7ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService7ProtocolTest { - svc := &InputService7ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "inputservice7protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "2014-01-01", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(ec2query.Build) - svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a InputService7ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService7ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opInputService7TestCaseOperation1 = "OperationName" - -// InputService7TestCaseOperation1Request generates a request for the InputService7TestCaseOperation1 operation. -func (c *InputService7ProtocolTest) InputService7TestCaseOperation1Request(input *InputService7TestShapeInputService7TestCaseOperation1Input) (req *request.Request, output *InputService7TestShapeInputService7TestCaseOperation1Output) { - op := &request.Operation{ - Name: opInputService7TestCaseOperation1, - } - - if input == nil { - input = &InputService7TestShapeInputService7TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &InputService7TestShapeInputService7TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService7ProtocolTest) InputService7TestCaseOperation1(input *InputService7TestShapeInputService7TestCaseOperation1Input) (*InputService7TestShapeInputService7TestCaseOperation1Output, error) { - req, out := c.InputService7TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService7TestShapeInputService7TestCaseOperation1Input struct { - BlobArg []byte `type:"blob"` - - metadataInputService7TestShapeInputService7TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataInputService7TestShapeInputService7TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService7TestShapeInputService7TestCaseOperation1Output struct { - metadataInputService7TestShapeInputService7TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService7TestShapeInputService7TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type InputService8ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the InputService8ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a InputService8ProtocolTest client from just a session. -// svc := inputservice8protocoltest.New(mySession) -// -// // Create a InputService8ProtocolTest client with additional configuration -// svc := inputservice8protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewInputService8ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService8ProtocolTest { - c := p.ClientConfig("inputservice8protocoltest", cfgs...) - return newInputService8ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newInputService8ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService8ProtocolTest { - svc := &InputService8ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "inputservice8protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "2014-01-01", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(ec2query.Build) - svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a InputService8ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService8ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opInputService8TestCaseOperation1 = "OperationName" - -// InputService8TestCaseOperation1Request generates a request for the InputService8TestCaseOperation1 operation. -func (c *InputService8ProtocolTest) InputService8TestCaseOperation1Request(input *InputService8TestShapeInputService8TestCaseOperation1Input) (req *request.Request, output *InputService8TestShapeInputService8TestCaseOperation1Output) { - op := &request.Operation{ - Name: opInputService8TestCaseOperation1, - } - - if input == nil { - input = &InputService8TestShapeInputService8TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &InputService8TestShapeInputService8TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService8ProtocolTest) InputService8TestCaseOperation1(input *InputService8TestShapeInputService8TestCaseOperation1Input) (*InputService8TestShapeInputService8TestCaseOperation1Output, error) { - req, out := c.InputService8TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService8TestShapeInputService8TestCaseOperation1Input struct { - TimeArg *time.Time `type:"timestamp" timestampFormat:"iso8601"` - - metadataInputService8TestShapeInputService8TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataInputService8TestShapeInputService8TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService8TestShapeInputService8TestCaseOperation1Output struct { - metadataInputService8TestShapeInputService8TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService8TestShapeInputService8TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -// -// Tests begin here -// - -func TestInputService1ProtocolTestScalarMembersCase1(t *testing.T) { - sess := session.New() - svc := NewInputService1ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService1TestShapeInputService1TestCaseOperation1Input{ - Bar: aws.String("val2"), - Foo: aws.String("val1"), - } - req, _ := svc.InputService1TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - ec2query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&Bar=val2&Foo=val1&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService2ProtocolTestStructureWithLocationNameAndQueryNameAppliedToMembersCase1(t *testing.T) { - sess := session.New() - svc := NewInputService2ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService2TestShapeInputService2TestCaseOperation1Input{ - Bar: aws.String("val2"), - Foo: aws.String("val1"), - Yuck: aws.String("val3"), - } - req, _ := svc.InputService2TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - ec2query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&BarLocationName=val2&Foo=val1&Version=2014-01-01&yuckQueryName=val3`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService3ProtocolTestNestedStructureMembersCase1(t *testing.T) { - sess := session.New() - svc := NewInputService3ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService3TestShapeInputService3TestCaseOperation1Input{ - StructArg: &InputService3TestShapeStructType{ - ScalarArg: aws.String("foo"), - }, - } - req, _ := svc.InputService3TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - ec2query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&Struct.Scalar=foo&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService4ProtocolTestListTypesCase1(t *testing.T) { - sess := session.New() - svc := NewInputService4ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService4TestShapeInputService4TestCaseOperation1Input{ - ListArg: []*string{ - aws.String("foo"), - aws.String("bar"), - aws.String("baz"), - }, - } - req, _ := svc.InputService4TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - ec2query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&ListArg.1=foo&ListArg.2=bar&ListArg.3=baz&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService5ProtocolTestListWithLocationNameAppliedToMemberCase1(t *testing.T) { - sess := session.New() - svc := NewInputService5ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService5TestShapeInputService5TestCaseOperation1Input{ - ListArg: []*string{ - aws.String("a"), - aws.String("b"), - aws.String("c"), - }, - } - req, _ := svc.InputService5TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - ec2query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&ListMemberName.1=a&ListMemberName.2=b&ListMemberName.3=c&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService6ProtocolTestListWithLocationNameAndQueryNameCase1(t *testing.T) { - sess := session.New() - svc := NewInputService6ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService6TestShapeInputService6TestCaseOperation1Input{ - ListArg: []*string{ - aws.String("a"), - aws.String("b"), - aws.String("c"), - }, - } - req, _ := svc.InputService6TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - ec2query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&ListQueryName.1=a&ListQueryName.2=b&ListQueryName.3=c&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService7ProtocolTestBase64EncodedBlobsCase1(t *testing.T) { - sess := session.New() - svc := NewInputService7ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService7TestShapeInputService7TestCaseOperation1Input{ - BlobArg: []byte("foo"), - } - req, _ := svc.InputService7TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - ec2query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&BlobArg=Zm9v&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService8ProtocolTestTimestampValuesCase1(t *testing.T) { - sess := session.New() - svc := NewInputService8ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService8TestShapeInputService8TestCaseOperation1Input{ - TimeArg: aws.Time(time.Unix(1422172800, 0)), - } - req, _ := svc.InputService8TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - ec2query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&TimeArg=2015-01-25T08%3A00%3A00Z&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/ec2query/unmarshal_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/ec2query/unmarshal_test.go deleted file mode 100644 index c347c371c10..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/ec2query/unmarshal_test.go +++ /dev/null @@ -1,1132 +0,0 @@ -package ec2query_test - -import ( - "bytes" - "encoding/json" - "encoding/xml" - "io" - "io/ioutil" - "net/http" - "net/url" - "testing" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/client" - "github.com/aws/aws-sdk-go/aws/client/metadata" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/awstesting" - "github.com/aws/aws-sdk-go/private/protocol/ec2query" - "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil" - "github.com/aws/aws-sdk-go/private/signer/v4" - "github.com/aws/aws-sdk-go/private/util" - "github.com/stretchr/testify/assert" -) - -var _ bytes.Buffer // always import bytes -var _ http.Request -var _ json.Marshaler -var _ time.Time -var _ xmlutil.XMLNode -var _ xml.Attr -var _ = awstesting.GenerateAssertions -var _ = ioutil.Discard -var _ = util.Trim("") -var _ = url.Values{} -var _ = io.EOF -var _ = aws.String - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService1ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService1ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService1ProtocolTest client from just a session. -// svc := outputservice1protocoltest.New(mySession) -// -// // Create a OutputService1ProtocolTest client with additional configuration -// svc := outputservice1protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService1ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService1ProtocolTest { - c := p.ClientConfig("outputservice1protocoltest", cfgs...) - return newOutputService1ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService1ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService1ProtocolTest { - svc := &OutputService1ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice1protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(ec2query.Build) - svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService1ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService1ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService1TestCaseOperation1 = "OperationName" - -// OutputService1TestCaseOperation1Request generates a request for the OutputService1TestCaseOperation1 operation. -func (c *OutputService1ProtocolTest) OutputService1TestCaseOperation1Request(input *OutputService1TestShapeOutputService1TestCaseOperation1Input) (req *request.Request, output *OutputService1TestShapeOutputService1TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService1TestCaseOperation1, - } - - if input == nil { - input = &OutputService1TestShapeOutputService1TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService1TestShapeOutputService1TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService1ProtocolTest) OutputService1TestCaseOperation1(input *OutputService1TestShapeOutputService1TestCaseOperation1Input) (*OutputService1TestShapeOutputService1TestCaseOperation1Output, error) { - req, out := c.OutputService1TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService1TestShapeOutputService1TestCaseOperation1Input struct { - metadataOutputService1TestShapeOutputService1TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService1TestShapeOutputService1TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService1TestShapeOutputService1TestCaseOperation1Output struct { - Char *string `type:"character"` - - Double *float64 `type:"double"` - - FalseBool *bool `type:"boolean"` - - Float *float64 `type:"float"` - - Long *int64 `type:"long"` - - Num *int64 `locationName:"FooNum" type:"integer"` - - Str *string `type:"string"` - - TrueBool *bool `type:"boolean"` - - metadataOutputService1TestShapeOutputService1TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService1TestShapeOutputService1TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService2ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService2ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService2ProtocolTest client from just a session. -// svc := outputservice2protocoltest.New(mySession) -// -// // Create a OutputService2ProtocolTest client with additional configuration -// svc := outputservice2protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService2ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService2ProtocolTest { - c := p.ClientConfig("outputservice2protocoltest", cfgs...) - return newOutputService2ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService2ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService2ProtocolTest { - svc := &OutputService2ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice2protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(ec2query.Build) - svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService2ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService2ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService2TestCaseOperation1 = "OperationName" - -// OutputService2TestCaseOperation1Request generates a request for the OutputService2TestCaseOperation1 operation. -func (c *OutputService2ProtocolTest) OutputService2TestCaseOperation1Request(input *OutputService2TestShapeOutputService2TestCaseOperation1Input) (req *request.Request, output *OutputService2TestShapeOutputService2TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService2TestCaseOperation1, - } - - if input == nil { - input = &OutputService2TestShapeOutputService2TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService2TestShapeOutputService2TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService2ProtocolTest) OutputService2TestCaseOperation1(input *OutputService2TestShapeOutputService2TestCaseOperation1Input) (*OutputService2TestShapeOutputService2TestCaseOperation1Output, error) { - req, out := c.OutputService2TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService2TestShapeOutputService2TestCaseOperation1Input struct { - metadataOutputService2TestShapeOutputService2TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService2TestShapeOutputService2TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService2TestShapeOutputService2TestCaseOperation1Output struct { - Blob []byte `type:"blob"` - - metadataOutputService2TestShapeOutputService2TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService2TestShapeOutputService2TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService3ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService3ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService3ProtocolTest client from just a session. -// svc := outputservice3protocoltest.New(mySession) -// -// // Create a OutputService3ProtocolTest client with additional configuration -// svc := outputservice3protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService3ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService3ProtocolTest { - c := p.ClientConfig("outputservice3protocoltest", cfgs...) - return newOutputService3ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService3ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService3ProtocolTest { - svc := &OutputService3ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice3protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(ec2query.Build) - svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService3ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService3ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService3TestCaseOperation1 = "OperationName" - -// OutputService3TestCaseOperation1Request generates a request for the OutputService3TestCaseOperation1 operation. -func (c *OutputService3ProtocolTest) OutputService3TestCaseOperation1Request(input *OutputService3TestShapeOutputService3TestCaseOperation1Input) (req *request.Request, output *OutputService3TestShapeOutputService3TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService3TestCaseOperation1, - } - - if input == nil { - input = &OutputService3TestShapeOutputService3TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService3TestShapeOutputService3TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService3ProtocolTest) OutputService3TestCaseOperation1(input *OutputService3TestShapeOutputService3TestCaseOperation1Input) (*OutputService3TestShapeOutputService3TestCaseOperation1Output, error) { - req, out := c.OutputService3TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService3TestShapeOutputService3TestCaseOperation1Input struct { - metadataOutputService3TestShapeOutputService3TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService3TestShapeOutputService3TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService3TestShapeOutputService3TestCaseOperation1Output struct { - ListMember []*string `type:"list"` - - metadataOutputService3TestShapeOutputService3TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService3TestShapeOutputService3TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService4ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService4ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService4ProtocolTest client from just a session. -// svc := outputservice4protocoltest.New(mySession) -// -// // Create a OutputService4ProtocolTest client with additional configuration -// svc := outputservice4protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService4ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService4ProtocolTest { - c := p.ClientConfig("outputservice4protocoltest", cfgs...) - return newOutputService4ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService4ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService4ProtocolTest { - svc := &OutputService4ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice4protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(ec2query.Build) - svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService4ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService4ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService4TestCaseOperation1 = "OperationName" - -// OutputService4TestCaseOperation1Request generates a request for the OutputService4TestCaseOperation1 operation. -func (c *OutputService4ProtocolTest) OutputService4TestCaseOperation1Request(input *OutputService4TestShapeOutputService4TestCaseOperation1Input) (req *request.Request, output *OutputService4TestShapeOutputService4TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService4TestCaseOperation1, - } - - if input == nil { - input = &OutputService4TestShapeOutputService4TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService4TestShapeOutputService4TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService4ProtocolTest) OutputService4TestCaseOperation1(input *OutputService4TestShapeOutputService4TestCaseOperation1Input) (*OutputService4TestShapeOutputService4TestCaseOperation1Output, error) { - req, out := c.OutputService4TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService4TestShapeOutputService4TestCaseOperation1Input struct { - metadataOutputService4TestShapeOutputService4TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService4TestShapeOutputService4TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService4TestShapeOutputService4TestCaseOperation1Output struct { - ListMember []*string `locationNameList:"item" type:"list"` - - metadataOutputService4TestShapeOutputService4TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService4TestShapeOutputService4TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService5ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService5ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService5ProtocolTest client from just a session. -// svc := outputservice5protocoltest.New(mySession) -// -// // Create a OutputService5ProtocolTest client with additional configuration -// svc := outputservice5protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService5ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService5ProtocolTest { - c := p.ClientConfig("outputservice5protocoltest", cfgs...) - return newOutputService5ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService5ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService5ProtocolTest { - svc := &OutputService5ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice5protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(ec2query.Build) - svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService5ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService5ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService5TestCaseOperation1 = "OperationName" - -// OutputService5TestCaseOperation1Request generates a request for the OutputService5TestCaseOperation1 operation. -func (c *OutputService5ProtocolTest) OutputService5TestCaseOperation1Request(input *OutputService5TestShapeOutputService5TestCaseOperation1Input) (req *request.Request, output *OutputService5TestShapeOutputService5TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService5TestCaseOperation1, - } - - if input == nil { - input = &OutputService5TestShapeOutputService5TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService5TestShapeOutputService5TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService5ProtocolTest) OutputService5TestCaseOperation1(input *OutputService5TestShapeOutputService5TestCaseOperation1Input) (*OutputService5TestShapeOutputService5TestCaseOperation1Output, error) { - req, out := c.OutputService5TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService5TestShapeOutputService5TestCaseOperation1Input struct { - metadataOutputService5TestShapeOutputService5TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService5TestShapeOutputService5TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService5TestShapeOutputService5TestCaseOperation1Output struct { - ListMember []*string `type:"list" flattened:"true"` - - metadataOutputService5TestShapeOutputService5TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService5TestShapeOutputService5TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService6ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService6ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService6ProtocolTest client from just a session. -// svc := outputservice6protocoltest.New(mySession) -// -// // Create a OutputService6ProtocolTest client with additional configuration -// svc := outputservice6protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService6ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService6ProtocolTest { - c := p.ClientConfig("outputservice6protocoltest", cfgs...) - return newOutputService6ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService6ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService6ProtocolTest { - svc := &OutputService6ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice6protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(ec2query.Build) - svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService6ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService6ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService6TestCaseOperation1 = "OperationName" - -// OutputService6TestCaseOperation1Request generates a request for the OutputService6TestCaseOperation1 operation. -func (c *OutputService6ProtocolTest) OutputService6TestCaseOperation1Request(input *OutputService6TestShapeOutputService6TestCaseOperation1Input) (req *request.Request, output *OutputService6TestShapeOutputService6TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService6TestCaseOperation1, - } - - if input == nil { - input = &OutputService6TestShapeOutputService6TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService6TestShapeOutputService6TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService6ProtocolTest) OutputService6TestCaseOperation1(input *OutputService6TestShapeOutputService6TestCaseOperation1Input) (*OutputService6TestShapeOutputService6TestCaseOperation1Output, error) { - req, out := c.OutputService6TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService6TestShapeOutputService6TestCaseOperation1Input struct { - metadataOutputService6TestShapeOutputService6TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService6TestShapeOutputService6TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService6TestShapeOutputService6TestCaseOperation1Output struct { - Map map[string]*OutputService6TestShapeStructureType `type:"map"` - - metadataOutputService6TestShapeOutputService6TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService6TestShapeOutputService6TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService6TestShapeStructureType struct { - Foo *string `locationName:"foo" type:"string"` - - metadataOutputService6TestShapeStructureType `json:"-" xml:"-"` -} - -type metadataOutputService6TestShapeStructureType struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService7ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService7ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService7ProtocolTest client from just a session. -// svc := outputservice7protocoltest.New(mySession) -// -// // Create a OutputService7ProtocolTest client with additional configuration -// svc := outputservice7protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService7ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService7ProtocolTest { - c := p.ClientConfig("outputservice7protocoltest", cfgs...) - return newOutputService7ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService7ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService7ProtocolTest { - svc := &OutputService7ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice7protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(ec2query.Build) - svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService7ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService7ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService7TestCaseOperation1 = "OperationName" - -// OutputService7TestCaseOperation1Request generates a request for the OutputService7TestCaseOperation1 operation. -func (c *OutputService7ProtocolTest) OutputService7TestCaseOperation1Request(input *OutputService7TestShapeOutputService7TestCaseOperation1Input) (req *request.Request, output *OutputService7TestShapeOutputService7TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService7TestCaseOperation1, - } - - if input == nil { - input = &OutputService7TestShapeOutputService7TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService7TestShapeOutputService7TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService7ProtocolTest) OutputService7TestCaseOperation1(input *OutputService7TestShapeOutputService7TestCaseOperation1Input) (*OutputService7TestShapeOutputService7TestCaseOperation1Output, error) { - req, out := c.OutputService7TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService7TestShapeOutputService7TestCaseOperation1Input struct { - metadataOutputService7TestShapeOutputService7TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService7TestShapeOutputService7TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService7TestShapeOutputService7TestCaseOperation1Output struct { - Map map[string]*string `type:"map" flattened:"true"` - - metadataOutputService7TestShapeOutputService7TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService7TestShapeOutputService7TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService8ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService8ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService8ProtocolTest client from just a session. -// svc := outputservice8protocoltest.New(mySession) -// -// // Create a OutputService8ProtocolTest client with additional configuration -// svc := outputservice8protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService8ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService8ProtocolTest { - c := p.ClientConfig("outputservice8protocoltest", cfgs...) - return newOutputService8ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService8ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService8ProtocolTest { - svc := &OutputService8ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice8protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(ec2query.Build) - svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService8ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService8ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService8TestCaseOperation1 = "OperationName" - -// OutputService8TestCaseOperation1Request generates a request for the OutputService8TestCaseOperation1 operation. -func (c *OutputService8ProtocolTest) OutputService8TestCaseOperation1Request(input *OutputService8TestShapeOutputService8TestCaseOperation1Input) (req *request.Request, output *OutputService8TestShapeOutputService8TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService8TestCaseOperation1, - } - - if input == nil { - input = &OutputService8TestShapeOutputService8TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService8TestShapeOutputService8TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService8ProtocolTest) OutputService8TestCaseOperation1(input *OutputService8TestShapeOutputService8TestCaseOperation1Input) (*OutputService8TestShapeOutputService8TestCaseOperation1Output, error) { - req, out := c.OutputService8TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService8TestShapeOutputService8TestCaseOperation1Input struct { - metadataOutputService8TestShapeOutputService8TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService8TestShapeOutputService8TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService8TestShapeOutputService8TestCaseOperation1Output struct { - Map map[string]*string `locationNameKey:"foo" locationNameValue:"bar" type:"map" flattened:"true"` - - metadataOutputService8TestShapeOutputService8TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService8TestShapeOutputService8TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService9ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService9ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService9ProtocolTest client from just a session. -// svc := outputservice9protocoltest.New(mySession) -// -// // Create a OutputService9ProtocolTest client with additional configuration -// svc := outputservice9protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService9ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService9ProtocolTest { - c := p.ClientConfig("outputservice9protocoltest", cfgs...) - return newOutputService9ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService9ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService9ProtocolTest { - svc := &OutputService9ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice9protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(ec2query.Build) - svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService9ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService9ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService9TestCaseOperation1 = "OperationName" - -// OutputService9TestCaseOperation1Request generates a request for the OutputService9TestCaseOperation1 operation. -func (c *OutputService9ProtocolTest) OutputService9TestCaseOperation1Request(input *OutputService9TestShapeOutputService9TestCaseOperation1Input) (req *request.Request, output *OutputService9TestShapeOutputService9TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService9TestCaseOperation1, - } - - if input == nil { - input = &OutputService9TestShapeOutputService9TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService9TestShapeOutputService9TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService9ProtocolTest) OutputService9TestCaseOperation1(input *OutputService9TestShapeOutputService9TestCaseOperation1Input) (*OutputService9TestShapeOutputService9TestCaseOperation1Output, error) { - req, out := c.OutputService9TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService9TestShapeOutputService9TestCaseOperation1Input struct { - metadataOutputService9TestShapeOutputService9TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService9TestShapeOutputService9TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService9TestShapeOutputService9TestCaseOperation1Output struct { - Foo *string `type:"string"` - - metadataOutputService9TestShapeOutputService9TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService9TestShapeOutputService9TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -// -// Tests begin here -// - -func TestOutputService1ProtocolTestScalarMembersCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService1ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("myname123falsetrue1.21.3200arequest-id")) - req, out := svc.OutputService1TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - ec2query.UnmarshalMeta(req) - ec2query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "a", *out.Char) - assert.Equal(t, 1.3, *out.Double) - assert.Equal(t, false, *out.FalseBool) - assert.Equal(t, 1.2, *out.Float) - assert.Equal(t, int64(200), *out.Long) - assert.Equal(t, int64(123), *out.Num) - assert.Equal(t, "myname", *out.Str) - assert.Equal(t, true, *out.TrueBool) - -} - -func TestOutputService2ProtocolTestBlobCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService2ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("dmFsdWU=requestid")) - req, out := svc.OutputService2TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - ec2query.UnmarshalMeta(req) - ec2query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "value", string(out.Blob)) - -} - -func TestOutputService3ProtocolTestListsCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService3ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("abc123requestid")) - req, out := svc.OutputService3TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - ec2query.UnmarshalMeta(req) - ec2query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "abc", *out.ListMember[0]) - assert.Equal(t, "123", *out.ListMember[1]) - -} - -func TestOutputService4ProtocolTestListWithCustomMemberNameCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService4ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("abc123requestid")) - req, out := svc.OutputService4TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - ec2query.UnmarshalMeta(req) - ec2query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "abc", *out.ListMember[0]) - assert.Equal(t, "123", *out.ListMember[1]) - -} - -func TestOutputService5ProtocolTestFlattenedListCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService5ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("abc123requestid")) - req, out := svc.OutputService5TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - ec2query.UnmarshalMeta(req) - ec2query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "abc", *out.ListMember[0]) - assert.Equal(t, "123", *out.ListMember[1]) - -} - -func TestOutputService6ProtocolTestNormalMapCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService6ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("quxbarbazbamrequestid")) - req, out := svc.OutputService6TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - ec2query.UnmarshalMeta(req) - ec2query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "bam", *out.Map["baz"].Foo) - assert.Equal(t, "bar", *out.Map["qux"].Foo) - -} - -func TestOutputService7ProtocolTestFlattenedMapCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService7ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("quxbarbazbamrequestid")) - req, out := svc.OutputService7TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - ec2query.UnmarshalMeta(req) - ec2query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "bam", *out.Map["baz"]) - assert.Equal(t, "bar", *out.Map["qux"]) - -} - -func TestOutputService8ProtocolTestNamedMapCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService8ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("quxbarbazbamrequestid")) - req, out := svc.OutputService8TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - ec2query.UnmarshalMeta(req) - ec2query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "bam", *out.Map["baz"]) - assert.Equal(t, "bar", *out.Map["qux"]) - -} - -func TestOutputService9ProtocolTestEmptyStringCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService9ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("requestid")) - req, out := svc.OutputService9TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - ec2query.UnmarshalMeta(req) - ec2query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "", *out.Foo) - -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/query/build_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/query/build_test.go deleted file mode 100644 index 535821b2fd4..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/query/build_test.go +++ /dev/null @@ -1,2139 +0,0 @@ -package query_test - -import ( - "bytes" - "encoding/json" - "encoding/xml" - "io" - "io/ioutil" - "net/http" - "net/url" - "testing" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/client" - "github.com/aws/aws-sdk-go/aws/client/metadata" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/awstesting" - "github.com/aws/aws-sdk-go/private/protocol/query" - "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil" - "github.com/aws/aws-sdk-go/private/signer/v4" - "github.com/aws/aws-sdk-go/private/util" - "github.com/stretchr/testify/assert" -) - -var _ bytes.Buffer // always import bytes -var _ http.Request -var _ json.Marshaler -var _ time.Time -var _ xmlutil.XMLNode -var _ xml.Attr -var _ = awstesting.GenerateAssertions -var _ = ioutil.Discard -var _ = util.Trim("") -var _ = url.Values{} -var _ = io.EOF -var _ = aws.String - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type InputService1ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the InputService1ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a InputService1ProtocolTest client from just a session. -// svc := inputservice1protocoltest.New(mySession) -// -// // Create a InputService1ProtocolTest client with additional configuration -// svc := inputservice1protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewInputService1ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService1ProtocolTest { - c := p.ClientConfig("inputservice1protocoltest", cfgs...) - return newInputService1ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newInputService1ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService1ProtocolTest { - svc := &InputService1ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "inputservice1protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "2014-01-01", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a InputService1ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService1ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opInputService1TestCaseOperation1 = "OperationName" - -// InputService1TestCaseOperation1Request generates a request for the InputService1TestCaseOperation1 operation. -func (c *InputService1ProtocolTest) InputService1TestCaseOperation1Request(input *InputService1TestShapeInputShape) (req *request.Request, output *InputService1TestShapeInputService1TestCaseOperation1Output) { - op := &request.Operation{ - Name: opInputService1TestCaseOperation1, - } - - if input == nil { - input = &InputService1TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService1TestShapeInputService1TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService1ProtocolTest) InputService1TestCaseOperation1(input *InputService1TestShapeInputShape) (*InputService1TestShapeInputService1TestCaseOperation1Output, error) { - req, out := c.InputService1TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -const opInputService1TestCaseOperation2 = "OperationName" - -// InputService1TestCaseOperation2Request generates a request for the InputService1TestCaseOperation2 operation. -func (c *InputService1ProtocolTest) InputService1TestCaseOperation2Request(input *InputService1TestShapeInputShape) (req *request.Request, output *InputService1TestShapeInputService1TestCaseOperation2Output) { - op := &request.Operation{ - Name: opInputService1TestCaseOperation2, - } - - if input == nil { - input = &InputService1TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService1TestShapeInputService1TestCaseOperation2Output{} - req.Data = output - return -} - -func (c *InputService1ProtocolTest) InputService1TestCaseOperation2(input *InputService1TestShapeInputShape) (*InputService1TestShapeInputService1TestCaseOperation2Output, error) { - req, out := c.InputService1TestCaseOperation2Request(input) - err := req.Send() - return out, err -} - -const opInputService1TestCaseOperation3 = "OperationName" - -// InputService1TestCaseOperation3Request generates a request for the InputService1TestCaseOperation3 operation. -func (c *InputService1ProtocolTest) InputService1TestCaseOperation3Request(input *InputService1TestShapeInputShape) (req *request.Request, output *InputService1TestShapeInputService1TestCaseOperation3Output) { - op := &request.Operation{ - Name: opInputService1TestCaseOperation3, - } - - if input == nil { - input = &InputService1TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService1TestShapeInputService1TestCaseOperation3Output{} - req.Data = output - return -} - -func (c *InputService1ProtocolTest) InputService1TestCaseOperation3(input *InputService1TestShapeInputShape) (*InputService1TestShapeInputService1TestCaseOperation3Output, error) { - req, out := c.InputService1TestCaseOperation3Request(input) - err := req.Send() - return out, err -} - -type InputService1TestShapeInputService1TestCaseOperation1Output struct { - metadataInputService1TestShapeInputService1TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService1TestShapeInputService1TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService1TestShapeInputService1TestCaseOperation2Output struct { - metadataInputService1TestShapeInputService1TestCaseOperation2Output `json:"-" xml:"-"` -} - -type metadataInputService1TestShapeInputService1TestCaseOperation2Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService1TestShapeInputService1TestCaseOperation3Output struct { - metadataInputService1TestShapeInputService1TestCaseOperation3Output `json:"-" xml:"-"` -} - -type metadataInputService1TestShapeInputService1TestCaseOperation3Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService1TestShapeInputShape struct { - Bar *string `type:"string"` - - Baz *bool `type:"boolean"` - - Foo *string `type:"string"` - - metadataInputService1TestShapeInputShape `json:"-" xml:"-"` -} - -type metadataInputService1TestShapeInputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type InputService2ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the InputService2ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a InputService2ProtocolTest client from just a session. -// svc := inputservice2protocoltest.New(mySession) -// -// // Create a InputService2ProtocolTest client with additional configuration -// svc := inputservice2protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewInputService2ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService2ProtocolTest { - c := p.ClientConfig("inputservice2protocoltest", cfgs...) - return newInputService2ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newInputService2ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService2ProtocolTest { - svc := &InputService2ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "inputservice2protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "2014-01-01", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a InputService2ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService2ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opInputService2TestCaseOperation1 = "OperationName" - -// InputService2TestCaseOperation1Request generates a request for the InputService2TestCaseOperation1 operation. -func (c *InputService2ProtocolTest) InputService2TestCaseOperation1Request(input *InputService2TestShapeInputService2TestCaseOperation1Input) (req *request.Request, output *InputService2TestShapeInputService2TestCaseOperation1Output) { - op := &request.Operation{ - Name: opInputService2TestCaseOperation1, - } - - if input == nil { - input = &InputService2TestShapeInputService2TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &InputService2TestShapeInputService2TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService2ProtocolTest) InputService2TestCaseOperation1(input *InputService2TestShapeInputService2TestCaseOperation1Input) (*InputService2TestShapeInputService2TestCaseOperation1Output, error) { - req, out := c.InputService2TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService2TestShapeInputService2TestCaseOperation1Input struct { - StructArg *InputService2TestShapeStructType `type:"structure"` - - metadataInputService2TestShapeInputService2TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataInputService2TestShapeInputService2TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService2TestShapeInputService2TestCaseOperation1Output struct { - metadataInputService2TestShapeInputService2TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService2TestShapeInputService2TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService2TestShapeStructType struct { - ScalarArg *string `type:"string"` - - metadataInputService2TestShapeStructType `json:"-" xml:"-"` -} - -type metadataInputService2TestShapeStructType struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type InputService3ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the InputService3ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a InputService3ProtocolTest client from just a session. -// svc := inputservice3protocoltest.New(mySession) -// -// // Create a InputService3ProtocolTest client with additional configuration -// svc := inputservice3protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewInputService3ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService3ProtocolTest { - c := p.ClientConfig("inputservice3protocoltest", cfgs...) - return newInputService3ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newInputService3ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService3ProtocolTest { - svc := &InputService3ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "inputservice3protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "2014-01-01", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a InputService3ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService3ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opInputService3TestCaseOperation1 = "OperationName" - -// InputService3TestCaseOperation1Request generates a request for the InputService3TestCaseOperation1 operation. -func (c *InputService3ProtocolTest) InputService3TestCaseOperation1Request(input *InputService3TestShapeInputShape) (req *request.Request, output *InputService3TestShapeInputService3TestCaseOperation1Output) { - op := &request.Operation{ - Name: opInputService3TestCaseOperation1, - } - - if input == nil { - input = &InputService3TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService3TestShapeInputService3TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService3ProtocolTest) InputService3TestCaseOperation1(input *InputService3TestShapeInputShape) (*InputService3TestShapeInputService3TestCaseOperation1Output, error) { - req, out := c.InputService3TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -const opInputService3TestCaseOperation2 = "OperationName" - -// InputService3TestCaseOperation2Request generates a request for the InputService3TestCaseOperation2 operation. -func (c *InputService3ProtocolTest) InputService3TestCaseOperation2Request(input *InputService3TestShapeInputShape) (req *request.Request, output *InputService3TestShapeInputService3TestCaseOperation2Output) { - op := &request.Operation{ - Name: opInputService3TestCaseOperation2, - } - - if input == nil { - input = &InputService3TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService3TestShapeInputService3TestCaseOperation2Output{} - req.Data = output - return -} - -func (c *InputService3ProtocolTest) InputService3TestCaseOperation2(input *InputService3TestShapeInputShape) (*InputService3TestShapeInputService3TestCaseOperation2Output, error) { - req, out := c.InputService3TestCaseOperation2Request(input) - err := req.Send() - return out, err -} - -type InputService3TestShapeInputService3TestCaseOperation1Output struct { - metadataInputService3TestShapeInputService3TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService3TestShapeInputService3TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService3TestShapeInputService3TestCaseOperation2Output struct { - metadataInputService3TestShapeInputService3TestCaseOperation2Output `json:"-" xml:"-"` -} - -type metadataInputService3TestShapeInputService3TestCaseOperation2Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService3TestShapeInputShape struct { - ListArg []*string `type:"list"` - - metadataInputService3TestShapeInputShape `json:"-" xml:"-"` -} - -type metadataInputService3TestShapeInputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type InputService4ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the InputService4ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a InputService4ProtocolTest client from just a session. -// svc := inputservice4protocoltest.New(mySession) -// -// // Create a InputService4ProtocolTest client with additional configuration -// svc := inputservice4protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewInputService4ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService4ProtocolTest { - c := p.ClientConfig("inputservice4protocoltest", cfgs...) - return newInputService4ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newInputService4ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService4ProtocolTest { - svc := &InputService4ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "inputservice4protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "2014-01-01", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a InputService4ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService4ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opInputService4TestCaseOperation1 = "OperationName" - -// InputService4TestCaseOperation1Request generates a request for the InputService4TestCaseOperation1 operation. -func (c *InputService4ProtocolTest) InputService4TestCaseOperation1Request(input *InputService4TestShapeInputShape) (req *request.Request, output *InputService4TestShapeInputService4TestCaseOperation1Output) { - op := &request.Operation{ - Name: opInputService4TestCaseOperation1, - } - - if input == nil { - input = &InputService4TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService4TestShapeInputService4TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService4ProtocolTest) InputService4TestCaseOperation1(input *InputService4TestShapeInputShape) (*InputService4TestShapeInputService4TestCaseOperation1Output, error) { - req, out := c.InputService4TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -const opInputService4TestCaseOperation2 = "OperationName" - -// InputService4TestCaseOperation2Request generates a request for the InputService4TestCaseOperation2 operation. -func (c *InputService4ProtocolTest) InputService4TestCaseOperation2Request(input *InputService4TestShapeInputShape) (req *request.Request, output *InputService4TestShapeInputService4TestCaseOperation2Output) { - op := &request.Operation{ - Name: opInputService4TestCaseOperation2, - } - - if input == nil { - input = &InputService4TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService4TestShapeInputService4TestCaseOperation2Output{} - req.Data = output - return -} - -func (c *InputService4ProtocolTest) InputService4TestCaseOperation2(input *InputService4TestShapeInputShape) (*InputService4TestShapeInputService4TestCaseOperation2Output, error) { - req, out := c.InputService4TestCaseOperation2Request(input) - err := req.Send() - return out, err -} - -type InputService4TestShapeInputService4TestCaseOperation1Output struct { - metadataInputService4TestShapeInputService4TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService4TestShapeInputService4TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService4TestShapeInputService4TestCaseOperation2Output struct { - metadataInputService4TestShapeInputService4TestCaseOperation2Output `json:"-" xml:"-"` -} - -type metadataInputService4TestShapeInputService4TestCaseOperation2Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService4TestShapeInputShape struct { - ListArg []*string `type:"list" flattened:"true"` - - NamedListArg []*string `locationNameList:"Foo" type:"list" flattened:"true"` - - ScalarArg *string `type:"string"` - - metadataInputService4TestShapeInputShape `json:"-" xml:"-"` -} - -type metadataInputService4TestShapeInputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type InputService5ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the InputService5ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a InputService5ProtocolTest client from just a session. -// svc := inputservice5protocoltest.New(mySession) -// -// // Create a InputService5ProtocolTest client with additional configuration -// svc := inputservice5protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewInputService5ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService5ProtocolTest { - c := p.ClientConfig("inputservice5protocoltest", cfgs...) - return newInputService5ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newInputService5ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService5ProtocolTest { - svc := &InputService5ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "inputservice5protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "2014-01-01", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a InputService5ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService5ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opInputService5TestCaseOperation1 = "OperationName" - -// InputService5TestCaseOperation1Request generates a request for the InputService5TestCaseOperation1 operation. -func (c *InputService5ProtocolTest) InputService5TestCaseOperation1Request(input *InputService5TestShapeInputService5TestCaseOperation1Input) (req *request.Request, output *InputService5TestShapeInputService5TestCaseOperation1Output) { - op := &request.Operation{ - Name: opInputService5TestCaseOperation1, - } - - if input == nil { - input = &InputService5TestShapeInputService5TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &InputService5TestShapeInputService5TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService5ProtocolTest) InputService5TestCaseOperation1(input *InputService5TestShapeInputService5TestCaseOperation1Input) (*InputService5TestShapeInputService5TestCaseOperation1Output, error) { - req, out := c.InputService5TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService5TestShapeInputService5TestCaseOperation1Input struct { - MapArg map[string]*string `type:"map" flattened:"true"` - - metadataInputService5TestShapeInputService5TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataInputService5TestShapeInputService5TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService5TestShapeInputService5TestCaseOperation1Output struct { - metadataInputService5TestShapeInputService5TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService5TestShapeInputService5TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type InputService6ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the InputService6ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a InputService6ProtocolTest client from just a session. -// svc := inputservice6protocoltest.New(mySession) -// -// // Create a InputService6ProtocolTest client with additional configuration -// svc := inputservice6protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewInputService6ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService6ProtocolTest { - c := p.ClientConfig("inputservice6protocoltest", cfgs...) - return newInputService6ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newInputService6ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService6ProtocolTest { - svc := &InputService6ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "inputservice6protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "2014-01-01", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a InputService6ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService6ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opInputService6TestCaseOperation1 = "OperationName" - -// InputService6TestCaseOperation1Request generates a request for the InputService6TestCaseOperation1 operation. -func (c *InputService6ProtocolTest) InputService6TestCaseOperation1Request(input *InputService6TestShapeInputService6TestCaseOperation1Input) (req *request.Request, output *InputService6TestShapeInputService6TestCaseOperation1Output) { - op := &request.Operation{ - Name: opInputService6TestCaseOperation1, - } - - if input == nil { - input = &InputService6TestShapeInputService6TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &InputService6TestShapeInputService6TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService6ProtocolTest) InputService6TestCaseOperation1(input *InputService6TestShapeInputService6TestCaseOperation1Input) (*InputService6TestShapeInputService6TestCaseOperation1Output, error) { - req, out := c.InputService6TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService6TestShapeInputService6TestCaseOperation1Input struct { - ListArg []*string `locationNameList:"item" type:"list"` - - metadataInputService6TestShapeInputService6TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataInputService6TestShapeInputService6TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService6TestShapeInputService6TestCaseOperation1Output struct { - metadataInputService6TestShapeInputService6TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService6TestShapeInputService6TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type InputService7ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the InputService7ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a InputService7ProtocolTest client from just a session. -// svc := inputservice7protocoltest.New(mySession) -// -// // Create a InputService7ProtocolTest client with additional configuration -// svc := inputservice7protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewInputService7ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService7ProtocolTest { - c := p.ClientConfig("inputservice7protocoltest", cfgs...) - return newInputService7ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newInputService7ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService7ProtocolTest { - svc := &InputService7ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "inputservice7protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "2014-01-01", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a InputService7ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService7ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opInputService7TestCaseOperation1 = "OperationName" - -// InputService7TestCaseOperation1Request generates a request for the InputService7TestCaseOperation1 operation. -func (c *InputService7ProtocolTest) InputService7TestCaseOperation1Request(input *InputService7TestShapeInputService7TestCaseOperation1Input) (req *request.Request, output *InputService7TestShapeInputService7TestCaseOperation1Output) { - op := &request.Operation{ - Name: opInputService7TestCaseOperation1, - } - - if input == nil { - input = &InputService7TestShapeInputService7TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &InputService7TestShapeInputService7TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService7ProtocolTest) InputService7TestCaseOperation1(input *InputService7TestShapeInputService7TestCaseOperation1Input) (*InputService7TestShapeInputService7TestCaseOperation1Output, error) { - req, out := c.InputService7TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService7TestShapeInputService7TestCaseOperation1Input struct { - ListArg []*string `locationNameList:"ListArgLocation" type:"list" flattened:"true"` - - ScalarArg *string `type:"string"` - - metadataInputService7TestShapeInputService7TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataInputService7TestShapeInputService7TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService7TestShapeInputService7TestCaseOperation1Output struct { - metadataInputService7TestShapeInputService7TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService7TestShapeInputService7TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type InputService8ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the InputService8ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a InputService8ProtocolTest client from just a session. -// svc := inputservice8protocoltest.New(mySession) -// -// // Create a InputService8ProtocolTest client with additional configuration -// svc := inputservice8protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewInputService8ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService8ProtocolTest { - c := p.ClientConfig("inputservice8protocoltest", cfgs...) - return newInputService8ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newInputService8ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService8ProtocolTest { - svc := &InputService8ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "inputservice8protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "2014-01-01", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a InputService8ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService8ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opInputService8TestCaseOperation1 = "OperationName" - -// InputService8TestCaseOperation1Request generates a request for the InputService8TestCaseOperation1 operation. -func (c *InputService8ProtocolTest) InputService8TestCaseOperation1Request(input *InputService8TestShapeInputService8TestCaseOperation1Input) (req *request.Request, output *InputService8TestShapeInputService8TestCaseOperation1Output) { - op := &request.Operation{ - Name: opInputService8TestCaseOperation1, - } - - if input == nil { - input = &InputService8TestShapeInputService8TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &InputService8TestShapeInputService8TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService8ProtocolTest) InputService8TestCaseOperation1(input *InputService8TestShapeInputService8TestCaseOperation1Input) (*InputService8TestShapeInputService8TestCaseOperation1Output, error) { - req, out := c.InputService8TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService8TestShapeInputService8TestCaseOperation1Input struct { - MapArg map[string]*string `type:"map"` - - metadataInputService8TestShapeInputService8TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataInputService8TestShapeInputService8TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService8TestShapeInputService8TestCaseOperation1Output struct { - metadataInputService8TestShapeInputService8TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService8TestShapeInputService8TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type InputService9ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the InputService9ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a InputService9ProtocolTest client from just a session. -// svc := inputservice9protocoltest.New(mySession) -// -// // Create a InputService9ProtocolTest client with additional configuration -// svc := inputservice9protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewInputService9ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService9ProtocolTest { - c := p.ClientConfig("inputservice9protocoltest", cfgs...) - return newInputService9ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newInputService9ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService9ProtocolTest { - svc := &InputService9ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "inputservice9protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "2014-01-01", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a InputService9ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService9ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opInputService9TestCaseOperation1 = "OperationName" - -// InputService9TestCaseOperation1Request generates a request for the InputService9TestCaseOperation1 operation. -func (c *InputService9ProtocolTest) InputService9TestCaseOperation1Request(input *InputService9TestShapeInputService9TestCaseOperation1Input) (req *request.Request, output *InputService9TestShapeInputService9TestCaseOperation1Output) { - op := &request.Operation{ - Name: opInputService9TestCaseOperation1, - } - - if input == nil { - input = &InputService9TestShapeInputService9TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &InputService9TestShapeInputService9TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService9ProtocolTest) InputService9TestCaseOperation1(input *InputService9TestShapeInputService9TestCaseOperation1Input) (*InputService9TestShapeInputService9TestCaseOperation1Output, error) { - req, out := c.InputService9TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService9TestShapeInputService9TestCaseOperation1Input struct { - MapArg map[string]*string `locationNameKey:"TheKey" locationNameValue:"TheValue" type:"map"` - - metadataInputService9TestShapeInputService9TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataInputService9TestShapeInputService9TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService9TestShapeInputService9TestCaseOperation1Output struct { - metadataInputService9TestShapeInputService9TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService9TestShapeInputService9TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type InputService10ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the InputService10ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a InputService10ProtocolTest client from just a session. -// svc := inputservice10protocoltest.New(mySession) -// -// // Create a InputService10ProtocolTest client with additional configuration -// svc := inputservice10protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewInputService10ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService10ProtocolTest { - c := p.ClientConfig("inputservice10protocoltest", cfgs...) - return newInputService10ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newInputService10ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService10ProtocolTest { - svc := &InputService10ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "inputservice10protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "2014-01-01", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a InputService10ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService10ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opInputService10TestCaseOperation1 = "OperationName" - -// InputService10TestCaseOperation1Request generates a request for the InputService10TestCaseOperation1 operation. -func (c *InputService10ProtocolTest) InputService10TestCaseOperation1Request(input *InputService10TestShapeInputService10TestCaseOperation1Input) (req *request.Request, output *InputService10TestShapeInputService10TestCaseOperation1Output) { - op := &request.Operation{ - Name: opInputService10TestCaseOperation1, - } - - if input == nil { - input = &InputService10TestShapeInputService10TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &InputService10TestShapeInputService10TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService10ProtocolTest) InputService10TestCaseOperation1(input *InputService10TestShapeInputService10TestCaseOperation1Input) (*InputService10TestShapeInputService10TestCaseOperation1Output, error) { - req, out := c.InputService10TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService10TestShapeInputService10TestCaseOperation1Input struct { - BlobArg []byte `type:"blob"` - - metadataInputService10TestShapeInputService10TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataInputService10TestShapeInputService10TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService10TestShapeInputService10TestCaseOperation1Output struct { - metadataInputService10TestShapeInputService10TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService10TestShapeInputService10TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type InputService11ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the InputService11ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a InputService11ProtocolTest client from just a session. -// svc := inputservice11protocoltest.New(mySession) -// -// // Create a InputService11ProtocolTest client with additional configuration -// svc := inputservice11protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewInputService11ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService11ProtocolTest { - c := p.ClientConfig("inputservice11protocoltest", cfgs...) - return newInputService11ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newInputService11ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService11ProtocolTest { - svc := &InputService11ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "inputservice11protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "2014-01-01", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a InputService11ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService11ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opInputService11TestCaseOperation1 = "OperationName" - -// InputService11TestCaseOperation1Request generates a request for the InputService11TestCaseOperation1 operation. -func (c *InputService11ProtocolTest) InputService11TestCaseOperation1Request(input *InputService11TestShapeInputService11TestCaseOperation1Input) (req *request.Request, output *InputService11TestShapeInputService11TestCaseOperation1Output) { - op := &request.Operation{ - Name: opInputService11TestCaseOperation1, - } - - if input == nil { - input = &InputService11TestShapeInputService11TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &InputService11TestShapeInputService11TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService11ProtocolTest) InputService11TestCaseOperation1(input *InputService11TestShapeInputService11TestCaseOperation1Input) (*InputService11TestShapeInputService11TestCaseOperation1Output, error) { - req, out := c.InputService11TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type InputService11TestShapeInputService11TestCaseOperation1Input struct { - TimeArg *time.Time `type:"timestamp" timestampFormat:"iso8601"` - - metadataInputService11TestShapeInputService11TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataInputService11TestShapeInputService11TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService11TestShapeInputService11TestCaseOperation1Output struct { - metadataInputService11TestShapeInputService11TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService11TestShapeInputService11TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type InputService12ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the InputService12ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a InputService12ProtocolTest client from just a session. -// svc := inputservice12protocoltest.New(mySession) -// -// // Create a InputService12ProtocolTest client with additional configuration -// svc := inputservice12protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewInputService12ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService12ProtocolTest { - c := p.ClientConfig("inputservice12protocoltest", cfgs...) - return newInputService12ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newInputService12ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService12ProtocolTest { - svc := &InputService12ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "inputservice12protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "2014-01-01", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a InputService12ProtocolTest operation and runs any -// custom request initialization. -func (c *InputService12ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opInputService12TestCaseOperation1 = "OperationName" - -// InputService12TestCaseOperation1Request generates a request for the InputService12TestCaseOperation1 operation. -func (c *InputService12ProtocolTest) InputService12TestCaseOperation1Request(input *InputService12TestShapeInputShape) (req *request.Request, output *InputService12TestShapeInputService12TestCaseOperation1Output) { - op := &request.Operation{ - Name: opInputService12TestCaseOperation1, - } - - if input == nil { - input = &InputService12TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService12TestShapeInputService12TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *InputService12ProtocolTest) InputService12TestCaseOperation1(input *InputService12TestShapeInputShape) (*InputService12TestShapeInputService12TestCaseOperation1Output, error) { - req, out := c.InputService12TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -const opInputService12TestCaseOperation2 = "OperationName" - -// InputService12TestCaseOperation2Request generates a request for the InputService12TestCaseOperation2 operation. -func (c *InputService12ProtocolTest) InputService12TestCaseOperation2Request(input *InputService12TestShapeInputShape) (req *request.Request, output *InputService12TestShapeInputService12TestCaseOperation2Output) { - op := &request.Operation{ - Name: opInputService12TestCaseOperation2, - } - - if input == nil { - input = &InputService12TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService12TestShapeInputService12TestCaseOperation2Output{} - req.Data = output - return -} - -func (c *InputService12ProtocolTest) InputService12TestCaseOperation2(input *InputService12TestShapeInputShape) (*InputService12TestShapeInputService12TestCaseOperation2Output, error) { - req, out := c.InputService12TestCaseOperation2Request(input) - err := req.Send() - return out, err -} - -const opInputService12TestCaseOperation3 = "OperationName" - -// InputService12TestCaseOperation3Request generates a request for the InputService12TestCaseOperation3 operation. -func (c *InputService12ProtocolTest) InputService12TestCaseOperation3Request(input *InputService12TestShapeInputShape) (req *request.Request, output *InputService12TestShapeInputService12TestCaseOperation3Output) { - op := &request.Operation{ - Name: opInputService12TestCaseOperation3, - } - - if input == nil { - input = &InputService12TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService12TestShapeInputService12TestCaseOperation3Output{} - req.Data = output - return -} - -func (c *InputService12ProtocolTest) InputService12TestCaseOperation3(input *InputService12TestShapeInputShape) (*InputService12TestShapeInputService12TestCaseOperation3Output, error) { - req, out := c.InputService12TestCaseOperation3Request(input) - err := req.Send() - return out, err -} - -const opInputService12TestCaseOperation4 = "OperationName" - -// InputService12TestCaseOperation4Request generates a request for the InputService12TestCaseOperation4 operation. -func (c *InputService12ProtocolTest) InputService12TestCaseOperation4Request(input *InputService12TestShapeInputShape) (req *request.Request, output *InputService12TestShapeInputService12TestCaseOperation4Output) { - op := &request.Operation{ - Name: opInputService12TestCaseOperation4, - } - - if input == nil { - input = &InputService12TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService12TestShapeInputService12TestCaseOperation4Output{} - req.Data = output - return -} - -func (c *InputService12ProtocolTest) InputService12TestCaseOperation4(input *InputService12TestShapeInputShape) (*InputService12TestShapeInputService12TestCaseOperation4Output, error) { - req, out := c.InputService12TestCaseOperation4Request(input) - err := req.Send() - return out, err -} - -const opInputService12TestCaseOperation5 = "OperationName" - -// InputService12TestCaseOperation5Request generates a request for the InputService12TestCaseOperation5 operation. -func (c *InputService12ProtocolTest) InputService12TestCaseOperation5Request(input *InputService12TestShapeInputShape) (req *request.Request, output *InputService12TestShapeInputService12TestCaseOperation5Output) { - op := &request.Operation{ - Name: opInputService12TestCaseOperation5, - } - - if input == nil { - input = &InputService12TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService12TestShapeInputService12TestCaseOperation5Output{} - req.Data = output - return -} - -func (c *InputService12ProtocolTest) InputService12TestCaseOperation5(input *InputService12TestShapeInputShape) (*InputService12TestShapeInputService12TestCaseOperation5Output, error) { - req, out := c.InputService12TestCaseOperation5Request(input) - err := req.Send() - return out, err -} - -const opInputService12TestCaseOperation6 = "OperationName" - -// InputService12TestCaseOperation6Request generates a request for the InputService12TestCaseOperation6 operation. -func (c *InputService12ProtocolTest) InputService12TestCaseOperation6Request(input *InputService12TestShapeInputShape) (req *request.Request, output *InputService12TestShapeInputService12TestCaseOperation6Output) { - op := &request.Operation{ - Name: opInputService12TestCaseOperation6, - } - - if input == nil { - input = &InputService12TestShapeInputShape{} - } - - req = c.newRequest(op, input, output) - output = &InputService12TestShapeInputService12TestCaseOperation6Output{} - req.Data = output - return -} - -func (c *InputService12ProtocolTest) InputService12TestCaseOperation6(input *InputService12TestShapeInputShape) (*InputService12TestShapeInputService12TestCaseOperation6Output, error) { - req, out := c.InputService12TestCaseOperation6Request(input) - err := req.Send() - return out, err -} - -type InputService12TestShapeInputService12TestCaseOperation1Output struct { - metadataInputService12TestShapeInputService12TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataInputService12TestShapeInputService12TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService12TestShapeInputService12TestCaseOperation2Output struct { - metadataInputService12TestShapeInputService12TestCaseOperation2Output `json:"-" xml:"-"` -} - -type metadataInputService12TestShapeInputService12TestCaseOperation2Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService12TestShapeInputService12TestCaseOperation3Output struct { - metadataInputService12TestShapeInputService12TestCaseOperation3Output `json:"-" xml:"-"` -} - -type metadataInputService12TestShapeInputService12TestCaseOperation3Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService12TestShapeInputService12TestCaseOperation4Output struct { - metadataInputService12TestShapeInputService12TestCaseOperation4Output `json:"-" xml:"-"` -} - -type metadataInputService12TestShapeInputService12TestCaseOperation4Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService12TestShapeInputService12TestCaseOperation5Output struct { - metadataInputService12TestShapeInputService12TestCaseOperation5Output `json:"-" xml:"-"` -} - -type metadataInputService12TestShapeInputService12TestCaseOperation5Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService12TestShapeInputService12TestCaseOperation6Output struct { - metadataInputService12TestShapeInputService12TestCaseOperation6Output `json:"-" xml:"-"` -} - -type metadataInputService12TestShapeInputService12TestCaseOperation6Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService12TestShapeInputShape struct { - RecursiveStruct *InputService12TestShapeRecursiveStructType `type:"structure"` - - metadataInputService12TestShapeInputShape `json:"-" xml:"-"` -} - -type metadataInputService12TestShapeInputShape struct { - SDKShapeTraits bool `type:"structure"` -} - -type InputService12TestShapeRecursiveStructType struct { - NoRecurse *string `type:"string"` - - RecursiveList []*InputService12TestShapeRecursiveStructType `type:"list"` - - RecursiveMap map[string]*InputService12TestShapeRecursiveStructType `type:"map"` - - RecursiveStruct *InputService12TestShapeRecursiveStructType `type:"structure"` - - metadataInputService12TestShapeRecursiveStructType `json:"-" xml:"-"` -} - -type metadataInputService12TestShapeRecursiveStructType struct { - SDKShapeTraits bool `type:"structure"` -} - -// -// Tests begin here -// - -func TestInputService1ProtocolTestScalarMembersCase1(t *testing.T) { - sess := session.New() - svc := NewInputService1ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService1TestShapeInputShape{ - Bar: aws.String("val2"), - Foo: aws.String("val1"), - } - req, _ := svc.InputService1TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&Bar=val2&Foo=val1&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService1ProtocolTestScalarMembersCase2(t *testing.T) { - sess := session.New() - svc := NewInputService1ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService1TestShapeInputShape{ - Baz: aws.Bool(true), - } - req, _ := svc.InputService1TestCaseOperation2Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&Baz=true&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService1ProtocolTestScalarMembersCase3(t *testing.T) { - sess := session.New() - svc := NewInputService1ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService1TestShapeInputShape{ - Baz: aws.Bool(false), - } - req, _ := svc.InputService1TestCaseOperation3Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&Baz=false&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService2ProtocolTestNestedStructureMembersCase1(t *testing.T) { - sess := session.New() - svc := NewInputService2ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService2TestShapeInputService2TestCaseOperation1Input{ - StructArg: &InputService2TestShapeStructType{ - ScalarArg: aws.String("foo"), - }, - } - req, _ := svc.InputService2TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&StructArg.ScalarArg=foo&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService3ProtocolTestListTypesCase1(t *testing.T) { - sess := session.New() - svc := NewInputService3ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService3TestShapeInputShape{ - ListArg: []*string{ - aws.String("foo"), - aws.String("bar"), - aws.String("baz"), - }, - } - req, _ := svc.InputService3TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&ListArg.member.1=foo&ListArg.member.2=bar&ListArg.member.3=baz&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService3ProtocolTestListTypesCase2(t *testing.T) { - sess := session.New() - svc := NewInputService3ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService3TestShapeInputShape{ - ListArg: []*string{}, - } - req, _ := svc.InputService3TestCaseOperation2Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&ListArg=&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService4ProtocolTestFlattenedListCase1(t *testing.T) { - sess := session.New() - svc := NewInputService4ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService4TestShapeInputShape{ - ListArg: []*string{ - aws.String("a"), - aws.String("b"), - aws.String("c"), - }, - ScalarArg: aws.String("foo"), - } - req, _ := svc.InputService4TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&ListArg.1=a&ListArg.2=b&ListArg.3=c&ScalarArg=foo&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService4ProtocolTestFlattenedListCase2(t *testing.T) { - sess := session.New() - svc := NewInputService4ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService4TestShapeInputShape{ - NamedListArg: []*string{ - aws.String("a"), - }, - } - req, _ := svc.InputService4TestCaseOperation2Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&Foo.1=a&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService5ProtocolTestSerializeFlattenedMapTypeCase1(t *testing.T) { - sess := session.New() - svc := NewInputService5ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService5TestShapeInputService5TestCaseOperation1Input{ - MapArg: map[string]*string{ - "key1": aws.String("val1"), - "key2": aws.String("val2"), - }, - } - req, _ := svc.InputService5TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&MapArg.1.key=key1&MapArg.1.value=val1&MapArg.2.key=key2&MapArg.2.value=val2&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService6ProtocolTestNonFlattenedListWithLocationNameCase1(t *testing.T) { - sess := session.New() - svc := NewInputService6ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService6TestShapeInputService6TestCaseOperation1Input{ - ListArg: []*string{ - aws.String("a"), - aws.String("b"), - aws.String("c"), - }, - } - req, _ := svc.InputService6TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&ListArg.item.1=a&ListArg.item.2=b&ListArg.item.3=c&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService7ProtocolTestFlattenedListWithLocationNameCase1(t *testing.T) { - sess := session.New() - svc := NewInputService7ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService7TestShapeInputService7TestCaseOperation1Input{ - ListArg: []*string{ - aws.String("a"), - aws.String("b"), - aws.String("c"), - }, - ScalarArg: aws.String("foo"), - } - req, _ := svc.InputService7TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&ListArgLocation.1=a&ListArgLocation.2=b&ListArgLocation.3=c&ScalarArg=foo&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService8ProtocolTestSerializeMapTypeCase1(t *testing.T) { - sess := session.New() - svc := NewInputService8ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService8TestShapeInputService8TestCaseOperation1Input{ - MapArg: map[string]*string{ - "key1": aws.String("val1"), - "key2": aws.String("val2"), - }, - } - req, _ := svc.InputService8TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&MapArg.entry.1.key=key1&MapArg.entry.1.value=val1&MapArg.entry.2.key=key2&MapArg.entry.2.value=val2&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService9ProtocolTestSerializeMapTypeWithLocationNameCase1(t *testing.T) { - sess := session.New() - svc := NewInputService9ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService9TestShapeInputService9TestCaseOperation1Input{ - MapArg: map[string]*string{ - "key1": aws.String("val1"), - "key2": aws.String("val2"), - }, - } - req, _ := svc.InputService9TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&MapArg.entry.1.TheKey=key1&MapArg.entry.1.TheValue=val1&MapArg.entry.2.TheKey=key2&MapArg.entry.2.TheValue=val2&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService10ProtocolTestBase64EncodedBlobsCase1(t *testing.T) { - sess := session.New() - svc := NewInputService10ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService10TestShapeInputService10TestCaseOperation1Input{ - BlobArg: []byte("foo"), - } - req, _ := svc.InputService10TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&BlobArg=Zm9v&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService11ProtocolTestTimestampValuesCase1(t *testing.T) { - sess := session.New() - svc := NewInputService11ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService11TestShapeInputService11TestCaseOperation1Input{ - TimeArg: aws.Time(time.Unix(1422172800, 0)), - } - req, _ := svc.InputService11TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&TimeArg=2015-01-25T08%3A00%3A00Z&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService12ProtocolTestRecursiveShapesCase1(t *testing.T) { - sess := session.New() - svc := NewInputService12ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService12TestShapeInputShape{ - RecursiveStruct: &InputService12TestShapeRecursiveStructType{ - NoRecurse: aws.String("foo"), - }, - } - req, _ := svc.InputService12TestCaseOperation1Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&RecursiveStruct.NoRecurse=foo&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService12ProtocolTestRecursiveShapesCase2(t *testing.T) { - sess := session.New() - svc := NewInputService12ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService12TestShapeInputShape{ - RecursiveStruct: &InputService12TestShapeRecursiveStructType{ - RecursiveStruct: &InputService12TestShapeRecursiveStructType{ - NoRecurse: aws.String("foo"), - }, - }, - } - req, _ := svc.InputService12TestCaseOperation2Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&RecursiveStruct.RecursiveStruct.NoRecurse=foo&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService12ProtocolTestRecursiveShapesCase3(t *testing.T) { - sess := session.New() - svc := NewInputService12ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService12TestShapeInputShape{ - RecursiveStruct: &InputService12TestShapeRecursiveStructType{ - RecursiveStruct: &InputService12TestShapeRecursiveStructType{ - RecursiveStruct: &InputService12TestShapeRecursiveStructType{ - RecursiveStruct: &InputService12TestShapeRecursiveStructType{ - NoRecurse: aws.String("foo"), - }, - }, - }, - }, - } - req, _ := svc.InputService12TestCaseOperation3Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&RecursiveStruct.RecursiveStruct.RecursiveStruct.RecursiveStruct.NoRecurse=foo&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService12ProtocolTestRecursiveShapesCase4(t *testing.T) { - sess := session.New() - svc := NewInputService12ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService12TestShapeInputShape{ - RecursiveStruct: &InputService12TestShapeRecursiveStructType{ - RecursiveList: []*InputService12TestShapeRecursiveStructType{ - { - NoRecurse: aws.String("foo"), - }, - { - NoRecurse: aws.String("bar"), - }, - }, - }, - } - req, _ := svc.InputService12TestCaseOperation4Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&RecursiveStruct.RecursiveList.member.1.NoRecurse=foo&RecursiveStruct.RecursiveList.member.2.NoRecurse=bar&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService12ProtocolTestRecursiveShapesCase5(t *testing.T) { - sess := session.New() - svc := NewInputService12ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService12TestShapeInputShape{ - RecursiveStruct: &InputService12TestShapeRecursiveStructType{ - RecursiveList: []*InputService12TestShapeRecursiveStructType{ - { - NoRecurse: aws.String("foo"), - }, - { - RecursiveStruct: &InputService12TestShapeRecursiveStructType{ - NoRecurse: aws.String("bar"), - }, - }, - }, - }, - } - req, _ := svc.InputService12TestCaseOperation5Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&RecursiveStruct.RecursiveList.member.1.NoRecurse=foo&RecursiveStruct.RecursiveList.member.2.RecursiveStruct.NoRecurse=bar&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} - -func TestInputService12ProtocolTestRecursiveShapesCase6(t *testing.T) { - sess := session.New() - svc := NewInputService12ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - input := &InputService12TestShapeInputShape{ - RecursiveStruct: &InputService12TestShapeRecursiveStructType{ - RecursiveMap: map[string]*InputService12TestShapeRecursiveStructType{ - "bar": { - NoRecurse: aws.String("bar"), - }, - "foo": { - NoRecurse: aws.String("foo"), - }, - }, - }, - } - req, _ := svc.InputService12TestCaseOperation6Request(input) - r := req.HTTPRequest - - // build request - query.Build(req) - assert.NoError(t, req.Error) - - // assert body - assert.NotNil(t, r.Body) - body, _ := ioutil.ReadAll(r.Body) - awstesting.AssertQuery(t, `Action=OperationName&RecursiveStruct.RecursiveMap.entry.1.key=foo&RecursiveStruct.RecursiveMap.entry.1.value.NoRecurse=foo&RecursiveStruct.RecursiveMap.entry.2.key=bar&RecursiveStruct.RecursiveMap.entry.2.value.NoRecurse=bar&Version=2014-01-01`, util.Trim(string(body))) - - // assert URL - awstesting.AssertURL(t, "https://test/", r.URL.String()) - - // assert headers - -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal_error.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal_error.go deleted file mode 100644 index 08609d92088..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal_error.go +++ /dev/null @@ -1,33 +0,0 @@ -package query - -import ( - "encoding/xml" - "io" - - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/aws/request" -) - -type xmlErrorResponse struct { - XMLName xml.Name `xml:"ErrorResponse"` - Code string `xml:"Error>Code"` - Message string `xml:"Error>Message"` - RequestID string `xml:"RequestId"` -} - -// UnmarshalError unmarshals an error response for an AWS Query service. -func UnmarshalError(r *request.Request) { - defer r.HTTPResponse.Body.Close() - - resp := &xmlErrorResponse{} - err := xml.NewDecoder(r.HTTPResponse.Body).Decode(resp) - if err != nil && err != io.EOF { - r.Error = awserr.New("SerializationError", "failed to decode query XML error response", err) - } else { - r.Error = awserr.NewRequestFailure( - awserr.New(resp.Code, resp.Message, nil), - r.HTTPResponse.StatusCode, - resp.RequestID, - ) - } -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal_test.go deleted file mode 100644 index fe2a58e3650..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal_test.go +++ /dev/null @@ -1,1878 +0,0 @@ -package query_test - -import ( - "bytes" - "encoding/json" - "encoding/xml" - "io" - "io/ioutil" - "net/http" - "net/url" - "testing" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/client" - "github.com/aws/aws-sdk-go/aws/client/metadata" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/awstesting" - "github.com/aws/aws-sdk-go/private/protocol/query" - "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil" - "github.com/aws/aws-sdk-go/private/signer/v4" - "github.com/aws/aws-sdk-go/private/util" - "github.com/stretchr/testify/assert" -) - -var _ bytes.Buffer // always import bytes -var _ http.Request -var _ json.Marshaler -var _ time.Time -var _ xmlutil.XMLNode -var _ xml.Attr -var _ = awstesting.GenerateAssertions -var _ = ioutil.Discard -var _ = util.Trim("") -var _ = url.Values{} -var _ = io.EOF -var _ = aws.String - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService1ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService1ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService1ProtocolTest client from just a session. -// svc := outputservice1protocoltest.New(mySession) -// -// // Create a OutputService1ProtocolTest client with additional configuration -// svc := outputservice1protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService1ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService1ProtocolTest { - c := p.ClientConfig("outputservice1protocoltest", cfgs...) - return newOutputService1ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService1ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService1ProtocolTest { - svc := &OutputService1ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice1protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService1ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService1ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService1TestCaseOperation1 = "OperationName" - -// OutputService1TestCaseOperation1Request generates a request for the OutputService1TestCaseOperation1 operation. -func (c *OutputService1ProtocolTest) OutputService1TestCaseOperation1Request(input *OutputService1TestShapeOutputService1TestCaseOperation1Input) (req *request.Request, output *OutputService1TestShapeOutputService1TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService1TestCaseOperation1, - } - - if input == nil { - input = &OutputService1TestShapeOutputService1TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService1TestShapeOutputService1TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService1ProtocolTest) OutputService1TestCaseOperation1(input *OutputService1TestShapeOutputService1TestCaseOperation1Input) (*OutputService1TestShapeOutputService1TestCaseOperation1Output, error) { - req, out := c.OutputService1TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService1TestShapeOutputService1TestCaseOperation1Input struct { - metadataOutputService1TestShapeOutputService1TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService1TestShapeOutputService1TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService1TestShapeOutputService1TestCaseOperation1Output struct { - Char *string `type:"character"` - - Double *float64 `type:"double"` - - FalseBool *bool `type:"boolean"` - - Float *float64 `type:"float"` - - Long *int64 `type:"long"` - - Num *int64 `locationName:"FooNum" type:"integer"` - - Str *string `type:"string"` - - Timestamp *time.Time `type:"timestamp" timestampFormat:"iso8601"` - - TrueBool *bool `type:"boolean"` - - metadataOutputService1TestShapeOutputService1TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService1TestShapeOutputService1TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService2ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService2ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService2ProtocolTest client from just a session. -// svc := outputservice2protocoltest.New(mySession) -// -// // Create a OutputService2ProtocolTest client with additional configuration -// svc := outputservice2protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService2ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService2ProtocolTest { - c := p.ClientConfig("outputservice2protocoltest", cfgs...) - return newOutputService2ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService2ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService2ProtocolTest { - svc := &OutputService2ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice2protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService2ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService2ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService2TestCaseOperation1 = "OperationName" - -// OutputService2TestCaseOperation1Request generates a request for the OutputService2TestCaseOperation1 operation. -func (c *OutputService2ProtocolTest) OutputService2TestCaseOperation1Request(input *OutputService2TestShapeOutputService2TestCaseOperation1Input) (req *request.Request, output *OutputService2TestShapeOutputService2TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService2TestCaseOperation1, - } - - if input == nil { - input = &OutputService2TestShapeOutputService2TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService2TestShapeOutputService2TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService2ProtocolTest) OutputService2TestCaseOperation1(input *OutputService2TestShapeOutputService2TestCaseOperation1Input) (*OutputService2TestShapeOutputService2TestCaseOperation1Output, error) { - req, out := c.OutputService2TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService2TestShapeOutputService2TestCaseOperation1Input struct { - metadataOutputService2TestShapeOutputService2TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService2TestShapeOutputService2TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService2TestShapeOutputService2TestCaseOperation1Output struct { - Num *int64 `type:"integer"` - - Str *string `type:"string"` - - metadataOutputService2TestShapeOutputService2TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService2TestShapeOutputService2TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService3ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService3ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService3ProtocolTest client from just a session. -// svc := outputservice3protocoltest.New(mySession) -// -// // Create a OutputService3ProtocolTest client with additional configuration -// svc := outputservice3protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService3ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService3ProtocolTest { - c := p.ClientConfig("outputservice3protocoltest", cfgs...) - return newOutputService3ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService3ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService3ProtocolTest { - svc := &OutputService3ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice3protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService3ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService3ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService3TestCaseOperation1 = "OperationName" - -// OutputService3TestCaseOperation1Request generates a request for the OutputService3TestCaseOperation1 operation. -func (c *OutputService3ProtocolTest) OutputService3TestCaseOperation1Request(input *OutputService3TestShapeOutputService3TestCaseOperation1Input) (req *request.Request, output *OutputService3TestShapeOutputService3TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService3TestCaseOperation1, - } - - if input == nil { - input = &OutputService3TestShapeOutputService3TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService3TestShapeOutputService3TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService3ProtocolTest) OutputService3TestCaseOperation1(input *OutputService3TestShapeOutputService3TestCaseOperation1Input) (*OutputService3TestShapeOutputService3TestCaseOperation1Output, error) { - req, out := c.OutputService3TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService3TestShapeOutputService3TestCaseOperation1Input struct { - metadataOutputService3TestShapeOutputService3TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService3TestShapeOutputService3TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService3TestShapeOutputService3TestCaseOperation1Output struct { - Blob []byte `type:"blob"` - - metadataOutputService3TestShapeOutputService3TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService3TestShapeOutputService3TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService4ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService4ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService4ProtocolTest client from just a session. -// svc := outputservice4protocoltest.New(mySession) -// -// // Create a OutputService4ProtocolTest client with additional configuration -// svc := outputservice4protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService4ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService4ProtocolTest { - c := p.ClientConfig("outputservice4protocoltest", cfgs...) - return newOutputService4ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService4ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService4ProtocolTest { - svc := &OutputService4ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice4protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService4ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService4ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService4TestCaseOperation1 = "OperationName" - -// OutputService4TestCaseOperation1Request generates a request for the OutputService4TestCaseOperation1 operation. -func (c *OutputService4ProtocolTest) OutputService4TestCaseOperation1Request(input *OutputService4TestShapeOutputService4TestCaseOperation1Input) (req *request.Request, output *OutputService4TestShapeOutputService4TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService4TestCaseOperation1, - } - - if input == nil { - input = &OutputService4TestShapeOutputService4TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService4TestShapeOutputService4TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService4ProtocolTest) OutputService4TestCaseOperation1(input *OutputService4TestShapeOutputService4TestCaseOperation1Input) (*OutputService4TestShapeOutputService4TestCaseOperation1Output, error) { - req, out := c.OutputService4TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService4TestShapeOutputService4TestCaseOperation1Input struct { - metadataOutputService4TestShapeOutputService4TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService4TestShapeOutputService4TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService4TestShapeOutputService4TestCaseOperation1Output struct { - ListMember []*string `type:"list"` - - metadataOutputService4TestShapeOutputService4TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService4TestShapeOutputService4TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService5ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService5ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService5ProtocolTest client from just a session. -// svc := outputservice5protocoltest.New(mySession) -// -// // Create a OutputService5ProtocolTest client with additional configuration -// svc := outputservice5protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService5ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService5ProtocolTest { - c := p.ClientConfig("outputservice5protocoltest", cfgs...) - return newOutputService5ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService5ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService5ProtocolTest { - svc := &OutputService5ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice5protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService5ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService5ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService5TestCaseOperation1 = "OperationName" - -// OutputService5TestCaseOperation1Request generates a request for the OutputService5TestCaseOperation1 operation. -func (c *OutputService5ProtocolTest) OutputService5TestCaseOperation1Request(input *OutputService5TestShapeOutputService5TestCaseOperation1Input) (req *request.Request, output *OutputService5TestShapeOutputService5TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService5TestCaseOperation1, - } - - if input == nil { - input = &OutputService5TestShapeOutputService5TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService5TestShapeOutputService5TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService5ProtocolTest) OutputService5TestCaseOperation1(input *OutputService5TestShapeOutputService5TestCaseOperation1Input) (*OutputService5TestShapeOutputService5TestCaseOperation1Output, error) { - req, out := c.OutputService5TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService5TestShapeOutputService5TestCaseOperation1Input struct { - metadataOutputService5TestShapeOutputService5TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService5TestShapeOutputService5TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService5TestShapeOutputService5TestCaseOperation1Output struct { - ListMember []*string `locationNameList:"item" type:"list"` - - metadataOutputService5TestShapeOutputService5TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService5TestShapeOutputService5TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService6ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService6ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService6ProtocolTest client from just a session. -// svc := outputservice6protocoltest.New(mySession) -// -// // Create a OutputService6ProtocolTest client with additional configuration -// svc := outputservice6protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService6ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService6ProtocolTest { - c := p.ClientConfig("outputservice6protocoltest", cfgs...) - return newOutputService6ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService6ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService6ProtocolTest { - svc := &OutputService6ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice6protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService6ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService6ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService6TestCaseOperation1 = "OperationName" - -// OutputService6TestCaseOperation1Request generates a request for the OutputService6TestCaseOperation1 operation. -func (c *OutputService6ProtocolTest) OutputService6TestCaseOperation1Request(input *OutputService6TestShapeOutputService6TestCaseOperation1Input) (req *request.Request, output *OutputService6TestShapeOutputService6TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService6TestCaseOperation1, - } - - if input == nil { - input = &OutputService6TestShapeOutputService6TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService6TestShapeOutputService6TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService6ProtocolTest) OutputService6TestCaseOperation1(input *OutputService6TestShapeOutputService6TestCaseOperation1Input) (*OutputService6TestShapeOutputService6TestCaseOperation1Output, error) { - req, out := c.OutputService6TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService6TestShapeOutputService6TestCaseOperation1Input struct { - metadataOutputService6TestShapeOutputService6TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService6TestShapeOutputService6TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService6TestShapeOutputService6TestCaseOperation1Output struct { - ListMember []*string `type:"list" flattened:"true"` - - metadataOutputService6TestShapeOutputService6TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService6TestShapeOutputService6TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService7ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService7ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService7ProtocolTest client from just a session. -// svc := outputservice7protocoltest.New(mySession) -// -// // Create a OutputService7ProtocolTest client with additional configuration -// svc := outputservice7protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService7ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService7ProtocolTest { - c := p.ClientConfig("outputservice7protocoltest", cfgs...) - return newOutputService7ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService7ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService7ProtocolTest { - svc := &OutputService7ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice7protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService7ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService7ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService7TestCaseOperation1 = "OperationName" - -// OutputService7TestCaseOperation1Request generates a request for the OutputService7TestCaseOperation1 operation. -func (c *OutputService7ProtocolTest) OutputService7TestCaseOperation1Request(input *OutputService7TestShapeOutputService7TestCaseOperation1Input) (req *request.Request, output *OutputService7TestShapeOutputService7TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService7TestCaseOperation1, - } - - if input == nil { - input = &OutputService7TestShapeOutputService7TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService7TestShapeOutputService7TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService7ProtocolTest) OutputService7TestCaseOperation1(input *OutputService7TestShapeOutputService7TestCaseOperation1Input) (*OutputService7TestShapeOutputService7TestCaseOperation1Output, error) { - req, out := c.OutputService7TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService7TestShapeOutputService7TestCaseOperation1Input struct { - metadataOutputService7TestShapeOutputService7TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService7TestShapeOutputService7TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService7TestShapeOutputService7TestCaseOperation1Output struct { - ListMember []*string `type:"list" flattened:"true"` - - metadataOutputService7TestShapeOutputService7TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService7TestShapeOutputService7TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService8ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService8ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService8ProtocolTest client from just a session. -// svc := outputservice8protocoltest.New(mySession) -// -// // Create a OutputService8ProtocolTest client with additional configuration -// svc := outputservice8protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService8ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService8ProtocolTest { - c := p.ClientConfig("outputservice8protocoltest", cfgs...) - return newOutputService8ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService8ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService8ProtocolTest { - svc := &OutputService8ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice8protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService8ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService8ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService8TestCaseOperation1 = "OperationName" - -// OutputService8TestCaseOperation1Request generates a request for the OutputService8TestCaseOperation1 operation. -func (c *OutputService8ProtocolTest) OutputService8TestCaseOperation1Request(input *OutputService8TestShapeOutputService8TestCaseOperation1Input) (req *request.Request, output *OutputService8TestShapeOutputService8TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService8TestCaseOperation1, - } - - if input == nil { - input = &OutputService8TestShapeOutputService8TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService8TestShapeOutputService8TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService8ProtocolTest) OutputService8TestCaseOperation1(input *OutputService8TestShapeOutputService8TestCaseOperation1Input) (*OutputService8TestShapeOutputService8TestCaseOperation1Output, error) { - req, out := c.OutputService8TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService8TestShapeOutputService8TestCaseOperation1Input struct { - metadataOutputService8TestShapeOutputService8TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService8TestShapeOutputService8TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService8TestShapeOutputService8TestCaseOperation1Output struct { - List []*OutputService8TestShapeStructureShape `type:"list"` - - metadataOutputService8TestShapeOutputService8TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService8TestShapeOutputService8TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService8TestShapeStructureShape struct { - Bar *string `type:"string"` - - Baz *string `type:"string"` - - Foo *string `type:"string"` - - metadataOutputService8TestShapeStructureShape `json:"-" xml:"-"` -} - -type metadataOutputService8TestShapeStructureShape struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService9ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService9ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService9ProtocolTest client from just a session. -// svc := outputservice9protocoltest.New(mySession) -// -// // Create a OutputService9ProtocolTest client with additional configuration -// svc := outputservice9protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService9ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService9ProtocolTest { - c := p.ClientConfig("outputservice9protocoltest", cfgs...) - return newOutputService9ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService9ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService9ProtocolTest { - svc := &OutputService9ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice9protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService9ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService9ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService9TestCaseOperation1 = "OperationName" - -// OutputService9TestCaseOperation1Request generates a request for the OutputService9TestCaseOperation1 operation. -func (c *OutputService9ProtocolTest) OutputService9TestCaseOperation1Request(input *OutputService9TestShapeOutputService9TestCaseOperation1Input) (req *request.Request, output *OutputService9TestShapeOutputService9TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService9TestCaseOperation1, - } - - if input == nil { - input = &OutputService9TestShapeOutputService9TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService9TestShapeOutputService9TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService9ProtocolTest) OutputService9TestCaseOperation1(input *OutputService9TestShapeOutputService9TestCaseOperation1Input) (*OutputService9TestShapeOutputService9TestCaseOperation1Output, error) { - req, out := c.OutputService9TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService9TestShapeOutputService9TestCaseOperation1Input struct { - metadataOutputService9TestShapeOutputService9TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService9TestShapeOutputService9TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService9TestShapeOutputService9TestCaseOperation1Output struct { - List []*OutputService9TestShapeStructureShape `type:"list" flattened:"true"` - - metadataOutputService9TestShapeOutputService9TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService9TestShapeOutputService9TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService9TestShapeStructureShape struct { - Bar *string `type:"string"` - - Baz *string `type:"string"` - - Foo *string `type:"string"` - - metadataOutputService9TestShapeStructureShape `json:"-" xml:"-"` -} - -type metadataOutputService9TestShapeStructureShape struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService10ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService10ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService10ProtocolTest client from just a session. -// svc := outputservice10protocoltest.New(mySession) -// -// // Create a OutputService10ProtocolTest client with additional configuration -// svc := outputservice10protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService10ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService10ProtocolTest { - c := p.ClientConfig("outputservice10protocoltest", cfgs...) - return newOutputService10ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService10ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService10ProtocolTest { - svc := &OutputService10ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice10protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService10ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService10ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService10TestCaseOperation1 = "OperationName" - -// OutputService10TestCaseOperation1Request generates a request for the OutputService10TestCaseOperation1 operation. -func (c *OutputService10ProtocolTest) OutputService10TestCaseOperation1Request(input *OutputService10TestShapeOutputService10TestCaseOperation1Input) (req *request.Request, output *OutputService10TestShapeOutputService10TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService10TestCaseOperation1, - } - - if input == nil { - input = &OutputService10TestShapeOutputService10TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService10TestShapeOutputService10TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService10ProtocolTest) OutputService10TestCaseOperation1(input *OutputService10TestShapeOutputService10TestCaseOperation1Input) (*OutputService10TestShapeOutputService10TestCaseOperation1Output, error) { - req, out := c.OutputService10TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService10TestShapeOutputService10TestCaseOperation1Input struct { - metadataOutputService10TestShapeOutputService10TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService10TestShapeOutputService10TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService10TestShapeOutputService10TestCaseOperation1Output struct { - List []*string `locationNameList:"NamedList" type:"list" flattened:"true"` - - metadataOutputService10TestShapeOutputService10TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService10TestShapeOutputService10TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService11ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService11ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService11ProtocolTest client from just a session. -// svc := outputservice11protocoltest.New(mySession) -// -// // Create a OutputService11ProtocolTest client with additional configuration -// svc := outputservice11protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService11ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService11ProtocolTest { - c := p.ClientConfig("outputservice11protocoltest", cfgs...) - return newOutputService11ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService11ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService11ProtocolTest { - svc := &OutputService11ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice11protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService11ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService11ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService11TestCaseOperation1 = "OperationName" - -// OutputService11TestCaseOperation1Request generates a request for the OutputService11TestCaseOperation1 operation. -func (c *OutputService11ProtocolTest) OutputService11TestCaseOperation1Request(input *OutputService11TestShapeOutputService11TestCaseOperation1Input) (req *request.Request, output *OutputService11TestShapeOutputService11TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService11TestCaseOperation1, - } - - if input == nil { - input = &OutputService11TestShapeOutputService11TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService11TestShapeOutputService11TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService11ProtocolTest) OutputService11TestCaseOperation1(input *OutputService11TestShapeOutputService11TestCaseOperation1Input) (*OutputService11TestShapeOutputService11TestCaseOperation1Output, error) { - req, out := c.OutputService11TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService11TestShapeOutputService11TestCaseOperation1Input struct { - metadataOutputService11TestShapeOutputService11TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService11TestShapeOutputService11TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService11TestShapeOutputService11TestCaseOperation1Output struct { - Map map[string]*OutputService11TestShapeStructType `type:"map"` - - metadataOutputService11TestShapeOutputService11TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService11TestShapeOutputService11TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService11TestShapeStructType struct { - Foo *string `locationName:"foo" type:"string"` - - metadataOutputService11TestShapeStructType `json:"-" xml:"-"` -} - -type metadataOutputService11TestShapeStructType struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService12ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService12ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService12ProtocolTest client from just a session. -// svc := outputservice12protocoltest.New(mySession) -// -// // Create a OutputService12ProtocolTest client with additional configuration -// svc := outputservice12protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService12ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService12ProtocolTest { - c := p.ClientConfig("outputservice12protocoltest", cfgs...) - return newOutputService12ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService12ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService12ProtocolTest { - svc := &OutputService12ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice12protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService12ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService12ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService12TestCaseOperation1 = "OperationName" - -// OutputService12TestCaseOperation1Request generates a request for the OutputService12TestCaseOperation1 operation. -func (c *OutputService12ProtocolTest) OutputService12TestCaseOperation1Request(input *OutputService12TestShapeOutputService12TestCaseOperation1Input) (req *request.Request, output *OutputService12TestShapeOutputService12TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService12TestCaseOperation1, - } - - if input == nil { - input = &OutputService12TestShapeOutputService12TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService12TestShapeOutputService12TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService12ProtocolTest) OutputService12TestCaseOperation1(input *OutputService12TestShapeOutputService12TestCaseOperation1Input) (*OutputService12TestShapeOutputService12TestCaseOperation1Output, error) { - req, out := c.OutputService12TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService12TestShapeOutputService12TestCaseOperation1Input struct { - metadataOutputService12TestShapeOutputService12TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService12TestShapeOutputService12TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService12TestShapeOutputService12TestCaseOperation1Output struct { - Map map[string]*string `type:"map" flattened:"true"` - - metadataOutputService12TestShapeOutputService12TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService12TestShapeOutputService12TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService13ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService13ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService13ProtocolTest client from just a session. -// svc := outputservice13protocoltest.New(mySession) -// -// // Create a OutputService13ProtocolTest client with additional configuration -// svc := outputservice13protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService13ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService13ProtocolTest { - c := p.ClientConfig("outputservice13protocoltest", cfgs...) - return newOutputService13ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService13ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService13ProtocolTest { - svc := &OutputService13ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice13protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService13ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService13ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService13TestCaseOperation1 = "OperationName" - -// OutputService13TestCaseOperation1Request generates a request for the OutputService13TestCaseOperation1 operation. -func (c *OutputService13ProtocolTest) OutputService13TestCaseOperation1Request(input *OutputService13TestShapeOutputService13TestCaseOperation1Input) (req *request.Request, output *OutputService13TestShapeOutputService13TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService13TestCaseOperation1, - } - - if input == nil { - input = &OutputService13TestShapeOutputService13TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService13TestShapeOutputService13TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService13ProtocolTest) OutputService13TestCaseOperation1(input *OutputService13TestShapeOutputService13TestCaseOperation1Input) (*OutputService13TestShapeOutputService13TestCaseOperation1Output, error) { - req, out := c.OutputService13TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService13TestShapeOutputService13TestCaseOperation1Input struct { - metadataOutputService13TestShapeOutputService13TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService13TestShapeOutputService13TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService13TestShapeOutputService13TestCaseOperation1Output struct { - Map map[string]*string `locationName:"Attribute" locationNameKey:"Name" locationNameValue:"Value" type:"map" flattened:"true"` - - metadataOutputService13TestShapeOutputService13TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService13TestShapeOutputService13TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService14ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService14ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService14ProtocolTest client from just a session. -// svc := outputservice14protocoltest.New(mySession) -// -// // Create a OutputService14ProtocolTest client with additional configuration -// svc := outputservice14protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService14ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService14ProtocolTest { - c := p.ClientConfig("outputservice14protocoltest", cfgs...) - return newOutputService14ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService14ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService14ProtocolTest { - svc := &OutputService14ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice14protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService14ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService14ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService14TestCaseOperation1 = "OperationName" - -// OutputService14TestCaseOperation1Request generates a request for the OutputService14TestCaseOperation1 operation. -func (c *OutputService14ProtocolTest) OutputService14TestCaseOperation1Request(input *OutputService14TestShapeOutputService14TestCaseOperation1Input) (req *request.Request, output *OutputService14TestShapeOutputService14TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService14TestCaseOperation1, - } - - if input == nil { - input = &OutputService14TestShapeOutputService14TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService14TestShapeOutputService14TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService14ProtocolTest) OutputService14TestCaseOperation1(input *OutputService14TestShapeOutputService14TestCaseOperation1Input) (*OutputService14TestShapeOutputService14TestCaseOperation1Output, error) { - req, out := c.OutputService14TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService14TestShapeOutputService14TestCaseOperation1Input struct { - metadataOutputService14TestShapeOutputService14TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService14TestShapeOutputService14TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService14TestShapeOutputService14TestCaseOperation1Output struct { - Map map[string]*string `locationNameKey:"foo" locationNameValue:"bar" type:"map" flattened:"true"` - - metadataOutputService14TestShapeOutputService14TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService14TestShapeOutputService14TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type OutputService15ProtocolTest struct { - *client.Client -} - -// New creates a new instance of the OutputService15ProtocolTest client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a OutputService15ProtocolTest client from just a session. -// svc := outputservice15protocoltest.New(mySession) -// -// // Create a OutputService15ProtocolTest client with additional configuration -// svc := outputservice15protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func NewOutputService15ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService15ProtocolTest { - c := p.ClientConfig("outputservice15protocoltest", cfgs...) - return newOutputService15ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newOutputService15ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService15ProtocolTest { - svc := &OutputService15ProtocolTest{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: "outputservice15protocoltest", - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - return svc -} - -// newRequest creates a new request for a OutputService15ProtocolTest operation and runs any -// custom request initialization. -func (c *OutputService15ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - return req -} - -const opOutputService15TestCaseOperation1 = "OperationName" - -// OutputService15TestCaseOperation1Request generates a request for the OutputService15TestCaseOperation1 operation. -func (c *OutputService15ProtocolTest) OutputService15TestCaseOperation1Request(input *OutputService15TestShapeOutputService15TestCaseOperation1Input) (req *request.Request, output *OutputService15TestShapeOutputService15TestCaseOperation1Output) { - op := &request.Operation{ - Name: opOutputService15TestCaseOperation1, - } - - if input == nil { - input = &OutputService15TestShapeOutputService15TestCaseOperation1Input{} - } - - req = c.newRequest(op, input, output) - output = &OutputService15TestShapeOutputService15TestCaseOperation1Output{} - req.Data = output - return -} - -func (c *OutputService15ProtocolTest) OutputService15TestCaseOperation1(input *OutputService15TestShapeOutputService15TestCaseOperation1Input) (*OutputService15TestShapeOutputService15TestCaseOperation1Output, error) { - req, out := c.OutputService15TestCaseOperation1Request(input) - err := req.Send() - return out, err -} - -type OutputService15TestShapeOutputService15TestCaseOperation1Input struct { - metadataOutputService15TestShapeOutputService15TestCaseOperation1Input `json:"-" xml:"-"` -} - -type metadataOutputService15TestShapeOutputService15TestCaseOperation1Input struct { - SDKShapeTraits bool `type:"structure"` -} - -type OutputService15TestShapeOutputService15TestCaseOperation1Output struct { - Foo *string `type:"string"` - - metadataOutputService15TestShapeOutputService15TestCaseOperation1Output `json:"-" xml:"-"` -} - -type metadataOutputService15TestShapeOutputService15TestCaseOperation1Output struct { - SDKShapeTraits bool `type:"structure"` -} - -// -// Tests begin here -// - -func TestOutputService1ProtocolTestScalarMembersCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService1ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("myname123falsetrue1.21.3200a2015-01-25T08:00:00Zrequest-id")) - req, out := svc.OutputService1TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "a", *out.Char) - assert.Equal(t, 1.3, *out.Double) - assert.Equal(t, false, *out.FalseBool) - assert.Equal(t, 1.2, *out.Float) - assert.Equal(t, int64(200), *out.Long) - assert.Equal(t, int64(123), *out.Num) - assert.Equal(t, "myname", *out.Str) - assert.Equal(t, time.Unix(1.4221728e+09, 0).UTC().String(), out.Timestamp.String()) - assert.Equal(t, true, *out.TrueBool) - -} - -func TestOutputService2ProtocolTestNotAllMembersInResponseCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService2ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("mynamerequest-id")) - req, out := svc.OutputService2TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "myname", *out.Str) - -} - -func TestOutputService3ProtocolTestBlobCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService3ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("dmFsdWU=requestid")) - req, out := svc.OutputService3TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "value", string(out.Blob)) - -} - -func TestOutputService4ProtocolTestListsCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService4ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("abc123requestid")) - req, out := svc.OutputService4TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "abc", *out.ListMember[0]) - assert.Equal(t, "123", *out.ListMember[1]) - -} - -func TestOutputService5ProtocolTestListWithCustomMemberNameCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService5ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("abc123requestid")) - req, out := svc.OutputService5TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "abc", *out.ListMember[0]) - assert.Equal(t, "123", *out.ListMember[1]) - -} - -func TestOutputService6ProtocolTestFlattenedListCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService6ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("abc123requestid")) - req, out := svc.OutputService6TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "abc", *out.ListMember[0]) - assert.Equal(t, "123", *out.ListMember[1]) - -} - -func TestOutputService7ProtocolTestFlattenedSingleElementListCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService7ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("abcrequestid")) - req, out := svc.OutputService7TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "abc", *out.ListMember[0]) - -} - -func TestOutputService8ProtocolTestListOfStructuresCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService8ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("firstfoofirstbarfirstbazsecondfoosecondbarsecondbazrequestid")) - req, out := svc.OutputService8TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "firstbar", *out.List[0].Bar) - assert.Equal(t, "firstbaz", *out.List[0].Baz) - assert.Equal(t, "firstfoo", *out.List[0].Foo) - assert.Equal(t, "secondbar", *out.List[1].Bar) - assert.Equal(t, "secondbaz", *out.List[1].Baz) - assert.Equal(t, "secondfoo", *out.List[1].Foo) - -} - -func TestOutputService9ProtocolTestFlattenedListOfStructuresCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService9ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("firstfoofirstbarfirstbazsecondfoosecondbarsecondbazrequestid")) - req, out := svc.OutputService9TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "firstbar", *out.List[0].Bar) - assert.Equal(t, "firstbaz", *out.List[0].Baz) - assert.Equal(t, "firstfoo", *out.List[0].Foo) - assert.Equal(t, "secondbar", *out.List[1].Bar) - assert.Equal(t, "secondbaz", *out.List[1].Baz) - assert.Equal(t, "secondfoo", *out.List[1].Foo) - -} - -func TestOutputService10ProtocolTestFlattenedListWithLocationNameCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService10ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("abrequestid")) - req, out := svc.OutputService10TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "a", *out.List[0]) - assert.Equal(t, "b", *out.List[1]) - -} - -func TestOutputService11ProtocolTestNormalMapCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService11ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("quxbarbazbamrequestid")) - req, out := svc.OutputService11TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "bam", *out.Map["baz"].Foo) - assert.Equal(t, "bar", *out.Map["qux"].Foo) - -} - -func TestOutputService12ProtocolTestFlattenedMapCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService12ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("quxbarbazbamrequestid")) - req, out := svc.OutputService12TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "bam", *out.Map["baz"]) - assert.Equal(t, "bar", *out.Map["qux"]) - -} - -func TestOutputService13ProtocolTestFlattenedMapInShapeDefinitionCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService13ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("quxbarrequestid")) - req, out := svc.OutputService13TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "bar", *out.Map["qux"]) - -} - -func TestOutputService14ProtocolTestNamedMapCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService14ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("quxbarbazbamrequestid")) - req, out := svc.OutputService14TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "bam", *out.Map["baz"]) - assert.Equal(t, "bar", *out.Map["qux"]) - -} - -func TestOutputService15ProtocolTestEmptyStringCase1(t *testing.T) { - sess := session.New() - svc := NewOutputService15ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")}) - - buf := bytes.NewReader([]byte("requestid")) - req, out := svc.OutputService15TestCaseOperation1Request(nil) - req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} - - // set headers - - // unmarshal response - query.UnmarshalMeta(req) - query.Unmarshal(req) - assert.NoError(t, req.Error) - - // assert response - assert.NotNil(t, out) // ensure out variable is used - assert.Equal(t, "", *out.Foo) - -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/rest/payload.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/rest/payload.go deleted file mode 100644 index 1f603bb719f..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/rest/payload.go +++ /dev/null @@ -1,45 +0,0 @@ -package rest - -import "reflect" - -// PayloadMember returns the payload field member of i if there is one, or nil. -func PayloadMember(i interface{}) interface{} { - if i == nil { - return nil - } - - v := reflect.ValueOf(i).Elem() - if !v.IsValid() { - return nil - } - if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok { - if payloadName := field.Tag.Get("payload"); payloadName != "" { - field, _ := v.Type().FieldByName(payloadName) - if field.Tag.Get("type") != "structure" { - return nil - } - - payload := v.FieldByName(payloadName) - if payload.IsValid() || (payload.Kind() == reflect.Ptr && !payload.IsNil()) { - return payload.Interface() - } - } - } - return nil -} - -// PayloadType returns the type of a payload field member of i if there is one, or "". -func PayloadType(i interface{}) string { - v := reflect.Indirect(reflect.ValueOf(i)) - if !v.IsValid() { - return "" - } - if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok { - if payloadName := field.Tag.Get("payload"); payloadName != "" { - if member, ok := v.Type().FieldByName(payloadName); ok { - return member.Tag.Get("type") - } - } - } - return "" -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/unmarshal.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/unmarshal.go deleted file mode 100644 index 5e4fe210b36..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/unmarshal.go +++ /dev/null @@ -1,260 +0,0 @@ -package xmlutil - -import ( - "encoding/base64" - "encoding/xml" - "fmt" - "io" - "reflect" - "strconv" - "strings" - "time" -) - -// UnmarshalXML deserializes an xml.Decoder into the container v. V -// needs to match the shape of the XML expected to be decoded. -// If the shape doesn't match unmarshaling will fail. -func UnmarshalXML(v interface{}, d *xml.Decoder, wrapper string) error { - n, _ := XMLToStruct(d, nil) - if n.Children != nil { - for _, root := range n.Children { - for _, c := range root { - if wrappedChild, ok := c.Children[wrapper]; ok { - c = wrappedChild[0] // pull out wrapped element - } - - err := parse(reflect.ValueOf(v), c, "") - if err != nil { - if err == io.EOF { - return nil - } - return err - } - } - } - return nil - } - return nil -} - -// parse deserializes any value from the XMLNode. The type tag is used to infer the type, or reflect -// will be used to determine the type from r. -func parse(r reflect.Value, node *XMLNode, tag reflect.StructTag) error { - rtype := r.Type() - if rtype.Kind() == reflect.Ptr { - rtype = rtype.Elem() // check kind of actual element type - } - - t := tag.Get("type") - if t == "" { - switch rtype.Kind() { - case reflect.Struct: - t = "structure" - case reflect.Slice: - t = "list" - case reflect.Map: - t = "map" - } - } - - switch t { - case "structure": - if field, ok := rtype.FieldByName("SDKShapeTraits"); ok { - tag = field.Tag - } - return parseStruct(r, node, tag) - case "list": - return parseList(r, node, tag) - case "map": - return parseMap(r, node, tag) - default: - return parseScalar(r, node, tag) - } -} - -// parseStruct deserializes a structure and its fields from an XMLNode. Any nested -// types in the structure will also be deserialized. -func parseStruct(r reflect.Value, node *XMLNode, tag reflect.StructTag) error { - t := r.Type() - if r.Kind() == reflect.Ptr { - if r.IsNil() { // create the structure if it's nil - s := reflect.New(r.Type().Elem()) - r.Set(s) - r = s - } - - r = r.Elem() - t = t.Elem() - } - - // unwrap any payloads - if payload := tag.Get("payload"); payload != "" { - field, _ := t.FieldByName(payload) - return parseStruct(r.FieldByName(payload), node, field.Tag) - } - - for i := 0; i < t.NumField(); i++ { - field := t.Field(i) - if c := field.Name[0:1]; strings.ToLower(c) == c { - continue // ignore unexported fields - } - - // figure out what this field is called - name := field.Name - if field.Tag.Get("flattened") != "" && field.Tag.Get("locationNameList") != "" { - name = field.Tag.Get("locationNameList") - } else if locName := field.Tag.Get("locationName"); locName != "" { - name = locName - } - - // try to find the field by name in elements - elems := node.Children[name] - - if elems == nil { // try to find the field in attributes - for _, a := range node.Attr { - if name == a.Name.Local { - // turn this into a text node for de-serializing - elems = []*XMLNode{{Text: a.Value}} - } - } - } - - member := r.FieldByName(field.Name) - for _, elem := range elems { - err := parse(member, elem, field.Tag) - if err != nil { - return err - } - } - } - return nil -} - -// parseList deserializes a list of values from an XML node. Each list entry -// will also be deserialized. -func parseList(r reflect.Value, node *XMLNode, tag reflect.StructTag) error { - t := r.Type() - - if tag.Get("flattened") == "" { // look at all item entries - mname := "member" - if name := tag.Get("locationNameList"); name != "" { - mname = name - } - - if Children, ok := node.Children[mname]; ok { - if r.IsNil() { - r.Set(reflect.MakeSlice(t, len(Children), len(Children))) - } - - for i, c := range Children { - err := parse(r.Index(i), c, "") - if err != nil { - return err - } - } - } - } else { // flattened list means this is a single element - if r.IsNil() { - r.Set(reflect.MakeSlice(t, 0, 0)) - } - - childR := reflect.Zero(t.Elem()) - r.Set(reflect.Append(r, childR)) - err := parse(r.Index(r.Len()-1), node, "") - if err != nil { - return err - } - } - - return nil -} - -// parseMap deserializes a map from an XMLNode. The direct children of the XMLNode -// will also be deserialized as map entries. -func parseMap(r reflect.Value, node *XMLNode, tag reflect.StructTag) error { - if r.IsNil() { - r.Set(reflect.MakeMap(r.Type())) - } - - if tag.Get("flattened") == "" { // look at all child entries - for _, entry := range node.Children["entry"] { - parseMapEntry(r, entry, tag) - } - } else { // this element is itself an entry - parseMapEntry(r, node, tag) - } - - return nil -} - -// parseMapEntry deserializes a map entry from a XML node. -func parseMapEntry(r reflect.Value, node *XMLNode, tag reflect.StructTag) error { - kname, vname := "key", "value" - if n := tag.Get("locationNameKey"); n != "" { - kname = n - } - if n := tag.Get("locationNameValue"); n != "" { - vname = n - } - - keys, ok := node.Children[kname] - values := node.Children[vname] - if ok { - for i, key := range keys { - keyR := reflect.ValueOf(key.Text) - value := values[i] - valueR := reflect.New(r.Type().Elem()).Elem() - - parse(valueR, value, "") - r.SetMapIndex(keyR, valueR) - } - } - return nil -} - -// parseScaller deserializes an XMLNode value into a concrete type based on the -// interface type of r. -// -// Error is returned if the deserialization fails due to invalid type conversion, -// or unsupported interface type. -func parseScalar(r reflect.Value, node *XMLNode, tag reflect.StructTag) error { - switch r.Interface().(type) { - case *string: - r.Set(reflect.ValueOf(&node.Text)) - return nil - case []byte: - b, err := base64.StdEncoding.DecodeString(node.Text) - if err != nil { - return err - } - r.Set(reflect.ValueOf(b)) - case *bool: - v, err := strconv.ParseBool(node.Text) - if err != nil { - return err - } - r.Set(reflect.ValueOf(&v)) - case *int64: - v, err := strconv.ParseInt(node.Text, 10, 64) - if err != nil { - return err - } - r.Set(reflect.ValueOf(&v)) - case *float64: - v, err := strconv.ParseFloat(node.Text, 64) - if err != nil { - return err - } - r.Set(reflect.ValueOf(&v)) - case *time.Time: - const ISO8601UTC = "2006-01-02T15:04:05Z" - t, err := time.Parse(ISO8601UTC, node.Text) - if err != nil { - return err - } - r.Set(reflect.ValueOf(&t)) - default: - return fmt.Errorf("unsupported value: %v (%s)", r.Interface(), r.Type()) - } - return nil -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go deleted file mode 100644 index 72c198a9d8d..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go +++ /dev/null @@ -1,105 +0,0 @@ -package xmlutil - -import ( - "encoding/xml" - "io" - "sort" -) - -// A XMLNode contains the values to be encoded or decoded. -type XMLNode struct { - Name xml.Name `json:",omitempty"` - Children map[string][]*XMLNode `json:",omitempty"` - Text string `json:",omitempty"` - Attr []xml.Attr `json:",omitempty"` -} - -// NewXMLElement returns a pointer to a new XMLNode initialized to default values. -func NewXMLElement(name xml.Name) *XMLNode { - return &XMLNode{ - Name: name, - Children: map[string][]*XMLNode{}, - Attr: []xml.Attr{}, - } -} - -// AddChild adds child to the XMLNode. -func (n *XMLNode) AddChild(child *XMLNode) { - if _, ok := n.Children[child.Name.Local]; !ok { - n.Children[child.Name.Local] = []*XMLNode{} - } - n.Children[child.Name.Local] = append(n.Children[child.Name.Local], child) -} - -// XMLToStruct converts a xml.Decoder stream to XMLNode with nested values. -func XMLToStruct(d *xml.Decoder, s *xml.StartElement) (*XMLNode, error) { - out := &XMLNode{} - for { - tok, err := d.Token() - if tok == nil || err == io.EOF { - break - } - if err != nil { - return out, err - } - - switch typed := tok.(type) { - case xml.CharData: - out.Text = string(typed.Copy()) - case xml.StartElement: - el := typed.Copy() - out.Attr = el.Attr - if out.Children == nil { - out.Children = map[string][]*XMLNode{} - } - - name := typed.Name.Local - slice := out.Children[name] - if slice == nil { - slice = []*XMLNode{} - } - node, e := XMLToStruct(d, &el) - if e != nil { - return out, e - } - node.Name = typed.Name - slice = append(slice, node) - out.Children[name] = slice - case xml.EndElement: - if s != nil && s.Name.Local == typed.Name.Local { // matching end token - return out, nil - } - } - } - return out, nil -} - -// StructToXML writes an XMLNode to a xml.Encoder as tokens. -func StructToXML(e *xml.Encoder, node *XMLNode, sorted bool) error { - e.EncodeToken(xml.StartElement{Name: node.Name, Attr: node.Attr}) - - if node.Text != "" { - e.EncodeToken(xml.CharData([]byte(node.Text))) - } else if sorted { - sortedNames := []string{} - for k := range node.Children { - sortedNames = append(sortedNames, k) - } - sort.Strings(sortedNames) - - for _, k := range sortedNames { - for _, v := range node.Children[k] { - StructToXML(e, v, sorted) - } - } - } else { - for _, c := range node.Children { - for _, v := range c { - StructToXML(e, v, sorted) - } - } - } - - e.EncodeToken(xml.EndElement{Name: node.Name}) - return e.Flush() -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/signer/v4/functional_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/signer/v4/functional_test.go deleted file mode 100644 index 51a26d6ade6..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/signer/v4/functional_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package v4_test - -import ( - "net/url" - "testing" - "time" - - "github.com/stretchr/testify/assert" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/awstesting/unit" - "github.com/aws/aws-sdk-go/service/s3" -) - -func TestPresignHandler(t *testing.T) { - svc := s3.New(unit.Session) - req, _ := svc.PutObjectRequest(&s3.PutObjectInput{ - Bucket: aws.String("bucket"), - Key: aws.String("key"), - ContentDisposition: aws.String("a+b c$d"), - ACL: aws.String("public-read"), - }) - req.Time = time.Unix(0, 0) - urlstr, err := req.Presign(5 * time.Minute) - - assert.NoError(t, err) - - expectedDate := "19700101T000000Z" - expectedHeaders := "host;x-amz-acl" - expectedSig := "7edcb4e3a1bf12f4989018d75acbe3a7f03df24bd6f3112602d59fc551f0e4e2" - expectedCred := "AKID/19700101/mock-region/s3/aws4_request" - - u, _ := url.Parse(urlstr) - urlQ := u.Query() - assert.Equal(t, expectedSig, urlQ.Get("X-Amz-Signature")) - assert.Equal(t, expectedCred, urlQ.Get("X-Amz-Credential")) - assert.Equal(t, expectedHeaders, urlQ.Get("X-Amz-SignedHeaders")) - assert.Equal(t, expectedDate, urlQ.Get("X-Amz-Date")) - assert.Equal(t, "300", urlQ.Get("X-Amz-Expires")) - - assert.NotContains(t, urlstr, "+") // + encoded as %20 -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/signer/v4/v4.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/signer/v4/v4.go deleted file mode 100644 index dc176f312ba..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/signer/v4/v4.go +++ /dev/null @@ -1,365 +0,0 @@ -// Package v4 implements signing for AWS V4 signer -package v4 - -import ( - "crypto/hmac" - "crypto/sha256" - "encoding/hex" - "fmt" - "io" - "net/http" - "net/url" - "sort" - "strconv" - "strings" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/credentials" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/private/protocol/rest" -) - -const ( - authHeaderPrefix = "AWS4-HMAC-SHA256" - timeFormat = "20060102T150405Z" - shortTimeFormat = "20060102" -) - -var ignoredHeaders = map[string]bool{ - "Authorization": true, - "Content-Type": true, - "Content-Length": true, - "User-Agent": true, -} - -type signer struct { - Request *http.Request - Time time.Time - ExpireTime time.Duration - ServiceName string - Region string - CredValues credentials.Value - Credentials *credentials.Credentials - Query url.Values - Body io.ReadSeeker - Debug aws.LogLevelType - Logger aws.Logger - - isPresign bool - formattedTime string - formattedShortTime string - - signedHeaders string - canonicalHeaders string - canonicalString string - credentialString string - stringToSign string - signature string - authorization string -} - -// Sign requests with signature version 4. -// -// Will sign the requests with the service config's Credentials object -// Signing is skipped if the credentials is the credentials.AnonymousCredentials -// object. -func Sign(req *request.Request) { - // If the request does not need to be signed ignore the signing of the - // request if the AnonymousCredentials object is used. - if req.Config.Credentials == credentials.AnonymousCredentials { - return - } - - region := req.ClientInfo.SigningRegion - if region == "" { - region = aws.StringValue(req.Config.Region) - } - - name := req.ClientInfo.SigningName - if name == "" { - name = req.ClientInfo.ServiceName - } - - s := signer{ - Request: req.HTTPRequest, - Time: req.Time, - ExpireTime: req.ExpireTime, - Query: req.HTTPRequest.URL.Query(), - Body: req.Body, - ServiceName: name, - Region: region, - Credentials: req.Config.Credentials, - Debug: req.Config.LogLevel.Value(), - Logger: req.Config.Logger, - } - - req.Error = s.sign() -} - -func (v4 *signer) sign() error { - if v4.ExpireTime != 0 { - v4.isPresign = true - } - - if v4.isRequestSigned() { - if !v4.Credentials.IsExpired() { - // If the request is already signed, and the credentials have not - // expired yet ignore the signing request. - return nil - } - - // The credentials have expired for this request. The current signing - // is invalid, and needs to be request because the request will fail. - if v4.isPresign { - v4.removePresign() - // Update the request's query string to ensure the values stays in - // sync in the case retrieving the new credentials fails. - v4.Request.URL.RawQuery = v4.Query.Encode() - } - } - - var err error - v4.CredValues, err = v4.Credentials.Get() - if err != nil { - return err - } - - if v4.isPresign { - v4.Query.Set("X-Amz-Algorithm", authHeaderPrefix) - if v4.CredValues.SessionToken != "" { - v4.Query.Set("X-Amz-Security-Token", v4.CredValues.SessionToken) - } else { - v4.Query.Del("X-Amz-Security-Token") - } - } else if v4.CredValues.SessionToken != "" { - v4.Request.Header.Set("X-Amz-Security-Token", v4.CredValues.SessionToken) - } - - v4.build() - - if v4.Debug.Matches(aws.LogDebugWithSigning) { - v4.logSigningInfo() - } - - return nil -} - -const logSignInfoMsg = `DEBUG: Request Signiture: ----[ CANONICAL STRING ]----------------------------- -%s ----[ STRING TO SIGN ]-------------------------------- -%s%s ------------------------------------------------------` -const logSignedURLMsg = ` ----[ SIGNED URL ]------------------------------------ -%s` - -func (v4 *signer) logSigningInfo() { - signedURLMsg := "" - if v4.isPresign { - signedURLMsg = fmt.Sprintf(logSignedURLMsg, v4.Request.URL.String()) - } - msg := fmt.Sprintf(logSignInfoMsg, v4.canonicalString, v4.stringToSign, signedURLMsg) - v4.Logger.Log(msg) -} - -func (v4 *signer) build() { - v4.buildTime() // no depends - v4.buildCredentialString() // no depends - if v4.isPresign { - v4.buildQuery() // no depends - } - v4.buildCanonicalHeaders() // depends on cred string - v4.buildCanonicalString() // depends on canon headers / signed headers - v4.buildStringToSign() // depends on canon string - v4.buildSignature() // depends on string to sign - - if v4.isPresign { - v4.Request.URL.RawQuery += "&X-Amz-Signature=" + v4.signature - } else { - parts := []string{ - authHeaderPrefix + " Credential=" + v4.CredValues.AccessKeyID + "/" + v4.credentialString, - "SignedHeaders=" + v4.signedHeaders, - "Signature=" + v4.signature, - } - v4.Request.Header.Set("Authorization", strings.Join(parts, ", ")) - } -} - -func (v4 *signer) buildTime() { - v4.formattedTime = v4.Time.UTC().Format(timeFormat) - v4.formattedShortTime = v4.Time.UTC().Format(shortTimeFormat) - - if v4.isPresign { - duration := int64(v4.ExpireTime / time.Second) - v4.Query.Set("X-Amz-Date", v4.formattedTime) - v4.Query.Set("X-Amz-Expires", strconv.FormatInt(duration, 10)) - } else { - v4.Request.Header.Set("X-Amz-Date", v4.formattedTime) - } -} - -func (v4 *signer) buildCredentialString() { - v4.credentialString = strings.Join([]string{ - v4.formattedShortTime, - v4.Region, - v4.ServiceName, - "aws4_request", - }, "/") - - if v4.isPresign { - v4.Query.Set("X-Amz-Credential", v4.CredValues.AccessKeyID+"/"+v4.credentialString) - } -} - -func (v4 *signer) buildQuery() { - for k, h := range v4.Request.Header { - if strings.HasPrefix(http.CanonicalHeaderKey(k), "X-Amz-") { - continue // never hoist x-amz-* headers, they must be signed - } - if _, ok := ignoredHeaders[http.CanonicalHeaderKey(k)]; ok { - continue // never hoist ignored headers - } - - v4.Request.Header.Del(k) - v4.Query.Del(k) - for _, v := range h { - v4.Query.Add(k, v) - } - } -} - -func (v4 *signer) buildCanonicalHeaders() { - var headers []string - headers = append(headers, "host") - for k := range v4.Request.Header { - if _, ok := ignoredHeaders[http.CanonicalHeaderKey(k)]; ok { - continue // ignored header - } - headers = append(headers, strings.ToLower(k)) - } - sort.Strings(headers) - - v4.signedHeaders = strings.Join(headers, ";") - - if v4.isPresign { - v4.Query.Set("X-Amz-SignedHeaders", v4.signedHeaders) - } - - headerValues := make([]string, len(headers)) - for i, k := range headers { - if k == "host" { - headerValues[i] = "host:" + v4.Request.URL.Host - } else { - headerValues[i] = k + ":" + - strings.Join(v4.Request.Header[http.CanonicalHeaderKey(k)], ",") - } - } - - v4.canonicalHeaders = strings.Join(headerValues, "\n") -} - -func (v4 *signer) buildCanonicalString() { - v4.Request.URL.RawQuery = strings.Replace(v4.Query.Encode(), "+", "%20", -1) - uri := v4.Request.URL.Opaque - if uri != "" { - uri = "/" + strings.Join(strings.Split(uri, "/")[3:], "/") - } else { - uri = v4.Request.URL.Path - } - if uri == "" { - uri = "/" - } - - if v4.ServiceName != "s3" { - uri = rest.EscapePath(uri, false) - } - - v4.canonicalString = strings.Join([]string{ - v4.Request.Method, - uri, - v4.Request.URL.RawQuery, - v4.canonicalHeaders + "\n", - v4.signedHeaders, - v4.bodyDigest(), - }, "\n") -} - -func (v4 *signer) buildStringToSign() { - v4.stringToSign = strings.Join([]string{ - authHeaderPrefix, - v4.formattedTime, - v4.credentialString, - hex.EncodeToString(makeSha256([]byte(v4.canonicalString))), - }, "\n") -} - -func (v4 *signer) buildSignature() { - secret := v4.CredValues.SecretAccessKey - date := makeHmac([]byte("AWS4"+secret), []byte(v4.formattedShortTime)) - region := makeHmac(date, []byte(v4.Region)) - service := makeHmac(region, []byte(v4.ServiceName)) - credentials := makeHmac(service, []byte("aws4_request")) - signature := makeHmac(credentials, []byte(v4.stringToSign)) - v4.signature = hex.EncodeToString(signature) -} - -func (v4 *signer) bodyDigest() string { - hash := v4.Request.Header.Get("X-Amz-Content-Sha256") - if hash == "" { - if v4.isPresign && v4.ServiceName == "s3" { - hash = "UNSIGNED-PAYLOAD" - } else if v4.Body == nil { - hash = hex.EncodeToString(makeSha256([]byte{})) - } else { - hash = hex.EncodeToString(makeSha256Reader(v4.Body)) - } - v4.Request.Header.Add("X-Amz-Content-Sha256", hash) - } - return hash -} - -// isRequestSigned returns if the request is currently signed or presigned -func (v4 *signer) isRequestSigned() bool { - if v4.isPresign && v4.Query.Get("X-Amz-Signature") != "" { - return true - } - if v4.Request.Header.Get("Authorization") != "" { - return true - } - - return false -} - -// unsign removes signing flags for both signed and presigned requests. -func (v4 *signer) removePresign() { - v4.Query.Del("X-Amz-Algorithm") - v4.Query.Del("X-Amz-Signature") - v4.Query.Del("X-Amz-Security-Token") - v4.Query.Del("X-Amz-Date") - v4.Query.Del("X-Amz-Expires") - v4.Query.Del("X-Amz-Credential") - v4.Query.Del("X-Amz-SignedHeaders") -} - -func makeHmac(key []byte, data []byte) []byte { - hash := hmac.New(sha256.New, key) - hash.Write(data) - return hash.Sum(nil) -} - -func makeSha256(data []byte) []byte { - hash := sha256.New() - hash.Write(data) - return hash.Sum(nil) -} - -func makeSha256Reader(reader io.ReadSeeker) []byte { - hash := sha256.New() - start, _ := reader.Seek(0, 1) - defer reader.Seek(start, 0) - - io.Copy(hash, reader) - return hash.Sum(nil) -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/signer/v4/v4_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/signer/v4/v4_test.go deleted file mode 100644 index f39414fcf91..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/signer/v4/v4_test.go +++ /dev/null @@ -1,252 +0,0 @@ -package v4 - -import ( - "net/http" - "strings" - "testing" - "time" - - "github.com/stretchr/testify/assert" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/credentials" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/awstesting" -) - -func buildSigner(serviceName string, region string, signTime time.Time, expireTime time.Duration, body string) signer { - endpoint := "https://" + serviceName + "." + region + ".amazonaws.com" - reader := strings.NewReader(body) - req, _ := http.NewRequest("POST", endpoint, reader) - req.URL.Opaque = "//example.org/bucket/key-._~,!@#$%^&*()" - req.Header.Add("X-Amz-Target", "prefix.Operation") - req.Header.Add("Content-Type", "application/x-amz-json-1.0") - req.Header.Add("Content-Length", string(len(body))) - req.Header.Add("X-Amz-Meta-Other-Header", "some-value=!@#$%^&* (+)") - - return signer{ - Request: req, - Time: signTime, - ExpireTime: expireTime, - Query: req.URL.Query(), - Body: reader, - ServiceName: serviceName, - Region: region, - Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "SESSION"), - } -} - -func removeWS(text string) string { - text = strings.Replace(text, " ", "", -1) - text = strings.Replace(text, "\n", "", -1) - text = strings.Replace(text, "\t", "", -1) - return text -} - -func assertEqual(t *testing.T, expected, given string) { - if removeWS(expected) != removeWS(given) { - t.Errorf("\nExpected: %s\nGiven: %s", expected, given) - } -} - -func TestPresignRequest(t *testing.T) { - signer := buildSigner("dynamodb", "us-east-1", time.Unix(0, 0), 300*time.Second, "{}") - signer.sign() - - expectedDate := "19700101T000000Z" - expectedHeaders := "host;x-amz-meta-other-header;x-amz-target" - expectedSig := "5eeedebf6f995145ce56daa02902d10485246d3defb34f97b973c1f40ab82d36" - expectedCred := "AKID/19700101/us-east-1/dynamodb/aws4_request" - - q := signer.Request.URL.Query() - assert.Equal(t, expectedSig, q.Get("X-Amz-Signature")) - assert.Equal(t, expectedCred, q.Get("X-Amz-Credential")) - assert.Equal(t, expectedHeaders, q.Get("X-Amz-SignedHeaders")) - assert.Equal(t, expectedDate, q.Get("X-Amz-Date")) -} - -func TestSignRequest(t *testing.T) { - signer := buildSigner("dynamodb", "us-east-1", time.Unix(0, 0), 0, "{}") - signer.sign() - - expectedDate := "19700101T000000Z" - expectedSig := "AWS4-HMAC-SHA256 Credential=AKID/19700101/us-east-1/dynamodb/aws4_request, SignedHeaders=host;x-amz-date;x-amz-meta-other-header;x-amz-security-token;x-amz-target, Signature=69ada33fec48180dab153576e4dd80c4e04124f80dda3eccfed8a67c2b91ed5e" - - q := signer.Request.Header - assert.Equal(t, expectedSig, q.Get("Authorization")) - assert.Equal(t, expectedDate, q.Get("X-Amz-Date")) -} - -func TestSignEmptyBody(t *testing.T) { - signer := buildSigner("dynamodb", "us-east-1", time.Now(), 0, "") - signer.Body = nil - signer.sign() - hash := signer.Request.Header.Get("X-Amz-Content-Sha256") - assert.Equal(t, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", hash) -} - -func TestSignBody(t *testing.T) { - signer := buildSigner("dynamodb", "us-east-1", time.Now(), 0, "hello") - signer.sign() - hash := signer.Request.Header.Get("X-Amz-Content-Sha256") - assert.Equal(t, "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824", hash) -} - -func TestSignSeekedBody(t *testing.T) { - signer := buildSigner("dynamodb", "us-east-1", time.Now(), 0, " hello") - signer.Body.Read(make([]byte, 3)) // consume first 3 bytes so body is now "hello" - signer.sign() - hash := signer.Request.Header.Get("X-Amz-Content-Sha256") - assert.Equal(t, "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824", hash) - - start, _ := signer.Body.Seek(0, 1) - assert.Equal(t, int64(3), start) -} - -func TestPresignEmptyBodyS3(t *testing.T) { - signer := buildSigner("s3", "us-east-1", time.Now(), 5*time.Minute, "hello") - signer.sign() - hash := signer.Request.Header.Get("X-Amz-Content-Sha256") - assert.Equal(t, "UNSIGNED-PAYLOAD", hash) -} - -func TestSignPrecomputedBodyChecksum(t *testing.T) { - signer := buildSigner("dynamodb", "us-east-1", time.Now(), 0, "hello") - signer.Request.Header.Set("X-Amz-Content-Sha256", "PRECOMPUTED") - signer.sign() - hash := signer.Request.Header.Get("X-Amz-Content-Sha256") - assert.Equal(t, "PRECOMPUTED", hash) -} - -func TestAnonymousCredentials(t *testing.T) { - svc := awstesting.NewClient(&aws.Config{Credentials: credentials.AnonymousCredentials}) - r := svc.NewRequest( - &request.Operation{ - Name: "BatchGetItem", - HTTPMethod: "POST", - HTTPPath: "/", - }, - nil, - nil, - ) - Sign(r) - - urlQ := r.HTTPRequest.URL.Query() - assert.Empty(t, urlQ.Get("X-Amz-Signature")) - assert.Empty(t, urlQ.Get("X-Amz-Credential")) - assert.Empty(t, urlQ.Get("X-Amz-SignedHeaders")) - assert.Empty(t, urlQ.Get("X-Amz-Date")) - - hQ := r.HTTPRequest.Header - assert.Empty(t, hQ.Get("Authorization")) - assert.Empty(t, hQ.Get("X-Amz-Date")) -} - -func TestIgnoreResignRequestWithValidCreds(t *testing.T) { - svc := awstesting.NewClient(&aws.Config{ - Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "SESSION"), - Region: aws.String("us-west-2"), - }) - r := svc.NewRequest( - &request.Operation{ - Name: "BatchGetItem", - HTTPMethod: "POST", - HTTPPath: "/", - }, - nil, - nil, - ) - - Sign(r) - sig := r.HTTPRequest.Header.Get("Authorization") - - Sign(r) - assert.Equal(t, sig, r.HTTPRequest.Header.Get("Authorization")) -} - -func TestIgnorePreResignRequestWithValidCreds(t *testing.T) { - svc := awstesting.NewClient(&aws.Config{ - Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "SESSION"), - Region: aws.String("us-west-2"), - }) - r := svc.NewRequest( - &request.Operation{ - Name: "BatchGetItem", - HTTPMethod: "POST", - HTTPPath: "/", - }, - nil, - nil, - ) - r.ExpireTime = time.Minute * 10 - - Sign(r) - sig := r.HTTPRequest.Header.Get("X-Amz-Signature") - - Sign(r) - assert.Equal(t, sig, r.HTTPRequest.Header.Get("X-Amz-Signature")) -} - -func TestResignRequestExpiredCreds(t *testing.T) { - creds := credentials.NewStaticCredentials("AKID", "SECRET", "SESSION") - svc := awstesting.NewClient(&aws.Config{Credentials: creds}) - r := svc.NewRequest( - &request.Operation{ - Name: "BatchGetItem", - HTTPMethod: "POST", - HTTPPath: "/", - }, - nil, - nil, - ) - Sign(r) - querySig := r.HTTPRequest.Header.Get("Authorization") - - creds.Expire() - - Sign(r) - assert.NotEqual(t, querySig, r.HTTPRequest.Header.Get("Authorization")) -} - -func TestPreResignRequestExpiredCreds(t *testing.T) { - provider := &credentials.StaticProvider{Value: credentials.Value{ - AccessKeyID: "AKID", - SecretAccessKey: "SECRET", - SessionToken: "SESSION", - }} - creds := credentials.NewCredentials(provider) - svc := awstesting.NewClient(&aws.Config{Credentials: creds}) - r := svc.NewRequest( - &request.Operation{ - Name: "BatchGetItem", - HTTPMethod: "POST", - HTTPPath: "/", - }, - nil, - nil, - ) - r.ExpireTime = time.Minute * 10 - - Sign(r) - querySig := r.HTTPRequest.URL.Query().Get("X-Amz-Signature") - - creds.Expire() - r.Time = time.Now().Add(time.Hour * 48) - - Sign(r) - assert.NotEqual(t, querySig, r.HTTPRequest.URL.Query().Get("X-Amz-Signature")) -} - -func BenchmarkPresignRequest(b *testing.B) { - signer := buildSigner("dynamodb", "us-east-1", time.Now(), 300*time.Second, "{}") - for i := 0; i < b.N; i++ { - signer.sign() - } -} - -func BenchmarkSignRequest(b *testing.B) { - signer := buildSigner("dynamodb", "us-east-1", time.Now(), 0, "{}") - for i := 0; i < b.N; i++ { - signer.sign() - } -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/waiter/waiter_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/waiter/waiter_test.go deleted file mode 100644 index d545f35370f..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/waiter/waiter_test.go +++ /dev/null @@ -1,391 +0,0 @@ -package waiter_test - -import ( - "bytes" - "io/ioutil" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/aws/client" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/awstesting" - "github.com/aws/aws-sdk-go/private/waiter" -) - -type mockClient struct { - *client.Client -} -type MockInput struct{} -type MockOutput struct { - States []*MockState -} -type MockState struct { - State *string -} - -func (c *mockClient) MockRequest(input *MockInput) (*request.Request, *MockOutput) { - op := &request.Operation{ - Name: "Mock", - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &MockInput{} - } - - output := &MockOutput{} - req := c.NewRequest(op, input, output) - req.Data = output - return req, output -} - -func TestWaiterPathAll(t *testing.T) { - svc := &mockClient{Client: awstesting.NewClient(&aws.Config{ - Region: aws.String("mock-region"), - })} - svc.Handlers.Send.Clear() // mock sending - svc.Handlers.Unmarshal.Clear() - svc.Handlers.UnmarshalMeta.Clear() - svc.Handlers.ValidateResponse.Clear() - - reqNum := 0 - resps := []*MockOutput{ - { // Request 1 - States: []*MockState{ - {State: aws.String("pending")}, - {State: aws.String("pending")}, - }, - }, - { // Request 2 - States: []*MockState{ - {State: aws.String("running")}, - {State: aws.String("pending")}, - }, - }, - { // Request 3 - States: []*MockState{ - {State: aws.String("running")}, - {State: aws.String("running")}, - }, - }, - } - - numBuiltReq := 0 - svc.Handlers.Build.PushBack(func(r *request.Request) { - numBuiltReq++ - }) - svc.Handlers.Unmarshal.PushBack(func(r *request.Request) { - if reqNum >= len(resps) { - assert.Fail(t, "too many polling requests made") - return - } - r.Data = resps[reqNum] - reqNum++ - }) - - waiterCfg := waiter.Config{ - Operation: "Mock", - Delay: 0, - MaxAttempts: 10, - Acceptors: []waiter.WaitAcceptor{ - { - State: "success", - Matcher: "pathAll", - Argument: "States[].State", - Expected: "running", - }, - }, - } - w := waiter.Waiter{ - Client: svc, - Input: &MockInput{}, - Config: waiterCfg, - } - - err := w.Wait() - assert.NoError(t, err) - assert.Equal(t, 3, numBuiltReq) - assert.Equal(t, 3, reqNum) -} - -func TestWaiterPath(t *testing.T) { - svc := &mockClient{Client: awstesting.NewClient(&aws.Config{ - Region: aws.String("mock-region"), - })} - svc.Handlers.Send.Clear() // mock sending - svc.Handlers.Unmarshal.Clear() - svc.Handlers.UnmarshalMeta.Clear() - svc.Handlers.ValidateResponse.Clear() - - reqNum := 0 - resps := []*MockOutput{ - { // Request 1 - States: []*MockState{ - {State: aws.String("pending")}, - {State: aws.String("pending")}, - }, - }, - { // Request 2 - States: []*MockState{ - {State: aws.String("running")}, - {State: aws.String("pending")}, - }, - }, - { // Request 3 - States: []*MockState{ - {State: aws.String("running")}, - {State: aws.String("running")}, - }, - }, - } - - numBuiltReq := 0 - svc.Handlers.Build.PushBack(func(r *request.Request) { - numBuiltReq++ - }) - svc.Handlers.Unmarshal.PushBack(func(r *request.Request) { - if reqNum >= len(resps) { - assert.Fail(t, "too many polling requests made") - return - } - r.Data = resps[reqNum] - reqNum++ - }) - - waiterCfg := waiter.Config{ - Operation: "Mock", - Delay: 0, - MaxAttempts: 10, - Acceptors: []waiter.WaitAcceptor{ - { - State: "success", - Matcher: "path", - Argument: "States[].State", - Expected: "running", - }, - }, - } - w := waiter.Waiter{ - Client: svc, - Input: &MockInput{}, - Config: waiterCfg, - } - - err := w.Wait() - assert.NoError(t, err) - assert.Equal(t, 3, numBuiltReq) - assert.Equal(t, 3, reqNum) -} - -func TestWaiterFailure(t *testing.T) { - svc := &mockClient{Client: awstesting.NewClient(&aws.Config{ - Region: aws.String("mock-region"), - })} - svc.Handlers.Send.Clear() // mock sending - svc.Handlers.Unmarshal.Clear() - svc.Handlers.UnmarshalMeta.Clear() - svc.Handlers.ValidateResponse.Clear() - - reqNum := 0 - resps := []*MockOutput{ - { // Request 1 - States: []*MockState{ - {State: aws.String("pending")}, - {State: aws.String("pending")}, - }, - }, - { // Request 2 - States: []*MockState{ - {State: aws.String("running")}, - {State: aws.String("pending")}, - }, - }, - { // Request 3 - States: []*MockState{ - {State: aws.String("running")}, - {State: aws.String("stopping")}, - }, - }, - } - - numBuiltReq := 0 - svc.Handlers.Build.PushBack(func(r *request.Request) { - numBuiltReq++ - }) - svc.Handlers.Unmarshal.PushBack(func(r *request.Request) { - if reqNum >= len(resps) { - assert.Fail(t, "too many polling requests made") - return - } - r.Data = resps[reqNum] - reqNum++ - }) - - waiterCfg := waiter.Config{ - Operation: "Mock", - Delay: 0, - MaxAttempts: 10, - Acceptors: []waiter.WaitAcceptor{ - { - State: "success", - Matcher: "pathAll", - Argument: "States[].State", - Expected: "running", - }, - { - State: "failure", - Matcher: "pathAny", - Argument: "States[].State", - Expected: "stopping", - }, - }, - } - w := waiter.Waiter{ - Client: svc, - Input: &MockInput{}, - Config: waiterCfg, - } - - err := w.Wait().(awserr.Error) - assert.Error(t, err) - assert.Equal(t, "ResourceNotReady", err.Code()) - assert.Equal(t, "failed waiting for successful resource state", err.Message()) - assert.Equal(t, 3, numBuiltReq) - assert.Equal(t, 3, reqNum) -} - -func TestWaiterError(t *testing.T) { - svc := &mockClient{Client: awstesting.NewClient(&aws.Config{ - Region: aws.String("mock-region"), - })} - svc.Handlers.Send.Clear() // mock sending - svc.Handlers.Unmarshal.Clear() - svc.Handlers.UnmarshalMeta.Clear() - svc.Handlers.ValidateResponse.Clear() - - reqNum := 0 - resps := []*MockOutput{ - { // Request 1 - States: []*MockState{ - {State: aws.String("pending")}, - {State: aws.String("pending")}, - }, - }, - { // Request 2, error case - }, - { // Request 3 - States: []*MockState{ - {State: aws.String("running")}, - {State: aws.String("running")}, - }, - }, - } - - numBuiltReq := 0 - svc.Handlers.Build.PushBack(func(r *request.Request) { - numBuiltReq++ - }) - svc.Handlers.Send.PushBack(func(r *request.Request) { - if reqNum == 1 { - r.Error = awserr.New("MockException", "mock exception message", nil) - r.HTTPResponse = &http.Response{ - StatusCode: 400, - Status: http.StatusText(400), - Body: ioutil.NopCloser(bytes.NewReader([]byte{})), - } - reqNum++ - } - }) - svc.Handlers.Unmarshal.PushBack(func(r *request.Request) { - if reqNum >= len(resps) { - assert.Fail(t, "too many polling requests made") - return - } - r.Data = resps[reqNum] - reqNum++ - }) - - waiterCfg := waiter.Config{ - Operation: "Mock", - Delay: 0, - MaxAttempts: 10, - Acceptors: []waiter.WaitAcceptor{ - { - State: "success", - Matcher: "pathAll", - Argument: "States[].State", - Expected: "running", - }, - { - State: "retry", - Matcher: "error", - Argument: "", - Expected: "MockException", - }, - }, - } - w := waiter.Waiter{ - Client: svc, - Input: &MockInput{}, - Config: waiterCfg, - } - - err := w.Wait() - assert.NoError(t, err) - assert.Equal(t, 3, numBuiltReq) - assert.Equal(t, 3, reqNum) -} - -func TestWaiterStatus(t *testing.T) { - svc := &mockClient{Client: awstesting.NewClient(&aws.Config{ - Region: aws.String("mock-region"), - })} - svc.Handlers.Send.Clear() // mock sending - svc.Handlers.Unmarshal.Clear() - svc.Handlers.UnmarshalMeta.Clear() - svc.Handlers.ValidateResponse.Clear() - - reqNum := 0 - svc.Handlers.Build.PushBack(func(r *request.Request) { - reqNum++ - }) - svc.Handlers.Send.PushBack(func(r *request.Request) { - code := 200 - if reqNum == 3 { - code = 404 - } - r.HTTPResponse = &http.Response{ - StatusCode: code, - Status: http.StatusText(code), - Body: ioutil.NopCloser(bytes.NewReader([]byte{})), - } - }) - - waiterCfg := waiter.Config{ - Operation: "Mock", - Delay: 0, - MaxAttempts: 10, - Acceptors: []waiter.WaitAcceptor{ - { - State: "success", - Matcher: "status", - Argument: "", - Expected: 404, - }, - }, - } - w := waiter.Waiter{ - Client: svc, - Input: &MockInput{}, - Config: waiterCfg, - } - - err := w.Wait() - assert.NoError(t, err) - assert.Equal(t, 3, reqNum) -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/cloudwatch/api.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/cloudwatch/api.go deleted file mode 100644 index 2099e40491d..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/cloudwatch/api.go +++ /dev/null @@ -1,1481 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. - -// Package cloudwatch provides a client for Amazon CloudWatch. -package cloudwatch - -import ( - "time" - - "github.com/aws/aws-sdk-go/aws/awsutil" - "github.com/aws/aws-sdk-go/aws/request" -) - -const opDeleteAlarms = "DeleteAlarms" - -// DeleteAlarmsRequest generates a request for the DeleteAlarms operation. -func (c *CloudWatch) DeleteAlarmsRequest(input *DeleteAlarmsInput) (req *request.Request, output *DeleteAlarmsOutput) { - op := &request.Operation{ - Name: opDeleteAlarms, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteAlarmsInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteAlarmsOutput{} - req.Data = output - return -} - -// Deletes all specified alarms. In the event of an error, no alarms are deleted. -func (c *CloudWatch) DeleteAlarms(input *DeleteAlarmsInput) (*DeleteAlarmsOutput, error) { - req, out := c.DeleteAlarmsRequest(input) - err := req.Send() - return out, err -} - -const opDescribeAlarmHistory = "DescribeAlarmHistory" - -// DescribeAlarmHistoryRequest generates a request for the DescribeAlarmHistory operation. -func (c *CloudWatch) DescribeAlarmHistoryRequest(input *DescribeAlarmHistoryInput) (req *request.Request, output *DescribeAlarmHistoryOutput) { - op := &request.Operation{ - Name: opDescribeAlarmHistory, - HTTPMethod: "POST", - HTTPPath: "/", - Paginator: &request.Paginator{ - InputTokens: []string{"NextToken"}, - OutputTokens: []string{"NextToken"}, - LimitToken: "MaxRecords", - TruncationToken: "", - }, - } - - if input == nil { - input = &DescribeAlarmHistoryInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeAlarmHistoryOutput{} - req.Data = output - return -} - -// Retrieves history for the specified alarm. Filter alarms by date range or -// item type. If an alarm name is not specified, Amazon CloudWatch returns histories -// for all of the owner's alarms. -func (c *CloudWatch) DescribeAlarmHistory(input *DescribeAlarmHistoryInput) (*DescribeAlarmHistoryOutput, error) { - req, out := c.DescribeAlarmHistoryRequest(input) - err := req.Send() - return out, err -} - -func (c *CloudWatch) DescribeAlarmHistoryPages(input *DescribeAlarmHistoryInput, fn func(p *DescribeAlarmHistoryOutput, lastPage bool) (shouldContinue bool)) error { - page, _ := c.DescribeAlarmHistoryRequest(input) - page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) - return page.EachPage(func(p interface{}, lastPage bool) bool { - return fn(p.(*DescribeAlarmHistoryOutput), lastPage) - }) -} - -const opDescribeAlarms = "DescribeAlarms" - -// DescribeAlarmsRequest generates a request for the DescribeAlarms operation. -func (c *CloudWatch) DescribeAlarmsRequest(input *DescribeAlarmsInput) (req *request.Request, output *DescribeAlarmsOutput) { - op := &request.Operation{ - Name: opDescribeAlarms, - HTTPMethod: "POST", - HTTPPath: "/", - Paginator: &request.Paginator{ - InputTokens: []string{"NextToken"}, - OutputTokens: []string{"NextToken"}, - LimitToken: "MaxRecords", - TruncationToken: "", - }, - } - - if input == nil { - input = &DescribeAlarmsInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeAlarmsOutput{} - req.Data = output - return -} - -// Retrieves alarms with the specified names. If no name is specified, all alarms -// for the user are returned. Alarms can be retrieved by using only a prefix -// for the alarm name, the alarm state, or a prefix for any action. -func (c *CloudWatch) DescribeAlarms(input *DescribeAlarmsInput) (*DescribeAlarmsOutput, error) { - req, out := c.DescribeAlarmsRequest(input) - err := req.Send() - return out, err -} - -func (c *CloudWatch) DescribeAlarmsPages(input *DescribeAlarmsInput, fn func(p *DescribeAlarmsOutput, lastPage bool) (shouldContinue bool)) error { - page, _ := c.DescribeAlarmsRequest(input) - page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) - return page.EachPage(func(p interface{}, lastPage bool) bool { - return fn(p.(*DescribeAlarmsOutput), lastPage) - }) -} - -const opDescribeAlarmsForMetric = "DescribeAlarmsForMetric" - -// DescribeAlarmsForMetricRequest generates a request for the DescribeAlarmsForMetric operation. -func (c *CloudWatch) DescribeAlarmsForMetricRequest(input *DescribeAlarmsForMetricInput) (req *request.Request, output *DescribeAlarmsForMetricOutput) { - op := &request.Operation{ - Name: opDescribeAlarmsForMetric, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeAlarmsForMetricInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeAlarmsForMetricOutput{} - req.Data = output - return -} - -// Retrieves all alarms for a single metric. Specify a statistic, period, or -// unit to filter the set of alarms further. -func (c *CloudWatch) DescribeAlarmsForMetric(input *DescribeAlarmsForMetricInput) (*DescribeAlarmsForMetricOutput, error) { - req, out := c.DescribeAlarmsForMetricRequest(input) - err := req.Send() - return out, err -} - -const opDisableAlarmActions = "DisableAlarmActions" - -// DisableAlarmActionsRequest generates a request for the DisableAlarmActions operation. -func (c *CloudWatch) DisableAlarmActionsRequest(input *DisableAlarmActionsInput) (req *request.Request, output *DisableAlarmActionsOutput) { - op := &request.Operation{ - Name: opDisableAlarmActions, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DisableAlarmActionsInput{} - } - - req = c.newRequest(op, input, output) - output = &DisableAlarmActionsOutput{} - req.Data = output - return -} - -// Disables actions for the specified alarms. When an alarm's actions are disabled -// the alarm's state may change, but none of the alarm's actions will execute. -func (c *CloudWatch) DisableAlarmActions(input *DisableAlarmActionsInput) (*DisableAlarmActionsOutput, error) { - req, out := c.DisableAlarmActionsRequest(input) - err := req.Send() - return out, err -} - -const opEnableAlarmActions = "EnableAlarmActions" - -// EnableAlarmActionsRequest generates a request for the EnableAlarmActions operation. -func (c *CloudWatch) EnableAlarmActionsRequest(input *EnableAlarmActionsInput) (req *request.Request, output *EnableAlarmActionsOutput) { - op := &request.Operation{ - Name: opEnableAlarmActions, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &EnableAlarmActionsInput{} - } - - req = c.newRequest(op, input, output) - output = &EnableAlarmActionsOutput{} - req.Data = output - return -} - -// Enables actions for the specified alarms. -func (c *CloudWatch) EnableAlarmActions(input *EnableAlarmActionsInput) (*EnableAlarmActionsOutput, error) { - req, out := c.EnableAlarmActionsRequest(input) - err := req.Send() - return out, err -} - -const opGetMetricStatistics = "GetMetricStatistics" - -// GetMetricStatisticsRequest generates a request for the GetMetricStatistics operation. -func (c *CloudWatch) GetMetricStatisticsRequest(input *GetMetricStatisticsInput) (req *request.Request, output *GetMetricStatisticsOutput) { - op := &request.Operation{ - Name: opGetMetricStatistics, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &GetMetricStatisticsInput{} - } - - req = c.newRequest(op, input, output) - output = &GetMetricStatisticsOutput{} - req.Data = output - return -} - -// Gets statistics for the specified metric. -// -// The maximum number of data points returned from a single GetMetricStatistics -// request is 1,440, wereas the maximum number of data points that can be queried -// is 50,850. If you make a request that generates more than 1,440 data points, -// Amazon CloudWatch returns an error. In such a case, you can alter the request -// by narrowing the specified time range or increasing the specified period. -// Alternatively, you can make multiple requests across adjacent time ranges. -// -// Amazon CloudWatch aggregates data points based on the length of the period -// that you specify. For example, if you request statistics with a one-minute -// granularity, Amazon CloudWatch aggregates data points with time stamps that -// fall within the same one-minute period. In such a case, the data points queried -// can greatly outnumber the data points returned. -// -// The following examples show various statistics allowed by the data point -// query maximum of 50,850 when you call GetMetricStatistics on Amazon EC2 instances -// with detailed (one-minute) monitoring enabled: -// -// Statistics for up to 400 instances for a span of one hour Statistics for -// up to 35 instances over a span of 24 hours Statistics for up to 2 instances -// over a span of 2 weeks For information about the namespace, metric names, -// and dimensions that other Amazon Web Services products use to send metrics -// to Cloudwatch, go to Amazon CloudWatch Metrics, Namespaces, and Dimensions -// Reference (http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/CW_Support_For_AWS.html) -// in the Amazon CloudWatch Developer Guide. -func (c *CloudWatch) GetMetricStatistics(input *GetMetricStatisticsInput) (*GetMetricStatisticsOutput, error) { - req, out := c.GetMetricStatisticsRequest(input) - err := req.Send() - return out, err -} - -const opListMetrics = "ListMetrics" - -// ListMetricsRequest generates a request for the ListMetrics operation. -func (c *CloudWatch) ListMetricsRequest(input *ListMetricsInput) (req *request.Request, output *ListMetricsOutput) { - op := &request.Operation{ - Name: opListMetrics, - HTTPMethod: "POST", - HTTPPath: "/", - Paginator: &request.Paginator{ - InputTokens: []string{"NextToken"}, - OutputTokens: []string{"NextToken"}, - LimitToken: "", - TruncationToken: "", - }, - } - - if input == nil { - input = &ListMetricsInput{} - } - - req = c.newRequest(op, input, output) - output = &ListMetricsOutput{} - req.Data = output - return -} - -// Returns a list of valid metrics stored for the AWS account owner. Returned -// metrics can be used with GetMetricStatistics to obtain statistical data for -// a given metric. -func (c *CloudWatch) ListMetrics(input *ListMetricsInput) (*ListMetricsOutput, error) { - req, out := c.ListMetricsRequest(input) - err := req.Send() - return out, err -} - -func (c *CloudWatch) ListMetricsPages(input *ListMetricsInput, fn func(p *ListMetricsOutput, lastPage bool) (shouldContinue bool)) error { - page, _ := c.ListMetricsRequest(input) - page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) - return page.EachPage(func(p interface{}, lastPage bool) bool { - return fn(p.(*ListMetricsOutput), lastPage) - }) -} - -const opPutMetricAlarm = "PutMetricAlarm" - -// PutMetricAlarmRequest generates a request for the PutMetricAlarm operation. -func (c *CloudWatch) PutMetricAlarmRequest(input *PutMetricAlarmInput) (req *request.Request, output *PutMetricAlarmOutput) { - op := &request.Operation{ - Name: opPutMetricAlarm, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &PutMetricAlarmInput{} - } - - req = c.newRequest(op, input, output) - output = &PutMetricAlarmOutput{} - req.Data = output - return -} - -// Creates or updates an alarm and associates it with the specified Amazon CloudWatch -// metric. Optionally, this operation can associate one or more Amazon Simple -// Notification Service resources with the alarm. -// -// When this operation creates an alarm, the alarm state is immediately set -// to INSUFFICIENT_DATA. The alarm is evaluated and its StateValue is set appropriately. -// Any actions associated with the StateValue is then executed. -func (c *CloudWatch) PutMetricAlarm(input *PutMetricAlarmInput) (*PutMetricAlarmOutput, error) { - req, out := c.PutMetricAlarmRequest(input) - err := req.Send() - return out, err -} - -const opPutMetricData = "PutMetricData" - -// PutMetricDataRequest generates a request for the PutMetricData operation. -func (c *CloudWatch) PutMetricDataRequest(input *PutMetricDataInput) (req *request.Request, output *PutMetricDataOutput) { - op := &request.Operation{ - Name: opPutMetricData, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &PutMetricDataInput{} - } - - req = c.newRequest(op, input, output) - output = &PutMetricDataOutput{} - req.Data = output - return -} - -// Publishes metric data points to Amazon CloudWatch. Amazon Cloudwatch associates -// the data points with the specified metric. If the specified metric does not -// exist, Amazon CloudWatch creates the metric. It can take up to fifteen minutes -// for a new metric to appear in calls to the ListMetrics action. -// -// The size of a PutMetricData request is limited to 8 KB for HTTP GET requests -// and 40 KB for HTTP POST requests. -// -// Although the Value parameter accepts numbers of type Double, Amazon CloudWatch -// truncates values with very large exponents. Values with base-10 exponents -// greater than 126 (1 x 10^126) are truncated. Likewise, values with base-10 -// exponents less than -130 (1 x 10^-130) are also truncated. Data that is -// timestamped 24 hours or more in the past may take in excess of 48 hours to -// become available from submission time using GetMetricStatistics. -func (c *CloudWatch) PutMetricData(input *PutMetricDataInput) (*PutMetricDataOutput, error) { - req, out := c.PutMetricDataRequest(input) - err := req.Send() - return out, err -} - -const opSetAlarmState = "SetAlarmState" - -// SetAlarmStateRequest generates a request for the SetAlarmState operation. -func (c *CloudWatch) SetAlarmStateRequest(input *SetAlarmStateInput) (req *request.Request, output *SetAlarmStateOutput) { - op := &request.Operation{ - Name: opSetAlarmState, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &SetAlarmStateInput{} - } - - req = c.newRequest(op, input, output) - output = &SetAlarmStateOutput{} - req.Data = output - return -} - -// Temporarily sets the state of an alarm. When the updated StateValue differs -// from the previous value, the action configured for the appropriate state -// is invoked. This is not a permanent change. The next periodic alarm check -// (in about a minute) will set the alarm to its actual state. -func (c *CloudWatch) SetAlarmState(input *SetAlarmStateInput) (*SetAlarmStateOutput, error) { - req, out := c.SetAlarmStateRequest(input) - err := req.Send() - return out, err -} - -// The AlarmHistoryItem data type contains descriptive information about the -// history of a specific alarm. If you call DescribeAlarmHistory, Amazon CloudWatch -// returns this data type as part of the DescribeAlarmHistoryResult data type. -type AlarmHistoryItem struct { - // The descriptive name for the alarm. - AlarmName *string `min:"1" type:"string"` - - // Machine-readable data about the alarm in JSON format. - HistoryData *string `min:"1" type:"string"` - - // The type of alarm history item. - HistoryItemType *string `type:"string" enum:"HistoryItemType"` - - // A human-readable summary of the alarm history. - HistorySummary *string `min:"1" type:"string"` - - // The time stamp for the alarm history item. Amazon CloudWatch uses Coordinated - // Universal Time (UTC) when returning time stamps, which do not accommodate - // seasonal adjustments such as daylight savings time. For more information, - // see Time stamps (http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/cloudwatch_concepts.html#about_timestamp) - // in the Amazon CloudWatch Developer Guide. - Timestamp *time.Time `type:"timestamp" timestampFormat:"iso8601"` - - metadataAlarmHistoryItem `json:"-" xml:"-"` -} - -type metadataAlarmHistoryItem struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AlarmHistoryItem) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AlarmHistoryItem) GoString() string { - return s.String() -} - -// The Datapoint data type encapsulates the statistical data that Amazon CloudWatch -// computes from metric data. -type Datapoint struct { - // The average of metric values that correspond to the datapoint. - Average *float64 `type:"double"` - - // The maximum of the metric value used for the datapoint. - Maximum *float64 `type:"double"` - - // The minimum metric value used for the datapoint. - Minimum *float64 `type:"double"` - - // The number of metric values that contributed to the aggregate value of this - // datapoint. - SampleCount *float64 `type:"double"` - - // The sum of metric values used for the datapoint. - Sum *float64 `type:"double"` - - // The time stamp used for the datapoint. Amazon CloudWatch uses Coordinated - // Universal Time (UTC) when returning time stamps, which do not accommodate - // seasonal adjustments such as daylight savings time. For more information, - // see Time stamps (http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/cloudwatch_concepts.html#about_timestamp) - // in the Amazon CloudWatch Developer Guide. - Timestamp *time.Time `type:"timestamp" timestampFormat:"iso8601"` - - // The standard unit used for the datapoint. - Unit *string `type:"string" enum:"StandardUnit"` - - metadataDatapoint `json:"-" xml:"-"` -} - -type metadataDatapoint struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s Datapoint) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s Datapoint) GoString() string { - return s.String() -} - -type DeleteAlarmsInput struct { - // A list of alarms to be deleted. - AlarmNames []*string `type:"list" required:"true"` - - metadataDeleteAlarmsInput `json:"-" xml:"-"` -} - -type metadataDeleteAlarmsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteAlarmsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteAlarmsInput) GoString() string { - return s.String() -} - -type DeleteAlarmsOutput struct { - metadataDeleteAlarmsOutput `json:"-" xml:"-"` -} - -type metadataDeleteAlarmsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteAlarmsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteAlarmsOutput) GoString() string { - return s.String() -} - -type DescribeAlarmHistoryInput struct { - // The name of the alarm. - AlarmName *string `min:"1" type:"string"` - - // The ending date to retrieve alarm history. - EndDate *time.Time `type:"timestamp" timestampFormat:"iso8601"` - - // The type of alarm histories to retrieve. - HistoryItemType *string `type:"string" enum:"HistoryItemType"` - - // The maximum number of alarm history records to retrieve. - MaxRecords *int64 `min:"1" type:"integer"` - - // The token returned by a previous call to indicate that there is more data - // available. - NextToken *string `type:"string"` - - // The starting date to retrieve alarm history. - StartDate *time.Time `type:"timestamp" timestampFormat:"iso8601"` - - metadataDescribeAlarmHistoryInput `json:"-" xml:"-"` -} - -type metadataDescribeAlarmHistoryInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeAlarmHistoryInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeAlarmHistoryInput) GoString() string { - return s.String() -} - -// The output for the DescribeAlarmHistory action. -type DescribeAlarmHistoryOutput struct { - // A list of alarm histories in JSON format. - AlarmHistoryItems []*AlarmHistoryItem `type:"list"` - - // A string that marks the start of the next batch of returned results. - NextToken *string `type:"string"` - - metadataDescribeAlarmHistoryOutput `json:"-" xml:"-"` -} - -type metadataDescribeAlarmHistoryOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeAlarmHistoryOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeAlarmHistoryOutput) GoString() string { - return s.String() -} - -type DescribeAlarmsForMetricInput struct { - // The list of dimensions associated with the metric. - Dimensions []*Dimension `type:"list"` - - // The name of the metric. - MetricName *string `min:"1" type:"string" required:"true"` - - // The namespace of the metric. - Namespace *string `min:"1" type:"string" required:"true"` - - // The period in seconds over which the statistic is applied. - Period *int64 `min:"60" type:"integer"` - - // The statistic for the metric. - Statistic *string `type:"string" enum:"Statistic"` - - // The unit for the metric. - Unit *string `type:"string" enum:"StandardUnit"` - - metadataDescribeAlarmsForMetricInput `json:"-" xml:"-"` -} - -type metadataDescribeAlarmsForMetricInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeAlarmsForMetricInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeAlarmsForMetricInput) GoString() string { - return s.String() -} - -// The output for the DescribeAlarmsForMetric action. -type DescribeAlarmsForMetricOutput struct { - // A list of information for each alarm with the specified metric. - MetricAlarms []*MetricAlarm `type:"list"` - - metadataDescribeAlarmsForMetricOutput `json:"-" xml:"-"` -} - -type metadataDescribeAlarmsForMetricOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeAlarmsForMetricOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeAlarmsForMetricOutput) GoString() string { - return s.String() -} - -type DescribeAlarmsInput struct { - // The action name prefix. - ActionPrefix *string `min:"1" type:"string"` - - // The alarm name prefix. AlarmNames cannot be specified if this parameter is - // specified. - AlarmNamePrefix *string `min:"1" type:"string"` - - // A list of alarm names to retrieve information for. - AlarmNames []*string `type:"list"` - - // The maximum number of alarm descriptions to retrieve. - MaxRecords *int64 `min:"1" type:"integer"` - - // The token returned by a previous call to indicate that there is more data - // available. - NextToken *string `type:"string"` - - // The state value to be used in matching alarms. - StateValue *string `type:"string" enum:"StateValue"` - - metadataDescribeAlarmsInput `json:"-" xml:"-"` -} - -type metadataDescribeAlarmsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeAlarmsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeAlarmsInput) GoString() string { - return s.String() -} - -// The output for the DescribeAlarms action. -type DescribeAlarmsOutput struct { - // A list of information for the specified alarms. - MetricAlarms []*MetricAlarm `type:"list"` - - // A string that marks the start of the next batch of returned results. - NextToken *string `type:"string"` - - metadataDescribeAlarmsOutput `json:"-" xml:"-"` -} - -type metadataDescribeAlarmsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeAlarmsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeAlarmsOutput) GoString() string { - return s.String() -} - -// The Dimension data type further expands on the identity of a metric using -// a Name, Value pair. -// -// For examples that use one or more dimensions, see PutMetricData. -type Dimension struct { - // The name of the dimension. - Name *string `min:"1" type:"string" required:"true"` - - // The value representing the dimension measurement - Value *string `min:"1" type:"string" required:"true"` - - metadataDimension `json:"-" xml:"-"` -} - -type metadataDimension struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s Dimension) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s Dimension) GoString() string { - return s.String() -} - -// The DimensionFilter data type is used to filter ListMetrics results. -type DimensionFilter struct { - // The dimension name to be matched. - Name *string `min:"1" type:"string" required:"true"` - - // The value of the dimension to be matched. - Value *string `min:"1" type:"string"` - - metadataDimensionFilter `json:"-" xml:"-"` -} - -type metadataDimensionFilter struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DimensionFilter) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DimensionFilter) GoString() string { - return s.String() -} - -type DisableAlarmActionsInput struct { - // The names of the alarms to disable actions for. - AlarmNames []*string `type:"list" required:"true"` - - metadataDisableAlarmActionsInput `json:"-" xml:"-"` -} - -type metadataDisableAlarmActionsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DisableAlarmActionsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DisableAlarmActionsInput) GoString() string { - return s.String() -} - -type DisableAlarmActionsOutput struct { - metadataDisableAlarmActionsOutput `json:"-" xml:"-"` -} - -type metadataDisableAlarmActionsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DisableAlarmActionsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DisableAlarmActionsOutput) GoString() string { - return s.String() -} - -type EnableAlarmActionsInput struct { - // The names of the alarms to enable actions for. - AlarmNames []*string `type:"list" required:"true"` - - metadataEnableAlarmActionsInput `json:"-" xml:"-"` -} - -type metadataEnableAlarmActionsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s EnableAlarmActionsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s EnableAlarmActionsInput) GoString() string { - return s.String() -} - -type EnableAlarmActionsOutput struct { - metadataEnableAlarmActionsOutput `json:"-" xml:"-"` -} - -type metadataEnableAlarmActionsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s EnableAlarmActionsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s EnableAlarmActionsOutput) GoString() string { - return s.String() -} - -type GetMetricStatisticsInput struct { - // A list of dimensions describing qualities of the metric. - Dimensions []*Dimension `type:"list"` - - // The time stamp to use for determining the last datapoint to return. The value - // specified is exclusive; results will include datapoints up to the time stamp - // specified. - EndTime *time.Time `type:"timestamp" timestampFormat:"iso8601" required:"true"` - - // The name of the metric, with or without spaces. - MetricName *string `min:"1" type:"string" required:"true"` - - // The namespace of the metric, with or without spaces. - Namespace *string `min:"1" type:"string" required:"true"` - - // The granularity, in seconds, of the returned datapoints. Period must be at - // least 60 seconds and must be a multiple of 60. The default value is 60. - Period *int64 `min:"60" type:"integer" required:"true"` - - // The time stamp to use for determining the first datapoint to return. The - // value specified is inclusive; results include datapoints with the time stamp - // specified. - StartTime *time.Time `type:"timestamp" timestampFormat:"iso8601" required:"true"` - - // The metric statistics to return. For information about specific statistics - // returned by GetMetricStatistics, go to Statistics (http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/index.html?CHAP_TerminologyandKeyConcepts.html#Statistic) - // in the Amazon CloudWatch Developer Guide. - // - // Valid Values: Average | Sum | SampleCount | Maximum | Minimum - Statistics []*string `min:"1" type:"list" required:"true"` - - // The unit for the metric. - Unit *string `type:"string" enum:"StandardUnit"` - - metadataGetMetricStatisticsInput `json:"-" xml:"-"` -} - -type metadataGetMetricStatisticsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s GetMetricStatisticsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s GetMetricStatisticsInput) GoString() string { - return s.String() -} - -// The output for the GetMetricStatistics action. -type GetMetricStatisticsOutput struct { - // The datapoints for the specified metric. - Datapoints []*Datapoint `type:"list"` - - // A label describing the specified metric. - Label *string `type:"string"` - - metadataGetMetricStatisticsOutput `json:"-" xml:"-"` -} - -type metadataGetMetricStatisticsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s GetMetricStatisticsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s GetMetricStatisticsOutput) GoString() string { - return s.String() -} - -type ListMetricsInput struct { - // A list of dimensions to filter against. - Dimensions []*DimensionFilter `type:"list"` - - // The name of the metric to filter against. - MetricName *string `min:"1" type:"string"` - - // The namespace to filter against. - Namespace *string `min:"1" type:"string"` - - // The token returned by a previous call to indicate that there is more data - // available. - NextToken *string `type:"string"` - - metadataListMetricsInput `json:"-" xml:"-"` -} - -type metadataListMetricsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ListMetricsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ListMetricsInput) GoString() string { - return s.String() -} - -// The output for the ListMetrics action. -type ListMetricsOutput struct { - // A list of metrics used to generate statistics for an AWS account. - Metrics []*Metric `type:"list"` - - // A string that marks the start of the next batch of returned results. - NextToken *string `type:"string"` - - metadataListMetricsOutput `json:"-" xml:"-"` -} - -type metadataListMetricsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ListMetricsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ListMetricsOutput) GoString() string { - return s.String() -} - -// The Metric data type contains information about a specific metric. If you -// call ListMetrics, Amazon CloudWatch returns information contained by this -// data type. -// -// The example in the Examples section publishes two metrics named buffers -// and latency. Both metrics are in the examples namespace. Both metrics have -// two dimensions, InstanceID and InstanceType. -type Metric struct { - // A list of dimensions associated with the metric. - Dimensions []*Dimension `type:"list"` - - // The name of the metric. - MetricName *string `min:"1" type:"string"` - - // The namespace of the metric. - Namespace *string `min:"1" type:"string"` - - metadataMetric `json:"-" xml:"-"` -} - -type metadataMetric struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s Metric) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s Metric) GoString() string { - return s.String() -} - -// The MetricAlarm data type represents an alarm. You can use PutMetricAlarm -// to create or update an alarm. -type MetricAlarm struct { - // Indicates whether actions should be executed during any changes to the alarm's - // state. - ActionsEnabled *bool `type:"boolean"` - - // The list of actions to execute when this alarm transitions into an ALARM - // state from any other state. Each action is specified as an Amazon Resource - // Number (ARN). Currently the only actions supported are publishing to an Amazon - // SNS topic and triggering an Auto Scaling policy. - AlarmActions []*string `type:"list"` - - // The Amazon Resource Name (ARN) of the alarm. - AlarmArn *string `min:"1" type:"string"` - - // The time stamp of the last update to the alarm configuration. Amazon CloudWatch - // uses Coordinated Universal Time (UTC) when returning time stamps, which do - // not accommodate seasonal adjustments such as daylight savings time. For more - // information, see Time stamps (http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/cloudwatch_concepts.html#about_timestamp) - // in the Amazon CloudWatch Developer Guide. - AlarmConfigurationUpdatedTimestamp *time.Time `type:"timestamp" timestampFormat:"iso8601"` - - // The description for the alarm. - AlarmDescription *string `type:"string"` - - // The name of the alarm. - AlarmName *string `min:"1" type:"string"` - - // The arithmetic operation to use when comparing the specified Statistic and - // Threshold. The specified Statistic value is used as the first operand. - ComparisonOperator *string `type:"string" enum:"ComparisonOperator"` - - // The list of dimensions associated with the alarm's associated metric. - Dimensions []*Dimension `type:"list"` - - // The number of periods over which data is compared to the specified threshold. - EvaluationPeriods *int64 `min:"1" type:"integer"` - - // The list of actions to execute when this alarm transitions into an INSUFFICIENT_DATA - // state from any other state. Each action is specified as an Amazon Resource - // Number (ARN). Currently the only actions supported are publishing to an Amazon - // SNS topic or triggering an Auto Scaling policy. - // - // The current WSDL lists this attribute as UnknownActions. - InsufficientDataActions []*string `type:"list"` - - // The name of the alarm's metric. - MetricName *string `min:"1" type:"string"` - - // The namespace of alarm's associated metric. - Namespace *string `min:"1" type:"string"` - - // The list of actions to execute when this alarm transitions into an OK state - // from any other state. Each action is specified as an Amazon Resource Number - // (ARN). Currently the only actions supported are publishing to an Amazon SNS - // topic and triggering an Auto Scaling policy. - OKActions []*string `type:"list"` - - // The period in seconds over which the statistic is applied. - Period *int64 `min:"60" type:"integer"` - - // A human-readable explanation for the alarm's state. - StateReason *string `type:"string"` - - // An explanation for the alarm's state in machine-readable JSON format - StateReasonData *string `type:"string"` - - // The time stamp of the last update to the alarm's state. Amazon CloudWatch - // uses Coordinated Universal Time (UTC) when returning time stamps, which do - // not accommodate seasonal adjustments such as daylight savings time. For more - // information, see Time stamps (http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/cloudwatch_concepts.html#about_timestamp) - // in the Amazon CloudWatch Developer Guide. - StateUpdatedTimestamp *time.Time `type:"timestamp" timestampFormat:"iso8601"` - - // The state value for the alarm. - StateValue *string `type:"string" enum:"StateValue"` - - // The statistic to apply to the alarm's associated metric. - Statistic *string `type:"string" enum:"Statistic"` - - // The value against which the specified statistic is compared. - Threshold *float64 `type:"double"` - - // The unit of the alarm's associated metric. - Unit *string `type:"string" enum:"StandardUnit"` - - metadataMetricAlarm `json:"-" xml:"-"` -} - -type metadataMetricAlarm struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s MetricAlarm) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s MetricAlarm) GoString() string { - return s.String() -} - -// The MetricDatum data type encapsulates the information sent with PutMetricData -// to either create a new metric or add new values to be aggregated into an -// existing metric. -type MetricDatum struct { - // A list of dimensions associated with the metric. Note, when using the Dimensions - // value in a query, you need to append .member.N to it (e.g., Dimensions.member.N). - Dimensions []*Dimension `type:"list"` - - // The name of the metric. - MetricName *string `min:"1" type:"string" required:"true"` - - // A set of statistical values describing the metric. - StatisticValues *StatisticSet `type:"structure"` - - // The time stamp used for the metric. If not specified, the default value is - // set to the time the metric data was received. Amazon CloudWatch uses Coordinated - // Universal Time (UTC) when returning time stamps, which do not accommodate - // seasonal adjustments such as daylight savings time. For more information, - // see Time stamps (http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/cloudwatch_concepts.html#about_timestamp) - // in the Amazon CloudWatch Developer Guide. - Timestamp *time.Time `type:"timestamp" timestampFormat:"iso8601"` - - // The unit of the metric. - Unit *string `type:"string" enum:"StandardUnit"` - - // The value for the metric. - // - // Although the Value parameter accepts numbers of type Double, Amazon CloudWatch - // truncates values with very large exponents. Values with base-10 exponents - // greater than 126 (1 x 10^126) are truncated. Likewise, values with base-10 - // exponents less than -130 (1 x 10^-130) are also truncated. - Value *float64 `type:"double"` - - metadataMetricDatum `json:"-" xml:"-"` -} - -type metadataMetricDatum struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s MetricDatum) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s MetricDatum) GoString() string { - return s.String() -} - -type PutMetricAlarmInput struct { - // Indicates whether or not actions should be executed during any changes to - // the alarm's state. - ActionsEnabled *bool `type:"boolean"` - - // The list of actions to execute when this alarm transitions into an ALARM - // state from any other state. Each action is specified as an Amazon Resource - // Number (ARN). Currently the only action supported is publishing to an Amazon - // SNS topic or an Amazon Auto Scaling policy. - AlarmActions []*string `type:"list"` - - // The description for the alarm. - AlarmDescription *string `type:"string"` - - // The descriptive name for the alarm. This name must be unique within the user's - // AWS account - AlarmName *string `min:"1" type:"string" required:"true"` - - // The arithmetic operation to use when comparing the specified Statistic and - // Threshold. The specified Statistic value is used as the first operand. - ComparisonOperator *string `type:"string" required:"true" enum:"ComparisonOperator"` - - // The dimensions for the alarm's associated metric. - Dimensions []*Dimension `type:"list"` - - // The number of periods over which data is compared to the specified threshold. - EvaluationPeriods *int64 `min:"1" type:"integer" required:"true"` - - // The list of actions to execute when this alarm transitions into an INSUFFICIENT_DATA - // state from any other state. Each action is specified as an Amazon Resource - // Number (ARN). Currently the only action supported is publishing to an Amazon - // SNS topic or an Amazon Auto Scaling policy. - InsufficientDataActions []*string `type:"list"` - - // The name for the alarm's associated metric. - MetricName *string `min:"1" type:"string" required:"true"` - - // The namespace for the alarm's associated metric. - Namespace *string `min:"1" type:"string" required:"true"` - - // The list of actions to execute when this alarm transitions into an OK state - // from any other state. Each action is specified as an Amazon Resource Number - // (ARN). Currently the only action supported is publishing to an Amazon SNS - // topic or an Amazon Auto Scaling policy. - OKActions []*string `type:"list"` - - // The period in seconds over which the specified statistic is applied. - Period *int64 `min:"60" type:"integer" required:"true"` - - // The statistic to apply to the alarm's associated metric. - Statistic *string `type:"string" required:"true" enum:"Statistic"` - - // The value against which the specified statistic is compared. - Threshold *float64 `type:"double" required:"true"` - - // The unit for the alarm's associated metric. - Unit *string `type:"string" enum:"StandardUnit"` - - metadataPutMetricAlarmInput `json:"-" xml:"-"` -} - -type metadataPutMetricAlarmInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s PutMetricAlarmInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s PutMetricAlarmInput) GoString() string { - return s.String() -} - -type PutMetricAlarmOutput struct { - metadataPutMetricAlarmOutput `json:"-" xml:"-"` -} - -type metadataPutMetricAlarmOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s PutMetricAlarmOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s PutMetricAlarmOutput) GoString() string { - return s.String() -} - -type PutMetricDataInput struct { - // A list of data describing the metric. - MetricData []*MetricDatum `type:"list" required:"true"` - - // The namespace for the metric data. - Namespace *string `min:"1" type:"string" required:"true"` - - metadataPutMetricDataInput `json:"-" xml:"-"` -} - -type metadataPutMetricDataInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s PutMetricDataInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s PutMetricDataInput) GoString() string { - return s.String() -} - -type PutMetricDataOutput struct { - metadataPutMetricDataOutput `json:"-" xml:"-"` -} - -type metadataPutMetricDataOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s PutMetricDataOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s PutMetricDataOutput) GoString() string { - return s.String() -} - -type SetAlarmStateInput struct { - // The descriptive name for the alarm. This name must be unique within the user's - // AWS account. The maximum length is 255 characters. - AlarmName *string `min:"1" type:"string" required:"true"` - - // The reason that this alarm is set to this specific state (in human-readable - // text format) - StateReason *string `type:"string" required:"true"` - - // The reason that this alarm is set to this specific state (in machine-readable - // JSON format) - StateReasonData *string `type:"string"` - - // The value of the state. - StateValue *string `type:"string" required:"true" enum:"StateValue"` - - metadataSetAlarmStateInput `json:"-" xml:"-"` -} - -type metadataSetAlarmStateInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s SetAlarmStateInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s SetAlarmStateInput) GoString() string { - return s.String() -} - -type SetAlarmStateOutput struct { - metadataSetAlarmStateOutput `json:"-" xml:"-"` -} - -type metadataSetAlarmStateOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s SetAlarmStateOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s SetAlarmStateOutput) GoString() string { - return s.String() -} - -// The StatisticSet data type describes the StatisticValues component of MetricDatum, -// and represents a set of statistics that describes a specific metric. -type StatisticSet struct { - // The maximum value of the sample set. - Maximum *float64 `type:"double" required:"true"` - - // The minimum value of the sample set. - Minimum *float64 `type:"double" required:"true"` - - // The number of samples used for the statistic set. - SampleCount *float64 `type:"double" required:"true"` - - // The sum of values for the sample set. - Sum *float64 `type:"double" required:"true"` - - metadataStatisticSet `json:"-" xml:"-"` -} - -type metadataStatisticSet struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s StatisticSet) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s StatisticSet) GoString() string { - return s.String() -} - -const ( - // @enum ComparisonOperator - ComparisonOperatorGreaterThanOrEqualToThreshold = "GreaterThanOrEqualToThreshold" - // @enum ComparisonOperator - ComparisonOperatorGreaterThanThreshold = "GreaterThanThreshold" - // @enum ComparisonOperator - ComparisonOperatorLessThanThreshold = "LessThanThreshold" - // @enum ComparisonOperator - ComparisonOperatorLessThanOrEqualToThreshold = "LessThanOrEqualToThreshold" -) - -const ( - // @enum HistoryItemType - HistoryItemTypeConfigurationUpdate = "ConfigurationUpdate" - // @enum HistoryItemType - HistoryItemTypeStateUpdate = "StateUpdate" - // @enum HistoryItemType - HistoryItemTypeAction = "Action" -) - -const ( - // @enum StandardUnit - StandardUnitSeconds = "Seconds" - // @enum StandardUnit - StandardUnitMicroseconds = "Microseconds" - // @enum StandardUnit - StandardUnitMilliseconds = "Milliseconds" - // @enum StandardUnit - StandardUnitBytes = "Bytes" - // @enum StandardUnit - StandardUnitKilobytes = "Kilobytes" - // @enum StandardUnit - StandardUnitMegabytes = "Megabytes" - // @enum StandardUnit - StandardUnitGigabytes = "Gigabytes" - // @enum StandardUnit - StandardUnitTerabytes = "Terabytes" - // @enum StandardUnit - StandardUnitBits = "Bits" - // @enum StandardUnit - StandardUnitKilobits = "Kilobits" - // @enum StandardUnit - StandardUnitMegabits = "Megabits" - // @enum StandardUnit - StandardUnitGigabits = "Gigabits" - // @enum StandardUnit - StandardUnitTerabits = "Terabits" - // @enum StandardUnit - StandardUnitPercent = "Percent" - // @enum StandardUnit - StandardUnitCount = "Count" - // @enum StandardUnit - StandardUnitBytesSecond = "Bytes/Second" - // @enum StandardUnit - StandardUnitKilobytesSecond = "Kilobytes/Second" - // @enum StandardUnit - StandardUnitMegabytesSecond = "Megabytes/Second" - // @enum StandardUnit - StandardUnitGigabytesSecond = "Gigabytes/Second" - // @enum StandardUnit - StandardUnitTerabytesSecond = "Terabytes/Second" - // @enum StandardUnit - StandardUnitBitsSecond = "Bits/Second" - // @enum StandardUnit - StandardUnitKilobitsSecond = "Kilobits/Second" - // @enum StandardUnit - StandardUnitMegabitsSecond = "Megabits/Second" - // @enum StandardUnit - StandardUnitGigabitsSecond = "Gigabits/Second" - // @enum StandardUnit - StandardUnitTerabitsSecond = "Terabits/Second" - // @enum StandardUnit - StandardUnitCountSecond = "Count/Second" - // @enum StandardUnit - StandardUnitNone = "None" -) - -const ( - // @enum StateValue - StateValueOk = "OK" - // @enum StateValue - StateValueAlarm = "ALARM" - // @enum StateValue - StateValueInsufficientData = "INSUFFICIENT_DATA" -) - -const ( - // @enum Statistic - StatisticSampleCount = "SampleCount" - // @enum Statistic - StatisticAverage = "Average" - // @enum Statistic - StatisticSum = "Sum" - // @enum Statistic - StatisticMinimum = "Minimum" - // @enum Statistic - StatisticMaximum = "Maximum" -) diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/cloudwatch/examples_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/cloudwatch/examples_test.go deleted file mode 100644 index 07b010852b9..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/cloudwatch/examples_test.go +++ /dev/null @@ -1,337 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. - -package cloudwatch_test - -import ( - "bytes" - "fmt" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/cloudwatch" -) - -var _ time.Duration -var _ bytes.Buffer - -func ExampleCloudWatch_DeleteAlarms() { - svc := cloudwatch.New(session.New()) - - params := &cloudwatch.DeleteAlarmsInput{ - AlarmNames: []*string{ // Required - aws.String("AlarmName"), // Required - // More values... - }, - } - resp, err := svc.DeleteAlarms(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleCloudWatch_DescribeAlarmHistory() { - svc := cloudwatch.New(session.New()) - - params := &cloudwatch.DescribeAlarmHistoryInput{ - AlarmName: aws.String("AlarmName"), - EndDate: aws.Time(time.Now()), - HistoryItemType: aws.String("HistoryItemType"), - MaxRecords: aws.Int64(1), - NextToken: aws.String("NextToken"), - StartDate: aws.Time(time.Now()), - } - resp, err := svc.DescribeAlarmHistory(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleCloudWatch_DescribeAlarms() { - svc := cloudwatch.New(session.New()) - - params := &cloudwatch.DescribeAlarmsInput{ - ActionPrefix: aws.String("ActionPrefix"), - AlarmNamePrefix: aws.String("AlarmNamePrefix"), - AlarmNames: []*string{ - aws.String("AlarmName"), // Required - // More values... - }, - MaxRecords: aws.Int64(1), - NextToken: aws.String("NextToken"), - StateValue: aws.String("StateValue"), - } - resp, err := svc.DescribeAlarms(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleCloudWatch_DescribeAlarmsForMetric() { - svc := cloudwatch.New(session.New()) - - params := &cloudwatch.DescribeAlarmsForMetricInput{ - MetricName: aws.String("MetricName"), // Required - Namespace: aws.String("Namespace"), // Required - Dimensions: []*cloudwatch.Dimension{ - { // Required - Name: aws.String("DimensionName"), // Required - Value: aws.String("DimensionValue"), // Required - }, - // More values... - }, - Period: aws.Int64(1), - Statistic: aws.String("Statistic"), - Unit: aws.String("StandardUnit"), - } - resp, err := svc.DescribeAlarmsForMetric(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleCloudWatch_DisableAlarmActions() { - svc := cloudwatch.New(session.New()) - - params := &cloudwatch.DisableAlarmActionsInput{ - AlarmNames: []*string{ // Required - aws.String("AlarmName"), // Required - // More values... - }, - } - resp, err := svc.DisableAlarmActions(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleCloudWatch_EnableAlarmActions() { - svc := cloudwatch.New(session.New()) - - params := &cloudwatch.EnableAlarmActionsInput{ - AlarmNames: []*string{ // Required - aws.String("AlarmName"), // Required - // More values... - }, - } - resp, err := svc.EnableAlarmActions(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleCloudWatch_GetMetricStatistics() { - svc := cloudwatch.New(session.New()) - - params := &cloudwatch.GetMetricStatisticsInput{ - EndTime: aws.Time(time.Now()), // Required - MetricName: aws.String("MetricName"), // Required - Namespace: aws.String("Namespace"), // Required - Period: aws.Int64(1), // Required - StartTime: aws.Time(time.Now()), // Required - Statistics: []*string{ // Required - aws.String("Statistic"), // Required - // More values... - }, - Dimensions: []*cloudwatch.Dimension{ - { // Required - Name: aws.String("DimensionName"), // Required - Value: aws.String("DimensionValue"), // Required - }, - // More values... - }, - Unit: aws.String("StandardUnit"), - } - resp, err := svc.GetMetricStatistics(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleCloudWatch_ListMetrics() { - svc := cloudwatch.New(session.New()) - - params := &cloudwatch.ListMetricsInput{ - Dimensions: []*cloudwatch.DimensionFilter{ - { // Required - Name: aws.String("DimensionName"), // Required - Value: aws.String("DimensionValue"), - }, - // More values... - }, - MetricName: aws.String("MetricName"), - Namespace: aws.String("Namespace"), - NextToken: aws.String("NextToken"), - } - resp, err := svc.ListMetrics(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleCloudWatch_PutMetricAlarm() { - svc := cloudwatch.New(session.New()) - - params := &cloudwatch.PutMetricAlarmInput{ - AlarmName: aws.String("AlarmName"), // Required - ComparisonOperator: aws.String("ComparisonOperator"), // Required - EvaluationPeriods: aws.Int64(1), // Required - MetricName: aws.String("MetricName"), // Required - Namespace: aws.String("Namespace"), // Required - Period: aws.Int64(1), // Required - Statistic: aws.String("Statistic"), // Required - Threshold: aws.Float64(1.0), // Required - ActionsEnabled: aws.Bool(true), - AlarmActions: []*string{ - aws.String("ResourceName"), // Required - // More values... - }, - AlarmDescription: aws.String("AlarmDescription"), - Dimensions: []*cloudwatch.Dimension{ - { // Required - Name: aws.String("DimensionName"), // Required - Value: aws.String("DimensionValue"), // Required - }, - // More values... - }, - InsufficientDataActions: []*string{ - aws.String("ResourceName"), // Required - // More values... - }, - OKActions: []*string{ - aws.String("ResourceName"), // Required - // More values... - }, - Unit: aws.String("StandardUnit"), - } - resp, err := svc.PutMetricAlarm(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleCloudWatch_PutMetricData() { - svc := cloudwatch.New(session.New()) - - params := &cloudwatch.PutMetricDataInput{ - MetricData: []*cloudwatch.MetricDatum{ // Required - { // Required - MetricName: aws.String("MetricName"), // Required - Dimensions: []*cloudwatch.Dimension{ - { // Required - Name: aws.String("DimensionName"), // Required - Value: aws.String("DimensionValue"), // Required - }, - // More values... - }, - StatisticValues: &cloudwatch.StatisticSet{ - Maximum: aws.Float64(1.0), // Required - Minimum: aws.Float64(1.0), // Required - SampleCount: aws.Float64(1.0), // Required - Sum: aws.Float64(1.0), // Required - }, - Timestamp: aws.Time(time.Now()), - Unit: aws.String("StandardUnit"), - Value: aws.Float64(1.0), - }, - // More values... - }, - Namespace: aws.String("Namespace"), // Required - } - resp, err := svc.PutMetricData(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleCloudWatch_SetAlarmState() { - svc := cloudwatch.New(session.New()) - - params := &cloudwatch.SetAlarmStateInput{ - AlarmName: aws.String("AlarmName"), // Required - StateReason: aws.String("StateReason"), // Required - StateValue: aws.String("StateValue"), // Required - StateReasonData: aws.String("StateReasonData"), - } - resp, err := svc.SetAlarmState(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/cloudwatch/service.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/cloudwatch/service.go deleted file mode 100644 index e6f85068460..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/cloudwatch/service.go +++ /dev/null @@ -1,125 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. - -package cloudwatch - -import ( - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/client" - "github.com/aws/aws-sdk-go/aws/client/metadata" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/private/protocol/query" - "github.com/aws/aws-sdk-go/private/signer/v4" -) - -// This is the Amazon CloudWatch API Reference. This guide provides detailed -// information about Amazon CloudWatch actions, data types, parameters, and -// errors. For detailed information about Amazon CloudWatch features and their -// associated API calls, go to the Amazon CloudWatch Developer Guide (http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide). -// -// Amazon CloudWatch is a web service that enables you to publish, monitor, -// and manage various metrics, as well as configure alarm actions based on data -// from metrics. For more information about this product go to http://aws.amazon.com/cloudwatch -// (http://aws.amazon.com/cloudwatch). -// -// For information about the namespace, metric names, and dimensions that -// other Amazon Web Services products use to send metrics to Cloudwatch, go -// to Amazon CloudWatch Metrics, Namespaces, and Dimensions Reference (http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/CW_Support_For_AWS.html) -// in the Amazon CloudWatch Developer Guide. -// -// Use the following links to get started using the Amazon CloudWatch API Reference: -// -// Actions (http://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_Operations.html): -// An alphabetical list of all Amazon CloudWatch actions. Data Types (http://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_Types.html): -// An alphabetical list of all Amazon CloudWatch data types. Common Parameters -// (http://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/CommonParameters.html): -// Parameters that all Query actions can use. Common Errors (http://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/CommonErrors.html): -// Client and server errors that all actions can return. Regions and Endpoints -// (http://docs.aws.amazon.com/general/latest/gr/index.html?rande.html): Itemized -// regions and endpoints for all AWS products. WSDL Location (http://monitoring.amazonaws.com/doc/2010-08-01/CloudWatch.wsdl): -// http://monitoring.amazonaws.com/doc/2010-08-01/CloudWatch.wsdl In addition -// to using the Amazon CloudWatch API, you can also use the following SDKs and -// third-party libraries to access Amazon CloudWatch programmatically. -// -// AWS SDK for Java Documentation (http://aws.amazon.com/documentation/sdkforjava/) -// AWS SDK for .NET Documentation (http://aws.amazon.com/documentation/sdkfornet/) -// AWS SDK for PHP Documentation (http://aws.amazon.com/documentation/sdkforphp/) -// AWS SDK for Ruby Documentation (http://aws.amazon.com/documentation/sdkforruby/) -// Developers in the AWS developer community also provide their own libraries, -// which you can find at the following AWS developer centers: -// -// AWS Java Developer Center (http://aws.amazon.com/java/) AWS PHP Developer -// Center (http://aws.amazon.com/php/) AWS Python Developer Center (http://aws.amazon.com/python/) -// AWS Ruby Developer Center (http://aws.amazon.com/ruby/) AWS Windows and .NET -// Developer Center (http://aws.amazon.com/net/) -//The service client's operations are safe to be used concurrently. -// It is not safe to mutate any of the client's properties though. -type CloudWatch struct { - *client.Client -} - -// Used for custom client initialization logic -var initClient func(*client.Client) - -// Used for custom request initialization logic -var initRequest func(*request.Request) - -// A ServiceName is the name of the service the client will make API calls to. -const ServiceName = "monitoring" - -// New creates a new instance of the CloudWatch client with a session. -// If additional configuration is needed for the client instance use the optional -// aws.Config parameter to add your extra config. -// -// Example: -// // Create a CloudWatch client from just a session. -// svc := cloudwatch.New(mySession) -// -// // Create a CloudWatch client with additional configuration -// svc := cloudwatch.New(mySession, aws.NewConfig().WithRegion("us-west-2")) -func New(p client.ConfigProvider, cfgs ...*aws.Config) *CloudWatch { - c := p.ClientConfig(ServiceName, cfgs...) - return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) -} - -// newClient creates, initializes and returns a new service client instance. -func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *CloudWatch { - svc := &CloudWatch{ - Client: client.New( - cfg, - metadata.ClientInfo{ - ServiceName: ServiceName, - SigningRegion: signingRegion, - Endpoint: endpoint, - APIVersion: "2010-08-01", - }, - handlers, - ), - } - - // Handlers - svc.Handlers.Sign.PushBack(v4.Sign) - svc.Handlers.Build.PushBack(query.Build) - svc.Handlers.Unmarshal.PushBack(query.Unmarshal) - svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta) - svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError) - - // Run custom client initialization if present - if initClient != nil { - initClient(svc.Client) - } - - return svc -} - -// newRequest creates a new request for a CloudWatch operation and runs any -// custom request initialization. -func (c *CloudWatch) newRequest(op *request.Operation, params, data interface{}) *request.Request { - req := c.NewRequest(op, params, data) - - // Run custom request initialization if present - if initRequest != nil { - initRequest(req) - } - - return req -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/api.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/api.go deleted file mode 100644 index 337392a86f2..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/api.go +++ /dev/null @@ -1,24756 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. - -// Package ec2 provides a client for Amazon Elastic Compute Cloud. -package ec2 - -import ( - "time" - - "github.com/aws/aws-sdk-go/aws/awsutil" - "github.com/aws/aws-sdk-go/aws/request" -) - -const opAcceptVpcPeeringConnection = "AcceptVpcPeeringConnection" - -// AcceptVpcPeeringConnectionRequest generates a request for the AcceptVpcPeeringConnection operation. -func (c *EC2) AcceptVpcPeeringConnectionRequest(input *AcceptVpcPeeringConnectionInput) (req *request.Request, output *AcceptVpcPeeringConnectionOutput) { - op := &request.Operation{ - Name: opAcceptVpcPeeringConnection, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &AcceptVpcPeeringConnectionInput{} - } - - req = c.newRequest(op, input, output) - output = &AcceptVpcPeeringConnectionOutput{} - req.Data = output - return -} - -// Accept a VPC peering connection request. To accept a request, the VPC peering -// connection must be in the pending-acceptance state, and you must be the owner -// of the peer VPC. Use the DescribeVpcPeeringConnections request to view your -// outstanding VPC peering connection requests. -func (c *EC2) AcceptVpcPeeringConnection(input *AcceptVpcPeeringConnectionInput) (*AcceptVpcPeeringConnectionOutput, error) { - req, out := c.AcceptVpcPeeringConnectionRequest(input) - err := req.Send() - return out, err -} - -const opAllocateAddress = "AllocateAddress" - -// AllocateAddressRequest generates a request for the AllocateAddress operation. -func (c *EC2) AllocateAddressRequest(input *AllocateAddressInput) (req *request.Request, output *AllocateAddressOutput) { - op := &request.Operation{ - Name: opAllocateAddress, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &AllocateAddressInput{} - } - - req = c.newRequest(op, input, output) - output = &AllocateAddressOutput{} - req.Data = output - return -} - -// Acquires an Elastic IP address. -// -// An Elastic IP address is for use either in the EC2-Classic platform or in -// a VPC. For more information, see Elastic IP Addresses (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) AllocateAddress(input *AllocateAddressInput) (*AllocateAddressOutput, error) { - req, out := c.AllocateAddressRequest(input) - err := req.Send() - return out, err -} - -const opAssignPrivateIpAddresses = "AssignPrivateIpAddresses" - -// AssignPrivateIpAddressesRequest generates a request for the AssignPrivateIpAddresses operation. -func (c *EC2) AssignPrivateIpAddressesRequest(input *AssignPrivateIpAddressesInput) (req *request.Request, output *AssignPrivateIpAddressesOutput) { - op := &request.Operation{ - Name: opAssignPrivateIpAddresses, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &AssignPrivateIpAddressesInput{} - } - - req = c.newRequest(op, input, output) - output = &AssignPrivateIpAddressesOutput{} - req.Data = output - return -} - -// Assigns one or more secondary private IP addresses to the specified network -// interface. You can specify one or more specific secondary IP addresses, or -// you can specify the number of secondary IP addresses to be automatically -// assigned within the subnet's CIDR block range. The number of secondary IP -// addresses that you can assign to an instance varies by instance type. For -// information about instance types, see Instance Types (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html) -// in the Amazon Elastic Compute Cloud User Guide. For more information about -// Elastic IP addresses, see Elastic IP Addresses (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html) -// in the Amazon Elastic Compute Cloud User Guide. -// -// AssignPrivateIpAddresses is available only in EC2-VPC. -func (c *EC2) AssignPrivateIpAddresses(input *AssignPrivateIpAddressesInput) (*AssignPrivateIpAddressesOutput, error) { - req, out := c.AssignPrivateIpAddressesRequest(input) - err := req.Send() - return out, err -} - -const opAssociateAddress = "AssociateAddress" - -// AssociateAddressRequest generates a request for the AssociateAddress operation. -func (c *EC2) AssociateAddressRequest(input *AssociateAddressInput) (req *request.Request, output *AssociateAddressOutput) { - op := &request.Operation{ - Name: opAssociateAddress, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &AssociateAddressInput{} - } - - req = c.newRequest(op, input, output) - output = &AssociateAddressOutput{} - req.Data = output - return -} - -// Associates an Elastic IP address with an instance or a network interface. -// -// An Elastic IP address is for use in either the EC2-Classic platform or in -// a VPC. For more information, see Elastic IP Addresses (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html) -// in the Amazon Elastic Compute Cloud User Guide. -// -// [EC2-Classic, VPC in an EC2-VPC-only account] If the Elastic IP address -// is already associated with a different instance, it is disassociated from -// that instance and associated with the specified instance. -// -// [VPC in an EC2-Classic account] If you don't specify a private IP address, -// the Elastic IP address is associated with the primary IP address. If the -// Elastic IP address is already associated with a different instance or a network -// interface, you get an error unless you allow reassociation. -// -// This is an idempotent operation. If you perform the operation more than -// once, Amazon EC2 doesn't return an error. -func (c *EC2) AssociateAddress(input *AssociateAddressInput) (*AssociateAddressOutput, error) { - req, out := c.AssociateAddressRequest(input) - err := req.Send() - return out, err -} - -const opAssociateDhcpOptions = "AssociateDhcpOptions" - -// AssociateDhcpOptionsRequest generates a request for the AssociateDhcpOptions operation. -func (c *EC2) AssociateDhcpOptionsRequest(input *AssociateDhcpOptionsInput) (req *request.Request, output *AssociateDhcpOptionsOutput) { - op := &request.Operation{ - Name: opAssociateDhcpOptions, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &AssociateDhcpOptionsInput{} - } - - req = c.newRequest(op, input, output) - output = &AssociateDhcpOptionsOutput{} - req.Data = output - return -} - -// Associates a set of DHCP options (that you've previously created) with the -// specified VPC, or associates no DHCP options with the VPC. -// -// After you associate the options with the VPC, any existing instances and -// all new instances that you launch in that VPC use the options. You don't -// need to restart or relaunch the instances. They automatically pick up the -// changes within a few hours, depending on how frequently the instance renews -// its DHCP lease. You can explicitly renew the lease using the operating system -// on the instance. -// -// For more information, see DHCP Options Sets (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_DHCP_Options.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) AssociateDhcpOptions(input *AssociateDhcpOptionsInput) (*AssociateDhcpOptionsOutput, error) { - req, out := c.AssociateDhcpOptionsRequest(input) - err := req.Send() - return out, err -} - -const opAssociateRouteTable = "AssociateRouteTable" - -// AssociateRouteTableRequest generates a request for the AssociateRouteTable operation. -func (c *EC2) AssociateRouteTableRequest(input *AssociateRouteTableInput) (req *request.Request, output *AssociateRouteTableOutput) { - op := &request.Operation{ - Name: opAssociateRouteTable, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &AssociateRouteTableInput{} - } - - req = c.newRequest(op, input, output) - output = &AssociateRouteTableOutput{} - req.Data = output - return -} - -// Associates a subnet with a route table. The subnet and route table must be -// in the same VPC. This association causes traffic originating from the subnet -// to be routed according to the routes in the route table. The action returns -// an association ID, which you need in order to disassociate the route table -// from the subnet later. A route table can be associated with multiple subnets. -// -// For more information about route tables, see Route Tables (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Route_Tables.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) AssociateRouteTable(input *AssociateRouteTableInput) (*AssociateRouteTableOutput, error) { - req, out := c.AssociateRouteTableRequest(input) - err := req.Send() - return out, err -} - -const opAttachClassicLinkVpc = "AttachClassicLinkVpc" - -// AttachClassicLinkVpcRequest generates a request for the AttachClassicLinkVpc operation. -func (c *EC2) AttachClassicLinkVpcRequest(input *AttachClassicLinkVpcInput) (req *request.Request, output *AttachClassicLinkVpcOutput) { - op := &request.Operation{ - Name: opAttachClassicLinkVpc, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &AttachClassicLinkVpcInput{} - } - - req = c.newRequest(op, input, output) - output = &AttachClassicLinkVpcOutput{} - req.Data = output - return -} - -// Links an EC2-Classic instance to a ClassicLink-enabled VPC through one or -// more of the VPC's security groups. You cannot link an EC2-Classic instance -// to more than one VPC at a time. You can only link an instance that's in the -// running state. An instance is automatically unlinked from a VPC when it's -// stopped - you can link it to the VPC again when you restart it. -// -// After you've linked an instance, you cannot change the VPC security groups -// that are associated with it. To change the security groups, you must first -// unlink the instance, and then link it again. -// -// Linking your instance to a VPC is sometimes referred to as attaching your -// instance. -func (c *EC2) AttachClassicLinkVpc(input *AttachClassicLinkVpcInput) (*AttachClassicLinkVpcOutput, error) { - req, out := c.AttachClassicLinkVpcRequest(input) - err := req.Send() - return out, err -} - -const opAttachInternetGateway = "AttachInternetGateway" - -// AttachInternetGatewayRequest generates a request for the AttachInternetGateway operation. -func (c *EC2) AttachInternetGatewayRequest(input *AttachInternetGatewayInput) (req *request.Request, output *AttachInternetGatewayOutput) { - op := &request.Operation{ - Name: opAttachInternetGateway, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &AttachInternetGatewayInput{} - } - - req = c.newRequest(op, input, output) - output = &AttachInternetGatewayOutput{} - req.Data = output - return -} - -// Attaches an Internet gateway to a VPC, enabling connectivity between the -// Internet and the VPC. For more information about your VPC and Internet gateway, -// see the Amazon Virtual Private Cloud User Guide (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/). -func (c *EC2) AttachInternetGateway(input *AttachInternetGatewayInput) (*AttachInternetGatewayOutput, error) { - req, out := c.AttachInternetGatewayRequest(input) - err := req.Send() - return out, err -} - -const opAttachNetworkInterface = "AttachNetworkInterface" - -// AttachNetworkInterfaceRequest generates a request for the AttachNetworkInterface operation. -func (c *EC2) AttachNetworkInterfaceRequest(input *AttachNetworkInterfaceInput) (req *request.Request, output *AttachNetworkInterfaceOutput) { - op := &request.Operation{ - Name: opAttachNetworkInterface, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &AttachNetworkInterfaceInput{} - } - - req = c.newRequest(op, input, output) - output = &AttachNetworkInterfaceOutput{} - req.Data = output - return -} - -// Attaches a network interface to an instance. -func (c *EC2) AttachNetworkInterface(input *AttachNetworkInterfaceInput) (*AttachNetworkInterfaceOutput, error) { - req, out := c.AttachNetworkInterfaceRequest(input) - err := req.Send() - return out, err -} - -const opAttachVolume = "AttachVolume" - -// AttachVolumeRequest generates a request for the AttachVolume operation. -func (c *EC2) AttachVolumeRequest(input *AttachVolumeInput) (req *request.Request, output *VolumeAttachment) { - op := &request.Operation{ - Name: opAttachVolume, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &AttachVolumeInput{} - } - - req = c.newRequest(op, input, output) - output = &VolumeAttachment{} - req.Data = output - return -} - -// Attaches an EBS volume to a running or stopped instance and exposes it to -// the instance with the specified device name. -// -// Encrypted EBS volumes may only be attached to instances that support Amazon -// EBS encryption. For more information, see Amazon EBS Encryption (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html) -// in the Amazon Elastic Compute Cloud User Guide. -// -// For a list of supported device names, see Attaching an EBS Volume to an -// Instance (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-attaching-volume.html). -// Any device names that aren't reserved for instance store volumes can be used -// for EBS volumes. For more information, see Amazon EC2 Instance Store (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/InstanceStorage.html) -// in the Amazon Elastic Compute Cloud User Guide. -// -// If a volume has an AWS Marketplace product code: -// -// The volume can be attached only to a stopped instance. AWS Marketplace -// product codes are copied from the volume to the instance. You must be subscribed -// to the product. The instance type and operating system of the instance must -// support the product. For example, you can't detach a volume from a Windows -// instance and attach it to a Linux instance. For an overview of the AWS Marketplace, -// see Introducing AWS Marketplace (https://aws.amazon.com/marketplace/help/200900000). -// -// For more information about EBS volumes, see Attaching Amazon EBS Volumes -// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-attaching-volume.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) AttachVolume(input *AttachVolumeInput) (*VolumeAttachment, error) { - req, out := c.AttachVolumeRequest(input) - err := req.Send() - return out, err -} - -const opAttachVpnGateway = "AttachVpnGateway" - -// AttachVpnGatewayRequest generates a request for the AttachVpnGateway operation. -func (c *EC2) AttachVpnGatewayRequest(input *AttachVpnGatewayInput) (req *request.Request, output *AttachVpnGatewayOutput) { - op := &request.Operation{ - Name: opAttachVpnGateway, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &AttachVpnGatewayInput{} - } - - req = c.newRequest(op, input, output) - output = &AttachVpnGatewayOutput{} - req.Data = output - return -} - -// Attaches a virtual private gateway to a VPC. For more information, see Adding -// a Hardware Virtual Private Gateway to Your VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_VPN.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) AttachVpnGateway(input *AttachVpnGatewayInput) (*AttachVpnGatewayOutput, error) { - req, out := c.AttachVpnGatewayRequest(input) - err := req.Send() - return out, err -} - -const opAuthorizeSecurityGroupEgress = "AuthorizeSecurityGroupEgress" - -// AuthorizeSecurityGroupEgressRequest generates a request for the AuthorizeSecurityGroupEgress operation. -func (c *EC2) AuthorizeSecurityGroupEgressRequest(input *AuthorizeSecurityGroupEgressInput) (req *request.Request, output *AuthorizeSecurityGroupEgressOutput) { - op := &request.Operation{ - Name: opAuthorizeSecurityGroupEgress, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &AuthorizeSecurityGroupEgressInput{} - } - - req = c.newRequest(op, input, output) - output = &AuthorizeSecurityGroupEgressOutput{} - req.Data = output - return -} - -// Adds one or more egress rules to a security group for use with a VPC. Specifically, -// this action permits instances to send traffic to one or more destination -// CIDR IP address ranges, or to one or more destination security groups for -// the same VPC. -// -// You can have up to 50 rules per security group (covering both ingress and -// egress rules). -// -// A security group is for use with instances either in the EC2-Classic platform -// or in a specific VPC. This action doesn't apply to security groups for use -// in EC2-Classic. For more information, see Security Groups for Your VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_SecurityGroups.html) -// in the Amazon Virtual Private Cloud User Guide. -// -// Each rule consists of the protocol (for example, TCP), plus either a CIDR -// range or a source group. For the TCP and UDP protocols, you must also specify -// the destination port or port range. For the ICMP protocol, you must also -// specify the ICMP type and code. You can use -1 for the type or code to mean -// all types or all codes. -// -// Rule changes are propagated to affected instances as quickly as possible. -// However, a small delay might occur. -func (c *EC2) AuthorizeSecurityGroupEgress(input *AuthorizeSecurityGroupEgressInput) (*AuthorizeSecurityGroupEgressOutput, error) { - req, out := c.AuthorizeSecurityGroupEgressRequest(input) - err := req.Send() - return out, err -} - -const opAuthorizeSecurityGroupIngress = "AuthorizeSecurityGroupIngress" - -// AuthorizeSecurityGroupIngressRequest generates a request for the AuthorizeSecurityGroupIngress operation. -func (c *EC2) AuthorizeSecurityGroupIngressRequest(input *AuthorizeSecurityGroupIngressInput) (req *request.Request, output *AuthorizeSecurityGroupIngressOutput) { - op := &request.Operation{ - Name: opAuthorizeSecurityGroupIngress, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &AuthorizeSecurityGroupIngressInput{} - } - - req = c.newRequest(op, input, output) - output = &AuthorizeSecurityGroupIngressOutput{} - req.Data = output - return -} - -// Adds one or more ingress rules to a security group. -// -// EC2-Classic: You can have up to 100 rules per group. -// -// EC2-VPC: You can have up to 50 rules per group (covering both ingress and -// egress rules). -// -// Rule changes are propagated to instances within the security group as quickly -// as possible. However, a small delay might occur. -// -// [EC2-Classic] This action gives one or more CIDR IP address ranges permission -// to access a security group in your account, or gives one or more security -// groups (called the source groups) permission to access a security group for -// your account. A source group can be for your own AWS account, or another. -// -// [EC2-VPC] This action gives one or more CIDR IP address ranges permission -// to access a security group in your VPC, or gives one or more other security -// groups (called the source groups) permission to access a security group for -// your VPC. The security groups must all be for the same VPC. -func (c *EC2) AuthorizeSecurityGroupIngress(input *AuthorizeSecurityGroupIngressInput) (*AuthorizeSecurityGroupIngressOutput, error) { - req, out := c.AuthorizeSecurityGroupIngressRequest(input) - err := req.Send() - return out, err -} - -const opBundleInstance = "BundleInstance" - -// BundleInstanceRequest generates a request for the BundleInstance operation. -func (c *EC2) BundleInstanceRequest(input *BundleInstanceInput) (req *request.Request, output *BundleInstanceOutput) { - op := &request.Operation{ - Name: opBundleInstance, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &BundleInstanceInput{} - } - - req = c.newRequest(op, input, output) - output = &BundleInstanceOutput{} - req.Data = output - return -} - -// Bundles an Amazon instance store-backed Windows instance. -// -// During bundling, only the root device volume (C:\) is bundled. Data on other -// instance store volumes is not preserved. -// -// This action is not applicable for Linux/Unix instances or Windows instances -// that are backed by Amazon EBS. -// -// For more information, see Creating an Instance Store-Backed Windows AMI -// (http://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/Creating_InstanceStoreBacked_WinAMI.html). -func (c *EC2) BundleInstance(input *BundleInstanceInput) (*BundleInstanceOutput, error) { - req, out := c.BundleInstanceRequest(input) - err := req.Send() - return out, err -} - -const opCancelBundleTask = "CancelBundleTask" - -// CancelBundleTaskRequest generates a request for the CancelBundleTask operation. -func (c *EC2) CancelBundleTaskRequest(input *CancelBundleTaskInput) (req *request.Request, output *CancelBundleTaskOutput) { - op := &request.Operation{ - Name: opCancelBundleTask, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CancelBundleTaskInput{} - } - - req = c.newRequest(op, input, output) - output = &CancelBundleTaskOutput{} - req.Data = output - return -} - -// Cancels a bundling operation for an instance store-backed Windows instance. -func (c *EC2) CancelBundleTask(input *CancelBundleTaskInput) (*CancelBundleTaskOutput, error) { - req, out := c.CancelBundleTaskRequest(input) - err := req.Send() - return out, err -} - -const opCancelConversionTask = "CancelConversionTask" - -// CancelConversionTaskRequest generates a request for the CancelConversionTask operation. -func (c *EC2) CancelConversionTaskRequest(input *CancelConversionTaskInput) (req *request.Request, output *CancelConversionTaskOutput) { - op := &request.Operation{ - Name: opCancelConversionTask, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CancelConversionTaskInput{} - } - - req = c.newRequest(op, input, output) - output = &CancelConversionTaskOutput{} - req.Data = output - return -} - -// Cancels an active conversion task. The task can be the import of an instance -// or volume. The action removes all artifacts of the conversion, including -// a partially uploaded volume or instance. If the conversion is complete or -// is in the process of transferring the final disk image, the command fails -// and returns an exception. -// -// For more information, see Using the Command Line Tools to Import Your Virtual -// Machine to Amazon EC2 (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/UploadingYourInstancesandVolumes.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) CancelConversionTask(input *CancelConversionTaskInput) (*CancelConversionTaskOutput, error) { - req, out := c.CancelConversionTaskRequest(input) - err := req.Send() - return out, err -} - -const opCancelExportTask = "CancelExportTask" - -// CancelExportTaskRequest generates a request for the CancelExportTask operation. -func (c *EC2) CancelExportTaskRequest(input *CancelExportTaskInput) (req *request.Request, output *CancelExportTaskOutput) { - op := &request.Operation{ - Name: opCancelExportTask, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CancelExportTaskInput{} - } - - req = c.newRequest(op, input, output) - output = &CancelExportTaskOutput{} - req.Data = output - return -} - -// Cancels an active export task. The request removes all artifacts of the export, -// including any partially-created Amazon S3 objects. If the export task is -// complete or is in the process of transferring the final disk image, the command -// fails and returns an error. -func (c *EC2) CancelExportTask(input *CancelExportTaskInput) (*CancelExportTaskOutput, error) { - req, out := c.CancelExportTaskRequest(input) - err := req.Send() - return out, err -} - -const opCancelImportTask = "CancelImportTask" - -// CancelImportTaskRequest generates a request for the CancelImportTask operation. -func (c *EC2) CancelImportTaskRequest(input *CancelImportTaskInput) (req *request.Request, output *CancelImportTaskOutput) { - op := &request.Operation{ - Name: opCancelImportTask, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CancelImportTaskInput{} - } - - req = c.newRequest(op, input, output) - output = &CancelImportTaskOutput{} - req.Data = output - return -} - -// Cancels an in-process import virtual machine or import snapshot task. -func (c *EC2) CancelImportTask(input *CancelImportTaskInput) (*CancelImportTaskOutput, error) { - req, out := c.CancelImportTaskRequest(input) - err := req.Send() - return out, err -} - -const opCancelReservedInstancesListing = "CancelReservedInstancesListing" - -// CancelReservedInstancesListingRequest generates a request for the CancelReservedInstancesListing operation. -func (c *EC2) CancelReservedInstancesListingRequest(input *CancelReservedInstancesListingInput) (req *request.Request, output *CancelReservedInstancesListingOutput) { - op := &request.Operation{ - Name: opCancelReservedInstancesListing, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CancelReservedInstancesListingInput{} - } - - req = c.newRequest(op, input, output) - output = &CancelReservedInstancesListingOutput{} - req.Data = output - return -} - -// Cancels the specified Reserved Instance listing in the Reserved Instance -// Marketplace. -// -// For more information, see Reserved Instance Marketplace (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ri-market-general.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) CancelReservedInstancesListing(input *CancelReservedInstancesListingInput) (*CancelReservedInstancesListingOutput, error) { - req, out := c.CancelReservedInstancesListingRequest(input) - err := req.Send() - return out, err -} - -const opCancelSpotFleetRequests = "CancelSpotFleetRequests" - -// CancelSpotFleetRequestsRequest generates a request for the CancelSpotFleetRequests operation. -func (c *EC2) CancelSpotFleetRequestsRequest(input *CancelSpotFleetRequestsInput) (req *request.Request, output *CancelSpotFleetRequestsOutput) { - op := &request.Operation{ - Name: opCancelSpotFleetRequests, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CancelSpotFleetRequestsInput{} - } - - req = c.newRequest(op, input, output) - output = &CancelSpotFleetRequestsOutput{} - req.Data = output - return -} - -// Cancels the specified Spot fleet requests. -// -// After you cancel a Spot fleet request, the Spot fleet launches no new Spot -// instances. You must specify whether the Spot fleet should also terminate -// its Spot instances. If you terminate the instances, the Spot fleet request -// enters the cancelled_terminating state. Otherwise, the Spot fleet request -// enters the cancelled_running state and the instances continue to run until -// they are interrupted or you terminate them manually. -func (c *EC2) CancelSpotFleetRequests(input *CancelSpotFleetRequestsInput) (*CancelSpotFleetRequestsOutput, error) { - req, out := c.CancelSpotFleetRequestsRequest(input) - err := req.Send() - return out, err -} - -const opCancelSpotInstanceRequests = "CancelSpotInstanceRequests" - -// CancelSpotInstanceRequestsRequest generates a request for the CancelSpotInstanceRequests operation. -func (c *EC2) CancelSpotInstanceRequestsRequest(input *CancelSpotInstanceRequestsInput) (req *request.Request, output *CancelSpotInstanceRequestsOutput) { - op := &request.Operation{ - Name: opCancelSpotInstanceRequests, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CancelSpotInstanceRequestsInput{} - } - - req = c.newRequest(op, input, output) - output = &CancelSpotInstanceRequestsOutput{} - req.Data = output - return -} - -// Cancels one or more Spot instance requests. Spot instances are instances -// that Amazon EC2 starts on your behalf when the bid price that you specify -// exceeds the current Spot price. Amazon EC2 periodically sets the Spot price -// based on available Spot instance capacity and current Spot instance requests. -// For more information, see Spot Instance Requests (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-requests.html) -// in the Amazon Elastic Compute Cloud User Guide. -// -// Canceling a Spot instance request does not terminate running Spot instances -// associated with the request. -func (c *EC2) CancelSpotInstanceRequests(input *CancelSpotInstanceRequestsInput) (*CancelSpotInstanceRequestsOutput, error) { - req, out := c.CancelSpotInstanceRequestsRequest(input) - err := req.Send() - return out, err -} - -const opConfirmProductInstance = "ConfirmProductInstance" - -// ConfirmProductInstanceRequest generates a request for the ConfirmProductInstance operation. -func (c *EC2) ConfirmProductInstanceRequest(input *ConfirmProductInstanceInput) (req *request.Request, output *ConfirmProductInstanceOutput) { - op := &request.Operation{ - Name: opConfirmProductInstance, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ConfirmProductInstanceInput{} - } - - req = c.newRequest(op, input, output) - output = &ConfirmProductInstanceOutput{} - req.Data = output - return -} - -// Determines whether a product code is associated with an instance. This action -// can only be used by the owner of the product code. It is useful when a product -// code owner needs to verify whether another user's instance is eligible for -// support. -func (c *EC2) ConfirmProductInstance(input *ConfirmProductInstanceInput) (*ConfirmProductInstanceOutput, error) { - req, out := c.ConfirmProductInstanceRequest(input) - err := req.Send() - return out, err -} - -const opCopyImage = "CopyImage" - -// CopyImageRequest generates a request for the CopyImage operation. -func (c *EC2) CopyImageRequest(input *CopyImageInput) (req *request.Request, output *CopyImageOutput) { - op := &request.Operation{ - Name: opCopyImage, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CopyImageInput{} - } - - req = c.newRequest(op, input, output) - output = &CopyImageOutput{} - req.Data = output - return -} - -// Initiates the copy of an AMI from the specified source region to the current -// region. You specify the destination region by using its endpoint when making -// the request. AMIs that use encrypted EBS snapshots cannot be copied with -// this method. -// -// For more information, see Copying AMIs (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/CopyingAMIs.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) CopyImage(input *CopyImageInput) (*CopyImageOutput, error) { - req, out := c.CopyImageRequest(input) - err := req.Send() - return out, err -} - -const opCopySnapshot = "CopySnapshot" - -// CopySnapshotRequest generates a request for the CopySnapshot operation. -func (c *EC2) CopySnapshotRequest(input *CopySnapshotInput) (req *request.Request, output *CopySnapshotOutput) { - op := &request.Operation{ - Name: opCopySnapshot, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CopySnapshotInput{} - } - - req = c.newRequest(op, input, output) - output = &CopySnapshotOutput{} - req.Data = output - return -} - -// Copies a point-in-time snapshot of an EBS volume and stores it in Amazon -// S3. You can copy the snapshot within the same region or from one region to -// another. You can use the snapshot to create EBS volumes or Amazon Machine -// Images (AMIs). The snapshot is copied to the regional endpoint that you send -// the HTTP request to. -// -// Copies of encrypted EBS snapshots remain encrypted. Copies of unencrypted -// snapshots remain unencrypted, unless the Encrypted flag is specified during -// the snapshot copy operation. By default, encrypted snapshot copies use the -// default AWS Key Management Service (AWS KMS) customer master key (CMK); however, -// you can specify a non-default CMK with the KmsKeyId parameter. -// -// For more information, see Copying an Amazon EBS Snapshot (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-copy-snapshot.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) CopySnapshot(input *CopySnapshotInput) (*CopySnapshotOutput, error) { - req, out := c.CopySnapshotRequest(input) - err := req.Send() - return out, err -} - -const opCreateCustomerGateway = "CreateCustomerGateway" - -// CreateCustomerGatewayRequest generates a request for the CreateCustomerGateway operation. -func (c *EC2) CreateCustomerGatewayRequest(input *CreateCustomerGatewayInput) (req *request.Request, output *CreateCustomerGatewayOutput) { - op := &request.Operation{ - Name: opCreateCustomerGateway, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateCustomerGatewayInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateCustomerGatewayOutput{} - req.Data = output - return -} - -// Provides information to AWS about your VPN customer gateway device. The customer -// gateway is the appliance at your end of the VPN connection. (The device on -// the AWS side of the VPN connection is the virtual private gateway.) You must -// provide the Internet-routable IP address of the customer gateway's external -// interface. The IP address must be static and may be behind a device performing -// network address translation (NAT). -// -// For devices that use Border Gateway Protocol (BGP), you can also provide -// the device's BGP Autonomous System Number (ASN). You can use an existing -// ASN assigned to your network. If you don't have an ASN already, you can use -// a private ASN (in the 64512 - 65534 range). -// -// Amazon EC2 supports all 2-byte ASN numbers in the range of 1 - 65534, with -// the exception of 7224, which is reserved in the us-east-1 region, and 9059, -// which is reserved in the eu-west-1 region. -// -// For more information about VPN customer gateways, see Adding a Hardware -// Virtual Private Gateway to Your VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_VPN.html) -// in the Amazon Virtual Private Cloud User Guide. -// -// You cannot create more than one customer gateway with the same VPN type, -// IP address, and BGP ASN parameter values. If you run an identical request -// more than one time, the first request creates the customer gateway, and subsequent -// requests return information about the existing customer gateway. The subsequent -// requests do not create new customer gateway resources. -func (c *EC2) CreateCustomerGateway(input *CreateCustomerGatewayInput) (*CreateCustomerGatewayOutput, error) { - req, out := c.CreateCustomerGatewayRequest(input) - err := req.Send() - return out, err -} - -const opCreateDhcpOptions = "CreateDhcpOptions" - -// CreateDhcpOptionsRequest generates a request for the CreateDhcpOptions operation. -func (c *EC2) CreateDhcpOptionsRequest(input *CreateDhcpOptionsInput) (req *request.Request, output *CreateDhcpOptionsOutput) { - op := &request.Operation{ - Name: opCreateDhcpOptions, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateDhcpOptionsInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateDhcpOptionsOutput{} - req.Data = output - return -} - -// Creates a set of DHCP options for your VPC. After creating the set, you must -// associate it with the VPC, causing all existing and new instances that you -// launch in the VPC to use this set of DHCP options. The following are the -// individual DHCP options you can specify. For more information about the options, -// see RFC 2132 (http://www.ietf.org/rfc/rfc2132.txt). -// -// domain-name-servers - The IP addresses of up to four domain name servers, -// or AmazonProvidedDNS. The default DHCP option set specifies AmazonProvidedDNS. -// If specifying more than one domain name server, specify the IP addresses -// in a single parameter, separated by commas. domain-name - If you're using -// AmazonProvidedDNS in us-east-1, specify ec2.internal. If you're using AmazonProvidedDNS -// in another region, specify region.compute.internal (for example, ap-northeast-1.compute.internal). -// Otherwise, specify a domain name (for example, MyCompany.com). Important: -// Some Linux operating systems accept multiple domain names separated by spaces. -// However, Windows and other Linux operating systems treat the value as a single -// domain, which results in unexpected behavior. If your DHCP options set is -// associated with a VPC that has instances with multiple operating systems, -// specify only one domain name. ntp-servers - The IP addresses of up to four -// Network Time Protocol (NTP) servers. netbios-name-servers - The IP addresses -// of up to four NetBIOS name servers. netbios-node-type - The NetBIOS node -// type (1, 2, 4, or 8). We recommend that you specify 2 (broadcast and multicast -// are not currently supported). For more information about these node types, -// see RFC 2132 (http://www.ietf.org/rfc/rfc2132.txt). Your VPC automatically -// starts out with a set of DHCP options that includes only a DNS server that -// we provide (AmazonProvidedDNS). If you create a set of options, and if your -// VPC has an Internet gateway, make sure to set the domain-name-servers option -// either to AmazonProvidedDNS or to a domain name server of your choice. For -// more information about DHCP options, see DHCP Options Sets (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_DHCP_Options.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) CreateDhcpOptions(input *CreateDhcpOptionsInput) (*CreateDhcpOptionsOutput, error) { - req, out := c.CreateDhcpOptionsRequest(input) - err := req.Send() - return out, err -} - -const opCreateFlowLogs = "CreateFlowLogs" - -// CreateFlowLogsRequest generates a request for the CreateFlowLogs operation. -func (c *EC2) CreateFlowLogsRequest(input *CreateFlowLogsInput) (req *request.Request, output *CreateFlowLogsOutput) { - op := &request.Operation{ - Name: opCreateFlowLogs, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateFlowLogsInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateFlowLogsOutput{} - req.Data = output - return -} - -// Creates one or more flow logs to capture IP traffic for a specific network -// interface, subnet, or VPC. Flow logs are delivered to a specified log group -// in Amazon CloudWatch Logs. If you specify a VPC or subnet in the request, -// a log stream is created in CloudWatch Logs for each network interface in -// the subnet or VPC. Log streams can include information about accepted and -// rejected traffic to a network interface. You can view the data in your log -// streams using Amazon CloudWatch Logs. -// -// In your request, you must also specify an IAM role that has permission to -// publish logs to CloudWatch Logs. -func (c *EC2) CreateFlowLogs(input *CreateFlowLogsInput) (*CreateFlowLogsOutput, error) { - req, out := c.CreateFlowLogsRequest(input) - err := req.Send() - return out, err -} - -const opCreateImage = "CreateImage" - -// CreateImageRequest generates a request for the CreateImage operation. -func (c *EC2) CreateImageRequest(input *CreateImageInput) (req *request.Request, output *CreateImageOutput) { - op := &request.Operation{ - Name: opCreateImage, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateImageInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateImageOutput{} - req.Data = output - return -} - -// Creates an Amazon EBS-backed AMI from an Amazon EBS-backed instance that -// is either running or stopped. -// -// If you customized your instance with instance store volumes or EBS volumes -// in addition to the root device volume, the new AMI contains block device -// mapping information for those volumes. When you launch an instance from this -// new AMI, the instance automatically launches with those additional volumes. -// -// For more information, see Creating Amazon EBS-Backed Linux AMIs (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/creating-an-ami-ebs.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) CreateImage(input *CreateImageInput) (*CreateImageOutput, error) { - req, out := c.CreateImageRequest(input) - err := req.Send() - return out, err -} - -const opCreateInstanceExportTask = "CreateInstanceExportTask" - -// CreateInstanceExportTaskRequest generates a request for the CreateInstanceExportTask operation. -func (c *EC2) CreateInstanceExportTaskRequest(input *CreateInstanceExportTaskInput) (req *request.Request, output *CreateInstanceExportTaskOutput) { - op := &request.Operation{ - Name: opCreateInstanceExportTask, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateInstanceExportTaskInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateInstanceExportTaskOutput{} - req.Data = output - return -} - -// Exports a running or stopped instance to an S3 bucket. -// -// For information about the supported operating systems, image formats, and -// known limitations for the types of instances you can export, see Exporting -// EC2 Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ExportingEC2Instances.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) CreateInstanceExportTask(input *CreateInstanceExportTaskInput) (*CreateInstanceExportTaskOutput, error) { - req, out := c.CreateInstanceExportTaskRequest(input) - err := req.Send() - return out, err -} - -const opCreateInternetGateway = "CreateInternetGateway" - -// CreateInternetGatewayRequest generates a request for the CreateInternetGateway operation. -func (c *EC2) CreateInternetGatewayRequest(input *CreateInternetGatewayInput) (req *request.Request, output *CreateInternetGatewayOutput) { - op := &request.Operation{ - Name: opCreateInternetGateway, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateInternetGatewayInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateInternetGatewayOutput{} - req.Data = output - return -} - -// Creates an Internet gateway for use with a VPC. After creating the Internet -// gateway, you attach it to a VPC using AttachInternetGateway. -// -// For more information about your VPC and Internet gateway, see the Amazon -// Virtual Private Cloud User Guide (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/). -func (c *EC2) CreateInternetGateway(input *CreateInternetGatewayInput) (*CreateInternetGatewayOutput, error) { - req, out := c.CreateInternetGatewayRequest(input) - err := req.Send() - return out, err -} - -const opCreateKeyPair = "CreateKeyPair" - -// CreateKeyPairRequest generates a request for the CreateKeyPair operation. -func (c *EC2) CreateKeyPairRequest(input *CreateKeyPairInput) (req *request.Request, output *CreateKeyPairOutput) { - op := &request.Operation{ - Name: opCreateKeyPair, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateKeyPairInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateKeyPairOutput{} - req.Data = output - return -} - -// Creates a 2048-bit RSA key pair with the specified name. Amazon EC2 stores -// the public key and displays the private key for you to save to a file. The -// private key is returned as an unencrypted PEM encoded PKCS#8 private key. -// If a key with the specified name already exists, Amazon EC2 returns an error. -// -// You can have up to five thousand key pairs per region. -// -// The key pair returned to you is available only in the region in which you -// create it. To create a key pair that is available in all regions, use ImportKeyPair. -// -// For more information about key pairs, see Key Pairs (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) CreateKeyPair(input *CreateKeyPairInput) (*CreateKeyPairOutput, error) { - req, out := c.CreateKeyPairRequest(input) - err := req.Send() - return out, err -} - -const opCreateNetworkAcl = "CreateNetworkAcl" - -// CreateNetworkAclRequest generates a request for the CreateNetworkAcl operation. -func (c *EC2) CreateNetworkAclRequest(input *CreateNetworkAclInput) (req *request.Request, output *CreateNetworkAclOutput) { - op := &request.Operation{ - Name: opCreateNetworkAcl, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateNetworkAclInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateNetworkAclOutput{} - req.Data = output - return -} - -// Creates a network ACL in a VPC. Network ACLs provide an optional layer of -// security (in addition to security groups) for the instances in your VPC. -// -// For more information about network ACLs, see Network ACLs (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_ACLs.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) CreateNetworkAcl(input *CreateNetworkAclInput) (*CreateNetworkAclOutput, error) { - req, out := c.CreateNetworkAclRequest(input) - err := req.Send() - return out, err -} - -const opCreateNetworkAclEntry = "CreateNetworkAclEntry" - -// CreateNetworkAclEntryRequest generates a request for the CreateNetworkAclEntry operation. -func (c *EC2) CreateNetworkAclEntryRequest(input *CreateNetworkAclEntryInput) (req *request.Request, output *CreateNetworkAclEntryOutput) { - op := &request.Operation{ - Name: opCreateNetworkAclEntry, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateNetworkAclEntryInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateNetworkAclEntryOutput{} - req.Data = output - return -} - -// Creates an entry (a rule) in a network ACL with the specified rule number. -// Each network ACL has a set of numbered ingress rules and a separate set of -// numbered egress rules. When determining whether a packet should be allowed -// in or out of a subnet associated with the ACL, we process the entries in -// the ACL according to the rule numbers, in ascending order. Each network ACL -// has a set of ingress rules and a separate set of egress rules. -// -// We recommend that you leave room between the rule numbers (for example, -// 100, 110, 120, ...), and not number them one right after the other (for example, -// 101, 102, 103, ...). This makes it easier to add a rule between existing -// ones without having to renumber the rules. -// -// After you add an entry, you can't modify it; you must either replace it, -// or create an entry and delete the old one. -// -// For more information about network ACLs, see Network ACLs (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_ACLs.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) CreateNetworkAclEntry(input *CreateNetworkAclEntryInput) (*CreateNetworkAclEntryOutput, error) { - req, out := c.CreateNetworkAclEntryRequest(input) - err := req.Send() - return out, err -} - -const opCreateNetworkInterface = "CreateNetworkInterface" - -// CreateNetworkInterfaceRequest generates a request for the CreateNetworkInterface operation. -func (c *EC2) CreateNetworkInterfaceRequest(input *CreateNetworkInterfaceInput) (req *request.Request, output *CreateNetworkInterfaceOutput) { - op := &request.Operation{ - Name: opCreateNetworkInterface, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateNetworkInterfaceInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateNetworkInterfaceOutput{} - req.Data = output - return -} - -// Creates a network interface in the specified subnet. -// -// For more information about network interfaces, see Elastic Network Interfaces -// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html) in the -// Amazon Elastic Compute Cloud User Guide. -func (c *EC2) CreateNetworkInterface(input *CreateNetworkInterfaceInput) (*CreateNetworkInterfaceOutput, error) { - req, out := c.CreateNetworkInterfaceRequest(input) - err := req.Send() - return out, err -} - -const opCreatePlacementGroup = "CreatePlacementGroup" - -// CreatePlacementGroupRequest generates a request for the CreatePlacementGroup operation. -func (c *EC2) CreatePlacementGroupRequest(input *CreatePlacementGroupInput) (req *request.Request, output *CreatePlacementGroupOutput) { - op := &request.Operation{ - Name: opCreatePlacementGroup, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreatePlacementGroupInput{} - } - - req = c.newRequest(op, input, output) - output = &CreatePlacementGroupOutput{} - req.Data = output - return -} - -// Creates a placement group that you launch cluster instances into. You must -// give the group a name that's unique within the scope of your account. -// -// For more information about placement groups and cluster instances, see Cluster -// Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using_cluster_computing.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) CreatePlacementGroup(input *CreatePlacementGroupInput) (*CreatePlacementGroupOutput, error) { - req, out := c.CreatePlacementGroupRequest(input) - err := req.Send() - return out, err -} - -const opCreateReservedInstancesListing = "CreateReservedInstancesListing" - -// CreateReservedInstancesListingRequest generates a request for the CreateReservedInstancesListing operation. -func (c *EC2) CreateReservedInstancesListingRequest(input *CreateReservedInstancesListingInput) (req *request.Request, output *CreateReservedInstancesListingOutput) { - op := &request.Operation{ - Name: opCreateReservedInstancesListing, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateReservedInstancesListingInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateReservedInstancesListingOutput{} - req.Data = output - return -} - -// Creates a listing for Amazon EC2 Reserved Instances to be sold in the Reserved -// Instance Marketplace. You can submit one Reserved Instance listing at a time. -// To get a list of your Reserved Instances, you can use the DescribeReservedInstances -// operation. -// -// The Reserved Instance Marketplace matches sellers who want to resell Reserved -// Instance capacity that they no longer need with buyers who want to purchase -// additional capacity. Reserved Instances bought and sold through the Reserved -// Instance Marketplace work like any other Reserved Instances. -// -// To sell your Reserved Instances, you must first register as a seller in -// the Reserved Instance Marketplace. After completing the registration process, -// you can create a Reserved Instance Marketplace listing of some or all of -// your Reserved Instances, and specify the upfront price to receive for them. -// Your Reserved Instance listings then become available for purchase. To view -// the details of your Reserved Instance listing, you can use the DescribeReservedInstancesListings -// operation. -// -// For more information, see Reserved Instance Marketplace (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ri-market-general.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) CreateReservedInstancesListing(input *CreateReservedInstancesListingInput) (*CreateReservedInstancesListingOutput, error) { - req, out := c.CreateReservedInstancesListingRequest(input) - err := req.Send() - return out, err -} - -const opCreateRoute = "CreateRoute" - -// CreateRouteRequest generates a request for the CreateRoute operation. -func (c *EC2) CreateRouteRequest(input *CreateRouteInput) (req *request.Request, output *CreateRouteOutput) { - op := &request.Operation{ - Name: opCreateRoute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateRouteInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateRouteOutput{} - req.Data = output - return -} - -// Creates a route in a route table within a VPC. -// -// You must specify one of the following targets: Internet gateway or virtual -// private gateway, NAT instance, VPC peering connection, or network interface. -// -// When determining how to route traffic, we use the route with the most specific -// match. For example, let's say the traffic is destined for 192.0.2.3, and -// the route table includes the following two routes: -// -// 192.0.2.0/24 (goes to some target A) -// -// 192.0.2.0/28 (goes to some target B) -// -// Both routes apply to the traffic destined for 192.0.2.3. However, the -// second route in the list covers a smaller number of IP addresses and is therefore -// more specific, so we use that route to determine where to target the traffic. -// -// For more information about route tables, see Route Tables (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Route_Tables.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) CreateRoute(input *CreateRouteInput) (*CreateRouteOutput, error) { - req, out := c.CreateRouteRequest(input) - err := req.Send() - return out, err -} - -const opCreateRouteTable = "CreateRouteTable" - -// CreateRouteTableRequest generates a request for the CreateRouteTable operation. -func (c *EC2) CreateRouteTableRequest(input *CreateRouteTableInput) (req *request.Request, output *CreateRouteTableOutput) { - op := &request.Operation{ - Name: opCreateRouteTable, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateRouteTableInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateRouteTableOutput{} - req.Data = output - return -} - -// Creates a route table for the specified VPC. After you create a route table, -// you can add routes and associate the table with a subnet. -// -// For more information about route tables, see Route Tables (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Route_Tables.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) CreateRouteTable(input *CreateRouteTableInput) (*CreateRouteTableOutput, error) { - req, out := c.CreateRouteTableRequest(input) - err := req.Send() - return out, err -} - -const opCreateSecurityGroup = "CreateSecurityGroup" - -// CreateSecurityGroupRequest generates a request for the CreateSecurityGroup operation. -func (c *EC2) CreateSecurityGroupRequest(input *CreateSecurityGroupInput) (req *request.Request, output *CreateSecurityGroupOutput) { - op := &request.Operation{ - Name: opCreateSecurityGroup, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateSecurityGroupInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateSecurityGroupOutput{} - req.Data = output - return -} - -// Creates a security group. -// -// A security group is for use with instances either in the EC2-Classic platform -// or in a specific VPC. For more information, see Amazon EC2 Security Groups -// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-network-security.html) -// in the Amazon Elastic Compute Cloud User Guide and Security Groups for Your -// VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_SecurityGroups.html) -// in the Amazon Virtual Private Cloud User Guide. -// -// EC2-Classic: You can have up to 500 security groups. -// -// EC2-VPC: You can create up to 100 security groups per VPC. -// -// When you create a security group, you specify a friendly name of your choice. -// You can have a security group for use in EC2-Classic with the same name as -// a security group for use in a VPC. However, you can't have two security groups -// for use in EC2-Classic with the same name or two security groups for use -// in a VPC with the same name. -// -// You have a default security group for use in EC2-Classic and a default security -// group for use in your VPC. If you don't specify a security group when you -// launch an instance, the instance is launched into the appropriate default -// security group. A default security group includes a default rule that grants -// instances unrestricted network access to each other. -// -// You can add or remove rules from your security groups using AuthorizeSecurityGroupIngress, -// AuthorizeSecurityGroupEgress, RevokeSecurityGroupIngress, and RevokeSecurityGroupEgress. -func (c *EC2) CreateSecurityGroup(input *CreateSecurityGroupInput) (*CreateSecurityGroupOutput, error) { - req, out := c.CreateSecurityGroupRequest(input) - err := req.Send() - return out, err -} - -const opCreateSnapshot = "CreateSnapshot" - -// CreateSnapshotRequest generates a request for the CreateSnapshot operation. -func (c *EC2) CreateSnapshotRequest(input *CreateSnapshotInput) (req *request.Request, output *Snapshot) { - op := &request.Operation{ - Name: opCreateSnapshot, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateSnapshotInput{} - } - - req = c.newRequest(op, input, output) - output = &Snapshot{} - req.Data = output - return -} - -// Creates a snapshot of an EBS volume and stores it in Amazon S3. You can use -// snapshots for backups, to make copies of EBS volumes, and to save data before -// shutting down an instance. -// -// When a snapshot is created, any AWS Marketplace product codes that are associated -// with the source volume are propagated to the snapshot. -// -// You can take a snapshot of an attached volume that is in use. However, snapshots -// only capture data that has been written to your EBS volume at the time the -// snapshot command is issued; this may exclude any data that has been cached -// by any applications or the operating system. If you can pause any file systems -// on the volume long enough to take a snapshot, your snapshot should be complete. -// However, if you cannot pause all file writes to the volume, you should unmount -// the volume from within the instance, issue the snapshot command, and then -// remount the volume to ensure a consistent and complete snapshot. You may -// remount and use your volume while the snapshot status is pending. -// -// To create a snapshot for EBS volumes that serve as root devices, you should -// stop the instance before taking the snapshot. -// -// Snapshots that are taken from encrypted volumes are automatically encrypted. -// Volumes that are created from encrypted snapshots are also automatically -// encrypted. Your encrypted volumes and any associated snapshots always remain -// protected. -// -// For more information, see Amazon Elastic Block Store (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AmazonEBS.html) -// and Amazon EBS Encryption (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) CreateSnapshot(input *CreateSnapshotInput) (*Snapshot, error) { - req, out := c.CreateSnapshotRequest(input) - err := req.Send() - return out, err -} - -const opCreateSpotDatafeedSubscription = "CreateSpotDatafeedSubscription" - -// CreateSpotDatafeedSubscriptionRequest generates a request for the CreateSpotDatafeedSubscription operation. -func (c *EC2) CreateSpotDatafeedSubscriptionRequest(input *CreateSpotDatafeedSubscriptionInput) (req *request.Request, output *CreateSpotDatafeedSubscriptionOutput) { - op := &request.Operation{ - Name: opCreateSpotDatafeedSubscription, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateSpotDatafeedSubscriptionInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateSpotDatafeedSubscriptionOutput{} - req.Data = output - return -} - -// Creates a data feed for Spot instances, enabling you to view Spot instance -// usage logs. You can create one data feed per AWS account. For more information, -// see Spot Instance Data Feed (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-data-feeds.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) CreateSpotDatafeedSubscription(input *CreateSpotDatafeedSubscriptionInput) (*CreateSpotDatafeedSubscriptionOutput, error) { - req, out := c.CreateSpotDatafeedSubscriptionRequest(input) - err := req.Send() - return out, err -} - -const opCreateSubnet = "CreateSubnet" - -// CreateSubnetRequest generates a request for the CreateSubnet operation. -func (c *EC2) CreateSubnetRequest(input *CreateSubnetInput) (req *request.Request, output *CreateSubnetOutput) { - op := &request.Operation{ - Name: opCreateSubnet, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateSubnetInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateSubnetOutput{} - req.Data = output - return -} - -// Creates a subnet in an existing VPC. -// -// When you create each subnet, you provide the VPC ID and the CIDR block you -// want for the subnet. After you create a subnet, you can't change its CIDR -// block. The subnet's CIDR block can be the same as the VPC's CIDR block (assuming -// you want only a single subnet in the VPC), or a subset of the VPC's CIDR -// block. If you create more than one subnet in a VPC, the subnets' CIDR blocks -// must not overlap. The smallest subnet (and VPC) you can create uses a /28 -// netmask (16 IP addresses), and the largest uses a /16 netmask (65,536 IP -// addresses). -// -// AWS reserves both the first four and the last IP address in each subnet's -// CIDR block. They're not available for use. -// -// If you add more than one subnet to a VPC, they're set up in a star topology -// with a logical router in the middle. -// -// If you launch an instance in a VPC using an Amazon EBS-backed AMI, the IP -// address doesn't change if you stop and restart the instance (unlike a similar -// instance launched outside a VPC, which gets a new IP address when restarted). -// It's therefore possible to have a subnet with no running instances (they're -// all stopped), but no remaining IP addresses available. -// -// For more information about subnets, see Your VPC and Subnets (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Subnets.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) CreateSubnet(input *CreateSubnetInput) (*CreateSubnetOutput, error) { - req, out := c.CreateSubnetRequest(input) - err := req.Send() - return out, err -} - -const opCreateTags = "CreateTags" - -// CreateTagsRequest generates a request for the CreateTags operation. -func (c *EC2) CreateTagsRequest(input *CreateTagsInput) (req *request.Request, output *CreateTagsOutput) { - op := &request.Operation{ - Name: opCreateTags, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateTagsInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateTagsOutput{} - req.Data = output - return -} - -// Adds or overwrites one or more tags for the specified Amazon EC2 resource -// or resources. Each resource can have a maximum of 10 tags. Each tag consists -// of a key and optional value. Tag keys must be unique per resource. -// -// For more information about tags, see Tagging Your Resources (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html) -// in the Amazon Elastic Compute Cloud User Guide. For more information about -// creating IAM policies that control users' access to resources based on tags, -// see Supported Resource-Level Permissions for Amazon EC2 API Actions (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-supported-iam-actions-resources.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) CreateTags(input *CreateTagsInput) (*CreateTagsOutput, error) { - req, out := c.CreateTagsRequest(input) - err := req.Send() - return out, err -} - -const opCreateVolume = "CreateVolume" - -// CreateVolumeRequest generates a request for the CreateVolume operation. -func (c *EC2) CreateVolumeRequest(input *CreateVolumeInput) (req *request.Request, output *Volume) { - op := &request.Operation{ - Name: opCreateVolume, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateVolumeInput{} - } - - req = c.newRequest(op, input, output) - output = &Volume{} - req.Data = output - return -} - -// Creates an EBS volume that can be attached to an instance in the same Availability -// Zone. The volume is created in the regional endpoint that you send the HTTP -// request to. For more information see Regions and Endpoints (http://docs.aws.amazon.com/general/latest/gr/rande.html). -// -// You can create a new empty volume or restore a volume from an EBS snapshot. -// Any AWS Marketplace product codes from the snapshot are propagated to the -// volume. -// -// You can create encrypted volumes with the Encrypted parameter. Encrypted -// volumes may only be attached to instances that support Amazon EBS encryption. -// Volumes that are created from encrypted snapshots are also automatically -// encrypted. For more information, see Amazon EBS Encryption (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html) -// in the Amazon Elastic Compute Cloud User Guide. -// -// For more information, see Creating or Restoring an Amazon EBS Volume (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-creating-volume.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) CreateVolume(input *CreateVolumeInput) (*Volume, error) { - req, out := c.CreateVolumeRequest(input) - err := req.Send() - return out, err -} - -const opCreateVpc = "CreateVpc" - -// CreateVpcRequest generates a request for the CreateVpc operation. -func (c *EC2) CreateVpcRequest(input *CreateVpcInput) (req *request.Request, output *CreateVpcOutput) { - op := &request.Operation{ - Name: opCreateVpc, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateVpcInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateVpcOutput{} - req.Data = output - return -} - -// Creates a VPC with the specified CIDR block. -// -// The smallest VPC you can create uses a /28 netmask (16 IP addresses), and -// the largest uses a /16 netmask (65,536 IP addresses). To help you decide -// how big to make your VPC, see Your VPC and Subnets (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Subnets.html) -// in the Amazon Virtual Private Cloud User Guide. -// -// By default, each instance you launch in the VPC has the default DHCP options, -// which includes only a default DNS server that we provide (AmazonProvidedDNS). -// For more information about DHCP options, see DHCP Options Sets (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_DHCP_Options.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) CreateVpc(input *CreateVpcInput) (*CreateVpcOutput, error) { - req, out := c.CreateVpcRequest(input) - err := req.Send() - return out, err -} - -const opCreateVpcEndpoint = "CreateVpcEndpoint" - -// CreateVpcEndpointRequest generates a request for the CreateVpcEndpoint operation. -func (c *EC2) CreateVpcEndpointRequest(input *CreateVpcEndpointInput) (req *request.Request, output *CreateVpcEndpointOutput) { - op := &request.Operation{ - Name: opCreateVpcEndpoint, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateVpcEndpointInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateVpcEndpointOutput{} - req.Data = output - return -} - -// Creates a VPC endpoint for a specified AWS service. An endpoint enables you -// to create a private connection between your VPC and another AWS service in -// your account. You can specify an endpoint policy to attach to the endpoint -// that will control access to the service from your VPC. You can also specify -// the VPC route tables that use the endpoint. -// -// Currently, only endpoints to Amazon S3 are supported. -func (c *EC2) CreateVpcEndpoint(input *CreateVpcEndpointInput) (*CreateVpcEndpointOutput, error) { - req, out := c.CreateVpcEndpointRequest(input) - err := req.Send() - return out, err -} - -const opCreateVpcPeeringConnection = "CreateVpcPeeringConnection" - -// CreateVpcPeeringConnectionRequest generates a request for the CreateVpcPeeringConnection operation. -func (c *EC2) CreateVpcPeeringConnectionRequest(input *CreateVpcPeeringConnectionInput) (req *request.Request, output *CreateVpcPeeringConnectionOutput) { - op := &request.Operation{ - Name: opCreateVpcPeeringConnection, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateVpcPeeringConnectionInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateVpcPeeringConnectionOutput{} - req.Data = output - return -} - -// Requests a VPC peering connection between two VPCs: a requester VPC that -// you own and a peer VPC with which to create the connection. The peer VPC -// can belong to another AWS account. The requester VPC and peer VPC cannot -// have overlapping CIDR blocks. -// -// The owner of the peer VPC must accept the peering request to activate the -// peering connection. The VPC peering connection request expires after 7 days, -// after which it cannot be accepted or rejected. -// -// A CreateVpcPeeringConnection request between VPCs with overlapping CIDR -// blocks results in the VPC peering connection having a status of failed. -func (c *EC2) CreateVpcPeeringConnection(input *CreateVpcPeeringConnectionInput) (*CreateVpcPeeringConnectionOutput, error) { - req, out := c.CreateVpcPeeringConnectionRequest(input) - err := req.Send() - return out, err -} - -const opCreateVpnConnection = "CreateVpnConnection" - -// CreateVpnConnectionRequest generates a request for the CreateVpnConnection operation. -func (c *EC2) CreateVpnConnectionRequest(input *CreateVpnConnectionInput) (req *request.Request, output *CreateVpnConnectionOutput) { - op := &request.Operation{ - Name: opCreateVpnConnection, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateVpnConnectionInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateVpnConnectionOutput{} - req.Data = output - return -} - -// Creates a VPN connection between an existing virtual private gateway and -// a VPN customer gateway. The only supported connection type is ipsec.1. -// -// The response includes information that you need to give to your network -// administrator to configure your customer gateway. -// -// We strongly recommend that you use HTTPS when calling this operation because -// the response contains sensitive cryptographic information for configuring -// your customer gateway. -// -// If you decide to shut down your VPN connection for any reason and later -// create a new VPN connection, you must reconfigure your customer gateway with -// the new information returned from this call. -// -// For more information about VPN connections, see Adding a Hardware Virtual -// Private Gateway to Your VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_VPN.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) CreateVpnConnection(input *CreateVpnConnectionInput) (*CreateVpnConnectionOutput, error) { - req, out := c.CreateVpnConnectionRequest(input) - err := req.Send() - return out, err -} - -const opCreateVpnConnectionRoute = "CreateVpnConnectionRoute" - -// CreateVpnConnectionRouteRequest generates a request for the CreateVpnConnectionRoute operation. -func (c *EC2) CreateVpnConnectionRouteRequest(input *CreateVpnConnectionRouteInput) (req *request.Request, output *CreateVpnConnectionRouteOutput) { - op := &request.Operation{ - Name: opCreateVpnConnectionRoute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateVpnConnectionRouteInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateVpnConnectionRouteOutput{} - req.Data = output - return -} - -// Creates a static route associated with a VPN connection between an existing -// virtual private gateway and a VPN customer gateway. The static route allows -// traffic to be routed from the virtual private gateway to the VPN customer -// gateway. -// -// For more information about VPN connections, see Adding a Hardware Virtual -// Private Gateway to Your VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_VPN.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) CreateVpnConnectionRoute(input *CreateVpnConnectionRouteInput) (*CreateVpnConnectionRouteOutput, error) { - req, out := c.CreateVpnConnectionRouteRequest(input) - err := req.Send() - return out, err -} - -const opCreateVpnGateway = "CreateVpnGateway" - -// CreateVpnGatewayRequest generates a request for the CreateVpnGateway operation. -func (c *EC2) CreateVpnGatewayRequest(input *CreateVpnGatewayInput) (req *request.Request, output *CreateVpnGatewayOutput) { - op := &request.Operation{ - Name: opCreateVpnGateway, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &CreateVpnGatewayInput{} - } - - req = c.newRequest(op, input, output) - output = &CreateVpnGatewayOutput{} - req.Data = output - return -} - -// Creates a virtual private gateway. A virtual private gateway is the endpoint -// on the VPC side of your VPN connection. You can create a virtual private -// gateway before creating the VPC itself. -// -// For more information about virtual private gateways, see Adding a Hardware -// Virtual Private Gateway to Your VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_VPN.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) CreateVpnGateway(input *CreateVpnGatewayInput) (*CreateVpnGatewayOutput, error) { - req, out := c.CreateVpnGatewayRequest(input) - err := req.Send() - return out, err -} - -const opDeleteCustomerGateway = "DeleteCustomerGateway" - -// DeleteCustomerGatewayRequest generates a request for the DeleteCustomerGateway operation. -func (c *EC2) DeleteCustomerGatewayRequest(input *DeleteCustomerGatewayInput) (req *request.Request, output *DeleteCustomerGatewayOutput) { - op := &request.Operation{ - Name: opDeleteCustomerGateway, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteCustomerGatewayInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteCustomerGatewayOutput{} - req.Data = output - return -} - -// Deletes the specified customer gateway. You must delete the VPN connection -// before you can delete the customer gateway. -func (c *EC2) DeleteCustomerGateway(input *DeleteCustomerGatewayInput) (*DeleteCustomerGatewayOutput, error) { - req, out := c.DeleteCustomerGatewayRequest(input) - err := req.Send() - return out, err -} - -const opDeleteDhcpOptions = "DeleteDhcpOptions" - -// DeleteDhcpOptionsRequest generates a request for the DeleteDhcpOptions operation. -func (c *EC2) DeleteDhcpOptionsRequest(input *DeleteDhcpOptionsInput) (req *request.Request, output *DeleteDhcpOptionsOutput) { - op := &request.Operation{ - Name: opDeleteDhcpOptions, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteDhcpOptionsInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteDhcpOptionsOutput{} - req.Data = output - return -} - -// Deletes the specified set of DHCP options. You must disassociate the set -// of DHCP options before you can delete it. You can disassociate the set of -// DHCP options by associating either a new set of options or the default set -// of options with the VPC. -func (c *EC2) DeleteDhcpOptions(input *DeleteDhcpOptionsInput) (*DeleteDhcpOptionsOutput, error) { - req, out := c.DeleteDhcpOptionsRequest(input) - err := req.Send() - return out, err -} - -const opDeleteFlowLogs = "DeleteFlowLogs" - -// DeleteFlowLogsRequest generates a request for the DeleteFlowLogs operation. -func (c *EC2) DeleteFlowLogsRequest(input *DeleteFlowLogsInput) (req *request.Request, output *DeleteFlowLogsOutput) { - op := &request.Operation{ - Name: opDeleteFlowLogs, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteFlowLogsInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteFlowLogsOutput{} - req.Data = output - return -} - -// Deletes one or more flow logs. -func (c *EC2) DeleteFlowLogs(input *DeleteFlowLogsInput) (*DeleteFlowLogsOutput, error) { - req, out := c.DeleteFlowLogsRequest(input) - err := req.Send() - return out, err -} - -const opDeleteInternetGateway = "DeleteInternetGateway" - -// DeleteInternetGatewayRequest generates a request for the DeleteInternetGateway operation. -func (c *EC2) DeleteInternetGatewayRequest(input *DeleteInternetGatewayInput) (req *request.Request, output *DeleteInternetGatewayOutput) { - op := &request.Operation{ - Name: opDeleteInternetGateway, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteInternetGatewayInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteInternetGatewayOutput{} - req.Data = output - return -} - -// Deletes the specified Internet gateway. You must detach the Internet gateway -// from the VPC before you can delete it. -func (c *EC2) DeleteInternetGateway(input *DeleteInternetGatewayInput) (*DeleteInternetGatewayOutput, error) { - req, out := c.DeleteInternetGatewayRequest(input) - err := req.Send() - return out, err -} - -const opDeleteKeyPair = "DeleteKeyPair" - -// DeleteKeyPairRequest generates a request for the DeleteKeyPair operation. -func (c *EC2) DeleteKeyPairRequest(input *DeleteKeyPairInput) (req *request.Request, output *DeleteKeyPairOutput) { - op := &request.Operation{ - Name: opDeleteKeyPair, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteKeyPairInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteKeyPairOutput{} - req.Data = output - return -} - -// Deletes the specified key pair, by removing the public key from Amazon EC2. -func (c *EC2) DeleteKeyPair(input *DeleteKeyPairInput) (*DeleteKeyPairOutput, error) { - req, out := c.DeleteKeyPairRequest(input) - err := req.Send() - return out, err -} - -const opDeleteNetworkAcl = "DeleteNetworkAcl" - -// DeleteNetworkAclRequest generates a request for the DeleteNetworkAcl operation. -func (c *EC2) DeleteNetworkAclRequest(input *DeleteNetworkAclInput) (req *request.Request, output *DeleteNetworkAclOutput) { - op := &request.Operation{ - Name: opDeleteNetworkAcl, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteNetworkAclInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteNetworkAclOutput{} - req.Data = output - return -} - -// Deletes the specified network ACL. You can't delete the ACL if it's associated -// with any subnets. You can't delete the default network ACL. -func (c *EC2) DeleteNetworkAcl(input *DeleteNetworkAclInput) (*DeleteNetworkAclOutput, error) { - req, out := c.DeleteNetworkAclRequest(input) - err := req.Send() - return out, err -} - -const opDeleteNetworkAclEntry = "DeleteNetworkAclEntry" - -// DeleteNetworkAclEntryRequest generates a request for the DeleteNetworkAclEntry operation. -func (c *EC2) DeleteNetworkAclEntryRequest(input *DeleteNetworkAclEntryInput) (req *request.Request, output *DeleteNetworkAclEntryOutput) { - op := &request.Operation{ - Name: opDeleteNetworkAclEntry, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteNetworkAclEntryInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteNetworkAclEntryOutput{} - req.Data = output - return -} - -// Deletes the specified ingress or egress entry (rule) from the specified network -// ACL. -func (c *EC2) DeleteNetworkAclEntry(input *DeleteNetworkAclEntryInput) (*DeleteNetworkAclEntryOutput, error) { - req, out := c.DeleteNetworkAclEntryRequest(input) - err := req.Send() - return out, err -} - -const opDeleteNetworkInterface = "DeleteNetworkInterface" - -// DeleteNetworkInterfaceRequest generates a request for the DeleteNetworkInterface operation. -func (c *EC2) DeleteNetworkInterfaceRequest(input *DeleteNetworkInterfaceInput) (req *request.Request, output *DeleteNetworkInterfaceOutput) { - op := &request.Operation{ - Name: opDeleteNetworkInterface, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteNetworkInterfaceInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteNetworkInterfaceOutput{} - req.Data = output - return -} - -// Deletes the specified network interface. You must detach the network interface -// before you can delete it. -func (c *EC2) DeleteNetworkInterface(input *DeleteNetworkInterfaceInput) (*DeleteNetworkInterfaceOutput, error) { - req, out := c.DeleteNetworkInterfaceRequest(input) - err := req.Send() - return out, err -} - -const opDeletePlacementGroup = "DeletePlacementGroup" - -// DeletePlacementGroupRequest generates a request for the DeletePlacementGroup operation. -func (c *EC2) DeletePlacementGroupRequest(input *DeletePlacementGroupInput) (req *request.Request, output *DeletePlacementGroupOutput) { - op := &request.Operation{ - Name: opDeletePlacementGroup, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeletePlacementGroupInput{} - } - - req = c.newRequest(op, input, output) - output = &DeletePlacementGroupOutput{} - req.Data = output - return -} - -// Deletes the specified placement group. You must terminate all instances in -// the placement group before you can delete the placement group. For more information -// about placement groups and cluster instances, see Cluster Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using_cluster_computing.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) DeletePlacementGroup(input *DeletePlacementGroupInput) (*DeletePlacementGroupOutput, error) { - req, out := c.DeletePlacementGroupRequest(input) - err := req.Send() - return out, err -} - -const opDeleteRoute = "DeleteRoute" - -// DeleteRouteRequest generates a request for the DeleteRoute operation. -func (c *EC2) DeleteRouteRequest(input *DeleteRouteInput) (req *request.Request, output *DeleteRouteOutput) { - op := &request.Operation{ - Name: opDeleteRoute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteRouteInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteRouteOutput{} - req.Data = output - return -} - -// Deletes the specified route from the specified route table. -func (c *EC2) DeleteRoute(input *DeleteRouteInput) (*DeleteRouteOutput, error) { - req, out := c.DeleteRouteRequest(input) - err := req.Send() - return out, err -} - -const opDeleteRouteTable = "DeleteRouteTable" - -// DeleteRouteTableRequest generates a request for the DeleteRouteTable operation. -func (c *EC2) DeleteRouteTableRequest(input *DeleteRouteTableInput) (req *request.Request, output *DeleteRouteTableOutput) { - op := &request.Operation{ - Name: opDeleteRouteTable, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteRouteTableInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteRouteTableOutput{} - req.Data = output - return -} - -// Deletes the specified route table. You must disassociate the route table -// from any subnets before you can delete it. You can't delete the main route -// table. -func (c *EC2) DeleteRouteTable(input *DeleteRouteTableInput) (*DeleteRouteTableOutput, error) { - req, out := c.DeleteRouteTableRequest(input) - err := req.Send() - return out, err -} - -const opDeleteSecurityGroup = "DeleteSecurityGroup" - -// DeleteSecurityGroupRequest generates a request for the DeleteSecurityGroup operation. -func (c *EC2) DeleteSecurityGroupRequest(input *DeleteSecurityGroupInput) (req *request.Request, output *DeleteSecurityGroupOutput) { - op := &request.Operation{ - Name: opDeleteSecurityGroup, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteSecurityGroupInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteSecurityGroupOutput{} - req.Data = output - return -} - -// Deletes a security group. -// -// If you attempt to delete a security group that is associated with an instance, -// or is referenced by another security group, the operation fails with InvalidGroup.InUse -// in EC2-Classic or DependencyViolation in EC2-VPC. -func (c *EC2) DeleteSecurityGroup(input *DeleteSecurityGroupInput) (*DeleteSecurityGroupOutput, error) { - req, out := c.DeleteSecurityGroupRequest(input) - err := req.Send() - return out, err -} - -const opDeleteSnapshot = "DeleteSnapshot" - -// DeleteSnapshotRequest generates a request for the DeleteSnapshot operation. -func (c *EC2) DeleteSnapshotRequest(input *DeleteSnapshotInput) (req *request.Request, output *DeleteSnapshotOutput) { - op := &request.Operation{ - Name: opDeleteSnapshot, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteSnapshotInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteSnapshotOutput{} - req.Data = output - return -} - -// Deletes the specified snapshot. -// -// When you make periodic snapshots of a volume, the snapshots are incremental, -// and only the blocks on the device that have changed since your last snapshot -// are saved in the new snapshot. When you delete a snapshot, only the data -// not needed for any other snapshot is removed. So regardless of which prior -// snapshots have been deleted, all active snapshots will have access to all -// the information needed to restore the volume. -// -// You cannot delete a snapshot of the root device of an EBS volume used by -// a registered AMI. You must first de-register the AMI before you can delete -// the snapshot. -// -// For more information, see Deleting an Amazon EBS Snapshot (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-deleting-snapshot.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) DeleteSnapshot(input *DeleteSnapshotInput) (*DeleteSnapshotOutput, error) { - req, out := c.DeleteSnapshotRequest(input) - err := req.Send() - return out, err -} - -const opDeleteSpotDatafeedSubscription = "DeleteSpotDatafeedSubscription" - -// DeleteSpotDatafeedSubscriptionRequest generates a request for the DeleteSpotDatafeedSubscription operation. -func (c *EC2) DeleteSpotDatafeedSubscriptionRequest(input *DeleteSpotDatafeedSubscriptionInput) (req *request.Request, output *DeleteSpotDatafeedSubscriptionOutput) { - op := &request.Operation{ - Name: opDeleteSpotDatafeedSubscription, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteSpotDatafeedSubscriptionInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteSpotDatafeedSubscriptionOutput{} - req.Data = output - return -} - -// Deletes the data feed for Spot instances. -func (c *EC2) DeleteSpotDatafeedSubscription(input *DeleteSpotDatafeedSubscriptionInput) (*DeleteSpotDatafeedSubscriptionOutput, error) { - req, out := c.DeleteSpotDatafeedSubscriptionRequest(input) - err := req.Send() - return out, err -} - -const opDeleteSubnet = "DeleteSubnet" - -// DeleteSubnetRequest generates a request for the DeleteSubnet operation. -func (c *EC2) DeleteSubnetRequest(input *DeleteSubnetInput) (req *request.Request, output *DeleteSubnetOutput) { - op := &request.Operation{ - Name: opDeleteSubnet, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteSubnetInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteSubnetOutput{} - req.Data = output - return -} - -// Deletes the specified subnet. You must terminate all running instances in -// the subnet before you can delete the subnet. -func (c *EC2) DeleteSubnet(input *DeleteSubnetInput) (*DeleteSubnetOutput, error) { - req, out := c.DeleteSubnetRequest(input) - err := req.Send() - return out, err -} - -const opDeleteTags = "DeleteTags" - -// DeleteTagsRequest generates a request for the DeleteTags operation. -func (c *EC2) DeleteTagsRequest(input *DeleteTagsInput) (req *request.Request, output *DeleteTagsOutput) { - op := &request.Operation{ - Name: opDeleteTags, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteTagsInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteTagsOutput{} - req.Data = output - return -} - -// Deletes the specified set of tags from the specified set of resources. This -// call is designed to follow a DescribeTags request. -// -// For more information about tags, see Tagging Your Resources (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) DeleteTags(input *DeleteTagsInput) (*DeleteTagsOutput, error) { - req, out := c.DeleteTagsRequest(input) - err := req.Send() - return out, err -} - -const opDeleteVolume = "DeleteVolume" - -// DeleteVolumeRequest generates a request for the DeleteVolume operation. -func (c *EC2) DeleteVolumeRequest(input *DeleteVolumeInput) (req *request.Request, output *DeleteVolumeOutput) { - op := &request.Operation{ - Name: opDeleteVolume, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteVolumeInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteVolumeOutput{} - req.Data = output - return -} - -// Deletes the specified EBS volume. The volume must be in the available state -// (not attached to an instance). -// -// The volume may remain in the deleting state for several minutes. -// -// For more information, see Deleting an Amazon EBS Volume (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-deleting-volume.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) DeleteVolume(input *DeleteVolumeInput) (*DeleteVolumeOutput, error) { - req, out := c.DeleteVolumeRequest(input) - err := req.Send() - return out, err -} - -const opDeleteVpc = "DeleteVpc" - -// DeleteVpcRequest generates a request for the DeleteVpc operation. -func (c *EC2) DeleteVpcRequest(input *DeleteVpcInput) (req *request.Request, output *DeleteVpcOutput) { - op := &request.Operation{ - Name: opDeleteVpc, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteVpcInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteVpcOutput{} - req.Data = output - return -} - -// Deletes the specified VPC. You must detach or delete all gateways and resources -// that are associated with the VPC before you can delete it. For example, you -// must terminate all instances running in the VPC, delete all security groups -// associated with the VPC (except the default one), delete all route tables -// associated with the VPC (except the default one), and so on. -func (c *EC2) DeleteVpc(input *DeleteVpcInput) (*DeleteVpcOutput, error) { - req, out := c.DeleteVpcRequest(input) - err := req.Send() - return out, err -} - -const opDeleteVpcEndpoints = "DeleteVpcEndpoints" - -// DeleteVpcEndpointsRequest generates a request for the DeleteVpcEndpoints operation. -func (c *EC2) DeleteVpcEndpointsRequest(input *DeleteVpcEndpointsInput) (req *request.Request, output *DeleteVpcEndpointsOutput) { - op := &request.Operation{ - Name: opDeleteVpcEndpoints, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteVpcEndpointsInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteVpcEndpointsOutput{} - req.Data = output - return -} - -// Deletes one or more specified VPC endpoints. Deleting the endpoint also deletes -// the endpoint routes in the route tables that were associated with the endpoint. -func (c *EC2) DeleteVpcEndpoints(input *DeleteVpcEndpointsInput) (*DeleteVpcEndpointsOutput, error) { - req, out := c.DeleteVpcEndpointsRequest(input) - err := req.Send() - return out, err -} - -const opDeleteVpcPeeringConnection = "DeleteVpcPeeringConnection" - -// DeleteVpcPeeringConnectionRequest generates a request for the DeleteVpcPeeringConnection operation. -func (c *EC2) DeleteVpcPeeringConnectionRequest(input *DeleteVpcPeeringConnectionInput) (req *request.Request, output *DeleteVpcPeeringConnectionOutput) { - op := &request.Operation{ - Name: opDeleteVpcPeeringConnection, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteVpcPeeringConnectionInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteVpcPeeringConnectionOutput{} - req.Data = output - return -} - -// Deletes a VPC peering connection. Either the owner of the requester VPC or -// the owner of the peer VPC can delete the VPC peering connection if it's in -// the active state. The owner of the requester VPC can delete a VPC peering -// connection in the pending-acceptance state. -func (c *EC2) DeleteVpcPeeringConnection(input *DeleteVpcPeeringConnectionInput) (*DeleteVpcPeeringConnectionOutput, error) { - req, out := c.DeleteVpcPeeringConnectionRequest(input) - err := req.Send() - return out, err -} - -const opDeleteVpnConnection = "DeleteVpnConnection" - -// DeleteVpnConnectionRequest generates a request for the DeleteVpnConnection operation. -func (c *EC2) DeleteVpnConnectionRequest(input *DeleteVpnConnectionInput) (req *request.Request, output *DeleteVpnConnectionOutput) { - op := &request.Operation{ - Name: opDeleteVpnConnection, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteVpnConnectionInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteVpnConnectionOutput{} - req.Data = output - return -} - -// Deletes the specified VPN connection. -// -// If you're deleting the VPC and its associated components, we recommend that -// you detach the virtual private gateway from the VPC and delete the VPC before -// deleting the VPN connection. If you believe that the tunnel credentials for -// your VPN connection have been compromised, you can delete the VPN connection -// and create a new one that has new keys, without needing to delete the VPC -// or virtual private gateway. If you create a new VPN connection, you must -// reconfigure the customer gateway using the new configuration information -// returned with the new VPN connection ID. -func (c *EC2) DeleteVpnConnection(input *DeleteVpnConnectionInput) (*DeleteVpnConnectionOutput, error) { - req, out := c.DeleteVpnConnectionRequest(input) - err := req.Send() - return out, err -} - -const opDeleteVpnConnectionRoute = "DeleteVpnConnectionRoute" - -// DeleteVpnConnectionRouteRequest generates a request for the DeleteVpnConnectionRoute operation. -func (c *EC2) DeleteVpnConnectionRouteRequest(input *DeleteVpnConnectionRouteInput) (req *request.Request, output *DeleteVpnConnectionRouteOutput) { - op := &request.Operation{ - Name: opDeleteVpnConnectionRoute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteVpnConnectionRouteInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteVpnConnectionRouteOutput{} - req.Data = output - return -} - -// Deletes the specified static route associated with a VPN connection between -// an existing virtual private gateway and a VPN customer gateway. The static -// route allows traffic to be routed from the virtual private gateway to the -// VPN customer gateway. -func (c *EC2) DeleteVpnConnectionRoute(input *DeleteVpnConnectionRouteInput) (*DeleteVpnConnectionRouteOutput, error) { - req, out := c.DeleteVpnConnectionRouteRequest(input) - err := req.Send() - return out, err -} - -const opDeleteVpnGateway = "DeleteVpnGateway" - -// DeleteVpnGatewayRequest generates a request for the DeleteVpnGateway operation. -func (c *EC2) DeleteVpnGatewayRequest(input *DeleteVpnGatewayInput) (req *request.Request, output *DeleteVpnGatewayOutput) { - op := &request.Operation{ - Name: opDeleteVpnGateway, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeleteVpnGatewayInput{} - } - - req = c.newRequest(op, input, output) - output = &DeleteVpnGatewayOutput{} - req.Data = output - return -} - -// Deletes the specified virtual private gateway. We recommend that before you -// delete a virtual private gateway, you detach it from the VPC and delete the -// VPN connection. Note that you don't need to delete the virtual private gateway -// if you plan to delete and recreate the VPN connection between your VPC and -// your network. -func (c *EC2) DeleteVpnGateway(input *DeleteVpnGatewayInput) (*DeleteVpnGatewayOutput, error) { - req, out := c.DeleteVpnGatewayRequest(input) - err := req.Send() - return out, err -} - -const opDeregisterImage = "DeregisterImage" - -// DeregisterImageRequest generates a request for the DeregisterImage operation. -func (c *EC2) DeregisterImageRequest(input *DeregisterImageInput) (req *request.Request, output *DeregisterImageOutput) { - op := &request.Operation{ - Name: opDeregisterImage, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DeregisterImageInput{} - } - - req = c.newRequest(op, input, output) - output = &DeregisterImageOutput{} - req.Data = output - return -} - -// Deregisters the specified AMI. After you deregister an AMI, it can't be used -// to launch new instances. -// -// This command does not delete the AMI. -func (c *EC2) DeregisterImage(input *DeregisterImageInput) (*DeregisterImageOutput, error) { - req, out := c.DeregisterImageRequest(input) - err := req.Send() - return out, err -} - -const opDescribeAccountAttributes = "DescribeAccountAttributes" - -// DescribeAccountAttributesRequest generates a request for the DescribeAccountAttributes operation. -func (c *EC2) DescribeAccountAttributesRequest(input *DescribeAccountAttributesInput) (req *request.Request, output *DescribeAccountAttributesOutput) { - op := &request.Operation{ - Name: opDescribeAccountAttributes, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeAccountAttributesInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeAccountAttributesOutput{} - req.Data = output - return -} - -// Describes attributes of your AWS account. The following are the supported -// account attributes: -// -// supported-platforms: Indicates whether your account can launch instances -// into EC2-Classic and EC2-VPC, or only into EC2-VPC. -// -// default-vpc: The ID of the default VPC for your account, or none. -// -// max-instances: The maximum number of On-Demand instances that you can -// run. -// -// vpc-max-security-groups-per-interface: The maximum number of security -// groups that you can assign to a network interface. -// -// max-elastic-ips: The maximum number of Elastic IP addresses that you can -// allocate for use with EC2-Classic. -// -// vpc-max-elastic-ips: The maximum number of Elastic IP addresses that you -// can allocate for use with EC2-VPC. -func (c *EC2) DescribeAccountAttributes(input *DescribeAccountAttributesInput) (*DescribeAccountAttributesOutput, error) { - req, out := c.DescribeAccountAttributesRequest(input) - err := req.Send() - return out, err -} - -const opDescribeAddresses = "DescribeAddresses" - -// DescribeAddressesRequest generates a request for the DescribeAddresses operation. -func (c *EC2) DescribeAddressesRequest(input *DescribeAddressesInput) (req *request.Request, output *DescribeAddressesOutput) { - op := &request.Operation{ - Name: opDescribeAddresses, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeAddressesInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeAddressesOutput{} - req.Data = output - return -} - -// Describes one or more of your Elastic IP addresses. -// -// An Elastic IP address is for use in either the EC2-Classic platform or in -// a VPC. For more information, see Elastic IP Addresses (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) DescribeAddresses(input *DescribeAddressesInput) (*DescribeAddressesOutput, error) { - req, out := c.DescribeAddressesRequest(input) - err := req.Send() - return out, err -} - -const opDescribeAvailabilityZones = "DescribeAvailabilityZones" - -// DescribeAvailabilityZonesRequest generates a request for the DescribeAvailabilityZones operation. -func (c *EC2) DescribeAvailabilityZonesRequest(input *DescribeAvailabilityZonesInput) (req *request.Request, output *DescribeAvailabilityZonesOutput) { - op := &request.Operation{ - Name: opDescribeAvailabilityZones, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeAvailabilityZonesInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeAvailabilityZonesOutput{} - req.Data = output - return -} - -// Describes one or more of the Availability Zones that are available to you. -// The results include zones only for the region you're currently using. If -// there is an event impacting an Availability Zone, you can use this request -// to view the state and any provided message for that Availability Zone. -// -// For more information, see Regions and Availability Zones (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) DescribeAvailabilityZones(input *DescribeAvailabilityZonesInput) (*DescribeAvailabilityZonesOutput, error) { - req, out := c.DescribeAvailabilityZonesRequest(input) - err := req.Send() - return out, err -} - -const opDescribeBundleTasks = "DescribeBundleTasks" - -// DescribeBundleTasksRequest generates a request for the DescribeBundleTasks operation. -func (c *EC2) DescribeBundleTasksRequest(input *DescribeBundleTasksInput) (req *request.Request, output *DescribeBundleTasksOutput) { - op := &request.Operation{ - Name: opDescribeBundleTasks, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeBundleTasksInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeBundleTasksOutput{} - req.Data = output - return -} - -// Describes one or more of your bundling tasks. -// -// Completed bundle tasks are listed for only a limited time. If your bundle -// task is no longer in the list, you can still register an AMI from it. Just -// use RegisterImage with the Amazon S3 bucket name and image manifest name -// you provided to the bundle task. -func (c *EC2) DescribeBundleTasks(input *DescribeBundleTasksInput) (*DescribeBundleTasksOutput, error) { - req, out := c.DescribeBundleTasksRequest(input) - err := req.Send() - return out, err -} - -const opDescribeClassicLinkInstances = "DescribeClassicLinkInstances" - -// DescribeClassicLinkInstancesRequest generates a request for the DescribeClassicLinkInstances operation. -func (c *EC2) DescribeClassicLinkInstancesRequest(input *DescribeClassicLinkInstancesInput) (req *request.Request, output *DescribeClassicLinkInstancesOutput) { - op := &request.Operation{ - Name: opDescribeClassicLinkInstances, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeClassicLinkInstancesInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeClassicLinkInstancesOutput{} - req.Data = output - return -} - -// Describes one or more of your linked EC2-Classic instances. This request -// only returns information about EC2-Classic instances linked to a VPC through -// ClassicLink; you cannot use this request to return information about other -// instances. -func (c *EC2) DescribeClassicLinkInstances(input *DescribeClassicLinkInstancesInput) (*DescribeClassicLinkInstancesOutput, error) { - req, out := c.DescribeClassicLinkInstancesRequest(input) - err := req.Send() - return out, err -} - -const opDescribeConversionTasks = "DescribeConversionTasks" - -// DescribeConversionTasksRequest generates a request for the DescribeConversionTasks operation. -func (c *EC2) DescribeConversionTasksRequest(input *DescribeConversionTasksInput) (req *request.Request, output *DescribeConversionTasksOutput) { - op := &request.Operation{ - Name: opDescribeConversionTasks, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeConversionTasksInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeConversionTasksOutput{} - req.Data = output - return -} - -// Describes one or more of your conversion tasks. For more information, see -// Using the Command Line Tools to Import Your Virtual Machine to Amazon EC2 -// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/UploadingYourInstancesandVolumes.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) DescribeConversionTasks(input *DescribeConversionTasksInput) (*DescribeConversionTasksOutput, error) { - req, out := c.DescribeConversionTasksRequest(input) - err := req.Send() - return out, err -} - -const opDescribeCustomerGateways = "DescribeCustomerGateways" - -// DescribeCustomerGatewaysRequest generates a request for the DescribeCustomerGateways operation. -func (c *EC2) DescribeCustomerGatewaysRequest(input *DescribeCustomerGatewaysInput) (req *request.Request, output *DescribeCustomerGatewaysOutput) { - op := &request.Operation{ - Name: opDescribeCustomerGateways, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeCustomerGatewaysInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeCustomerGatewaysOutput{} - req.Data = output - return -} - -// Describes one or more of your VPN customer gateways. -// -// For more information about VPN customer gateways, see Adding a Hardware -// Virtual Private Gateway to Your VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_VPN.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) DescribeCustomerGateways(input *DescribeCustomerGatewaysInput) (*DescribeCustomerGatewaysOutput, error) { - req, out := c.DescribeCustomerGatewaysRequest(input) - err := req.Send() - return out, err -} - -const opDescribeDhcpOptions = "DescribeDhcpOptions" - -// DescribeDhcpOptionsRequest generates a request for the DescribeDhcpOptions operation. -func (c *EC2) DescribeDhcpOptionsRequest(input *DescribeDhcpOptionsInput) (req *request.Request, output *DescribeDhcpOptionsOutput) { - op := &request.Operation{ - Name: opDescribeDhcpOptions, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeDhcpOptionsInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeDhcpOptionsOutput{} - req.Data = output - return -} - -// Describes one or more of your DHCP options sets. -// -// For more information about DHCP options sets, see DHCP Options Sets (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_DHCP_Options.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) DescribeDhcpOptions(input *DescribeDhcpOptionsInput) (*DescribeDhcpOptionsOutput, error) { - req, out := c.DescribeDhcpOptionsRequest(input) - err := req.Send() - return out, err -} - -const opDescribeExportTasks = "DescribeExportTasks" - -// DescribeExportTasksRequest generates a request for the DescribeExportTasks operation. -func (c *EC2) DescribeExportTasksRequest(input *DescribeExportTasksInput) (req *request.Request, output *DescribeExportTasksOutput) { - op := &request.Operation{ - Name: opDescribeExportTasks, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeExportTasksInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeExportTasksOutput{} - req.Data = output - return -} - -// Describes one or more of your export tasks. -func (c *EC2) DescribeExportTasks(input *DescribeExportTasksInput) (*DescribeExportTasksOutput, error) { - req, out := c.DescribeExportTasksRequest(input) - err := req.Send() - return out, err -} - -const opDescribeFlowLogs = "DescribeFlowLogs" - -// DescribeFlowLogsRequest generates a request for the DescribeFlowLogs operation. -func (c *EC2) DescribeFlowLogsRequest(input *DescribeFlowLogsInput) (req *request.Request, output *DescribeFlowLogsOutput) { - op := &request.Operation{ - Name: opDescribeFlowLogs, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeFlowLogsInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeFlowLogsOutput{} - req.Data = output - return -} - -// Describes one or more flow logs. To view the information in your flow logs -// (the log streams for the network interfaces), you must use the CloudWatch -// Logs console or the CloudWatch Logs API. -func (c *EC2) DescribeFlowLogs(input *DescribeFlowLogsInput) (*DescribeFlowLogsOutput, error) { - req, out := c.DescribeFlowLogsRequest(input) - err := req.Send() - return out, err -} - -const opDescribeImageAttribute = "DescribeImageAttribute" - -// DescribeImageAttributeRequest generates a request for the DescribeImageAttribute operation. -func (c *EC2) DescribeImageAttributeRequest(input *DescribeImageAttributeInput) (req *request.Request, output *DescribeImageAttributeOutput) { - op := &request.Operation{ - Name: opDescribeImageAttribute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeImageAttributeInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeImageAttributeOutput{} - req.Data = output - return -} - -// Describes the specified attribute of the specified AMI. You can specify only -// one attribute at a time. -func (c *EC2) DescribeImageAttribute(input *DescribeImageAttributeInput) (*DescribeImageAttributeOutput, error) { - req, out := c.DescribeImageAttributeRequest(input) - err := req.Send() - return out, err -} - -const opDescribeImages = "DescribeImages" - -// DescribeImagesRequest generates a request for the DescribeImages operation. -func (c *EC2) DescribeImagesRequest(input *DescribeImagesInput) (req *request.Request, output *DescribeImagesOutput) { - op := &request.Operation{ - Name: opDescribeImages, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeImagesInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeImagesOutput{} - req.Data = output - return -} - -// Describes one or more of the images (AMIs, AKIs, and ARIs) available to you. -// Images available to you include public images, private images that you own, -// and private images owned by other AWS accounts but for which you have explicit -// launch permissions. -// -// Deregistered images are included in the returned results for an unspecified -// interval after deregistration. -func (c *EC2) DescribeImages(input *DescribeImagesInput) (*DescribeImagesOutput, error) { - req, out := c.DescribeImagesRequest(input) - err := req.Send() - return out, err -} - -const opDescribeImportImageTasks = "DescribeImportImageTasks" - -// DescribeImportImageTasksRequest generates a request for the DescribeImportImageTasks operation. -func (c *EC2) DescribeImportImageTasksRequest(input *DescribeImportImageTasksInput) (req *request.Request, output *DescribeImportImageTasksOutput) { - op := &request.Operation{ - Name: opDescribeImportImageTasks, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeImportImageTasksInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeImportImageTasksOutput{} - req.Data = output - return -} - -// Displays details about an import virtual machine or import snapshot tasks -// that are already created. -func (c *EC2) DescribeImportImageTasks(input *DescribeImportImageTasksInput) (*DescribeImportImageTasksOutput, error) { - req, out := c.DescribeImportImageTasksRequest(input) - err := req.Send() - return out, err -} - -const opDescribeImportSnapshotTasks = "DescribeImportSnapshotTasks" - -// DescribeImportSnapshotTasksRequest generates a request for the DescribeImportSnapshotTasks operation. -func (c *EC2) DescribeImportSnapshotTasksRequest(input *DescribeImportSnapshotTasksInput) (req *request.Request, output *DescribeImportSnapshotTasksOutput) { - op := &request.Operation{ - Name: opDescribeImportSnapshotTasks, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeImportSnapshotTasksInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeImportSnapshotTasksOutput{} - req.Data = output - return -} - -// Describes your import snapshot tasks. -func (c *EC2) DescribeImportSnapshotTasks(input *DescribeImportSnapshotTasksInput) (*DescribeImportSnapshotTasksOutput, error) { - req, out := c.DescribeImportSnapshotTasksRequest(input) - err := req.Send() - return out, err -} - -const opDescribeInstanceAttribute = "DescribeInstanceAttribute" - -// DescribeInstanceAttributeRequest generates a request for the DescribeInstanceAttribute operation. -func (c *EC2) DescribeInstanceAttributeRequest(input *DescribeInstanceAttributeInput) (req *request.Request, output *DescribeInstanceAttributeOutput) { - op := &request.Operation{ - Name: opDescribeInstanceAttribute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeInstanceAttributeInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeInstanceAttributeOutput{} - req.Data = output - return -} - -// Describes the specified attribute of the specified instance. You can specify -// only one attribute at a time. Valid attribute values are: instanceType | -// kernel | ramdisk | userData | disableApiTermination | instanceInitiatedShutdownBehavior -// | rootDeviceName | blockDeviceMapping | productCodes | sourceDestCheck | -// groupSet | ebsOptimized | sriovNetSupport -func (c *EC2) DescribeInstanceAttribute(input *DescribeInstanceAttributeInput) (*DescribeInstanceAttributeOutput, error) { - req, out := c.DescribeInstanceAttributeRequest(input) - err := req.Send() - return out, err -} - -const opDescribeInstanceStatus = "DescribeInstanceStatus" - -// DescribeInstanceStatusRequest generates a request for the DescribeInstanceStatus operation. -func (c *EC2) DescribeInstanceStatusRequest(input *DescribeInstanceStatusInput) (req *request.Request, output *DescribeInstanceStatusOutput) { - op := &request.Operation{ - Name: opDescribeInstanceStatus, - HTTPMethod: "POST", - HTTPPath: "/", - Paginator: &request.Paginator{ - InputTokens: []string{"NextToken"}, - OutputTokens: []string{"NextToken"}, - LimitToken: "MaxResults", - TruncationToken: "", - }, - } - - if input == nil { - input = &DescribeInstanceStatusInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeInstanceStatusOutput{} - req.Data = output - return -} - -// Describes the status of one or more instances. -// -// Instance status includes the following components: -// -// Status checks - Amazon EC2 performs status checks on running EC2 instances -// to identify hardware and software issues. For more information, see Status -// Checks for Your Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-system-instance-status-check.html) -// and Troubleshooting Instances with Failed Status Checks (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/TroubleshootingInstances.html) -// in the Amazon Elastic Compute Cloud User Guide. -// -// Scheduled events - Amazon EC2 can schedule events (such as reboot, stop, -// or terminate) for your instances related to hardware issues, software updates, -// or system maintenance. For more information, see Scheduled Events for Your -// Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-instances-status-check_sched.html) -// in the Amazon Elastic Compute Cloud User Guide. -// -// Instance state - You can manage your instances from the moment you launch -// them through their termination. For more information, see Instance Lifecycle -// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) DescribeInstanceStatus(input *DescribeInstanceStatusInput) (*DescribeInstanceStatusOutput, error) { - req, out := c.DescribeInstanceStatusRequest(input) - err := req.Send() - return out, err -} - -func (c *EC2) DescribeInstanceStatusPages(input *DescribeInstanceStatusInput, fn func(p *DescribeInstanceStatusOutput, lastPage bool) (shouldContinue bool)) error { - page, _ := c.DescribeInstanceStatusRequest(input) - page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) - return page.EachPage(func(p interface{}, lastPage bool) bool { - return fn(p.(*DescribeInstanceStatusOutput), lastPage) - }) -} - -const opDescribeInstances = "DescribeInstances" - -// DescribeInstancesRequest generates a request for the DescribeInstances operation. -func (c *EC2) DescribeInstancesRequest(input *DescribeInstancesInput) (req *request.Request, output *DescribeInstancesOutput) { - op := &request.Operation{ - Name: opDescribeInstances, - HTTPMethod: "POST", - HTTPPath: "/", - Paginator: &request.Paginator{ - InputTokens: []string{"NextToken"}, - OutputTokens: []string{"NextToken"}, - LimitToken: "MaxResults", - TruncationToken: "", - }, - } - - if input == nil { - input = &DescribeInstancesInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeInstancesOutput{} - req.Data = output - return -} - -// Describes one or more of your instances. -// -// If you specify one or more instance IDs, Amazon EC2 returns information -// for those instances. If you do not specify instance IDs, Amazon EC2 returns -// information for all relevant instances. If you specify an instance ID that -// is not valid, an error is returned. If you specify an instance that you do -// not own, it is not included in the returned results. -// -// Recently terminated instances might appear in the returned results. This -// interval is usually less than one hour. -func (c *EC2) DescribeInstances(input *DescribeInstancesInput) (*DescribeInstancesOutput, error) { - req, out := c.DescribeInstancesRequest(input) - err := req.Send() - return out, err -} - -func (c *EC2) DescribeInstancesPages(input *DescribeInstancesInput, fn func(p *DescribeInstancesOutput, lastPage bool) (shouldContinue bool)) error { - page, _ := c.DescribeInstancesRequest(input) - page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) - return page.EachPage(func(p interface{}, lastPage bool) bool { - return fn(p.(*DescribeInstancesOutput), lastPage) - }) -} - -const opDescribeInternetGateways = "DescribeInternetGateways" - -// DescribeInternetGatewaysRequest generates a request for the DescribeInternetGateways operation. -func (c *EC2) DescribeInternetGatewaysRequest(input *DescribeInternetGatewaysInput) (req *request.Request, output *DescribeInternetGatewaysOutput) { - op := &request.Operation{ - Name: opDescribeInternetGateways, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeInternetGatewaysInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeInternetGatewaysOutput{} - req.Data = output - return -} - -// Describes one or more of your Internet gateways. -func (c *EC2) DescribeInternetGateways(input *DescribeInternetGatewaysInput) (*DescribeInternetGatewaysOutput, error) { - req, out := c.DescribeInternetGatewaysRequest(input) - err := req.Send() - return out, err -} - -const opDescribeKeyPairs = "DescribeKeyPairs" - -// DescribeKeyPairsRequest generates a request for the DescribeKeyPairs operation. -func (c *EC2) DescribeKeyPairsRequest(input *DescribeKeyPairsInput) (req *request.Request, output *DescribeKeyPairsOutput) { - op := &request.Operation{ - Name: opDescribeKeyPairs, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeKeyPairsInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeKeyPairsOutput{} - req.Data = output - return -} - -// Describes one or more of your key pairs. -// -// For more information about key pairs, see Key Pairs (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) DescribeKeyPairs(input *DescribeKeyPairsInput) (*DescribeKeyPairsOutput, error) { - req, out := c.DescribeKeyPairsRequest(input) - err := req.Send() - return out, err -} - -const opDescribeMovingAddresses = "DescribeMovingAddresses" - -// DescribeMovingAddressesRequest generates a request for the DescribeMovingAddresses operation. -func (c *EC2) DescribeMovingAddressesRequest(input *DescribeMovingAddressesInput) (req *request.Request, output *DescribeMovingAddressesOutput) { - op := &request.Operation{ - Name: opDescribeMovingAddresses, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeMovingAddressesInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeMovingAddressesOutput{} - req.Data = output - return -} - -// Describes your Elastic IP addresses that are being moved to the EC2-VPC platform, -// or that are being restored to the EC2-Classic platform. This request does -// not return information about any other Elastic IP addresses in your account. -func (c *EC2) DescribeMovingAddresses(input *DescribeMovingAddressesInput) (*DescribeMovingAddressesOutput, error) { - req, out := c.DescribeMovingAddressesRequest(input) - err := req.Send() - return out, err -} - -const opDescribeNetworkAcls = "DescribeNetworkAcls" - -// DescribeNetworkAclsRequest generates a request for the DescribeNetworkAcls operation. -func (c *EC2) DescribeNetworkAclsRequest(input *DescribeNetworkAclsInput) (req *request.Request, output *DescribeNetworkAclsOutput) { - op := &request.Operation{ - Name: opDescribeNetworkAcls, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeNetworkAclsInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeNetworkAclsOutput{} - req.Data = output - return -} - -// Describes one or more of your network ACLs. -// -// For more information about network ACLs, see Network ACLs (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_ACLs.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) DescribeNetworkAcls(input *DescribeNetworkAclsInput) (*DescribeNetworkAclsOutput, error) { - req, out := c.DescribeNetworkAclsRequest(input) - err := req.Send() - return out, err -} - -const opDescribeNetworkInterfaceAttribute = "DescribeNetworkInterfaceAttribute" - -// DescribeNetworkInterfaceAttributeRequest generates a request for the DescribeNetworkInterfaceAttribute operation. -func (c *EC2) DescribeNetworkInterfaceAttributeRequest(input *DescribeNetworkInterfaceAttributeInput) (req *request.Request, output *DescribeNetworkInterfaceAttributeOutput) { - op := &request.Operation{ - Name: opDescribeNetworkInterfaceAttribute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeNetworkInterfaceAttributeInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeNetworkInterfaceAttributeOutput{} - req.Data = output - return -} - -// Describes a network interface attribute. You can specify only one attribute -// at a time. -func (c *EC2) DescribeNetworkInterfaceAttribute(input *DescribeNetworkInterfaceAttributeInput) (*DescribeNetworkInterfaceAttributeOutput, error) { - req, out := c.DescribeNetworkInterfaceAttributeRequest(input) - err := req.Send() - return out, err -} - -const opDescribeNetworkInterfaces = "DescribeNetworkInterfaces" - -// DescribeNetworkInterfacesRequest generates a request for the DescribeNetworkInterfaces operation. -func (c *EC2) DescribeNetworkInterfacesRequest(input *DescribeNetworkInterfacesInput) (req *request.Request, output *DescribeNetworkInterfacesOutput) { - op := &request.Operation{ - Name: opDescribeNetworkInterfaces, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeNetworkInterfacesInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeNetworkInterfacesOutput{} - req.Data = output - return -} - -// Describes one or more of your network interfaces. -func (c *EC2) DescribeNetworkInterfaces(input *DescribeNetworkInterfacesInput) (*DescribeNetworkInterfacesOutput, error) { - req, out := c.DescribeNetworkInterfacesRequest(input) - err := req.Send() - return out, err -} - -const opDescribePlacementGroups = "DescribePlacementGroups" - -// DescribePlacementGroupsRequest generates a request for the DescribePlacementGroups operation. -func (c *EC2) DescribePlacementGroupsRequest(input *DescribePlacementGroupsInput) (req *request.Request, output *DescribePlacementGroupsOutput) { - op := &request.Operation{ - Name: opDescribePlacementGroups, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribePlacementGroupsInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribePlacementGroupsOutput{} - req.Data = output - return -} - -// Describes one or more of your placement groups. For more information about -// placement groups and cluster instances, see Cluster Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using_cluster_computing.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) DescribePlacementGroups(input *DescribePlacementGroupsInput) (*DescribePlacementGroupsOutput, error) { - req, out := c.DescribePlacementGroupsRequest(input) - err := req.Send() - return out, err -} - -const opDescribePrefixLists = "DescribePrefixLists" - -// DescribePrefixListsRequest generates a request for the DescribePrefixLists operation. -func (c *EC2) DescribePrefixListsRequest(input *DescribePrefixListsInput) (req *request.Request, output *DescribePrefixListsOutput) { - op := &request.Operation{ - Name: opDescribePrefixLists, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribePrefixListsInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribePrefixListsOutput{} - req.Data = output - return -} - -// Describes available AWS services in a prefix list format, which includes -// the prefix list name and prefix list ID of the service and the IP address -// range for the service. A prefix list ID is required for creating an outbound -// security group rule that allows traffic from a VPC to access an AWS service -// through a VPC endpoint. -func (c *EC2) DescribePrefixLists(input *DescribePrefixListsInput) (*DescribePrefixListsOutput, error) { - req, out := c.DescribePrefixListsRequest(input) - err := req.Send() - return out, err -} - -const opDescribeRegions = "DescribeRegions" - -// DescribeRegionsRequest generates a request for the DescribeRegions operation. -func (c *EC2) DescribeRegionsRequest(input *DescribeRegionsInput) (req *request.Request, output *DescribeRegionsOutput) { - op := &request.Operation{ - Name: opDescribeRegions, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeRegionsInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeRegionsOutput{} - req.Data = output - return -} - -// Describes one or more regions that are currently available to you. -// -// For a list of the regions supported by Amazon EC2, see Regions and Endpoints -// (http://docs.aws.amazon.com/general/latest/gr/rande.html#ec2_region). -func (c *EC2) DescribeRegions(input *DescribeRegionsInput) (*DescribeRegionsOutput, error) { - req, out := c.DescribeRegionsRequest(input) - err := req.Send() - return out, err -} - -const opDescribeReservedInstances = "DescribeReservedInstances" - -// DescribeReservedInstancesRequest generates a request for the DescribeReservedInstances operation. -func (c *EC2) DescribeReservedInstancesRequest(input *DescribeReservedInstancesInput) (req *request.Request, output *DescribeReservedInstancesOutput) { - op := &request.Operation{ - Name: opDescribeReservedInstances, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeReservedInstancesInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeReservedInstancesOutput{} - req.Data = output - return -} - -// Describes one or more of the Reserved Instances that you purchased. -// -// For more information about Reserved Instances, see Reserved Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/concepts-on-demand-reserved-instances.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) DescribeReservedInstances(input *DescribeReservedInstancesInput) (*DescribeReservedInstancesOutput, error) { - req, out := c.DescribeReservedInstancesRequest(input) - err := req.Send() - return out, err -} - -const opDescribeReservedInstancesListings = "DescribeReservedInstancesListings" - -// DescribeReservedInstancesListingsRequest generates a request for the DescribeReservedInstancesListings operation. -func (c *EC2) DescribeReservedInstancesListingsRequest(input *DescribeReservedInstancesListingsInput) (req *request.Request, output *DescribeReservedInstancesListingsOutput) { - op := &request.Operation{ - Name: opDescribeReservedInstancesListings, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeReservedInstancesListingsInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeReservedInstancesListingsOutput{} - req.Data = output - return -} - -// Describes your account's Reserved Instance listings in the Reserved Instance -// Marketplace. -// -// The Reserved Instance Marketplace matches sellers who want to resell Reserved -// Instance capacity that they no longer need with buyers who want to purchase -// additional capacity. Reserved Instances bought and sold through the Reserved -// Instance Marketplace work like any other Reserved Instances. -// -// As a seller, you choose to list some or all of your Reserved Instances, -// and you specify the upfront price to receive for them. Your Reserved Instances -// are then listed in the Reserved Instance Marketplace and are available for -// purchase. -// -// As a buyer, you specify the configuration of the Reserved Instance to purchase, -// and the Marketplace matches what you're searching for with what's available. -// The Marketplace first sells the lowest priced Reserved Instances to you, -// and continues to sell available Reserved Instance listings to you until your -// demand is met. You are charged based on the total price of all of the listings -// that you purchase. -// -// For more information, see Reserved Instance Marketplace (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ri-market-general.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) DescribeReservedInstancesListings(input *DescribeReservedInstancesListingsInput) (*DescribeReservedInstancesListingsOutput, error) { - req, out := c.DescribeReservedInstancesListingsRequest(input) - err := req.Send() - return out, err -} - -const opDescribeReservedInstancesModifications = "DescribeReservedInstancesModifications" - -// DescribeReservedInstancesModificationsRequest generates a request for the DescribeReservedInstancesModifications operation. -func (c *EC2) DescribeReservedInstancesModificationsRequest(input *DescribeReservedInstancesModificationsInput) (req *request.Request, output *DescribeReservedInstancesModificationsOutput) { - op := &request.Operation{ - Name: opDescribeReservedInstancesModifications, - HTTPMethod: "POST", - HTTPPath: "/", - Paginator: &request.Paginator{ - InputTokens: []string{"NextToken"}, - OutputTokens: []string{"NextToken"}, - LimitToken: "", - TruncationToken: "", - }, - } - - if input == nil { - input = &DescribeReservedInstancesModificationsInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeReservedInstancesModificationsOutput{} - req.Data = output - return -} - -// Describes the modifications made to your Reserved Instances. If no parameter -// is specified, information about all your Reserved Instances modification -// requests is returned. If a modification ID is specified, only information -// about the specific modification is returned. -// -// For more information, see Modifying Reserved Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ri-modifying.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) DescribeReservedInstancesModifications(input *DescribeReservedInstancesModificationsInput) (*DescribeReservedInstancesModificationsOutput, error) { - req, out := c.DescribeReservedInstancesModificationsRequest(input) - err := req.Send() - return out, err -} - -func (c *EC2) DescribeReservedInstancesModificationsPages(input *DescribeReservedInstancesModificationsInput, fn func(p *DescribeReservedInstancesModificationsOutput, lastPage bool) (shouldContinue bool)) error { - page, _ := c.DescribeReservedInstancesModificationsRequest(input) - page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) - return page.EachPage(func(p interface{}, lastPage bool) bool { - return fn(p.(*DescribeReservedInstancesModificationsOutput), lastPage) - }) -} - -const opDescribeReservedInstancesOfferings = "DescribeReservedInstancesOfferings" - -// DescribeReservedInstancesOfferingsRequest generates a request for the DescribeReservedInstancesOfferings operation. -func (c *EC2) DescribeReservedInstancesOfferingsRequest(input *DescribeReservedInstancesOfferingsInput) (req *request.Request, output *DescribeReservedInstancesOfferingsOutput) { - op := &request.Operation{ - Name: opDescribeReservedInstancesOfferings, - HTTPMethod: "POST", - HTTPPath: "/", - Paginator: &request.Paginator{ - InputTokens: []string{"NextToken"}, - OutputTokens: []string{"NextToken"}, - LimitToken: "MaxResults", - TruncationToken: "", - }, - } - - if input == nil { - input = &DescribeReservedInstancesOfferingsInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeReservedInstancesOfferingsOutput{} - req.Data = output - return -} - -// Describes Reserved Instance offerings that are available for purchase. With -// Reserved Instances, you purchase the right to launch instances for a period -// of time. During that time period, you do not receive insufficient capacity -// errors, and you pay a lower usage rate than the rate charged for On-Demand -// instances for the actual time used. -// -// For more information, see Reserved Instance Marketplace (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ri-market-general.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) DescribeReservedInstancesOfferings(input *DescribeReservedInstancesOfferingsInput) (*DescribeReservedInstancesOfferingsOutput, error) { - req, out := c.DescribeReservedInstancesOfferingsRequest(input) - err := req.Send() - return out, err -} - -func (c *EC2) DescribeReservedInstancesOfferingsPages(input *DescribeReservedInstancesOfferingsInput, fn func(p *DescribeReservedInstancesOfferingsOutput, lastPage bool) (shouldContinue bool)) error { - page, _ := c.DescribeReservedInstancesOfferingsRequest(input) - page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) - return page.EachPage(func(p interface{}, lastPage bool) bool { - return fn(p.(*DescribeReservedInstancesOfferingsOutput), lastPage) - }) -} - -const opDescribeRouteTables = "DescribeRouteTables" - -// DescribeRouteTablesRequest generates a request for the DescribeRouteTables operation. -func (c *EC2) DescribeRouteTablesRequest(input *DescribeRouteTablesInput) (req *request.Request, output *DescribeRouteTablesOutput) { - op := &request.Operation{ - Name: opDescribeRouteTables, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeRouteTablesInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeRouteTablesOutput{} - req.Data = output - return -} - -// Describes one or more of your route tables. -// -// Each subnet in your VPC must be associated with a route table. If a subnet -// is not explicitly associated with any route table, it is implicitly associated -// with the main route table. This command does not return the subnet ID for -// implicit associations. -// -// For more information about route tables, see Route Tables (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Route_Tables.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) DescribeRouteTables(input *DescribeRouteTablesInput) (*DescribeRouteTablesOutput, error) { - req, out := c.DescribeRouteTablesRequest(input) - err := req.Send() - return out, err -} - -const opDescribeSecurityGroups = "DescribeSecurityGroups" - -// DescribeSecurityGroupsRequest generates a request for the DescribeSecurityGroups operation. -func (c *EC2) DescribeSecurityGroupsRequest(input *DescribeSecurityGroupsInput) (req *request.Request, output *DescribeSecurityGroupsOutput) { - op := &request.Operation{ - Name: opDescribeSecurityGroups, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeSecurityGroupsInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeSecurityGroupsOutput{} - req.Data = output - return -} - -// Describes one or more of your security groups. -// -// A security group is for use with instances either in the EC2-Classic platform -// or in a specific VPC. For more information, see Amazon EC2 Security Groups -// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-network-security.html) -// in the Amazon Elastic Compute Cloud User Guide and Security Groups for Your -// VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_SecurityGroups.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) DescribeSecurityGroups(input *DescribeSecurityGroupsInput) (*DescribeSecurityGroupsOutput, error) { - req, out := c.DescribeSecurityGroupsRequest(input) - err := req.Send() - return out, err -} - -const opDescribeSnapshotAttribute = "DescribeSnapshotAttribute" - -// DescribeSnapshotAttributeRequest generates a request for the DescribeSnapshotAttribute operation. -func (c *EC2) DescribeSnapshotAttributeRequest(input *DescribeSnapshotAttributeInput) (req *request.Request, output *DescribeSnapshotAttributeOutput) { - op := &request.Operation{ - Name: opDescribeSnapshotAttribute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeSnapshotAttributeInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeSnapshotAttributeOutput{} - req.Data = output - return -} - -// Describes the specified attribute of the specified snapshot. You can specify -// only one attribute at a time. -// -// For more information about EBS snapshots, see Amazon EBS Snapshots in the -// Amazon Elastic Compute Cloud User Guide. -func (c *EC2) DescribeSnapshotAttribute(input *DescribeSnapshotAttributeInput) (*DescribeSnapshotAttributeOutput, error) { - req, out := c.DescribeSnapshotAttributeRequest(input) - err := req.Send() - return out, err -} - -const opDescribeSnapshots = "DescribeSnapshots" - -// DescribeSnapshotsRequest generates a request for the DescribeSnapshots operation. -func (c *EC2) DescribeSnapshotsRequest(input *DescribeSnapshotsInput) (req *request.Request, output *DescribeSnapshotsOutput) { - op := &request.Operation{ - Name: opDescribeSnapshots, - HTTPMethod: "POST", - HTTPPath: "/", - Paginator: &request.Paginator{ - InputTokens: []string{"NextToken"}, - OutputTokens: []string{"NextToken"}, - LimitToken: "MaxResults", - TruncationToken: "", - }, - } - - if input == nil { - input = &DescribeSnapshotsInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeSnapshotsOutput{} - req.Data = output - return -} - -// Describes one or more of the EBS snapshots available to you. Available snapshots -// include public snapshots available for any AWS account to launch, private -// snapshots that you own, and private snapshots owned by another AWS account -// but for which you've been given explicit create volume permissions. -// -// The create volume permissions fall into the following categories: -// -// public: The owner of the snapshot granted create volume permissions for -// the snapshot to the all group. All AWS accounts have create volume permissions -// for these snapshots. explicit: The owner of the snapshot granted create -// volume permissions to a specific AWS account. implicit: An AWS account has -// implicit create volume permissions for all snapshots it owns. The list of -// snapshots returned can be modified by specifying snapshot IDs, snapshot owners, -// or AWS accounts with create volume permissions. If no options are specified, -// Amazon EC2 returns all snapshots for which you have create volume permissions. -// -// If you specify one or more snapshot IDs, only snapshots that have the specified -// IDs are returned. If you specify an invalid snapshot ID, an error is returned. -// If you specify a snapshot ID for which you do not have access, it is not -// included in the returned results. -// -// If you specify one or more snapshot owners, only snapshots from the specified -// owners and for which you have access are returned. The results can include -// the AWS account IDs of the specified owners, amazon for snapshots owned by -// Amazon, or self for snapshots that you own. -// -// If you specify a list of restorable users, only snapshots with create snapshot -// permissions for those users are returned. You can specify AWS account IDs -// (if you own the snapshots), self for snapshots for which you own or have -// explicit permissions, or all for public snapshots. -// -// If you are describing a long list of snapshots, you can paginate the output -// to make the list more manageable. The MaxResults parameter sets the maximum -// number of results returned in a single page. If the list of results exceeds -// your MaxResults value, then that number of results is returned along with -// a NextToken value that can be passed to a subsequent DescribeSnapshots request -// to retrieve the remaining results. -// -// For more information about EBS snapshots, see Amazon EBS Snapshots in the -// Amazon Elastic Compute Cloud User Guide. -func (c *EC2) DescribeSnapshots(input *DescribeSnapshotsInput) (*DescribeSnapshotsOutput, error) { - req, out := c.DescribeSnapshotsRequest(input) - err := req.Send() - return out, err -} - -func (c *EC2) DescribeSnapshotsPages(input *DescribeSnapshotsInput, fn func(p *DescribeSnapshotsOutput, lastPage bool) (shouldContinue bool)) error { - page, _ := c.DescribeSnapshotsRequest(input) - page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) - return page.EachPage(func(p interface{}, lastPage bool) bool { - return fn(p.(*DescribeSnapshotsOutput), lastPage) - }) -} - -const opDescribeSpotDatafeedSubscription = "DescribeSpotDatafeedSubscription" - -// DescribeSpotDatafeedSubscriptionRequest generates a request for the DescribeSpotDatafeedSubscription operation. -func (c *EC2) DescribeSpotDatafeedSubscriptionRequest(input *DescribeSpotDatafeedSubscriptionInput) (req *request.Request, output *DescribeSpotDatafeedSubscriptionOutput) { - op := &request.Operation{ - Name: opDescribeSpotDatafeedSubscription, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeSpotDatafeedSubscriptionInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeSpotDatafeedSubscriptionOutput{} - req.Data = output - return -} - -// Describes the data feed for Spot instances. For more information, see Spot -// Instance Data Feed (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-data-feeds.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) DescribeSpotDatafeedSubscription(input *DescribeSpotDatafeedSubscriptionInput) (*DescribeSpotDatafeedSubscriptionOutput, error) { - req, out := c.DescribeSpotDatafeedSubscriptionRequest(input) - err := req.Send() - return out, err -} - -const opDescribeSpotFleetInstances = "DescribeSpotFleetInstances" - -// DescribeSpotFleetInstancesRequest generates a request for the DescribeSpotFleetInstances operation. -func (c *EC2) DescribeSpotFleetInstancesRequest(input *DescribeSpotFleetInstancesInput) (req *request.Request, output *DescribeSpotFleetInstancesOutput) { - op := &request.Operation{ - Name: opDescribeSpotFleetInstances, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeSpotFleetInstancesInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeSpotFleetInstancesOutput{} - req.Data = output - return -} - -// Describes the running instances for the specified Spot fleet. -func (c *EC2) DescribeSpotFleetInstances(input *DescribeSpotFleetInstancesInput) (*DescribeSpotFleetInstancesOutput, error) { - req, out := c.DescribeSpotFleetInstancesRequest(input) - err := req.Send() - return out, err -} - -const opDescribeSpotFleetRequestHistory = "DescribeSpotFleetRequestHistory" - -// DescribeSpotFleetRequestHistoryRequest generates a request for the DescribeSpotFleetRequestHistory operation. -func (c *EC2) DescribeSpotFleetRequestHistoryRequest(input *DescribeSpotFleetRequestHistoryInput) (req *request.Request, output *DescribeSpotFleetRequestHistoryOutput) { - op := &request.Operation{ - Name: opDescribeSpotFleetRequestHistory, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeSpotFleetRequestHistoryInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeSpotFleetRequestHistoryOutput{} - req.Data = output - return -} - -// Describes the events for the specified Spot fleet request during the specified -// time. -// -// Spot fleet events are delayed by up to 30 seconds before they can be described. -// This ensures that you can query by the last evaluated time and not miss a -// recorded event. -func (c *EC2) DescribeSpotFleetRequestHistory(input *DescribeSpotFleetRequestHistoryInput) (*DescribeSpotFleetRequestHistoryOutput, error) { - req, out := c.DescribeSpotFleetRequestHistoryRequest(input) - err := req.Send() - return out, err -} - -const opDescribeSpotFleetRequests = "DescribeSpotFleetRequests" - -// DescribeSpotFleetRequestsRequest generates a request for the DescribeSpotFleetRequests operation. -func (c *EC2) DescribeSpotFleetRequestsRequest(input *DescribeSpotFleetRequestsInput) (req *request.Request, output *DescribeSpotFleetRequestsOutput) { - op := &request.Operation{ - Name: opDescribeSpotFleetRequests, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeSpotFleetRequestsInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeSpotFleetRequestsOutput{} - req.Data = output - return -} - -// Describes your Spot fleet requests. -func (c *EC2) DescribeSpotFleetRequests(input *DescribeSpotFleetRequestsInput) (*DescribeSpotFleetRequestsOutput, error) { - req, out := c.DescribeSpotFleetRequestsRequest(input) - err := req.Send() - return out, err -} - -const opDescribeSpotInstanceRequests = "DescribeSpotInstanceRequests" - -// DescribeSpotInstanceRequestsRequest generates a request for the DescribeSpotInstanceRequests operation. -func (c *EC2) DescribeSpotInstanceRequestsRequest(input *DescribeSpotInstanceRequestsInput) (req *request.Request, output *DescribeSpotInstanceRequestsOutput) { - op := &request.Operation{ - Name: opDescribeSpotInstanceRequests, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeSpotInstanceRequestsInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeSpotInstanceRequestsOutput{} - req.Data = output - return -} - -// Describes the Spot instance requests that belong to your account. Spot instances -// are instances that Amazon EC2 launches when the bid price that you specify -// exceeds the current Spot price. Amazon EC2 periodically sets the Spot price -// based on available Spot instance capacity and current Spot instance requests. -// For more information, see Spot Instance Requests (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-requests.html) -// in the Amazon Elastic Compute Cloud User Guide. -// -// You can use DescribeSpotInstanceRequests to find a running Spot instance -// by examining the response. If the status of the Spot instance is fulfilled, -// the instance ID appears in the response and contains the identifier of the -// instance. Alternatively, you can use DescribeInstances with a filter to look -// for instances where the instance lifecycle is spot. -func (c *EC2) DescribeSpotInstanceRequests(input *DescribeSpotInstanceRequestsInput) (*DescribeSpotInstanceRequestsOutput, error) { - req, out := c.DescribeSpotInstanceRequestsRequest(input) - err := req.Send() - return out, err -} - -const opDescribeSpotPriceHistory = "DescribeSpotPriceHistory" - -// DescribeSpotPriceHistoryRequest generates a request for the DescribeSpotPriceHistory operation. -func (c *EC2) DescribeSpotPriceHistoryRequest(input *DescribeSpotPriceHistoryInput) (req *request.Request, output *DescribeSpotPriceHistoryOutput) { - op := &request.Operation{ - Name: opDescribeSpotPriceHistory, - HTTPMethod: "POST", - HTTPPath: "/", - Paginator: &request.Paginator{ - InputTokens: []string{"NextToken"}, - OutputTokens: []string{"NextToken"}, - LimitToken: "MaxResults", - TruncationToken: "", - }, - } - - if input == nil { - input = &DescribeSpotPriceHistoryInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeSpotPriceHistoryOutput{} - req.Data = output - return -} - -// Describes the Spot price history. The prices returned are listed in chronological -// order, from the oldest to the most recent, for up to the past 90 days. For -// more information, see Spot Instance Pricing History (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-spot-instances-history.html) -// in the Amazon Elastic Compute Cloud User Guide. -// -// When you specify a start and end time, this operation returns the prices -// of the instance types within the time range that you specified and the time -// when the price changed. The price is valid within the time period that you -// specified; the response merely indicates the last time that the price changed. -func (c *EC2) DescribeSpotPriceHistory(input *DescribeSpotPriceHistoryInput) (*DescribeSpotPriceHistoryOutput, error) { - req, out := c.DescribeSpotPriceHistoryRequest(input) - err := req.Send() - return out, err -} - -func (c *EC2) DescribeSpotPriceHistoryPages(input *DescribeSpotPriceHistoryInput, fn func(p *DescribeSpotPriceHistoryOutput, lastPage bool) (shouldContinue bool)) error { - page, _ := c.DescribeSpotPriceHistoryRequest(input) - page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) - return page.EachPage(func(p interface{}, lastPage bool) bool { - return fn(p.(*DescribeSpotPriceHistoryOutput), lastPage) - }) -} - -const opDescribeSubnets = "DescribeSubnets" - -// DescribeSubnetsRequest generates a request for the DescribeSubnets operation. -func (c *EC2) DescribeSubnetsRequest(input *DescribeSubnetsInput) (req *request.Request, output *DescribeSubnetsOutput) { - op := &request.Operation{ - Name: opDescribeSubnets, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeSubnetsInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeSubnetsOutput{} - req.Data = output - return -} - -// Describes one or more of your subnets. -// -// For more information about subnets, see Your VPC and Subnets (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Subnets.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) DescribeSubnets(input *DescribeSubnetsInput) (*DescribeSubnetsOutput, error) { - req, out := c.DescribeSubnetsRequest(input) - err := req.Send() - return out, err -} - -const opDescribeTags = "DescribeTags" - -// DescribeTagsRequest generates a request for the DescribeTags operation. -func (c *EC2) DescribeTagsRequest(input *DescribeTagsInput) (req *request.Request, output *DescribeTagsOutput) { - op := &request.Operation{ - Name: opDescribeTags, - HTTPMethod: "POST", - HTTPPath: "/", - Paginator: &request.Paginator{ - InputTokens: []string{"NextToken"}, - OutputTokens: []string{"NextToken"}, - LimitToken: "MaxResults", - TruncationToken: "", - }, - } - - if input == nil { - input = &DescribeTagsInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeTagsOutput{} - req.Data = output - return -} - -// Describes one or more of the tags for your EC2 resources. -// -// For more information about tags, see Tagging Your Resources (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) DescribeTags(input *DescribeTagsInput) (*DescribeTagsOutput, error) { - req, out := c.DescribeTagsRequest(input) - err := req.Send() - return out, err -} - -func (c *EC2) DescribeTagsPages(input *DescribeTagsInput, fn func(p *DescribeTagsOutput, lastPage bool) (shouldContinue bool)) error { - page, _ := c.DescribeTagsRequest(input) - page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) - return page.EachPage(func(p interface{}, lastPage bool) bool { - return fn(p.(*DescribeTagsOutput), lastPage) - }) -} - -const opDescribeVolumeAttribute = "DescribeVolumeAttribute" - -// DescribeVolumeAttributeRequest generates a request for the DescribeVolumeAttribute operation. -func (c *EC2) DescribeVolumeAttributeRequest(input *DescribeVolumeAttributeInput) (req *request.Request, output *DescribeVolumeAttributeOutput) { - op := &request.Operation{ - Name: opDescribeVolumeAttribute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeVolumeAttributeInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeVolumeAttributeOutput{} - req.Data = output - return -} - -// Describes the specified attribute of the specified volume. You can specify -// only one attribute at a time. -// -// For more information about EBS volumes, see Amazon EBS Volumes in the Amazon -// Elastic Compute Cloud User Guide. -func (c *EC2) DescribeVolumeAttribute(input *DescribeVolumeAttributeInput) (*DescribeVolumeAttributeOutput, error) { - req, out := c.DescribeVolumeAttributeRequest(input) - err := req.Send() - return out, err -} - -const opDescribeVolumeStatus = "DescribeVolumeStatus" - -// DescribeVolumeStatusRequest generates a request for the DescribeVolumeStatus operation. -func (c *EC2) DescribeVolumeStatusRequest(input *DescribeVolumeStatusInput) (req *request.Request, output *DescribeVolumeStatusOutput) { - op := &request.Operation{ - Name: opDescribeVolumeStatus, - HTTPMethod: "POST", - HTTPPath: "/", - Paginator: &request.Paginator{ - InputTokens: []string{"NextToken"}, - OutputTokens: []string{"NextToken"}, - LimitToken: "MaxResults", - TruncationToken: "", - }, - } - - if input == nil { - input = &DescribeVolumeStatusInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeVolumeStatusOutput{} - req.Data = output - return -} - -// Describes the status of the specified volumes. Volume status provides the -// result of the checks performed on your volumes to determine events that can -// impair the performance of your volumes. The performance of a volume can be -// affected if an issue occurs on the volume's underlying host. If the volume's -// underlying host experiences a power outage or system issue, after the system -// is restored, there could be data inconsistencies on the volume. Volume events -// notify you if this occurs. Volume actions notify you if any action needs -// to be taken in response to the event. -// -// The DescribeVolumeStatus operation provides the following information about -// the specified volumes: -// -// Status: Reflects the current status of the volume. The possible values are -// ok, impaired , warning, or insufficient-data. If all checks pass, the overall -// status of the volume is ok. If the check fails, the overall status is impaired. -// If the status is insufficient-data, then the checks may still be taking place -// on your volume at the time. We recommend that you retry the request. For -// more information on volume status, see Monitoring the Status of Your Volumes -// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-volume-status.html). -// -// Events: Reflect the cause of a volume status and may require you to take -// action. For example, if your volume returns an impaired status, then the -// volume event might be potential-data-inconsistency. This means that your -// volume has been affected by an issue with the underlying host, has all I/O -// operations disabled, and may have inconsistent data. -// -// Actions: Reflect the actions you may have to take in response to an event. -// For example, if the status of the volume is impaired and the volume event -// shows potential-data-inconsistency, then the action shows enable-volume-io. -// This means that you may want to enable the I/O operations for the volume -// by calling the EnableVolumeIO action and then check the volume for data consistency. -// -// Volume status is based on the volume status checks, and does not reflect -// the volume state. Therefore, volume status does not indicate volumes in the -// error state (for example, when a volume is incapable of accepting I/O.) -func (c *EC2) DescribeVolumeStatus(input *DescribeVolumeStatusInput) (*DescribeVolumeStatusOutput, error) { - req, out := c.DescribeVolumeStatusRequest(input) - err := req.Send() - return out, err -} - -func (c *EC2) DescribeVolumeStatusPages(input *DescribeVolumeStatusInput, fn func(p *DescribeVolumeStatusOutput, lastPage bool) (shouldContinue bool)) error { - page, _ := c.DescribeVolumeStatusRequest(input) - page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) - return page.EachPage(func(p interface{}, lastPage bool) bool { - return fn(p.(*DescribeVolumeStatusOutput), lastPage) - }) -} - -const opDescribeVolumes = "DescribeVolumes" - -// DescribeVolumesRequest generates a request for the DescribeVolumes operation. -func (c *EC2) DescribeVolumesRequest(input *DescribeVolumesInput) (req *request.Request, output *DescribeVolumesOutput) { - op := &request.Operation{ - Name: opDescribeVolumes, - HTTPMethod: "POST", - HTTPPath: "/", - Paginator: &request.Paginator{ - InputTokens: []string{"NextToken"}, - OutputTokens: []string{"NextToken"}, - LimitToken: "MaxResults", - TruncationToken: "", - }, - } - - if input == nil { - input = &DescribeVolumesInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeVolumesOutput{} - req.Data = output - return -} - -// Describes the specified EBS volumes. -// -// If you are describing a long list of volumes, you can paginate the output -// to make the list more manageable. The MaxResults parameter sets the maximum -// number of results returned in a single page. If the list of results exceeds -// your MaxResults value, then that number of results is returned along with -// a NextToken value that can be passed to a subsequent DescribeVolumes request -// to retrieve the remaining results. -// -// For more information about EBS volumes, see Amazon EBS Volumes in the Amazon -// Elastic Compute Cloud User Guide. -func (c *EC2) DescribeVolumes(input *DescribeVolumesInput) (*DescribeVolumesOutput, error) { - req, out := c.DescribeVolumesRequest(input) - err := req.Send() - return out, err -} - -func (c *EC2) DescribeVolumesPages(input *DescribeVolumesInput, fn func(p *DescribeVolumesOutput, lastPage bool) (shouldContinue bool)) error { - page, _ := c.DescribeVolumesRequest(input) - page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator")) - return page.EachPage(func(p interface{}, lastPage bool) bool { - return fn(p.(*DescribeVolumesOutput), lastPage) - }) -} - -const opDescribeVpcAttribute = "DescribeVpcAttribute" - -// DescribeVpcAttributeRequest generates a request for the DescribeVpcAttribute operation. -func (c *EC2) DescribeVpcAttributeRequest(input *DescribeVpcAttributeInput) (req *request.Request, output *DescribeVpcAttributeOutput) { - op := &request.Operation{ - Name: opDescribeVpcAttribute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeVpcAttributeInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeVpcAttributeOutput{} - req.Data = output - return -} - -// Describes the specified attribute of the specified VPC. You can specify only -// one attribute at a time. -func (c *EC2) DescribeVpcAttribute(input *DescribeVpcAttributeInput) (*DescribeVpcAttributeOutput, error) { - req, out := c.DescribeVpcAttributeRequest(input) - err := req.Send() - return out, err -} - -const opDescribeVpcClassicLink = "DescribeVpcClassicLink" - -// DescribeVpcClassicLinkRequest generates a request for the DescribeVpcClassicLink operation. -func (c *EC2) DescribeVpcClassicLinkRequest(input *DescribeVpcClassicLinkInput) (req *request.Request, output *DescribeVpcClassicLinkOutput) { - op := &request.Operation{ - Name: opDescribeVpcClassicLink, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeVpcClassicLinkInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeVpcClassicLinkOutput{} - req.Data = output - return -} - -// Describes the ClassicLink status of one or more VPCs. -func (c *EC2) DescribeVpcClassicLink(input *DescribeVpcClassicLinkInput) (*DescribeVpcClassicLinkOutput, error) { - req, out := c.DescribeVpcClassicLinkRequest(input) - err := req.Send() - return out, err -} - -const opDescribeVpcEndpointServices = "DescribeVpcEndpointServices" - -// DescribeVpcEndpointServicesRequest generates a request for the DescribeVpcEndpointServices operation. -func (c *EC2) DescribeVpcEndpointServicesRequest(input *DescribeVpcEndpointServicesInput) (req *request.Request, output *DescribeVpcEndpointServicesOutput) { - op := &request.Operation{ - Name: opDescribeVpcEndpointServices, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeVpcEndpointServicesInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeVpcEndpointServicesOutput{} - req.Data = output - return -} - -// Describes all supported AWS services that can be specified when creating -// a VPC endpoint. -func (c *EC2) DescribeVpcEndpointServices(input *DescribeVpcEndpointServicesInput) (*DescribeVpcEndpointServicesOutput, error) { - req, out := c.DescribeVpcEndpointServicesRequest(input) - err := req.Send() - return out, err -} - -const opDescribeVpcEndpoints = "DescribeVpcEndpoints" - -// DescribeVpcEndpointsRequest generates a request for the DescribeVpcEndpoints operation. -func (c *EC2) DescribeVpcEndpointsRequest(input *DescribeVpcEndpointsInput) (req *request.Request, output *DescribeVpcEndpointsOutput) { - op := &request.Operation{ - Name: opDescribeVpcEndpoints, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeVpcEndpointsInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeVpcEndpointsOutput{} - req.Data = output - return -} - -// Describes one or more of your VPC endpoints. -func (c *EC2) DescribeVpcEndpoints(input *DescribeVpcEndpointsInput) (*DescribeVpcEndpointsOutput, error) { - req, out := c.DescribeVpcEndpointsRequest(input) - err := req.Send() - return out, err -} - -const opDescribeVpcPeeringConnections = "DescribeVpcPeeringConnections" - -// DescribeVpcPeeringConnectionsRequest generates a request for the DescribeVpcPeeringConnections operation. -func (c *EC2) DescribeVpcPeeringConnectionsRequest(input *DescribeVpcPeeringConnectionsInput) (req *request.Request, output *DescribeVpcPeeringConnectionsOutput) { - op := &request.Operation{ - Name: opDescribeVpcPeeringConnections, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeVpcPeeringConnectionsInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeVpcPeeringConnectionsOutput{} - req.Data = output - return -} - -// Describes one or more of your VPC peering connections. -func (c *EC2) DescribeVpcPeeringConnections(input *DescribeVpcPeeringConnectionsInput) (*DescribeVpcPeeringConnectionsOutput, error) { - req, out := c.DescribeVpcPeeringConnectionsRequest(input) - err := req.Send() - return out, err -} - -const opDescribeVpcs = "DescribeVpcs" - -// DescribeVpcsRequest generates a request for the DescribeVpcs operation. -func (c *EC2) DescribeVpcsRequest(input *DescribeVpcsInput) (req *request.Request, output *DescribeVpcsOutput) { - op := &request.Operation{ - Name: opDescribeVpcs, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeVpcsInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeVpcsOutput{} - req.Data = output - return -} - -// Describes one or more of your VPCs. -func (c *EC2) DescribeVpcs(input *DescribeVpcsInput) (*DescribeVpcsOutput, error) { - req, out := c.DescribeVpcsRequest(input) - err := req.Send() - return out, err -} - -const opDescribeVpnConnections = "DescribeVpnConnections" - -// DescribeVpnConnectionsRequest generates a request for the DescribeVpnConnections operation. -func (c *EC2) DescribeVpnConnectionsRequest(input *DescribeVpnConnectionsInput) (req *request.Request, output *DescribeVpnConnectionsOutput) { - op := &request.Operation{ - Name: opDescribeVpnConnections, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeVpnConnectionsInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeVpnConnectionsOutput{} - req.Data = output - return -} - -// Describes one or more of your VPN connections. -// -// For more information about VPN connections, see Adding a Hardware Virtual -// Private Gateway to Your VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_VPN.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) DescribeVpnConnections(input *DescribeVpnConnectionsInput) (*DescribeVpnConnectionsOutput, error) { - req, out := c.DescribeVpnConnectionsRequest(input) - err := req.Send() - return out, err -} - -const opDescribeVpnGateways = "DescribeVpnGateways" - -// DescribeVpnGatewaysRequest generates a request for the DescribeVpnGateways operation. -func (c *EC2) DescribeVpnGatewaysRequest(input *DescribeVpnGatewaysInput) (req *request.Request, output *DescribeVpnGatewaysOutput) { - op := &request.Operation{ - Name: opDescribeVpnGateways, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DescribeVpnGatewaysInput{} - } - - req = c.newRequest(op, input, output) - output = &DescribeVpnGatewaysOutput{} - req.Data = output - return -} - -// Describes one or more of your virtual private gateways. -// -// For more information about virtual private gateways, see Adding an IPsec -// Hardware VPN to Your VPC (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_VPN.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) DescribeVpnGateways(input *DescribeVpnGatewaysInput) (*DescribeVpnGatewaysOutput, error) { - req, out := c.DescribeVpnGatewaysRequest(input) - err := req.Send() - return out, err -} - -const opDetachClassicLinkVpc = "DetachClassicLinkVpc" - -// DetachClassicLinkVpcRequest generates a request for the DetachClassicLinkVpc operation. -func (c *EC2) DetachClassicLinkVpcRequest(input *DetachClassicLinkVpcInput) (req *request.Request, output *DetachClassicLinkVpcOutput) { - op := &request.Operation{ - Name: opDetachClassicLinkVpc, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DetachClassicLinkVpcInput{} - } - - req = c.newRequest(op, input, output) - output = &DetachClassicLinkVpcOutput{} - req.Data = output - return -} - -// Unlinks (detaches) a linked EC2-Classic instance from a VPC. After the instance -// has been unlinked, the VPC security groups are no longer associated with -// it. An instance is automatically unlinked from a VPC when it's stopped. -func (c *EC2) DetachClassicLinkVpc(input *DetachClassicLinkVpcInput) (*DetachClassicLinkVpcOutput, error) { - req, out := c.DetachClassicLinkVpcRequest(input) - err := req.Send() - return out, err -} - -const opDetachInternetGateway = "DetachInternetGateway" - -// DetachInternetGatewayRequest generates a request for the DetachInternetGateway operation. -func (c *EC2) DetachInternetGatewayRequest(input *DetachInternetGatewayInput) (req *request.Request, output *DetachInternetGatewayOutput) { - op := &request.Operation{ - Name: opDetachInternetGateway, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DetachInternetGatewayInput{} - } - - req = c.newRequest(op, input, output) - output = &DetachInternetGatewayOutput{} - req.Data = output - return -} - -// Detaches an Internet gateway from a VPC, disabling connectivity between the -// Internet and the VPC. The VPC must not contain any running instances with -// Elastic IP addresses. -func (c *EC2) DetachInternetGateway(input *DetachInternetGatewayInput) (*DetachInternetGatewayOutput, error) { - req, out := c.DetachInternetGatewayRequest(input) - err := req.Send() - return out, err -} - -const opDetachNetworkInterface = "DetachNetworkInterface" - -// DetachNetworkInterfaceRequest generates a request for the DetachNetworkInterface operation. -func (c *EC2) DetachNetworkInterfaceRequest(input *DetachNetworkInterfaceInput) (req *request.Request, output *DetachNetworkInterfaceOutput) { - op := &request.Operation{ - Name: opDetachNetworkInterface, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DetachNetworkInterfaceInput{} - } - - req = c.newRequest(op, input, output) - output = &DetachNetworkInterfaceOutput{} - req.Data = output - return -} - -// Detaches a network interface from an instance. -func (c *EC2) DetachNetworkInterface(input *DetachNetworkInterfaceInput) (*DetachNetworkInterfaceOutput, error) { - req, out := c.DetachNetworkInterfaceRequest(input) - err := req.Send() - return out, err -} - -const opDetachVolume = "DetachVolume" - -// DetachVolumeRequest generates a request for the DetachVolume operation. -func (c *EC2) DetachVolumeRequest(input *DetachVolumeInput) (req *request.Request, output *VolumeAttachment) { - op := &request.Operation{ - Name: opDetachVolume, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DetachVolumeInput{} - } - - req = c.newRequest(op, input, output) - output = &VolumeAttachment{} - req.Data = output - return -} - -// Detaches an EBS volume from an instance. Make sure to unmount any file systems -// on the device within your operating system before detaching the volume. Failure -// to do so results in the volume being stuck in a busy state while detaching. -// -// If an Amazon EBS volume is the root device of an instance, it can't be detached -// while the instance is running. To detach the root volume, stop the instance -// first. -// -// When a volume with an AWS Marketplace product code is detached from an instance, -// the product code is no longer associated with the instance. -// -// For more information, see Detaching an Amazon EBS Volume (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-detaching-volume.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) DetachVolume(input *DetachVolumeInput) (*VolumeAttachment, error) { - req, out := c.DetachVolumeRequest(input) - err := req.Send() - return out, err -} - -const opDetachVpnGateway = "DetachVpnGateway" - -// DetachVpnGatewayRequest generates a request for the DetachVpnGateway operation. -func (c *EC2) DetachVpnGatewayRequest(input *DetachVpnGatewayInput) (req *request.Request, output *DetachVpnGatewayOutput) { - op := &request.Operation{ - Name: opDetachVpnGateway, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DetachVpnGatewayInput{} - } - - req = c.newRequest(op, input, output) - output = &DetachVpnGatewayOutput{} - req.Data = output - return -} - -// Detaches a virtual private gateway from a VPC. You do this if you're planning -// to turn off the VPC and not use it anymore. You can confirm a virtual private -// gateway has been completely detached from a VPC by describing the virtual -// private gateway (any attachments to the virtual private gateway are also -// described). -// -// You must wait for the attachment's state to switch to detached before you -// can delete the VPC or attach a different VPC to the virtual private gateway. -func (c *EC2) DetachVpnGateway(input *DetachVpnGatewayInput) (*DetachVpnGatewayOutput, error) { - req, out := c.DetachVpnGatewayRequest(input) - err := req.Send() - return out, err -} - -const opDisableVgwRoutePropagation = "DisableVgwRoutePropagation" - -// DisableVgwRoutePropagationRequest generates a request for the DisableVgwRoutePropagation operation. -func (c *EC2) DisableVgwRoutePropagationRequest(input *DisableVgwRoutePropagationInput) (req *request.Request, output *DisableVgwRoutePropagationOutput) { - op := &request.Operation{ - Name: opDisableVgwRoutePropagation, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DisableVgwRoutePropagationInput{} - } - - req = c.newRequest(op, input, output) - output = &DisableVgwRoutePropagationOutput{} - req.Data = output - return -} - -// Disables a virtual private gateway (VGW) from propagating routes to a specified -// route table of a VPC. -func (c *EC2) DisableVgwRoutePropagation(input *DisableVgwRoutePropagationInput) (*DisableVgwRoutePropagationOutput, error) { - req, out := c.DisableVgwRoutePropagationRequest(input) - err := req.Send() - return out, err -} - -const opDisableVpcClassicLink = "DisableVpcClassicLink" - -// DisableVpcClassicLinkRequest generates a request for the DisableVpcClassicLink operation. -func (c *EC2) DisableVpcClassicLinkRequest(input *DisableVpcClassicLinkInput) (req *request.Request, output *DisableVpcClassicLinkOutput) { - op := &request.Operation{ - Name: opDisableVpcClassicLink, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DisableVpcClassicLinkInput{} - } - - req = c.newRequest(op, input, output) - output = &DisableVpcClassicLinkOutput{} - req.Data = output - return -} - -// Disables ClassicLink for a VPC. You cannot disable ClassicLink for a VPC -// that has EC2-Classic instances linked to it. -func (c *EC2) DisableVpcClassicLink(input *DisableVpcClassicLinkInput) (*DisableVpcClassicLinkOutput, error) { - req, out := c.DisableVpcClassicLinkRequest(input) - err := req.Send() - return out, err -} - -const opDisassociateAddress = "DisassociateAddress" - -// DisassociateAddressRequest generates a request for the DisassociateAddress operation. -func (c *EC2) DisassociateAddressRequest(input *DisassociateAddressInput) (req *request.Request, output *DisassociateAddressOutput) { - op := &request.Operation{ - Name: opDisassociateAddress, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DisassociateAddressInput{} - } - - req = c.newRequest(op, input, output) - output = &DisassociateAddressOutput{} - req.Data = output - return -} - -// Disassociates an Elastic IP address from the instance or network interface -// it's associated with. -// -// An Elastic IP address is for use in either the EC2-Classic platform or in -// a VPC. For more information, see Elastic IP Addresses (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html) -// in the Amazon Elastic Compute Cloud User Guide. -// -// This is an idempotent operation. If you perform the operation more than -// once, Amazon EC2 doesn't return an error. -func (c *EC2) DisassociateAddress(input *DisassociateAddressInput) (*DisassociateAddressOutput, error) { - req, out := c.DisassociateAddressRequest(input) - err := req.Send() - return out, err -} - -const opDisassociateRouteTable = "DisassociateRouteTable" - -// DisassociateRouteTableRequest generates a request for the DisassociateRouteTable operation. -func (c *EC2) DisassociateRouteTableRequest(input *DisassociateRouteTableInput) (req *request.Request, output *DisassociateRouteTableOutput) { - op := &request.Operation{ - Name: opDisassociateRouteTable, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &DisassociateRouteTableInput{} - } - - req = c.newRequest(op, input, output) - output = &DisassociateRouteTableOutput{} - req.Data = output - return -} - -// Disassociates a subnet from a route table. -// -// After you perform this action, the subnet no longer uses the routes in the -// route table. Instead, it uses the routes in the VPC's main route table. For -// more information about route tables, see Route Tables (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Route_Tables.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) DisassociateRouteTable(input *DisassociateRouteTableInput) (*DisassociateRouteTableOutput, error) { - req, out := c.DisassociateRouteTableRequest(input) - err := req.Send() - return out, err -} - -const opEnableVgwRoutePropagation = "EnableVgwRoutePropagation" - -// EnableVgwRoutePropagationRequest generates a request for the EnableVgwRoutePropagation operation. -func (c *EC2) EnableVgwRoutePropagationRequest(input *EnableVgwRoutePropagationInput) (req *request.Request, output *EnableVgwRoutePropagationOutput) { - op := &request.Operation{ - Name: opEnableVgwRoutePropagation, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &EnableVgwRoutePropagationInput{} - } - - req = c.newRequest(op, input, output) - output = &EnableVgwRoutePropagationOutput{} - req.Data = output - return -} - -// Enables a virtual private gateway (VGW) to propagate routes to the specified -// route table of a VPC. -func (c *EC2) EnableVgwRoutePropagation(input *EnableVgwRoutePropagationInput) (*EnableVgwRoutePropagationOutput, error) { - req, out := c.EnableVgwRoutePropagationRequest(input) - err := req.Send() - return out, err -} - -const opEnableVolumeIO = "EnableVolumeIO" - -// EnableVolumeIORequest generates a request for the EnableVolumeIO operation. -func (c *EC2) EnableVolumeIORequest(input *EnableVolumeIOInput) (req *request.Request, output *EnableVolumeIOOutput) { - op := &request.Operation{ - Name: opEnableVolumeIO, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &EnableVolumeIOInput{} - } - - req = c.newRequest(op, input, output) - output = &EnableVolumeIOOutput{} - req.Data = output - return -} - -// Enables I/O operations for a volume that had I/O operations disabled because -// the data on the volume was potentially inconsistent. -func (c *EC2) EnableVolumeIO(input *EnableVolumeIOInput) (*EnableVolumeIOOutput, error) { - req, out := c.EnableVolumeIORequest(input) - err := req.Send() - return out, err -} - -const opEnableVpcClassicLink = "EnableVpcClassicLink" - -// EnableVpcClassicLinkRequest generates a request for the EnableVpcClassicLink operation. -func (c *EC2) EnableVpcClassicLinkRequest(input *EnableVpcClassicLinkInput) (req *request.Request, output *EnableVpcClassicLinkOutput) { - op := &request.Operation{ - Name: opEnableVpcClassicLink, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &EnableVpcClassicLinkInput{} - } - - req = c.newRequest(op, input, output) - output = &EnableVpcClassicLinkOutput{} - req.Data = output - return -} - -// Enables a VPC for ClassicLink. You can then link EC2-Classic instances to -// your ClassicLink-enabled VPC to allow communication over private IP addresses. -// You cannot enable your VPC for ClassicLink if any of your VPC's route tables -// have existing routes for address ranges within the 10.0.0.0/8 IP address -// range, excluding local routes for VPCs in the 10.0.0.0/16 and 10.1.0.0/16 -// IP address ranges. For more information, see ClassicLink (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/vpc-classiclink.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) EnableVpcClassicLink(input *EnableVpcClassicLinkInput) (*EnableVpcClassicLinkOutput, error) { - req, out := c.EnableVpcClassicLinkRequest(input) - err := req.Send() - return out, err -} - -const opGetConsoleOutput = "GetConsoleOutput" - -// GetConsoleOutputRequest generates a request for the GetConsoleOutput operation. -func (c *EC2) GetConsoleOutputRequest(input *GetConsoleOutputInput) (req *request.Request, output *GetConsoleOutputOutput) { - op := &request.Operation{ - Name: opGetConsoleOutput, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &GetConsoleOutputInput{} - } - - req = c.newRequest(op, input, output) - output = &GetConsoleOutputOutput{} - req.Data = output - return -} - -// Gets the console output for the specified instance. -// -// Instances do not have a physical monitor through which you can view their -// console output. They also lack physical controls that allow you to power -// up, reboot, or shut them down. To allow these actions, we provide them through -// the Amazon EC2 API and command line interface. -// -// Instance console output is buffered and posted shortly after instance boot, -// reboot, and termination. Amazon EC2 preserves the most recent 64 KB output -// which is available for at least one hour after the most recent post. -// -// For Linux instances, the instance console output displays the exact console -// output that would normally be displayed on a physical monitor attached to -// a computer. This output is buffered because the instance produces it and -// then posts it to a store where the instance's owner can retrieve it. -// -// For Windows instances, the instance console output includes output from -// the EC2Config service. -func (c *EC2) GetConsoleOutput(input *GetConsoleOutputInput) (*GetConsoleOutputOutput, error) { - req, out := c.GetConsoleOutputRequest(input) - err := req.Send() - return out, err -} - -const opGetPasswordData = "GetPasswordData" - -// GetPasswordDataRequest generates a request for the GetPasswordData operation. -func (c *EC2) GetPasswordDataRequest(input *GetPasswordDataInput) (req *request.Request, output *GetPasswordDataOutput) { - op := &request.Operation{ - Name: opGetPasswordData, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &GetPasswordDataInput{} - } - - req = c.newRequest(op, input, output) - output = &GetPasswordDataOutput{} - req.Data = output - return -} - -// Retrieves the encrypted administrator password for an instance running Windows. -// -// The Windows password is generated at boot if the EC2Config service plugin, -// Ec2SetPassword, is enabled. This usually only happens the first time an AMI -// is launched, and then Ec2SetPassword is automatically disabled. The password -// is not generated for rebundled AMIs unless Ec2SetPassword is enabled before -// bundling. -// -// The password is encrypted using the key pair that you specified when you -// launched the instance. You must provide the corresponding key pair file. -// -// Password generation and encryption takes a few moments. We recommend that -// you wait up to 15 minutes after launching an instance before trying to retrieve -// the generated password. -func (c *EC2) GetPasswordData(input *GetPasswordDataInput) (*GetPasswordDataOutput, error) { - req, out := c.GetPasswordDataRequest(input) - err := req.Send() - return out, err -} - -const opImportImage = "ImportImage" - -// ImportImageRequest generates a request for the ImportImage operation. -func (c *EC2) ImportImageRequest(input *ImportImageInput) (req *request.Request, output *ImportImageOutput) { - op := &request.Operation{ - Name: opImportImage, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ImportImageInput{} - } - - req = c.newRequest(op, input, output) - output = &ImportImageOutput{} - req.Data = output - return -} - -// Import single or multi-volume disk images or EBS snapshots into an Amazon -// Machine Image (AMI). -func (c *EC2) ImportImage(input *ImportImageInput) (*ImportImageOutput, error) { - req, out := c.ImportImageRequest(input) - err := req.Send() - return out, err -} - -const opImportInstance = "ImportInstance" - -// ImportInstanceRequest generates a request for the ImportInstance operation. -func (c *EC2) ImportInstanceRequest(input *ImportInstanceInput) (req *request.Request, output *ImportInstanceOutput) { - op := &request.Operation{ - Name: opImportInstance, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ImportInstanceInput{} - } - - req = c.newRequest(op, input, output) - output = &ImportInstanceOutput{} - req.Data = output - return -} - -// Creates an import instance task using metadata from the specified disk image. -// ImportInstance only supports single-volume VMs. To import multi-volume VMs, -// use ImportImage. After importing the image, you then upload it using the -// ec2-import-volume command in the EC2 command line tools. For more information, -// see Using the Command Line Tools to Import Your Virtual Machine to Amazon -// EC2 (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/UploadingYourInstancesandVolumes.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) ImportInstance(input *ImportInstanceInput) (*ImportInstanceOutput, error) { - req, out := c.ImportInstanceRequest(input) - err := req.Send() - return out, err -} - -const opImportKeyPair = "ImportKeyPair" - -// ImportKeyPairRequest generates a request for the ImportKeyPair operation. -func (c *EC2) ImportKeyPairRequest(input *ImportKeyPairInput) (req *request.Request, output *ImportKeyPairOutput) { - op := &request.Operation{ - Name: opImportKeyPair, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ImportKeyPairInput{} - } - - req = c.newRequest(op, input, output) - output = &ImportKeyPairOutput{} - req.Data = output - return -} - -// Imports the public key from an RSA key pair that you created with a third-party -// tool. Compare this with CreateKeyPair, in which AWS creates the key pair -// and gives the keys to you (AWS keeps a copy of the public key). With ImportKeyPair, -// you create the key pair and give AWS just the public key. The private key -// is never transferred between you and AWS. -// -// For more information about key pairs, see Key Pairs (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) ImportKeyPair(input *ImportKeyPairInput) (*ImportKeyPairOutput, error) { - req, out := c.ImportKeyPairRequest(input) - err := req.Send() - return out, err -} - -const opImportSnapshot = "ImportSnapshot" - -// ImportSnapshotRequest generates a request for the ImportSnapshot operation. -func (c *EC2) ImportSnapshotRequest(input *ImportSnapshotInput) (req *request.Request, output *ImportSnapshotOutput) { - op := &request.Operation{ - Name: opImportSnapshot, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ImportSnapshotInput{} - } - - req = c.newRequest(op, input, output) - output = &ImportSnapshotOutput{} - req.Data = output - return -} - -// Imports a disk into an EBS snapshot. -func (c *EC2) ImportSnapshot(input *ImportSnapshotInput) (*ImportSnapshotOutput, error) { - req, out := c.ImportSnapshotRequest(input) - err := req.Send() - return out, err -} - -const opImportVolume = "ImportVolume" - -// ImportVolumeRequest generates a request for the ImportVolume operation. -func (c *EC2) ImportVolumeRequest(input *ImportVolumeInput) (req *request.Request, output *ImportVolumeOutput) { - op := &request.Operation{ - Name: opImportVolume, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ImportVolumeInput{} - } - - req = c.newRequest(op, input, output) - output = &ImportVolumeOutput{} - req.Data = output - return -} - -// Creates an import volume task using metadata from the specified disk image. -// After importing the image, you then upload it using the ec2-import-volume -// command in the Amazon EC2 command-line interface (CLI) tools. For more information, -// see Using the Command Line Tools to Import Your Virtual Machine to Amazon -// EC2 (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/UploadingYourInstancesandVolumes.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) ImportVolume(input *ImportVolumeInput) (*ImportVolumeOutput, error) { - req, out := c.ImportVolumeRequest(input) - err := req.Send() - return out, err -} - -const opModifyImageAttribute = "ModifyImageAttribute" - -// ModifyImageAttributeRequest generates a request for the ModifyImageAttribute operation. -func (c *EC2) ModifyImageAttributeRequest(input *ModifyImageAttributeInput) (req *request.Request, output *ModifyImageAttributeOutput) { - op := &request.Operation{ - Name: opModifyImageAttribute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ModifyImageAttributeInput{} - } - - req = c.newRequest(op, input, output) - output = &ModifyImageAttributeOutput{} - req.Data = output - return -} - -// Modifies the specified attribute of the specified AMI. You can specify only -// one attribute at a time. -// -// AWS Marketplace product codes cannot be modified. Images with an AWS Marketplace -// product code cannot be made public. -func (c *EC2) ModifyImageAttribute(input *ModifyImageAttributeInput) (*ModifyImageAttributeOutput, error) { - req, out := c.ModifyImageAttributeRequest(input) - err := req.Send() - return out, err -} - -const opModifyInstanceAttribute = "ModifyInstanceAttribute" - -// ModifyInstanceAttributeRequest generates a request for the ModifyInstanceAttribute operation. -func (c *EC2) ModifyInstanceAttributeRequest(input *ModifyInstanceAttributeInput) (req *request.Request, output *ModifyInstanceAttributeOutput) { - op := &request.Operation{ - Name: opModifyInstanceAttribute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ModifyInstanceAttributeInput{} - } - - req = c.newRequest(op, input, output) - output = &ModifyInstanceAttributeOutput{} - req.Data = output - return -} - -// Modifies the specified attribute of the specified instance. You can specify -// only one attribute at a time. -// -// To modify some attributes, the instance must be stopped. For more information, -// see Modifying Attributes of a Stopped Instance (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_ChangingAttributesWhileInstanceStopped.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) ModifyInstanceAttribute(input *ModifyInstanceAttributeInput) (*ModifyInstanceAttributeOutput, error) { - req, out := c.ModifyInstanceAttributeRequest(input) - err := req.Send() - return out, err -} - -const opModifyNetworkInterfaceAttribute = "ModifyNetworkInterfaceAttribute" - -// ModifyNetworkInterfaceAttributeRequest generates a request for the ModifyNetworkInterfaceAttribute operation. -func (c *EC2) ModifyNetworkInterfaceAttributeRequest(input *ModifyNetworkInterfaceAttributeInput) (req *request.Request, output *ModifyNetworkInterfaceAttributeOutput) { - op := &request.Operation{ - Name: opModifyNetworkInterfaceAttribute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ModifyNetworkInterfaceAttributeInput{} - } - - req = c.newRequest(op, input, output) - output = &ModifyNetworkInterfaceAttributeOutput{} - req.Data = output - return -} - -// Modifies the specified network interface attribute. You can specify only -// one attribute at a time. -func (c *EC2) ModifyNetworkInterfaceAttribute(input *ModifyNetworkInterfaceAttributeInput) (*ModifyNetworkInterfaceAttributeOutput, error) { - req, out := c.ModifyNetworkInterfaceAttributeRequest(input) - err := req.Send() - return out, err -} - -const opModifyReservedInstances = "ModifyReservedInstances" - -// ModifyReservedInstancesRequest generates a request for the ModifyReservedInstances operation. -func (c *EC2) ModifyReservedInstancesRequest(input *ModifyReservedInstancesInput) (req *request.Request, output *ModifyReservedInstancesOutput) { - op := &request.Operation{ - Name: opModifyReservedInstances, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ModifyReservedInstancesInput{} - } - - req = c.newRequest(op, input, output) - output = &ModifyReservedInstancesOutput{} - req.Data = output - return -} - -// Modifies the Availability Zone, instance count, instance type, or network -// platform (EC2-Classic or EC2-VPC) of your Reserved Instances. The Reserved -// Instances to be modified must be identical, except for Availability Zone, -// network platform, and instance type. -// -// For more information, see Modifying Reserved Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ri-modifying.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) ModifyReservedInstances(input *ModifyReservedInstancesInput) (*ModifyReservedInstancesOutput, error) { - req, out := c.ModifyReservedInstancesRequest(input) - err := req.Send() - return out, err -} - -const opModifySnapshotAttribute = "ModifySnapshotAttribute" - -// ModifySnapshotAttributeRequest generates a request for the ModifySnapshotAttribute operation. -func (c *EC2) ModifySnapshotAttributeRequest(input *ModifySnapshotAttributeInput) (req *request.Request, output *ModifySnapshotAttributeOutput) { - op := &request.Operation{ - Name: opModifySnapshotAttribute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ModifySnapshotAttributeInput{} - } - - req = c.newRequest(op, input, output) - output = &ModifySnapshotAttributeOutput{} - req.Data = output - return -} - -// Adds or removes permission settings for the specified snapshot. You may add -// or remove specified AWS account IDs from a snapshot's list of create volume -// permissions, but you cannot do both in a single API call. If you need to -// both add and remove account IDs for a snapshot, you must use multiple API -// calls. -// -// For more information on modifying snapshot permissions, see Sharing Snapshots -// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-modifying-snapshot-permissions.html) -// in the Amazon Elastic Compute Cloud User Guide. -// -// Snapshots with AWS Marketplace product codes cannot be made public. -func (c *EC2) ModifySnapshotAttribute(input *ModifySnapshotAttributeInput) (*ModifySnapshotAttributeOutput, error) { - req, out := c.ModifySnapshotAttributeRequest(input) - err := req.Send() - return out, err -} - -const opModifySpotFleetRequest = "ModifySpotFleetRequest" - -// ModifySpotFleetRequestRequest generates a request for the ModifySpotFleetRequest operation. -func (c *EC2) ModifySpotFleetRequestRequest(input *ModifySpotFleetRequestInput) (req *request.Request, output *ModifySpotFleetRequestOutput) { - op := &request.Operation{ - Name: opModifySpotFleetRequest, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ModifySpotFleetRequestInput{} - } - - req = c.newRequest(op, input, output) - output = &ModifySpotFleetRequestOutput{} - req.Data = output - return -} - -// Modifies the specified Spot fleet request. -// -// While the Spot fleet request is being modified, it is in the modifying state. -// -// To scale up your Spot fleet, increase its target capacity. The Spot fleet -// launches the additional Spot instances according to the allocation strategy -// for the Spot fleet request. If the allocation strategy is lowestPrice, the -// Spot fleet launches instances using the Spot pool with the lowest price. -// If the allocation strategy is diversified, the Spot fleet distributes the -// instances across the Spot pools. -// -// To scale down your Spot fleet, decrease its target capacity. First, the -// Spot fleet cancels any open bids that exceed the new target capacity. You -// can request that the Spot fleet terminate Spot instances until the size of -// the fleet no longer exceeds the new target capacity. If the allocation strategy -// is lowestPrice, the Spot fleet terminates the instances with the highest -// price per unit. If the allocation strategy is diversified, the Spot fleet -// terminates instances across the Spot pools. Alternatively, you can request -// that the Spot fleet keep the fleet at its current size, but not replace any -// Spot instances that are interrupted or that you terminate manually. -func (c *EC2) ModifySpotFleetRequest(input *ModifySpotFleetRequestInput) (*ModifySpotFleetRequestOutput, error) { - req, out := c.ModifySpotFleetRequestRequest(input) - err := req.Send() - return out, err -} - -const opModifySubnetAttribute = "ModifySubnetAttribute" - -// ModifySubnetAttributeRequest generates a request for the ModifySubnetAttribute operation. -func (c *EC2) ModifySubnetAttributeRequest(input *ModifySubnetAttributeInput) (req *request.Request, output *ModifySubnetAttributeOutput) { - op := &request.Operation{ - Name: opModifySubnetAttribute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ModifySubnetAttributeInput{} - } - - req = c.newRequest(op, input, output) - output = &ModifySubnetAttributeOutput{} - req.Data = output - return -} - -// Modifies a subnet attribute. -func (c *EC2) ModifySubnetAttribute(input *ModifySubnetAttributeInput) (*ModifySubnetAttributeOutput, error) { - req, out := c.ModifySubnetAttributeRequest(input) - err := req.Send() - return out, err -} - -const opModifyVolumeAttribute = "ModifyVolumeAttribute" - -// ModifyVolumeAttributeRequest generates a request for the ModifyVolumeAttribute operation. -func (c *EC2) ModifyVolumeAttributeRequest(input *ModifyVolumeAttributeInput) (req *request.Request, output *ModifyVolumeAttributeOutput) { - op := &request.Operation{ - Name: opModifyVolumeAttribute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ModifyVolumeAttributeInput{} - } - - req = c.newRequest(op, input, output) - output = &ModifyVolumeAttributeOutput{} - req.Data = output - return -} - -// Modifies a volume attribute. -// -// By default, all I/O operations for the volume are suspended when the data -// on the volume is determined to be potentially inconsistent, to prevent undetectable, -// latent data corruption. The I/O access to the volume can be resumed by first -// enabling I/O access and then checking the data consistency on your volume. -// -// You can change the default behavior to resume I/O operations. We recommend -// that you change this only for boot volumes or for volumes that are stateless -// or disposable. -func (c *EC2) ModifyVolumeAttribute(input *ModifyVolumeAttributeInput) (*ModifyVolumeAttributeOutput, error) { - req, out := c.ModifyVolumeAttributeRequest(input) - err := req.Send() - return out, err -} - -const opModifyVpcAttribute = "ModifyVpcAttribute" - -// ModifyVpcAttributeRequest generates a request for the ModifyVpcAttribute operation. -func (c *EC2) ModifyVpcAttributeRequest(input *ModifyVpcAttributeInput) (req *request.Request, output *ModifyVpcAttributeOutput) { - op := &request.Operation{ - Name: opModifyVpcAttribute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ModifyVpcAttributeInput{} - } - - req = c.newRequest(op, input, output) - output = &ModifyVpcAttributeOutput{} - req.Data = output - return -} - -// Modifies the specified attribute of the specified VPC. -func (c *EC2) ModifyVpcAttribute(input *ModifyVpcAttributeInput) (*ModifyVpcAttributeOutput, error) { - req, out := c.ModifyVpcAttributeRequest(input) - err := req.Send() - return out, err -} - -const opModifyVpcEndpoint = "ModifyVpcEndpoint" - -// ModifyVpcEndpointRequest generates a request for the ModifyVpcEndpoint operation. -func (c *EC2) ModifyVpcEndpointRequest(input *ModifyVpcEndpointInput) (req *request.Request, output *ModifyVpcEndpointOutput) { - op := &request.Operation{ - Name: opModifyVpcEndpoint, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ModifyVpcEndpointInput{} - } - - req = c.newRequest(op, input, output) - output = &ModifyVpcEndpointOutput{} - req.Data = output - return -} - -// Modifies attributes of a specified VPC endpoint. You can modify the policy -// associated with the endpoint, and you can add and remove route tables associated -// with the endpoint. -func (c *EC2) ModifyVpcEndpoint(input *ModifyVpcEndpointInput) (*ModifyVpcEndpointOutput, error) { - req, out := c.ModifyVpcEndpointRequest(input) - err := req.Send() - return out, err -} - -const opMonitorInstances = "MonitorInstances" - -// MonitorInstancesRequest generates a request for the MonitorInstances operation. -func (c *EC2) MonitorInstancesRequest(input *MonitorInstancesInput) (req *request.Request, output *MonitorInstancesOutput) { - op := &request.Operation{ - Name: opMonitorInstances, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &MonitorInstancesInput{} - } - - req = c.newRequest(op, input, output) - output = &MonitorInstancesOutput{} - req.Data = output - return -} - -// Enables monitoring for a running instance. For more information about monitoring -// instances, see Monitoring Your Instances and Volumes (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-cloudwatch.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) MonitorInstances(input *MonitorInstancesInput) (*MonitorInstancesOutput, error) { - req, out := c.MonitorInstancesRequest(input) - err := req.Send() - return out, err -} - -const opMoveAddressToVpc = "MoveAddressToVpc" - -// MoveAddressToVpcRequest generates a request for the MoveAddressToVpc operation. -func (c *EC2) MoveAddressToVpcRequest(input *MoveAddressToVpcInput) (req *request.Request, output *MoveAddressToVpcOutput) { - op := &request.Operation{ - Name: opMoveAddressToVpc, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &MoveAddressToVpcInput{} - } - - req = c.newRequest(op, input, output) - output = &MoveAddressToVpcOutput{} - req.Data = output - return -} - -// Moves an Elastic IP address from the EC2-Classic platform to the EC2-VPC -// platform. The Elastic IP address must be allocated to your account, and it -// must not be associated with an instance. After the Elastic IP address is -// moved, it is no longer available for use in the EC2-Classic platform, unless -// you move it back using the RestoreAddressToClassic request. You cannot move -// an Elastic IP address that's allocated for use in the EC2-VPC platform to -// the EC2-Classic platform. -func (c *EC2) MoveAddressToVpc(input *MoveAddressToVpcInput) (*MoveAddressToVpcOutput, error) { - req, out := c.MoveAddressToVpcRequest(input) - err := req.Send() - return out, err -} - -const opPurchaseReservedInstancesOffering = "PurchaseReservedInstancesOffering" - -// PurchaseReservedInstancesOfferingRequest generates a request for the PurchaseReservedInstancesOffering operation. -func (c *EC2) PurchaseReservedInstancesOfferingRequest(input *PurchaseReservedInstancesOfferingInput) (req *request.Request, output *PurchaseReservedInstancesOfferingOutput) { - op := &request.Operation{ - Name: opPurchaseReservedInstancesOffering, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &PurchaseReservedInstancesOfferingInput{} - } - - req = c.newRequest(op, input, output) - output = &PurchaseReservedInstancesOfferingOutput{} - req.Data = output - return -} - -// Purchases a Reserved Instance for use with your account. With Amazon EC2 -// Reserved Instances, you obtain a capacity reservation for a certain instance -// configuration over a specified period of time and pay a lower hourly rate -// compared to on-Demand Instance pricing. -// -// Use DescribeReservedInstancesOfferings to get a list of Reserved Instance -// offerings that match your specifications. After you've purchased a Reserved -// Instance, you can check for your new Reserved Instance with DescribeReservedInstances. -// -// For more information, see Reserved Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/concepts-on-demand-reserved-instances.html) -// and Reserved Instance Marketplace (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ri-market-general.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) PurchaseReservedInstancesOffering(input *PurchaseReservedInstancesOfferingInput) (*PurchaseReservedInstancesOfferingOutput, error) { - req, out := c.PurchaseReservedInstancesOfferingRequest(input) - err := req.Send() - return out, err -} - -const opRebootInstances = "RebootInstances" - -// RebootInstancesRequest generates a request for the RebootInstances operation. -func (c *EC2) RebootInstancesRequest(input *RebootInstancesInput) (req *request.Request, output *RebootInstancesOutput) { - op := &request.Operation{ - Name: opRebootInstances, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &RebootInstancesInput{} - } - - req = c.newRequest(op, input, output) - output = &RebootInstancesOutput{} - req.Data = output - return -} - -// Requests a reboot of one or more instances. This operation is asynchronous; -// it only queues a request to reboot the specified instances. The operation -// succeeds if the instances are valid and belong to you. Requests to reboot -// terminated instances are ignored. -// -// If a Linux/Unix instance does not cleanly shut down within four minutes, -// Amazon EC2 performs a hard reboot. -// -// For more information about troubleshooting, see Getting Console Output and -// Rebooting Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-console.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) RebootInstances(input *RebootInstancesInput) (*RebootInstancesOutput, error) { - req, out := c.RebootInstancesRequest(input) - err := req.Send() - return out, err -} - -const opRegisterImage = "RegisterImage" - -// RegisterImageRequest generates a request for the RegisterImage operation. -func (c *EC2) RegisterImageRequest(input *RegisterImageInput) (req *request.Request, output *RegisterImageOutput) { - op := &request.Operation{ - Name: opRegisterImage, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &RegisterImageInput{} - } - - req = c.newRequest(op, input, output) - output = &RegisterImageOutput{} - req.Data = output - return -} - -// Registers an AMI. When you're creating an AMI, this is the final step you -// must complete before you can launch an instance from the AMI. For more information -// about creating AMIs, see Creating Your Own AMIs (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/creating-an-ami.html) -// in the Amazon Elastic Compute Cloud User Guide. -// -// For Amazon EBS-backed instances, CreateImage creates and registers the AMI -// in a single request, so you don't have to register the AMI yourself. -// -// You can also use RegisterImage to create an Amazon EBS-backed Linux AMI -// from a snapshot of a root device volume. For more information, see Launching -// an Instance from a Snapshot (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_LaunchingInstanceFromSnapshot.html) -// in the Amazon Elastic Compute Cloud User Guide. -// -// Some Linux distributions, such as Red Hat Enterprise Linux (RHEL) and SUSE -// Linux Enterprise Server (SLES), use the EC2 billingProduct code associated -// with an AMI to verify subscription status for package updates. Creating an -// AMI from an EBS snapshot does not maintain this billing code, and subsequent -// instances launched from such an AMI will not be able to connect to package -// update infrastructure. -// -// Similarly, although you can create a Windows AMI from a snapshot, you can't -// successfully launch an instance from the AMI. -// -// To create Windows AMIs or to create AMIs for Linux operating systems that -// must retain AMI billing codes to work properly, see CreateImage. -// -// If needed, you can deregister an AMI at any time. Any modifications you -// make to an AMI backed by an instance store volume invalidates its registration. -// If you make changes to an image, deregister the previous image and register -// the new image. -// -// You can't register an image where a secondary (non-root) snapshot has AWS -// Marketplace product codes. -func (c *EC2) RegisterImage(input *RegisterImageInput) (*RegisterImageOutput, error) { - req, out := c.RegisterImageRequest(input) - err := req.Send() - return out, err -} - -const opRejectVpcPeeringConnection = "RejectVpcPeeringConnection" - -// RejectVpcPeeringConnectionRequest generates a request for the RejectVpcPeeringConnection operation. -func (c *EC2) RejectVpcPeeringConnectionRequest(input *RejectVpcPeeringConnectionInput) (req *request.Request, output *RejectVpcPeeringConnectionOutput) { - op := &request.Operation{ - Name: opRejectVpcPeeringConnection, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &RejectVpcPeeringConnectionInput{} - } - - req = c.newRequest(op, input, output) - output = &RejectVpcPeeringConnectionOutput{} - req.Data = output - return -} - -// Rejects a VPC peering connection request. The VPC peering connection must -// be in the pending-acceptance state. Use the DescribeVpcPeeringConnections -// request to view your outstanding VPC peering connection requests. To delete -// an active VPC peering connection, or to delete a VPC peering connection request -// that you initiated, use DeleteVpcPeeringConnection. -func (c *EC2) RejectVpcPeeringConnection(input *RejectVpcPeeringConnectionInput) (*RejectVpcPeeringConnectionOutput, error) { - req, out := c.RejectVpcPeeringConnectionRequest(input) - err := req.Send() - return out, err -} - -const opReleaseAddress = "ReleaseAddress" - -// ReleaseAddressRequest generates a request for the ReleaseAddress operation. -func (c *EC2) ReleaseAddressRequest(input *ReleaseAddressInput) (req *request.Request, output *ReleaseAddressOutput) { - op := &request.Operation{ - Name: opReleaseAddress, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ReleaseAddressInput{} - } - - req = c.newRequest(op, input, output) - output = &ReleaseAddressOutput{} - req.Data = output - return -} - -// Releases the specified Elastic IP address. -// -// After releasing an Elastic IP address, it is released to the IP address -// pool and might be unavailable to you. Be sure to update your DNS records -// and any servers or devices that communicate with the address. If you attempt -// to release an Elastic IP address that you already released, you'll get an -// AuthFailure error if the address is already allocated to another AWS account. -// -// [EC2-Classic, default VPC] Releasing an Elastic IP address automatically -// disassociates it from any instance that it's associated with. To disassociate -// an Elastic IP address without releasing it, use DisassociateAddress. -// -// [Nondefault VPC] You must use DisassociateAddress to disassociate the Elastic -// IP address before you try to release it. Otherwise, Amazon EC2 returns an -// error (InvalidIPAddress.InUse). -func (c *EC2) ReleaseAddress(input *ReleaseAddressInput) (*ReleaseAddressOutput, error) { - req, out := c.ReleaseAddressRequest(input) - err := req.Send() - return out, err -} - -const opReplaceNetworkAclAssociation = "ReplaceNetworkAclAssociation" - -// ReplaceNetworkAclAssociationRequest generates a request for the ReplaceNetworkAclAssociation operation. -func (c *EC2) ReplaceNetworkAclAssociationRequest(input *ReplaceNetworkAclAssociationInput) (req *request.Request, output *ReplaceNetworkAclAssociationOutput) { - op := &request.Operation{ - Name: opReplaceNetworkAclAssociation, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ReplaceNetworkAclAssociationInput{} - } - - req = c.newRequest(op, input, output) - output = &ReplaceNetworkAclAssociationOutput{} - req.Data = output - return -} - -// Changes which network ACL a subnet is associated with. By default when you -// create a subnet, it's automatically associated with the default network ACL. -// For more information about network ACLs, see Network ACLs (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_ACLs.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) ReplaceNetworkAclAssociation(input *ReplaceNetworkAclAssociationInput) (*ReplaceNetworkAclAssociationOutput, error) { - req, out := c.ReplaceNetworkAclAssociationRequest(input) - err := req.Send() - return out, err -} - -const opReplaceNetworkAclEntry = "ReplaceNetworkAclEntry" - -// ReplaceNetworkAclEntryRequest generates a request for the ReplaceNetworkAclEntry operation. -func (c *EC2) ReplaceNetworkAclEntryRequest(input *ReplaceNetworkAclEntryInput) (req *request.Request, output *ReplaceNetworkAclEntryOutput) { - op := &request.Operation{ - Name: opReplaceNetworkAclEntry, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ReplaceNetworkAclEntryInput{} - } - - req = c.newRequest(op, input, output) - output = &ReplaceNetworkAclEntryOutput{} - req.Data = output - return -} - -// Replaces an entry (rule) in a network ACL. For more information about network -// ACLs, see Network ACLs (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_ACLs.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) ReplaceNetworkAclEntry(input *ReplaceNetworkAclEntryInput) (*ReplaceNetworkAclEntryOutput, error) { - req, out := c.ReplaceNetworkAclEntryRequest(input) - err := req.Send() - return out, err -} - -const opReplaceRoute = "ReplaceRoute" - -// ReplaceRouteRequest generates a request for the ReplaceRoute operation. -func (c *EC2) ReplaceRouteRequest(input *ReplaceRouteInput) (req *request.Request, output *ReplaceRouteOutput) { - op := &request.Operation{ - Name: opReplaceRoute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ReplaceRouteInput{} - } - - req = c.newRequest(op, input, output) - output = &ReplaceRouteOutput{} - req.Data = output - return -} - -// Replaces an existing route within a route table in a VPC. You must provide -// only one of the following: Internet gateway or virtual private gateway, NAT -// instance, VPC peering connection, or network interface. -// -// For more information about route tables, see Route Tables (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Route_Tables.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) ReplaceRoute(input *ReplaceRouteInput) (*ReplaceRouteOutput, error) { - req, out := c.ReplaceRouteRequest(input) - err := req.Send() - return out, err -} - -const opReplaceRouteTableAssociation = "ReplaceRouteTableAssociation" - -// ReplaceRouteTableAssociationRequest generates a request for the ReplaceRouteTableAssociation operation. -func (c *EC2) ReplaceRouteTableAssociationRequest(input *ReplaceRouteTableAssociationInput) (req *request.Request, output *ReplaceRouteTableAssociationOutput) { - op := &request.Operation{ - Name: opReplaceRouteTableAssociation, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ReplaceRouteTableAssociationInput{} - } - - req = c.newRequest(op, input, output) - output = &ReplaceRouteTableAssociationOutput{} - req.Data = output - return -} - -// Changes the route table associated with a given subnet in a VPC. After the -// operation completes, the subnet uses the routes in the new route table it's -// associated with. For more information about route tables, see Route Tables -// (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Route_Tables.html) -// in the Amazon Virtual Private Cloud User Guide. -// -// You can also use ReplaceRouteTableAssociation to change which table is the -// main route table in the VPC. You just specify the main route table's association -// ID and the route table to be the new main route table. -func (c *EC2) ReplaceRouteTableAssociation(input *ReplaceRouteTableAssociationInput) (*ReplaceRouteTableAssociationOutput, error) { - req, out := c.ReplaceRouteTableAssociationRequest(input) - err := req.Send() - return out, err -} - -const opReportInstanceStatus = "ReportInstanceStatus" - -// ReportInstanceStatusRequest generates a request for the ReportInstanceStatus operation. -func (c *EC2) ReportInstanceStatusRequest(input *ReportInstanceStatusInput) (req *request.Request, output *ReportInstanceStatusOutput) { - op := &request.Operation{ - Name: opReportInstanceStatus, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ReportInstanceStatusInput{} - } - - req = c.newRequest(op, input, output) - output = &ReportInstanceStatusOutput{} - req.Data = output - return -} - -// Submits feedback about the status of an instance. The instance must be in -// the running state. If your experience with the instance differs from the -// instance status returned by DescribeInstanceStatus, use ReportInstanceStatus -// to report your experience with the instance. Amazon EC2 collects this information -// to improve the accuracy of status checks. -// -// Use of this action does not change the value returned by DescribeInstanceStatus. -func (c *EC2) ReportInstanceStatus(input *ReportInstanceStatusInput) (*ReportInstanceStatusOutput, error) { - req, out := c.ReportInstanceStatusRequest(input) - err := req.Send() - return out, err -} - -const opRequestSpotFleet = "RequestSpotFleet" - -// RequestSpotFleetRequest generates a request for the RequestSpotFleet operation. -func (c *EC2) RequestSpotFleetRequest(input *RequestSpotFleetInput) (req *request.Request, output *RequestSpotFleetOutput) { - op := &request.Operation{ - Name: opRequestSpotFleet, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &RequestSpotFleetInput{} - } - - req = c.newRequest(op, input, output) - output = &RequestSpotFleetOutput{} - req.Data = output - return -} - -// Creates a Spot fleet request. -// -// You can submit a single request that includes multiple launch specifications -// that vary by instance type, AMI, Availability Zone, or subnet. -// -// By default, the Spot fleet requests Spot instances in the Spot pool where -// the price per unit is the lowest. Each launch specification can include its -// own instance weighting that reflects the value of the instance type to your -// application workload. -// -// Alternatively, you can specify that the Spot fleet distribute the target -// capacity across the Spot pools included in its launch specifications. By -// ensuring that the Spot instances in your Spot fleet are in different Spot -// pools, you can improve the availability of your fleet. -// -// For more information, see Spot Fleet Requests (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-fleet-requests.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) RequestSpotFleet(input *RequestSpotFleetInput) (*RequestSpotFleetOutput, error) { - req, out := c.RequestSpotFleetRequest(input) - err := req.Send() - return out, err -} - -const opRequestSpotInstances = "RequestSpotInstances" - -// RequestSpotInstancesRequest generates a request for the RequestSpotInstances operation. -func (c *EC2) RequestSpotInstancesRequest(input *RequestSpotInstancesInput) (req *request.Request, output *RequestSpotInstancesOutput) { - op := &request.Operation{ - Name: opRequestSpotInstances, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &RequestSpotInstancesInput{} - } - - req = c.newRequest(op, input, output) - output = &RequestSpotInstancesOutput{} - req.Data = output - return -} - -// Creates a Spot instance request. Spot instances are instances that Amazon -// EC2 launches when the bid price that you specify exceeds the current Spot -// price. Amazon EC2 periodically sets the Spot price based on available Spot -// Instance capacity and current Spot instance requests. For more information, -// see Spot Instance Requests (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-requests.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) RequestSpotInstances(input *RequestSpotInstancesInput) (*RequestSpotInstancesOutput, error) { - req, out := c.RequestSpotInstancesRequest(input) - err := req.Send() - return out, err -} - -const opResetImageAttribute = "ResetImageAttribute" - -// ResetImageAttributeRequest generates a request for the ResetImageAttribute operation. -func (c *EC2) ResetImageAttributeRequest(input *ResetImageAttributeInput) (req *request.Request, output *ResetImageAttributeOutput) { - op := &request.Operation{ - Name: opResetImageAttribute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ResetImageAttributeInput{} - } - - req = c.newRequest(op, input, output) - output = &ResetImageAttributeOutput{} - req.Data = output - return -} - -// Resets an attribute of an AMI to its default value. -// -// The productCodes attribute can't be reset. -func (c *EC2) ResetImageAttribute(input *ResetImageAttributeInput) (*ResetImageAttributeOutput, error) { - req, out := c.ResetImageAttributeRequest(input) - err := req.Send() - return out, err -} - -const opResetInstanceAttribute = "ResetInstanceAttribute" - -// ResetInstanceAttributeRequest generates a request for the ResetInstanceAttribute operation. -func (c *EC2) ResetInstanceAttributeRequest(input *ResetInstanceAttributeInput) (req *request.Request, output *ResetInstanceAttributeOutput) { - op := &request.Operation{ - Name: opResetInstanceAttribute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ResetInstanceAttributeInput{} - } - - req = c.newRequest(op, input, output) - output = &ResetInstanceAttributeOutput{} - req.Data = output - return -} - -// Resets an attribute of an instance to its default value. To reset the kernel -// or ramdisk, the instance must be in a stopped state. To reset the SourceDestCheck, -// the instance can be either running or stopped. -// -// The SourceDestCheck attribute controls whether source/destination checking -// is enabled. The default value is true, which means checking is enabled. This -// value must be false for a NAT instance to perform NAT. For more information, -// see NAT Instances (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_NAT_Instance.html) -// in the Amazon Virtual Private Cloud User Guide. -func (c *EC2) ResetInstanceAttribute(input *ResetInstanceAttributeInput) (*ResetInstanceAttributeOutput, error) { - req, out := c.ResetInstanceAttributeRequest(input) - err := req.Send() - return out, err -} - -const opResetNetworkInterfaceAttribute = "ResetNetworkInterfaceAttribute" - -// ResetNetworkInterfaceAttributeRequest generates a request for the ResetNetworkInterfaceAttribute operation. -func (c *EC2) ResetNetworkInterfaceAttributeRequest(input *ResetNetworkInterfaceAttributeInput) (req *request.Request, output *ResetNetworkInterfaceAttributeOutput) { - op := &request.Operation{ - Name: opResetNetworkInterfaceAttribute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ResetNetworkInterfaceAttributeInput{} - } - - req = c.newRequest(op, input, output) - output = &ResetNetworkInterfaceAttributeOutput{} - req.Data = output - return -} - -// Resets a network interface attribute. You can specify only one attribute -// at a time. -func (c *EC2) ResetNetworkInterfaceAttribute(input *ResetNetworkInterfaceAttributeInput) (*ResetNetworkInterfaceAttributeOutput, error) { - req, out := c.ResetNetworkInterfaceAttributeRequest(input) - err := req.Send() - return out, err -} - -const opResetSnapshotAttribute = "ResetSnapshotAttribute" - -// ResetSnapshotAttributeRequest generates a request for the ResetSnapshotAttribute operation. -func (c *EC2) ResetSnapshotAttributeRequest(input *ResetSnapshotAttributeInput) (req *request.Request, output *ResetSnapshotAttributeOutput) { - op := &request.Operation{ - Name: opResetSnapshotAttribute, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &ResetSnapshotAttributeInput{} - } - - req = c.newRequest(op, input, output) - output = &ResetSnapshotAttributeOutput{} - req.Data = output - return -} - -// Resets permission settings for the specified snapshot. -// -// For more information on modifying snapshot permissions, see Sharing Snapshots -// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-modifying-snapshot-permissions.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) ResetSnapshotAttribute(input *ResetSnapshotAttributeInput) (*ResetSnapshotAttributeOutput, error) { - req, out := c.ResetSnapshotAttributeRequest(input) - err := req.Send() - return out, err -} - -const opRestoreAddressToClassic = "RestoreAddressToClassic" - -// RestoreAddressToClassicRequest generates a request for the RestoreAddressToClassic operation. -func (c *EC2) RestoreAddressToClassicRequest(input *RestoreAddressToClassicInput) (req *request.Request, output *RestoreAddressToClassicOutput) { - op := &request.Operation{ - Name: opRestoreAddressToClassic, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &RestoreAddressToClassicInput{} - } - - req = c.newRequest(op, input, output) - output = &RestoreAddressToClassicOutput{} - req.Data = output - return -} - -// Restores an Elastic IP address that was previously moved to the EC2-VPC platform -// back to the EC2-Classic platform. You cannot move an Elastic IP address that -// was originally allocated for use in EC2-VPC. The Elastic IP address must -// not be associated with an instance or network interface. -func (c *EC2) RestoreAddressToClassic(input *RestoreAddressToClassicInput) (*RestoreAddressToClassicOutput, error) { - req, out := c.RestoreAddressToClassicRequest(input) - err := req.Send() - return out, err -} - -const opRevokeSecurityGroupEgress = "RevokeSecurityGroupEgress" - -// RevokeSecurityGroupEgressRequest generates a request for the RevokeSecurityGroupEgress operation. -func (c *EC2) RevokeSecurityGroupEgressRequest(input *RevokeSecurityGroupEgressInput) (req *request.Request, output *RevokeSecurityGroupEgressOutput) { - op := &request.Operation{ - Name: opRevokeSecurityGroupEgress, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &RevokeSecurityGroupEgressInput{} - } - - req = c.newRequest(op, input, output) - output = &RevokeSecurityGroupEgressOutput{} - req.Data = output - return -} - -// Removes one or more egress rules from a security group for EC2-VPC. The values -// that you specify in the revoke request (for example, ports) must match the -// existing rule's values for the rule to be revoked. -// -// Each rule consists of the protocol and the CIDR range or source security -// group. For the TCP and UDP protocols, you must also specify the destination -// port or range of ports. For the ICMP protocol, you must also specify the -// ICMP type and code. -// -// Rule changes are propagated to instances within the security group as quickly -// as possible. However, a small delay might occur. -func (c *EC2) RevokeSecurityGroupEgress(input *RevokeSecurityGroupEgressInput) (*RevokeSecurityGroupEgressOutput, error) { - req, out := c.RevokeSecurityGroupEgressRequest(input) - err := req.Send() - return out, err -} - -const opRevokeSecurityGroupIngress = "RevokeSecurityGroupIngress" - -// RevokeSecurityGroupIngressRequest generates a request for the RevokeSecurityGroupIngress operation. -func (c *EC2) RevokeSecurityGroupIngressRequest(input *RevokeSecurityGroupIngressInput) (req *request.Request, output *RevokeSecurityGroupIngressOutput) { - op := &request.Operation{ - Name: opRevokeSecurityGroupIngress, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &RevokeSecurityGroupIngressInput{} - } - - req = c.newRequest(op, input, output) - output = &RevokeSecurityGroupIngressOutput{} - req.Data = output - return -} - -// Removes one or more ingress rules from a security group. The values that -// you specify in the revoke request (for example, ports) must match the existing -// rule's values for the rule to be removed. -// -// Each rule consists of the protocol and the CIDR range or source security -// group. For the TCP and UDP protocols, you must also specify the destination -// port or range of ports. For the ICMP protocol, you must also specify the -// ICMP type and code. -// -// Rule changes are propagated to instances within the security group as quickly -// as possible. However, a small delay might occur. -func (c *EC2) RevokeSecurityGroupIngress(input *RevokeSecurityGroupIngressInput) (*RevokeSecurityGroupIngressOutput, error) { - req, out := c.RevokeSecurityGroupIngressRequest(input) - err := req.Send() - return out, err -} - -const opRunInstances = "RunInstances" - -// RunInstancesRequest generates a request for the RunInstances operation. -func (c *EC2) RunInstancesRequest(input *RunInstancesInput) (req *request.Request, output *Reservation) { - op := &request.Operation{ - Name: opRunInstances, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &RunInstancesInput{} - } - - req = c.newRequest(op, input, output) - output = &Reservation{} - req.Data = output - return -} - -// Launches the specified number of instances using an AMI for which you have -// permissions. -// -// When you launch an instance, it enters the pending state. After the instance -// is ready for you, it enters the running state. To check the state of your -// instance, call DescribeInstances. -// -// If you don't specify a security group when launching an instance, Amazon -// EC2 uses the default security group. For more information, see Security Groups -// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-network-security.html) -// in the Amazon Elastic Compute Cloud User Guide. -// -// [EC2-VPC only accounts] If you don't specify a subnet in the request, we -// choose a default subnet from your default VPC for you. -// -// [EC2-Classic accounts] If you're launching into EC2-Classic and you don't -// specify an Availability Zone, we choose one for you. -// -// Linux instances have access to the public key of the key pair at boot. You -// can use this key to provide secure access to the instance. Amazon EC2 public -// images use this feature to provide secure access without passwords. For more -// information, see Key Pairs (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) -// in the Amazon Elastic Compute Cloud User Guide. -// -// You can provide optional user data when launching an instance. For more -// information, see Instance Metadata (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html) -// in the Amazon Elastic Compute Cloud User Guide. -// -// If any of the AMIs have a product code attached for which the user has not -// subscribed, RunInstances fails. -// -// T2 instance types can only be launched into a VPC. If you do not have a -// default VPC, or if you do not specify a subnet ID in the request, RunInstances -// fails. -// -// For more information about troubleshooting, see What To Do If An Instance -// Immediately Terminates (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_InstanceStraightToTerminated.html), -// and Troubleshooting Connecting to Your Instance (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/TroubleshootingInstancesConnecting.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) RunInstances(input *RunInstancesInput) (*Reservation, error) { - req, out := c.RunInstancesRequest(input) - err := req.Send() - return out, err -} - -const opStartInstances = "StartInstances" - -// StartInstancesRequest generates a request for the StartInstances operation. -func (c *EC2) StartInstancesRequest(input *StartInstancesInput) (req *request.Request, output *StartInstancesOutput) { - op := &request.Operation{ - Name: opStartInstances, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &StartInstancesInput{} - } - - req = c.newRequest(op, input, output) - output = &StartInstancesOutput{} - req.Data = output - return -} - -// Starts an Amazon EBS-backed AMI that you've previously stopped. -// -// Instances that use Amazon EBS volumes as their root devices can be quickly -// stopped and started. When an instance is stopped, the compute resources are -// released and you are not billed for hourly instance usage. However, your -// root partition Amazon EBS volume remains, continues to persist your data, -// and you are charged for Amazon EBS volume usage. You can restart your instance -// at any time. Each time you transition an instance from stopped to started, -// Amazon EC2 charges a full instance hour, even if transitions happen multiple -// times within a single hour. -// -// Before stopping an instance, make sure it is in a state from which it can -// be restarted. Stopping an instance does not preserve data stored in RAM. -// -// Performing this operation on an instance that uses an instance store as -// its root device returns an error. -// -// For more information, see Stopping Instances (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Stop_Start.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) StartInstances(input *StartInstancesInput) (*StartInstancesOutput, error) { - req, out := c.StartInstancesRequest(input) - err := req.Send() - return out, err -} - -const opStopInstances = "StopInstances" - -// StopInstancesRequest generates a request for the StopInstances operation. -func (c *EC2) StopInstancesRequest(input *StopInstancesInput) (req *request.Request, output *StopInstancesOutput) { - op := &request.Operation{ - Name: opStopInstances, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &StopInstancesInput{} - } - - req = c.newRequest(op, input, output) - output = &StopInstancesOutput{} - req.Data = output - return -} - -// Stops an Amazon EBS-backed instance. Each time you transition an instance -// from stopped to started, Amazon EC2 charges a full instance hour, even if -// transitions happen multiple times within a single hour. -// -// You can't start or stop Spot Instances. -// -// Instances that use Amazon EBS volumes as their root devices can be quickly -// stopped and started. When an instance is stopped, the compute resources are -// released and you are not billed for hourly instance usage. However, your -// root partition Amazon EBS volume remains, continues to persist your data, -// and you are charged for Amazon EBS volume usage. You can restart your instance -// at any time. -// -// Before stopping an instance, make sure it is in a state from which it can -// be restarted. Stopping an instance does not preserve data stored in RAM. -// -// Performing this operation on an instance that uses an instance store as -// its root device returns an error. -// -// You can stop, start, and terminate EBS-backed instances. You can only terminate -// instance store-backed instances. What happens to an instance differs if you -// stop it or terminate it. For example, when you stop an instance, the root -// device and any other devices attached to the instance persist. When you terminate -// an instance, the root device and any other devices attached during the instance -// launch are automatically deleted. For more information about the differences -// between stopping and terminating instances, see Instance Lifecycle (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html) -// in the Amazon Elastic Compute Cloud User Guide. -// -// For more information about troubleshooting, see Troubleshooting Stopping -// Your Instance (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/TroubleshootingInstancesStopping.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) StopInstances(input *StopInstancesInput) (*StopInstancesOutput, error) { - req, out := c.StopInstancesRequest(input) - err := req.Send() - return out, err -} - -const opTerminateInstances = "TerminateInstances" - -// TerminateInstancesRequest generates a request for the TerminateInstances operation. -func (c *EC2) TerminateInstancesRequest(input *TerminateInstancesInput) (req *request.Request, output *TerminateInstancesOutput) { - op := &request.Operation{ - Name: opTerminateInstances, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &TerminateInstancesInput{} - } - - req = c.newRequest(op, input, output) - output = &TerminateInstancesOutput{} - req.Data = output - return -} - -// Shuts down one or more instances. This operation is idempotent; if you terminate -// an instance more than once, each call succeeds. -// -// Terminated instances remain visible after termination (for approximately -// one hour). -// -// By default, Amazon EC2 deletes all EBS volumes that were attached when the -// instance launched. Volumes attached after instance launch continue running. -// -// You can stop, start, and terminate EBS-backed instances. You can only terminate -// instance store-backed instances. What happens to an instance differs if you -// stop it or terminate it. For example, when you stop an instance, the root -// device and any other devices attached to the instance persist. When you terminate -// an instance, any attached EBS volumes with the DeleteOnTermination block -// device mapping parameter set to true are automatically deleted. For more -// information about the differences between stopping and terminating instances, -// see Instance Lifecycle (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html) -// in the Amazon Elastic Compute Cloud User Guide. -// -// For more information about troubleshooting, see Troubleshooting Terminating -// Your Instance (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/TroubleshootingInstancesShuttingDown.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) TerminateInstances(input *TerminateInstancesInput) (*TerminateInstancesOutput, error) { - req, out := c.TerminateInstancesRequest(input) - err := req.Send() - return out, err -} - -const opUnassignPrivateIpAddresses = "UnassignPrivateIpAddresses" - -// UnassignPrivateIpAddressesRequest generates a request for the UnassignPrivateIpAddresses operation. -func (c *EC2) UnassignPrivateIpAddressesRequest(input *UnassignPrivateIpAddressesInput) (req *request.Request, output *UnassignPrivateIpAddressesOutput) { - op := &request.Operation{ - Name: opUnassignPrivateIpAddresses, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &UnassignPrivateIpAddressesInput{} - } - - req = c.newRequest(op, input, output) - output = &UnassignPrivateIpAddressesOutput{} - req.Data = output - return -} - -// Unassigns one or more secondary private IP addresses from a network interface. -func (c *EC2) UnassignPrivateIpAddresses(input *UnassignPrivateIpAddressesInput) (*UnassignPrivateIpAddressesOutput, error) { - req, out := c.UnassignPrivateIpAddressesRequest(input) - err := req.Send() - return out, err -} - -const opUnmonitorInstances = "UnmonitorInstances" - -// UnmonitorInstancesRequest generates a request for the UnmonitorInstances operation. -func (c *EC2) UnmonitorInstancesRequest(input *UnmonitorInstancesInput) (req *request.Request, output *UnmonitorInstancesOutput) { - op := &request.Operation{ - Name: opUnmonitorInstances, - HTTPMethod: "POST", - HTTPPath: "/", - } - - if input == nil { - input = &UnmonitorInstancesInput{} - } - - req = c.newRequest(op, input, output) - output = &UnmonitorInstancesOutput{} - req.Data = output - return -} - -// Disables monitoring for a running instance. For more information about monitoring -// instances, see Monitoring Your Instances and Volumes (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-cloudwatch.html) -// in the Amazon Elastic Compute Cloud User Guide. -func (c *EC2) UnmonitorInstances(input *UnmonitorInstancesInput) (*UnmonitorInstancesOutput, error) { - req, out := c.UnmonitorInstancesRequest(input) - err := req.Send() - return out, err -} - -type AcceptVpcPeeringConnectionInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the VPC peering connection. - VpcPeeringConnectionId *string `locationName:"vpcPeeringConnectionId" type:"string"` - - metadataAcceptVpcPeeringConnectionInput `json:"-" xml:"-"` -} - -type metadataAcceptVpcPeeringConnectionInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AcceptVpcPeeringConnectionInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AcceptVpcPeeringConnectionInput) GoString() string { - return s.String() -} - -type AcceptVpcPeeringConnectionOutput struct { - // Information about the VPC peering connection. - VpcPeeringConnection *VpcPeeringConnection `locationName:"vpcPeeringConnection" type:"structure"` - - metadataAcceptVpcPeeringConnectionOutput `json:"-" xml:"-"` -} - -type metadataAcceptVpcPeeringConnectionOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AcceptVpcPeeringConnectionOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AcceptVpcPeeringConnectionOutput) GoString() string { - return s.String() -} - -// Describes an account attribute. -type AccountAttribute struct { - // The name of the account attribute. - AttributeName *string `locationName:"attributeName" type:"string"` - - // One or more values for the account attribute. - AttributeValues []*AccountAttributeValue `locationName:"attributeValueSet" locationNameList:"item" type:"list"` - - metadataAccountAttribute `json:"-" xml:"-"` -} - -type metadataAccountAttribute struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AccountAttribute) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AccountAttribute) GoString() string { - return s.String() -} - -// Describes a value of an account attribute. -type AccountAttributeValue struct { - // The value of the attribute. - AttributeValue *string `locationName:"attributeValue" type:"string"` - - metadataAccountAttributeValue `json:"-" xml:"-"` -} - -type metadataAccountAttributeValue struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AccountAttributeValue) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AccountAttributeValue) GoString() string { - return s.String() -} - -// Describes a running instance in a Spot fleet. -type ActiveInstance struct { - // The ID of the instance. - InstanceId *string `locationName:"instanceId" type:"string"` - - // The instance type. - InstanceType *string `locationName:"instanceType" type:"string"` - - // The ID of the Spot instance request. - SpotInstanceRequestId *string `locationName:"spotInstanceRequestId" type:"string"` - - metadataActiveInstance `json:"-" xml:"-"` -} - -type metadataActiveInstance struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ActiveInstance) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ActiveInstance) GoString() string { - return s.String() -} - -// Describes an Elastic IP address. -type Address struct { - // The ID representing the allocation of the address for use with EC2-VPC. - AllocationId *string `locationName:"allocationId" type:"string"` - - // The ID representing the association of the address with an instance in a - // VPC. - AssociationId *string `locationName:"associationId" type:"string"` - - // Indicates whether this Elastic IP address is for use with instances in EC2-Classic - // (standard) or instances in a VPC (vpc). - Domain *string `locationName:"domain" type:"string" enum:"DomainType"` - - // The ID of the instance that the address is associated with (if any). - InstanceId *string `locationName:"instanceId" type:"string"` - - // The ID of the network interface. - NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string"` - - // The ID of the AWS account that owns the network interface. - NetworkInterfaceOwnerId *string `locationName:"networkInterfaceOwnerId" type:"string"` - - // The private IP address associated with the Elastic IP address. - PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` - - // The Elastic IP address. - PublicIp *string `locationName:"publicIp" type:"string"` - - metadataAddress `json:"-" xml:"-"` -} - -type metadataAddress struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s Address) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s Address) GoString() string { - return s.String() -} - -type AllocateAddressInput struct { - // Set to vpc to allocate the address for use with instances in a VPC. - // - // Default: The address is for use with instances in EC2-Classic. - Domain *string `type:"string" enum:"DomainType"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - metadataAllocateAddressInput `json:"-" xml:"-"` -} - -type metadataAllocateAddressInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AllocateAddressInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AllocateAddressInput) GoString() string { - return s.String() -} - -type AllocateAddressOutput struct { - // [EC2-VPC] The ID that AWS assigns to represent the allocation of the Elastic - // IP address for use with instances in a VPC. - AllocationId *string `locationName:"allocationId" type:"string"` - - // Indicates whether this Elastic IP address is for use with instances in EC2-Classic - // (standard) or instances in a VPC (vpc). - Domain *string `locationName:"domain" type:"string" enum:"DomainType"` - - // The Elastic IP address. - PublicIp *string `locationName:"publicIp" type:"string"` - - metadataAllocateAddressOutput `json:"-" xml:"-"` -} - -type metadataAllocateAddressOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AllocateAddressOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AllocateAddressOutput) GoString() string { - return s.String() -} - -type AssignPrivateIpAddressesInput struct { - // Indicates whether to allow an IP address that is already assigned to another - // network interface or instance to be reassigned to the specified network interface. - AllowReassignment *bool `locationName:"allowReassignment" type:"boolean"` - - // The ID of the network interface. - NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string" required:"true"` - - // One or more IP addresses to be assigned as a secondary private IP address - // to the network interface. You can't specify this parameter when also specifying - // a number of secondary IP addresses. - // - // If you don't specify an IP address, Amazon EC2 automatically selects an - // IP address within the subnet range. - PrivateIpAddresses []*string `locationName:"privateIpAddress" locationNameList:"PrivateIpAddress" type:"list"` - - // The number of secondary IP addresses to assign to the network interface. - // You can't specify this parameter when also specifying private IP addresses. - SecondaryPrivateIpAddressCount *int64 `locationName:"secondaryPrivateIpAddressCount" type:"integer"` - - metadataAssignPrivateIpAddressesInput `json:"-" xml:"-"` -} - -type metadataAssignPrivateIpAddressesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AssignPrivateIpAddressesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AssignPrivateIpAddressesInput) GoString() string { - return s.String() -} - -type AssignPrivateIpAddressesOutput struct { - metadataAssignPrivateIpAddressesOutput `json:"-" xml:"-"` -} - -type metadataAssignPrivateIpAddressesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AssignPrivateIpAddressesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AssignPrivateIpAddressesOutput) GoString() string { - return s.String() -} - -type AssociateAddressInput struct { - // [EC2-VPC] The allocation ID. This is required for EC2-VPC. - AllocationId *string `type:"string"` - - // [EC2-VPC] Allows an Elastic IP address that is already associated with an - // instance or network interface to be re-associated with the specified instance - // or network interface. Otherwise, the operation fails. - // - // Default: false - AllowReassociation *bool `locationName:"allowReassociation" type:"boolean"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the instance. This is required for EC2-Classic. For EC2-VPC, you - // can specify either the instance ID or the network interface ID, but not both. - // The operation fails if you specify an instance ID unless exactly one network - // interface is attached. - InstanceId *string `type:"string"` - - // [EC2-VPC] The ID of the network interface. If the instance has more than - // one network interface, you must specify a network interface ID. - NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string"` - - // [EC2-VPC] The primary or secondary private IP address to associate with the - // Elastic IP address. If no private IP address is specified, the Elastic IP - // address is associated with the primary private IP address. - PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` - - // The Elastic IP address. This is required for EC2-Classic. - PublicIp *string `type:"string"` - - metadataAssociateAddressInput `json:"-" xml:"-"` -} - -type metadataAssociateAddressInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AssociateAddressInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AssociateAddressInput) GoString() string { - return s.String() -} - -type AssociateAddressOutput struct { - // [EC2-VPC] The ID that represents the association of the Elastic IP address - // with an instance. - AssociationId *string `locationName:"associationId" type:"string"` - - metadataAssociateAddressOutput `json:"-" xml:"-"` -} - -type metadataAssociateAddressOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AssociateAddressOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AssociateAddressOutput) GoString() string { - return s.String() -} - -type AssociateDhcpOptionsInput struct { - // The ID of the DHCP options set, or default to associate no DHCP options with - // the VPC. - DhcpOptionsId *string `type:"string" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the VPC. - VpcId *string `type:"string" required:"true"` - - metadataAssociateDhcpOptionsInput `json:"-" xml:"-"` -} - -type metadataAssociateDhcpOptionsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AssociateDhcpOptionsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AssociateDhcpOptionsInput) GoString() string { - return s.String() -} - -type AssociateDhcpOptionsOutput struct { - metadataAssociateDhcpOptionsOutput `json:"-" xml:"-"` -} - -type metadataAssociateDhcpOptionsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AssociateDhcpOptionsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AssociateDhcpOptionsOutput) GoString() string { - return s.String() -} - -type AssociateRouteTableInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the route table. - RouteTableId *string `locationName:"routeTableId" type:"string" required:"true"` - - // The ID of the subnet. - SubnetId *string `locationName:"subnetId" type:"string" required:"true"` - - metadataAssociateRouteTableInput `json:"-" xml:"-"` -} - -type metadataAssociateRouteTableInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AssociateRouteTableInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AssociateRouteTableInput) GoString() string { - return s.String() -} - -type AssociateRouteTableOutput struct { - // The route table association ID (needed to disassociate the route table). - AssociationId *string `locationName:"associationId" type:"string"` - - metadataAssociateRouteTableOutput `json:"-" xml:"-"` -} - -type metadataAssociateRouteTableOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AssociateRouteTableOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AssociateRouteTableOutput) GoString() string { - return s.String() -} - -type AttachClassicLinkVpcInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of one or more of the VPC's security groups. You cannot specify security - // groups from a different VPC. - Groups []*string `locationName:"SecurityGroupId" locationNameList:"groupId" type:"list" required:"true"` - - // The ID of an EC2-Classic instance to link to the ClassicLink-enabled VPC. - InstanceId *string `locationName:"instanceId" type:"string" required:"true"` - - // The ID of a ClassicLink-enabled VPC. - VpcId *string `locationName:"vpcId" type:"string" required:"true"` - - metadataAttachClassicLinkVpcInput `json:"-" xml:"-"` -} - -type metadataAttachClassicLinkVpcInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AttachClassicLinkVpcInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AttachClassicLinkVpcInput) GoString() string { - return s.String() -} - -type AttachClassicLinkVpcOutput struct { - // Returns true if the request succeeds; otherwise, it returns an error. - Return *bool `locationName:"return" type:"boolean"` - - metadataAttachClassicLinkVpcOutput `json:"-" xml:"-"` -} - -type metadataAttachClassicLinkVpcOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AttachClassicLinkVpcOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AttachClassicLinkVpcOutput) GoString() string { - return s.String() -} - -type AttachInternetGatewayInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the Internet gateway. - InternetGatewayId *string `locationName:"internetGatewayId" type:"string" required:"true"` - - // The ID of the VPC. - VpcId *string `locationName:"vpcId" type:"string" required:"true"` - - metadataAttachInternetGatewayInput `json:"-" xml:"-"` -} - -type metadataAttachInternetGatewayInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AttachInternetGatewayInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AttachInternetGatewayInput) GoString() string { - return s.String() -} - -type AttachInternetGatewayOutput struct { - metadataAttachInternetGatewayOutput `json:"-" xml:"-"` -} - -type metadataAttachInternetGatewayOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AttachInternetGatewayOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AttachInternetGatewayOutput) GoString() string { - return s.String() -} - -type AttachNetworkInterfaceInput struct { - // The index of the device for the network interface attachment. - DeviceIndex *int64 `locationName:"deviceIndex" type:"integer" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the instance. - InstanceId *string `locationName:"instanceId" type:"string" required:"true"` - - // The ID of the network interface. - NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string" required:"true"` - - metadataAttachNetworkInterfaceInput `json:"-" xml:"-"` -} - -type metadataAttachNetworkInterfaceInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AttachNetworkInterfaceInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AttachNetworkInterfaceInput) GoString() string { - return s.String() -} - -type AttachNetworkInterfaceOutput struct { - // The ID of the network interface attachment. - AttachmentId *string `locationName:"attachmentId" type:"string"` - - metadataAttachNetworkInterfaceOutput `json:"-" xml:"-"` -} - -type metadataAttachNetworkInterfaceOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AttachNetworkInterfaceOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AttachNetworkInterfaceOutput) GoString() string { - return s.String() -} - -type AttachVolumeInput struct { - // The device name to expose to the instance (for example, /dev/sdh or xvdh). - Device *string `type:"string" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the instance. - InstanceId *string `type:"string" required:"true"` - - // The ID of the EBS volume. The volume and instance must be within the same - // Availability Zone. - VolumeId *string `type:"string" required:"true"` - - metadataAttachVolumeInput `json:"-" xml:"-"` -} - -type metadataAttachVolumeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AttachVolumeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AttachVolumeInput) GoString() string { - return s.String() -} - -type AttachVpnGatewayInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the VPC. - VpcId *string `type:"string" required:"true"` - - // The ID of the virtual private gateway. - VpnGatewayId *string `type:"string" required:"true"` - - metadataAttachVpnGatewayInput `json:"-" xml:"-"` -} - -type metadataAttachVpnGatewayInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AttachVpnGatewayInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AttachVpnGatewayInput) GoString() string { - return s.String() -} - -type AttachVpnGatewayOutput struct { - // Information about the attachment. - VpcAttachment *VpcAttachment `locationName:"attachment" type:"structure"` - - metadataAttachVpnGatewayOutput `json:"-" xml:"-"` -} - -type metadataAttachVpnGatewayOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AttachVpnGatewayOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AttachVpnGatewayOutput) GoString() string { - return s.String() -} - -// The value to use when a resource attribute accepts a Boolean value. -type AttributeBooleanValue struct { - // Valid values are true or false. - Value *bool `locationName:"value" type:"boolean"` - - metadataAttributeBooleanValue `json:"-" xml:"-"` -} - -type metadataAttributeBooleanValue struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AttributeBooleanValue) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AttributeBooleanValue) GoString() string { - return s.String() -} - -// The value to use for a resource attribute. -type AttributeValue struct { - // Valid values are case-sensitive and vary by action. - Value *string `locationName:"value" type:"string"` - - metadataAttributeValue `json:"-" xml:"-"` -} - -type metadataAttributeValue struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AttributeValue) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AttributeValue) GoString() string { - return s.String() -} - -type AuthorizeSecurityGroupEgressInput struct { - // The CIDR IP address range. You can't specify this parameter when specifying - // a source security group. - CidrIp *string `locationName:"cidrIp" type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The start of port range for the TCP and UDP protocols, or an ICMP type number. - // For the ICMP type number, use -1 to specify all ICMP types. - FromPort *int64 `locationName:"fromPort" type:"integer"` - - // The ID of the security group. - GroupId *string `locationName:"groupId" type:"string" required:"true"` - - // A set of IP permissions. You can't specify a destination security group and - // a CIDR IP address range. - IpPermissions []*IpPermission `locationName:"ipPermissions" locationNameList:"item" type:"list"` - - // The IP protocol name (tcp, udp, icmp) or number (see Protocol Numbers (http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml)). - // Use -1 to specify all. - IpProtocol *string `locationName:"ipProtocol" type:"string"` - - // The name of a destination security group. To authorize outbound access to - // a destination security group, we recommend that you use a set of IP permissions - // instead. - SourceSecurityGroupName *string `locationName:"sourceSecurityGroupName" type:"string"` - - // The AWS account number for a destination security group. To authorize outbound - // access to a destination security group, we recommend that you use a set of - // IP permissions instead. - SourceSecurityGroupOwnerId *string `locationName:"sourceSecurityGroupOwnerId" type:"string"` - - // The end of port range for the TCP and UDP protocols, or an ICMP code number. - // For the ICMP code number, use -1 to specify all ICMP codes for the ICMP type. - ToPort *int64 `locationName:"toPort" type:"integer"` - - metadataAuthorizeSecurityGroupEgressInput `json:"-" xml:"-"` -} - -type metadataAuthorizeSecurityGroupEgressInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AuthorizeSecurityGroupEgressInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AuthorizeSecurityGroupEgressInput) GoString() string { - return s.String() -} - -type AuthorizeSecurityGroupEgressOutput struct { - metadataAuthorizeSecurityGroupEgressOutput `json:"-" xml:"-"` -} - -type metadataAuthorizeSecurityGroupEgressOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AuthorizeSecurityGroupEgressOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AuthorizeSecurityGroupEgressOutput) GoString() string { - return s.String() -} - -type AuthorizeSecurityGroupIngressInput struct { - // The CIDR IP address range. You can't specify this parameter when specifying - // a source security group. - CidrIp *string `type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The start of port range for the TCP and UDP protocols, or an ICMP type number. - // For the ICMP type number, use -1 to specify all ICMP types. - FromPort *int64 `type:"integer"` - - // The ID of the security group. Required for a nondefault VPC. - GroupId *string `type:"string"` - - // [EC2-Classic, default VPC] The name of the security group. - GroupName *string `type:"string"` - - // A set of IP permissions. Can be used to specify multiple rules in a single - // command. - IpPermissions []*IpPermission `locationNameList:"item" type:"list"` - - // The IP protocol name (tcp, udp, icmp) or number (see Protocol Numbers (http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml)). - // (VPC only) Use -1 to specify all. - IpProtocol *string `type:"string"` - - // [EC2-Classic, default VPC] The name of the source security group. You can't - // specify this parameter in combination with the following parameters: the - // CIDR IP address range, the start of the port range, the IP protocol, and - // the end of the port range. For EC2-VPC, the source security group must be - // in the same VPC. - SourceSecurityGroupName *string `type:"string"` - - // [EC2-Classic, default VPC] The AWS account number for the source security - // group. For EC2-VPC, the source security group must be in the same VPC. You - // can't specify this parameter in combination with the following parameters: - // the CIDR IP address range, the IP protocol, the start of the port range, - // and the end of the port range. Creates rules that grant full ICMP, UDP, and - // TCP access. To create a rule with a specific IP protocol and port range, - // use a set of IP permissions instead. - SourceSecurityGroupOwnerId *string `type:"string"` - - // The end of port range for the TCP and UDP protocols, or an ICMP code number. - // For the ICMP code number, use -1 to specify all ICMP codes for the ICMP type. - ToPort *int64 `type:"integer"` - - metadataAuthorizeSecurityGroupIngressInput `json:"-" xml:"-"` -} - -type metadataAuthorizeSecurityGroupIngressInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AuthorizeSecurityGroupIngressInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AuthorizeSecurityGroupIngressInput) GoString() string { - return s.String() -} - -type AuthorizeSecurityGroupIngressOutput struct { - metadataAuthorizeSecurityGroupIngressOutput `json:"-" xml:"-"` -} - -type metadataAuthorizeSecurityGroupIngressOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AuthorizeSecurityGroupIngressOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AuthorizeSecurityGroupIngressOutput) GoString() string { - return s.String() -} - -// Describes an Availability Zone. -type AvailabilityZone struct { - // Any messages about the Availability Zone. - Messages []*AvailabilityZoneMessage `locationName:"messageSet" locationNameList:"item" type:"list"` - - // The name of the region. - RegionName *string `locationName:"regionName" type:"string"` - - // The state of the Availability Zone. - State *string `locationName:"zoneState" type:"string" enum:"AvailabilityZoneState"` - - // The name of the Availability Zone. - ZoneName *string `locationName:"zoneName" type:"string"` - - metadataAvailabilityZone `json:"-" xml:"-"` -} - -type metadataAvailabilityZone struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AvailabilityZone) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AvailabilityZone) GoString() string { - return s.String() -} - -// Describes a message about an Availability Zone. -type AvailabilityZoneMessage struct { - // The message about the Availability Zone. - Message *string `locationName:"message" type:"string"` - - metadataAvailabilityZoneMessage `json:"-" xml:"-"` -} - -type metadataAvailabilityZoneMessage struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s AvailabilityZoneMessage) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s AvailabilityZoneMessage) GoString() string { - return s.String() -} - -type BlobAttributeValue struct { - Value []byte `locationName:"value" type:"blob"` - - metadataBlobAttributeValue `json:"-" xml:"-"` -} - -type metadataBlobAttributeValue struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s BlobAttributeValue) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s BlobAttributeValue) GoString() string { - return s.String() -} - -// Describes a block device mapping. -type BlockDeviceMapping struct { - // The device name exposed to the instance (for example, /dev/sdh or xvdh). - DeviceName *string `locationName:"deviceName" type:"string"` - - // Parameters used to automatically set up EBS volumes when the instance is - // launched. - Ebs *EbsBlockDevice `locationName:"ebs" type:"structure"` - - // Suppresses the specified device included in the block device mapping of the - // AMI. - NoDevice *string `locationName:"noDevice" type:"string"` - - // The virtual device name (ephemeralN). Instance store volumes are numbered - // starting from 0. An instance type with 2 available instance store volumes - // can specify mappings for ephemeral0 and ephemeral1.The number of available - // instance store volumes depends on the instance type. After you connect to - // the instance, you must mount the volume. - // - // Constraints: For M3 instances, you must specify instance store volumes in - // the block device mapping for the instance. When you launch an M3 instance, - // we ignore any instance store volumes specified in the block device mapping - // for the AMI. - VirtualName *string `locationName:"virtualName" type:"string"` - - metadataBlockDeviceMapping `json:"-" xml:"-"` -} - -type metadataBlockDeviceMapping struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s BlockDeviceMapping) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s BlockDeviceMapping) GoString() string { - return s.String() -} - -type BundleInstanceInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the instance to bundle. - // - // Type: String - // - // Default: None - // - // Required: Yes - InstanceId *string `type:"string" required:"true"` - - // The bucket in which to store the AMI. You can specify a bucket that you already - // own or a new bucket that Amazon EC2 creates on your behalf. If you specify - // a bucket that belongs to someone else, Amazon EC2 returns an error. - Storage *Storage `type:"structure" required:"true"` - - metadataBundleInstanceInput `json:"-" xml:"-"` -} - -type metadataBundleInstanceInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s BundleInstanceInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s BundleInstanceInput) GoString() string { - return s.String() -} - -type BundleInstanceOutput struct { - // Information about the bundle task. - BundleTask *BundleTask `locationName:"bundleInstanceTask" type:"structure"` - - metadataBundleInstanceOutput `json:"-" xml:"-"` -} - -type metadataBundleInstanceOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s BundleInstanceOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s BundleInstanceOutput) GoString() string { - return s.String() -} - -// Describes a bundle task. -type BundleTask struct { - // The ID of the bundle task. - BundleId *string `locationName:"bundleId" type:"string"` - - // If the task fails, a description of the error. - BundleTaskError *BundleTaskError `locationName:"error" type:"structure"` - - // The ID of the instance associated with this bundle task. - InstanceId *string `locationName:"instanceId" type:"string"` - - // The level of task completion, as a percent (for example, 20%). - Progress *string `locationName:"progress" type:"string"` - - // The time this task started. - StartTime *time.Time `locationName:"startTime" type:"timestamp" timestampFormat:"iso8601"` - - // The state of the task. - State *string `locationName:"state" type:"string" enum:"BundleTaskState"` - - // The Amazon S3 storage locations. - Storage *Storage `locationName:"storage" type:"structure"` - - // The time of the most recent update for the task. - UpdateTime *time.Time `locationName:"updateTime" type:"timestamp" timestampFormat:"iso8601"` - - metadataBundleTask `json:"-" xml:"-"` -} - -type metadataBundleTask struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s BundleTask) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s BundleTask) GoString() string { - return s.String() -} - -// Describes an error for BundleInstance. -type BundleTaskError struct { - // The error code. - Code *string `locationName:"code" type:"string"` - - // The error message. - Message *string `locationName:"message" type:"string"` - - metadataBundleTaskError `json:"-" xml:"-"` -} - -type metadataBundleTaskError struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s BundleTaskError) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s BundleTaskError) GoString() string { - return s.String() -} - -type CancelBundleTaskInput struct { - // The ID of the bundle task. - BundleId *string `type:"string" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - metadataCancelBundleTaskInput `json:"-" xml:"-"` -} - -type metadataCancelBundleTaskInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CancelBundleTaskInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CancelBundleTaskInput) GoString() string { - return s.String() -} - -type CancelBundleTaskOutput struct { - // Information about the bundle task. - BundleTask *BundleTask `locationName:"bundleInstanceTask" type:"structure"` - - metadataCancelBundleTaskOutput `json:"-" xml:"-"` -} - -type metadataCancelBundleTaskOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CancelBundleTaskOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CancelBundleTaskOutput) GoString() string { - return s.String() -} - -type CancelConversionTaskInput struct { - // The ID of the conversion task. - ConversionTaskId *string `locationName:"conversionTaskId" type:"string" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The reason for canceling the conversion task. - ReasonMessage *string `locationName:"reasonMessage" type:"string"` - - metadataCancelConversionTaskInput `json:"-" xml:"-"` -} - -type metadataCancelConversionTaskInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CancelConversionTaskInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CancelConversionTaskInput) GoString() string { - return s.String() -} - -type CancelConversionTaskOutput struct { - metadataCancelConversionTaskOutput `json:"-" xml:"-"` -} - -type metadataCancelConversionTaskOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CancelConversionTaskOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CancelConversionTaskOutput) GoString() string { - return s.String() -} - -type CancelExportTaskInput struct { - // The ID of the export task. This is the ID returned by CreateInstanceExportTask. - ExportTaskId *string `locationName:"exportTaskId" type:"string" required:"true"` - - metadataCancelExportTaskInput `json:"-" xml:"-"` -} - -type metadataCancelExportTaskInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CancelExportTaskInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CancelExportTaskInput) GoString() string { - return s.String() -} - -type CancelExportTaskOutput struct { - metadataCancelExportTaskOutput `json:"-" xml:"-"` -} - -type metadataCancelExportTaskOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CancelExportTaskOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CancelExportTaskOutput) GoString() string { - return s.String() -} - -type CancelImportTaskInput struct { - // The reason for canceling the task. - CancelReason *string `type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `type:"boolean"` - - // The ID of the import image or import snapshot task to be canceled. - ImportTaskId *string `type:"string"` - - metadataCancelImportTaskInput `json:"-" xml:"-"` -} - -type metadataCancelImportTaskInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CancelImportTaskInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CancelImportTaskInput) GoString() string { - return s.String() -} - -type CancelImportTaskOutput struct { - // The ID of the task being canceled. - ImportTaskId *string `locationName:"importTaskId" type:"string"` - - // The current state of the task being canceled. - PreviousState *string `locationName:"previousState" type:"string"` - - // The current state of the task being canceled. - State *string `locationName:"state" type:"string"` - - metadataCancelImportTaskOutput `json:"-" xml:"-"` -} - -type metadataCancelImportTaskOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CancelImportTaskOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CancelImportTaskOutput) GoString() string { - return s.String() -} - -type CancelReservedInstancesListingInput struct { - // The ID of the Reserved Instance listing. - ReservedInstancesListingId *string `locationName:"reservedInstancesListingId" type:"string" required:"true"` - - metadataCancelReservedInstancesListingInput `json:"-" xml:"-"` -} - -type metadataCancelReservedInstancesListingInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CancelReservedInstancesListingInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CancelReservedInstancesListingInput) GoString() string { - return s.String() -} - -type CancelReservedInstancesListingOutput struct { - // The Reserved Instance listing. - ReservedInstancesListings []*ReservedInstancesListing `locationName:"reservedInstancesListingsSet" locationNameList:"item" type:"list"` - - metadataCancelReservedInstancesListingOutput `json:"-" xml:"-"` -} - -type metadataCancelReservedInstancesListingOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CancelReservedInstancesListingOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CancelReservedInstancesListingOutput) GoString() string { - return s.String() -} - -// Describes a Spot fleet error. -type CancelSpotFleetRequestsError struct { - // The error code. - Code *string `locationName:"code" type:"string" required:"true" enum:"CancelBatchErrorCode"` - - // The description for the error code. - Message *string `locationName:"message" type:"string" required:"true"` - - metadataCancelSpotFleetRequestsError `json:"-" xml:"-"` -} - -type metadataCancelSpotFleetRequestsError struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CancelSpotFleetRequestsError) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CancelSpotFleetRequestsError) GoString() string { - return s.String() -} - -// Describes a Spot fleet request that was not successfully canceled. -type CancelSpotFleetRequestsErrorItem struct { - // The error. - Error *CancelSpotFleetRequestsError `locationName:"error" type:"structure" required:"true"` - - // The ID of the Spot fleet request. - SpotFleetRequestId *string `locationName:"spotFleetRequestId" type:"string" required:"true"` - - metadataCancelSpotFleetRequestsErrorItem `json:"-" xml:"-"` -} - -type metadataCancelSpotFleetRequestsErrorItem struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CancelSpotFleetRequestsErrorItem) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CancelSpotFleetRequestsErrorItem) GoString() string { - return s.String() -} - -// Contains the parameters for CancelSpotFleetRequests. -type CancelSpotFleetRequestsInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The IDs of the Spot fleet requests. - SpotFleetRequestIds []*string `locationName:"spotFleetRequestId" locationNameList:"item" type:"list" required:"true"` - - // Indicates whether to terminate instances for a Spot fleet request if it is - // canceled successfully. - TerminateInstances *bool `locationName:"terminateInstances" type:"boolean" required:"true"` - - metadataCancelSpotFleetRequestsInput `json:"-" xml:"-"` -} - -type metadataCancelSpotFleetRequestsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CancelSpotFleetRequestsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CancelSpotFleetRequestsInput) GoString() string { - return s.String() -} - -// Contains the output of CancelSpotFleetRequests. -type CancelSpotFleetRequestsOutput struct { - // Information about the Spot fleet requests that are successfully canceled. - SuccessfulFleetRequests []*CancelSpotFleetRequestsSuccessItem `locationName:"successfulFleetRequestSet" locationNameList:"item" type:"list"` - - // Information about the Spot fleet requests that are not successfully canceled. - UnsuccessfulFleetRequests []*CancelSpotFleetRequestsErrorItem `locationName:"unsuccessfulFleetRequestSet" locationNameList:"item" type:"list"` - - metadataCancelSpotFleetRequestsOutput `json:"-" xml:"-"` -} - -type metadataCancelSpotFleetRequestsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CancelSpotFleetRequestsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CancelSpotFleetRequestsOutput) GoString() string { - return s.String() -} - -// Describes a Spot fleet request that was successfully canceled. -type CancelSpotFleetRequestsSuccessItem struct { - // The current state of the Spot fleet request. - CurrentSpotFleetRequestState *string `locationName:"currentSpotFleetRequestState" type:"string" required:"true" enum:"BatchState"` - - // The previous state of the Spot fleet request. - PreviousSpotFleetRequestState *string `locationName:"previousSpotFleetRequestState" type:"string" required:"true" enum:"BatchState"` - - // The ID of the Spot fleet request. - SpotFleetRequestId *string `locationName:"spotFleetRequestId" type:"string" required:"true"` - - metadataCancelSpotFleetRequestsSuccessItem `json:"-" xml:"-"` -} - -type metadataCancelSpotFleetRequestsSuccessItem struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CancelSpotFleetRequestsSuccessItem) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CancelSpotFleetRequestsSuccessItem) GoString() string { - return s.String() -} - -// Contains the parameters for CancelSpotInstanceRequests. -type CancelSpotInstanceRequestsInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more Spot instance request IDs. - SpotInstanceRequestIds []*string `locationName:"SpotInstanceRequestId" locationNameList:"SpotInstanceRequestId" type:"list" required:"true"` - - metadataCancelSpotInstanceRequestsInput `json:"-" xml:"-"` -} - -type metadataCancelSpotInstanceRequestsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CancelSpotInstanceRequestsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CancelSpotInstanceRequestsInput) GoString() string { - return s.String() -} - -// Contains the output of CancelSpotInstanceRequests. -type CancelSpotInstanceRequestsOutput struct { - // One or more Spot instance requests. - CancelledSpotInstanceRequests []*CancelledSpotInstanceRequest `locationName:"spotInstanceRequestSet" locationNameList:"item" type:"list"` - - metadataCancelSpotInstanceRequestsOutput `json:"-" xml:"-"` -} - -type metadataCancelSpotInstanceRequestsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CancelSpotInstanceRequestsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CancelSpotInstanceRequestsOutput) GoString() string { - return s.String() -} - -// Describes a request to cancel a Spot instance. -type CancelledSpotInstanceRequest struct { - // The ID of the Spot instance request. - SpotInstanceRequestId *string `locationName:"spotInstanceRequestId" type:"string"` - - // The state of the Spot instance request. - State *string `locationName:"state" type:"string" enum:"CancelSpotInstanceRequestState"` - - metadataCancelledSpotInstanceRequest `json:"-" xml:"-"` -} - -type metadataCancelledSpotInstanceRequest struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CancelledSpotInstanceRequest) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CancelledSpotInstanceRequest) GoString() string { - return s.String() -} - -// Describes a linked EC2-Classic instance. -type ClassicLinkInstance struct { - // A list of security groups. - Groups []*GroupIdentifier `locationName:"groupSet" locationNameList:"item" type:"list"` - - // The ID of the instance. - InstanceId *string `locationName:"instanceId" type:"string"` - - // Any tags assigned to the instance. - Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - // The ID of the VPC. - VpcId *string `locationName:"vpcId" type:"string"` - - metadataClassicLinkInstance `json:"-" xml:"-"` -} - -type metadataClassicLinkInstance struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ClassicLinkInstance) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ClassicLinkInstance) GoString() string { - return s.String() -} - -// Describes the client-specific data. -type ClientData struct { - // A user-defined comment about the disk upload. - Comment *string `type:"string"` - - // The time that the disk upload ends. - UploadEnd *time.Time `type:"timestamp" timestampFormat:"iso8601"` - - // The size of the uploaded disk image, in GiB. - UploadSize *float64 `type:"double"` - - // The time that the disk upload starts. - UploadStart *time.Time `type:"timestamp" timestampFormat:"iso8601"` - - metadataClientData `json:"-" xml:"-"` -} - -type metadataClientData struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ClientData) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ClientData) GoString() string { - return s.String() -} - -type ConfirmProductInstanceInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the instance. - InstanceId *string `type:"string" required:"true"` - - // The product code. This must be a product code that you own. - ProductCode *string `type:"string" required:"true"` - - metadataConfirmProductInstanceInput `json:"-" xml:"-"` -} - -type metadataConfirmProductInstanceInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ConfirmProductInstanceInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ConfirmProductInstanceInput) GoString() string { - return s.String() -} - -type ConfirmProductInstanceOutput struct { - // The AWS account ID of the instance owner. This is only present if the product - // code is attached to the instance. - OwnerId *string `locationName:"ownerId" type:"string"` - - // The return value of the request. Returns true if the specified product code - // is owned by the requester and associated with the specified instance. - Return *bool `locationName:"return" type:"boolean"` - - metadataConfirmProductInstanceOutput `json:"-" xml:"-"` -} - -type metadataConfirmProductInstanceOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ConfirmProductInstanceOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ConfirmProductInstanceOutput) GoString() string { - return s.String() -} - -// Describes a conversion task. -type ConversionTask struct { - // The ID of the conversion task. - ConversionTaskId *string `locationName:"conversionTaskId" type:"string" required:"true"` - - // The time when the task expires. If the upload isn't complete before the expiration - // time, we automatically cancel the task. - ExpirationTime *string `locationName:"expirationTime" type:"string"` - - // If the task is for importing an instance, this contains information about - // the import instance task. - ImportInstance *ImportInstanceTaskDetails `locationName:"importInstance" type:"structure"` - - // If the task is for importing a volume, this contains information about the - // import volume task. - ImportVolume *ImportVolumeTaskDetails `locationName:"importVolume" type:"structure"` - - // The state of the conversion task. - State *string `locationName:"state" type:"string" required:"true" enum:"ConversionTaskState"` - - // The status message related to the conversion task. - StatusMessage *string `locationName:"statusMessage" type:"string"` - - // Any tags assigned to the task. - Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - metadataConversionTask `json:"-" xml:"-"` -} - -type metadataConversionTask struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ConversionTask) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ConversionTask) GoString() string { - return s.String() -} - -type CopyImageInput struct { - // Unique, case-sensitive identifier you provide to ensure idempotency of the - // request. For more information, see How to Ensure Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Run_Instance_Idempotency.html) - // in the Amazon Elastic Compute Cloud User Guide. - ClientToken *string `type:"string"` - - // A description for the new AMI in the destination region. - Description *string `type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The name of the new AMI in the destination region. - Name *string `type:"string" required:"true"` - - // The ID of the AMI to copy. - SourceImageId *string `type:"string" required:"true"` - - // The name of the region that contains the AMI to copy. - SourceRegion *string `type:"string" required:"true"` - - metadataCopyImageInput `json:"-" xml:"-"` -} - -type metadataCopyImageInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CopyImageInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CopyImageInput) GoString() string { - return s.String() -} - -type CopyImageOutput struct { - // The ID of the new AMI. - ImageId *string `locationName:"imageId" type:"string"` - - metadataCopyImageOutput `json:"-" xml:"-"` -} - -type metadataCopyImageOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CopyImageOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CopyImageOutput) GoString() string { - return s.String() -} - -type CopySnapshotInput struct { - // A description for the EBS snapshot. - Description *string `type:"string"` - - // The destination region to use in the PresignedUrl parameter of a snapshot - // copy operation. This parameter is only valid for specifying the destination - // region in a PresignedUrl parameter, where it is required. - // - // CopySnapshot sends the snapshot copy to the regional endpoint that you - // send the HTTP request to, such as ec2.us-east-1.amazonaws.com (in the AWS - // CLI, this is specified with the --region parameter or the default region - // in your AWS configuration file). - DestinationRegion *string `locationName:"destinationRegion" type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // Specifies whether the destination snapshot should be encrypted. There is - // no way to create an unencrypted snapshot copy from an encrypted snapshot; - // however, you can encrypt a copy of an unencrypted snapshot with this flag. - // The default CMK for EBS is used unless a non-default AWS Key Management Service - // (AWS KMS) CMK is specified with KmsKeyId. For more information, see Amazon - // EBS Encryption (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html) - // in the Amazon Elastic Compute Cloud User Guide. - Encrypted *bool `locationName:"encrypted" type:"boolean"` - - // The full ARN of the AWS Key Management Service (AWS KMS) CMK to use when - // creating the snapshot copy. This parameter is only required if you want to - // use a non-default CMK; if this parameter is not specified, the default CMK - // for EBS is used. The ARN contains the arn:aws:kms namespace, followed by - // the region of the CMK, the AWS account ID of the CMK owner, the key namespace, - // and then the CMK ID. For example, arn:aws:kms:us-east-1:012345678910:key/abcd1234-a123-456a-a12b-a123b4cd56ef. - // The specified CMK must exist in the region that the snapshot is being copied - // to. If a KmsKeyId is specified, the Encrypted flag must also be set. - KmsKeyId *string `locationName:"kmsKeyId" type:"string"` - - // The pre-signed URL that facilitates copying an encrypted snapshot. This parameter - // is only required when copying an encrypted snapshot with the Amazon EC2 Query - // API; it is available as an optional parameter in all other cases. The PresignedUrl - // should use the snapshot source endpoint, the CopySnapshot action, and include - // the SourceRegion, SourceSnapshotId, and DestinationRegion parameters. The - // PresignedUrl must be signed using AWS Signature Version 4. Because EBS snapshots - // are stored in Amazon S3, the signing algorithm for this parameter uses the - // same logic that is described in Authenticating Requests by Using Query Parameters - // (AWS Signature Version 4) (http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html) - // in the Amazon Simple Storage Service API Reference. An invalid or improperly - // signed PresignedUrl will cause the copy operation to fail asynchronously, - // and the snapshot will move to an error state. - PresignedUrl *string `locationName:"presignedUrl" type:"string"` - - // The ID of the region that contains the snapshot to be copied. - SourceRegion *string `type:"string" required:"true"` - - // The ID of the EBS snapshot to copy. - SourceSnapshotId *string `type:"string" required:"true"` - - metadataCopySnapshotInput `json:"-" xml:"-"` -} - -type metadataCopySnapshotInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CopySnapshotInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CopySnapshotInput) GoString() string { - return s.String() -} - -type CopySnapshotOutput struct { - // The ID of the new snapshot. - SnapshotId *string `locationName:"snapshotId" type:"string"` - - metadataCopySnapshotOutput `json:"-" xml:"-"` -} - -type metadataCopySnapshotOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CopySnapshotOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CopySnapshotOutput) GoString() string { - return s.String() -} - -type CreateCustomerGatewayInput struct { - // For devices that support BGP, the customer gateway's BGP ASN. - // - // Default: 65000 - BgpAsn *int64 `type:"integer" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The Internet-routable IP address for the customer gateway's outside interface. - // The address must be static. - PublicIp *string `locationName:"IpAddress" type:"string" required:"true"` - - // The type of VPN connection that this customer gateway supports (ipsec.1). - Type *string `type:"string" required:"true" enum:"GatewayType"` - - metadataCreateCustomerGatewayInput `json:"-" xml:"-"` -} - -type metadataCreateCustomerGatewayInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateCustomerGatewayInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateCustomerGatewayInput) GoString() string { - return s.String() -} - -type CreateCustomerGatewayOutput struct { - // Information about the customer gateway. - CustomerGateway *CustomerGateway `locationName:"customerGateway" type:"structure"` - - metadataCreateCustomerGatewayOutput `json:"-" xml:"-"` -} - -type metadataCreateCustomerGatewayOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateCustomerGatewayOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateCustomerGatewayOutput) GoString() string { - return s.String() -} - -type CreateDhcpOptionsInput struct { - // A DHCP configuration option. - DhcpConfigurations []*NewDhcpConfiguration `locationName:"dhcpConfiguration" locationNameList:"item" type:"list" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - metadataCreateDhcpOptionsInput `json:"-" xml:"-"` -} - -type metadataCreateDhcpOptionsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateDhcpOptionsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateDhcpOptionsInput) GoString() string { - return s.String() -} - -type CreateDhcpOptionsOutput struct { - // A set of DHCP options. - DhcpOptions *DhcpOptions `locationName:"dhcpOptions" type:"structure"` - - metadataCreateDhcpOptionsOutput `json:"-" xml:"-"` -} - -type metadataCreateDhcpOptionsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateDhcpOptionsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateDhcpOptionsOutput) GoString() string { - return s.String() -} - -type CreateFlowLogsInput struct { - // Unique, case-sensitive identifier you provide to ensure the idempotency of - // the request. For more information, see How to Ensure Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Run_Instance_Idempotency.html). - ClientToken *string `type:"string"` - - // The ARN for the IAM role that's used to post flow logs to a CloudWatch Logs - // log group. - DeliverLogsPermissionArn *string `type:"string" required:"true"` - - // The name of the CloudWatch log group. - LogGroupName *string `type:"string" required:"true"` - - // One or more subnet, network interface, or VPC IDs. - ResourceIds []*string `locationName:"ResourceId" locationNameList:"item" type:"list" required:"true"` - - // The type of resource on which to create the flow log. - ResourceType *string `type:"string" required:"true" enum:"FlowLogsResourceType"` - - // The type of traffic to log. - TrafficType *string `type:"string" required:"true" enum:"TrafficType"` - - metadataCreateFlowLogsInput `json:"-" xml:"-"` -} - -type metadataCreateFlowLogsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateFlowLogsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateFlowLogsInput) GoString() string { - return s.String() -} - -type CreateFlowLogsOutput struct { - // Unique, case-sensitive identifier you provide to ensure the idempotency of - // the request. - ClientToken *string `locationName:"clientToken" type:"string"` - - // The IDs of the flow logs. - FlowLogIds []*string `locationName:"flowLogIdSet" locationNameList:"item" type:"list"` - - // Information about the flow logs that could not be created successfully. - Unsuccessful []*UnsuccessfulItem `locationName:"unsuccessful" locationNameList:"item" type:"list"` - - metadataCreateFlowLogsOutput `json:"-" xml:"-"` -} - -type metadataCreateFlowLogsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateFlowLogsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateFlowLogsOutput) GoString() string { - return s.String() -} - -type CreateImageInput struct { - // Information about one or more block device mappings. - BlockDeviceMappings []*BlockDeviceMapping `locationName:"blockDeviceMapping" locationNameList:"BlockDeviceMapping" type:"list"` - - // A description for the new image. - Description *string `locationName:"description" type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the instance. - InstanceId *string `locationName:"instanceId" type:"string" required:"true"` - - // A name for the new image. - // - // Constraints: 3-128 alphanumeric characters, parentheses (()), square brackets - // ([]), spaces ( ), periods (.), slashes (/), dashes (-), single quotes ('), - // at-signs (@), or underscores(_) - Name *string `locationName:"name" type:"string" required:"true"` - - // By default, this parameter is set to false, which means Amazon EC2 attempts - // to shut down the instance cleanly before image creation and then reboots - // the instance. When the parameter is set to true, Amazon EC2 doesn't shut - // down the instance before creating the image. When this option is used, file - // system integrity on the created image can't be guaranteed. - NoReboot *bool `locationName:"noReboot" type:"boolean"` - - metadataCreateImageInput `json:"-" xml:"-"` -} - -type metadataCreateImageInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateImageInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateImageInput) GoString() string { - return s.String() -} - -type CreateImageOutput struct { - // The ID of the new AMI. - ImageId *string `locationName:"imageId" type:"string"` - - metadataCreateImageOutput `json:"-" xml:"-"` -} - -type metadataCreateImageOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateImageOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateImageOutput) GoString() string { - return s.String() -} - -type CreateInstanceExportTaskInput struct { - // A description for the conversion task or the resource being exported. The - // maximum length is 255 bytes. - Description *string `locationName:"description" type:"string"` - - // The format and location for an instance export task. - ExportToS3Task *ExportToS3TaskSpecification `locationName:"exportToS3" type:"structure"` - - // The ID of the instance. - InstanceId *string `locationName:"instanceId" type:"string" required:"true"` - - // The target virtualization environment. - TargetEnvironment *string `locationName:"targetEnvironment" type:"string" enum:"ExportEnvironment"` - - metadataCreateInstanceExportTaskInput `json:"-" xml:"-"` -} - -type metadataCreateInstanceExportTaskInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateInstanceExportTaskInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateInstanceExportTaskInput) GoString() string { - return s.String() -} - -type CreateInstanceExportTaskOutput struct { - // Information about the instance export task. - ExportTask *ExportTask `locationName:"exportTask" type:"structure"` - - metadataCreateInstanceExportTaskOutput `json:"-" xml:"-"` -} - -type metadataCreateInstanceExportTaskOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateInstanceExportTaskOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateInstanceExportTaskOutput) GoString() string { - return s.String() -} - -type CreateInternetGatewayInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - metadataCreateInternetGatewayInput `json:"-" xml:"-"` -} - -type metadataCreateInternetGatewayInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateInternetGatewayInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateInternetGatewayInput) GoString() string { - return s.String() -} - -type CreateInternetGatewayOutput struct { - // Information about the Internet gateway. - InternetGateway *InternetGateway `locationName:"internetGateway" type:"structure"` - - metadataCreateInternetGatewayOutput `json:"-" xml:"-"` -} - -type metadataCreateInternetGatewayOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateInternetGatewayOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateInternetGatewayOutput) GoString() string { - return s.String() -} - -type CreateKeyPairInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // A unique name for the key pair. - // - // Constraints: Up to 255 ASCII characters - KeyName *string `type:"string" required:"true"` - - metadataCreateKeyPairInput `json:"-" xml:"-"` -} - -type metadataCreateKeyPairInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateKeyPairInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateKeyPairInput) GoString() string { - return s.String() -} - -// Describes a key pair. -type CreateKeyPairOutput struct { - // The SHA-1 digest of the DER encoded private key. - KeyFingerprint *string `locationName:"keyFingerprint" type:"string"` - - // An unencrypted PEM encoded RSA private key. - KeyMaterial *string `locationName:"keyMaterial" type:"string"` - - // The name of the key pair. - KeyName *string `locationName:"keyName" type:"string"` - - metadataCreateKeyPairOutput `json:"-" xml:"-"` -} - -type metadataCreateKeyPairOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateKeyPairOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateKeyPairOutput) GoString() string { - return s.String() -} - -type CreateNetworkAclEntryInput struct { - // The network range to allow or deny, in CIDR notation (for example 172.16.0.0/24). - CidrBlock *string `locationName:"cidrBlock" type:"string" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // Indicates whether this is an egress rule (rule is applied to traffic leaving - // the subnet). - Egress *bool `locationName:"egress" type:"boolean" required:"true"` - - // ICMP protocol: The ICMP type and code. Required if specifying ICMP for the - // protocol. - IcmpTypeCode *IcmpTypeCode `locationName:"Icmp" type:"structure"` - - // The ID of the network ACL. - NetworkAclId *string `locationName:"networkAclId" type:"string" required:"true"` - - // TCP or UDP protocols: The range of ports the rule applies to. - PortRange *PortRange `locationName:"portRange" type:"structure"` - - // The protocol. A value of -1 means all protocols. - Protocol *string `locationName:"protocol" type:"string" required:"true"` - - // Indicates whether to allow or deny the traffic that matches the rule. - RuleAction *string `locationName:"ruleAction" type:"string" required:"true" enum:"RuleAction"` - - // The rule number for the entry (for example, 100). ACL entries are processed - // in ascending order by rule number. - // - // Constraints: Positive integer from 1 to 32766 - RuleNumber *int64 `locationName:"ruleNumber" type:"integer" required:"true"` - - metadataCreateNetworkAclEntryInput `json:"-" xml:"-"` -} - -type metadataCreateNetworkAclEntryInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateNetworkAclEntryInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateNetworkAclEntryInput) GoString() string { - return s.String() -} - -type CreateNetworkAclEntryOutput struct { - metadataCreateNetworkAclEntryOutput `json:"-" xml:"-"` -} - -type metadataCreateNetworkAclEntryOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateNetworkAclEntryOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateNetworkAclEntryOutput) GoString() string { - return s.String() -} - -type CreateNetworkAclInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the VPC. - VpcId *string `locationName:"vpcId" type:"string" required:"true"` - - metadataCreateNetworkAclInput `json:"-" xml:"-"` -} - -type metadataCreateNetworkAclInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateNetworkAclInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateNetworkAclInput) GoString() string { - return s.String() -} - -type CreateNetworkAclOutput struct { - // Information about the network ACL. - NetworkAcl *NetworkAcl `locationName:"networkAcl" type:"structure"` - - metadataCreateNetworkAclOutput `json:"-" xml:"-"` -} - -type metadataCreateNetworkAclOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateNetworkAclOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateNetworkAclOutput) GoString() string { - return s.String() -} - -type CreateNetworkInterfaceInput struct { - // A description for the network interface. - Description *string `locationName:"description" type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The IDs of one or more security groups. - Groups []*string `locationName:"SecurityGroupId" locationNameList:"SecurityGroupId" type:"list"` - - // The primary private IP address of the network interface. If you don't specify - // an IP address, Amazon EC2 selects one for you from the subnet range. If you - // specify an IP address, you cannot indicate any IP addresses specified in - // privateIpAddresses as primary (only one IP address can be designated as primary). - PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` - - // One or more private IP addresses. - PrivateIpAddresses []*PrivateIpAddressSpecification `locationName:"privateIpAddresses" locationNameList:"item" type:"list"` - - // The number of secondary private IP addresses to assign to a network interface. - // When you specify a number of secondary IP addresses, Amazon EC2 selects these - // IP addresses within the subnet range. You can't specify this option and specify - // more than one private IP address using privateIpAddresses. - // - // The number of IP addresses you can assign to a network interface varies - // by instance type. For more information, see Private IP Addresses Per ENI - // Per Instance Type (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html#AvailableIpPerENI) - // in the Amazon Elastic Compute Cloud User Guide. - SecondaryPrivateIpAddressCount *int64 `locationName:"secondaryPrivateIpAddressCount" type:"integer"` - - // The ID of the subnet to associate with the network interface. - SubnetId *string `locationName:"subnetId" type:"string" required:"true"` - - metadataCreateNetworkInterfaceInput `json:"-" xml:"-"` -} - -type metadataCreateNetworkInterfaceInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateNetworkInterfaceInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateNetworkInterfaceInput) GoString() string { - return s.String() -} - -type CreateNetworkInterfaceOutput struct { - // Information about the network interface. - NetworkInterface *NetworkInterface `locationName:"networkInterface" type:"structure"` - - metadataCreateNetworkInterfaceOutput `json:"-" xml:"-"` -} - -type metadataCreateNetworkInterfaceOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateNetworkInterfaceOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateNetworkInterfaceOutput) GoString() string { - return s.String() -} - -type CreatePlacementGroupInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // A name for the placement group. - // - // Constraints: Up to 255 ASCII characters - GroupName *string `locationName:"groupName" type:"string" required:"true"` - - // The placement strategy. - Strategy *string `locationName:"strategy" type:"string" required:"true" enum:"PlacementStrategy"` - - metadataCreatePlacementGroupInput `json:"-" xml:"-"` -} - -type metadataCreatePlacementGroupInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreatePlacementGroupInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreatePlacementGroupInput) GoString() string { - return s.String() -} - -type CreatePlacementGroupOutput struct { - metadataCreatePlacementGroupOutput `json:"-" xml:"-"` -} - -type metadataCreatePlacementGroupOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreatePlacementGroupOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreatePlacementGroupOutput) GoString() string { - return s.String() -} - -type CreateReservedInstancesListingInput struct { - // Unique, case-sensitive identifier you provide to ensure idempotency of your - // listings. This helps avoid duplicate listings. For more information, see - // Ensuring Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/APIReference/Run_Instance_Idempotency.html). - ClientToken *string `locationName:"clientToken" type:"string" required:"true"` - - // The number of instances that are a part of a Reserved Instance account to - // be listed in the Reserved Instance Marketplace. This number should be less - // than or equal to the instance count associated with the Reserved Instance - // ID specified in this call. - InstanceCount *int64 `locationName:"instanceCount" type:"integer" required:"true"` - - // A list specifying the price of the Reserved Instance for each month remaining - // in the Reserved Instance term. - PriceSchedules []*PriceScheduleSpecification `locationName:"priceSchedules" locationNameList:"item" type:"list" required:"true"` - - // The ID of the active Reserved Instance. - ReservedInstancesId *string `locationName:"reservedInstancesId" type:"string" required:"true"` - - metadataCreateReservedInstancesListingInput `json:"-" xml:"-"` -} - -type metadataCreateReservedInstancesListingInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateReservedInstancesListingInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateReservedInstancesListingInput) GoString() string { - return s.String() -} - -type CreateReservedInstancesListingOutput struct { - // Information about the Reserved Instances listing. - ReservedInstancesListings []*ReservedInstancesListing `locationName:"reservedInstancesListingsSet" locationNameList:"item" type:"list"` - - metadataCreateReservedInstancesListingOutput `json:"-" xml:"-"` -} - -type metadataCreateReservedInstancesListingOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateReservedInstancesListingOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateReservedInstancesListingOutput) GoString() string { - return s.String() -} - -type CreateRouteInput struct { - // The CIDR address block used for the destination match. Routing decisions - // are based on the most specific match. - DestinationCidrBlock *string `locationName:"destinationCidrBlock" type:"string" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of an Internet gateway or virtual private gateway attached to your - // VPC. - GatewayId *string `locationName:"gatewayId" type:"string"` - - // The ID of a NAT instance in your VPC. The operation fails if you specify - // an instance ID unless exactly one network interface is attached. - InstanceId *string `locationName:"instanceId" type:"string"` - - // The ID of a network interface. - NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string"` - - // The ID of the route table for the route. - RouteTableId *string `locationName:"routeTableId" type:"string" required:"true"` - - // The ID of a VPC peering connection. - VpcPeeringConnectionId *string `locationName:"vpcPeeringConnectionId" type:"string"` - - metadataCreateRouteInput `json:"-" xml:"-"` -} - -type metadataCreateRouteInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateRouteInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateRouteInput) GoString() string { - return s.String() -} - -type CreateRouteOutput struct { - // Returns true if the request succeeds; otherwise, it returns an error. - Return *bool `locationName:"return" type:"boolean"` - - metadataCreateRouteOutput `json:"-" xml:"-"` -} - -type metadataCreateRouteOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateRouteOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateRouteOutput) GoString() string { - return s.String() -} - -type CreateRouteTableInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the VPC. - VpcId *string `locationName:"vpcId" type:"string" required:"true"` - - metadataCreateRouteTableInput `json:"-" xml:"-"` -} - -type metadataCreateRouteTableInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateRouteTableInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateRouteTableInput) GoString() string { - return s.String() -} - -type CreateRouteTableOutput struct { - // Information about the route table. - RouteTable *RouteTable `locationName:"routeTable" type:"structure"` - - metadataCreateRouteTableOutput `json:"-" xml:"-"` -} - -type metadataCreateRouteTableOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateRouteTableOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateRouteTableOutput) GoString() string { - return s.String() -} - -type CreateSecurityGroupInput struct { - // A description for the security group. This is informational only. - // - // Constraints: Up to 255 characters in length - // - // Constraints for EC2-Classic: ASCII characters - // - // Constraints for EC2-VPC: a-z, A-Z, 0-9, spaces, and ._-:/()#,@[]+=&;{}!$* - Description *string `locationName:"GroupDescription" type:"string" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The name of the security group. - // - // Constraints: Up to 255 characters in length - // - // Constraints for EC2-Classic: ASCII characters - // - // Constraints for EC2-VPC: a-z, A-Z, 0-9, spaces, and ._-:/()#,@[]+=&;{}!$* - GroupName *string `type:"string" required:"true"` - - // [EC2-VPC] The ID of the VPC. Required for EC2-VPC. - VpcId *string `type:"string"` - - metadataCreateSecurityGroupInput `json:"-" xml:"-"` -} - -type metadataCreateSecurityGroupInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateSecurityGroupInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateSecurityGroupInput) GoString() string { - return s.String() -} - -type CreateSecurityGroupOutput struct { - // The ID of the security group. - GroupId *string `locationName:"groupId" type:"string"` - - metadataCreateSecurityGroupOutput `json:"-" xml:"-"` -} - -type metadataCreateSecurityGroupOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateSecurityGroupOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateSecurityGroupOutput) GoString() string { - return s.String() -} - -type CreateSnapshotInput struct { - // A description for the snapshot. - Description *string `type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the EBS volume. - VolumeId *string `type:"string" required:"true"` - - metadataCreateSnapshotInput `json:"-" xml:"-"` -} - -type metadataCreateSnapshotInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateSnapshotInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateSnapshotInput) GoString() string { - return s.String() -} - -// Contains the parameters for CreateSpotDatafeedSubscription. -type CreateSpotDatafeedSubscriptionInput struct { - // The Amazon S3 bucket in which to store the Spot instance data feed. - Bucket *string `locationName:"bucket" type:"string" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // A prefix for the data feed file names. - Prefix *string `locationName:"prefix" type:"string"` - - metadataCreateSpotDatafeedSubscriptionInput `json:"-" xml:"-"` -} - -type metadataCreateSpotDatafeedSubscriptionInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateSpotDatafeedSubscriptionInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateSpotDatafeedSubscriptionInput) GoString() string { - return s.String() -} - -// Contains the output of CreateSpotDatafeedSubscription. -type CreateSpotDatafeedSubscriptionOutput struct { - // The Spot instance data feed subscription. - SpotDatafeedSubscription *SpotDatafeedSubscription `locationName:"spotDatafeedSubscription" type:"structure"` - - metadataCreateSpotDatafeedSubscriptionOutput `json:"-" xml:"-"` -} - -type metadataCreateSpotDatafeedSubscriptionOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateSpotDatafeedSubscriptionOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateSpotDatafeedSubscriptionOutput) GoString() string { - return s.String() -} - -type CreateSubnetInput struct { - // The Availability Zone for the subnet. - // - // Default: AWS selects one for you. If you create more than one subnet in - // your VPC, we may not necessarily select a different zone for each subnet. - AvailabilityZone *string `type:"string"` - - // The network range for the subnet, in CIDR notation. For example, 10.0.0.0/24. - CidrBlock *string `type:"string" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the VPC. - VpcId *string `type:"string" required:"true"` - - metadataCreateSubnetInput `json:"-" xml:"-"` -} - -type metadataCreateSubnetInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateSubnetInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateSubnetInput) GoString() string { - return s.String() -} - -type CreateSubnetOutput struct { - // Information about the subnet. - Subnet *Subnet `locationName:"subnet" type:"structure"` - - metadataCreateSubnetOutput `json:"-" xml:"-"` -} - -type metadataCreateSubnetOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateSubnetOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateSubnetOutput) GoString() string { - return s.String() -} - -type CreateTagsInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The IDs of one or more resources to tag. For example, ami-1a2b3c4d. - Resources []*string `locationName:"ResourceId" type:"list" required:"true"` - - // One or more tags. The value parameter is required, but if you don't want - // the tag to have a value, specify the parameter with no value, and we set - // the value to an empty string. - Tags []*Tag `locationName:"Tag" locationNameList:"item" type:"list" required:"true"` - - metadataCreateTagsInput `json:"-" xml:"-"` -} - -type metadataCreateTagsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateTagsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateTagsInput) GoString() string { - return s.String() -} - -type CreateTagsOutput struct { - metadataCreateTagsOutput `json:"-" xml:"-"` -} - -type metadataCreateTagsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateTagsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateTagsOutput) GoString() string { - return s.String() -} - -type CreateVolumeInput struct { - // The Availability Zone in which to create the volume. Use DescribeAvailabilityZones - // to list the Availability Zones that are currently available to you. - AvailabilityZone *string `type:"string" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // Specifies whether the volume should be encrypted. Encrypted Amazon EBS volumes - // may only be attached to instances that support Amazon EBS encryption. Volumes - // that are created from encrypted snapshots are automatically encrypted. There - // is no way to create an encrypted volume from an unencrypted snapshot or vice - // versa. If your AMI uses encrypted volumes, you can only launch it on supported - // instance types. For more information, see Amazon EBS Encryption (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html) - // in the Amazon Elastic Compute Cloud User Guide. - Encrypted *bool `locationName:"encrypted" type:"boolean"` - - // Only valid for Provisioned IOPS (SSD) volumes. The number of I/O operations - // per second (IOPS) to provision for the volume, with a maximum ratio of 30 - // IOPS/GiB. - // - // Constraint: Range is 100 to 20000 for Provisioned IOPS (SSD) volumes - Iops *int64 `type:"integer"` - - // The full ARN of the AWS Key Management Service (AWS KMS) customer master - // key (CMK) to use when creating the encrypted volume. This parameter is only - // required if you want to use a non-default CMK; if this parameter is not specified, - // the default CMK for EBS is used. The ARN contains the arn:aws:kms namespace, - // followed by the region of the CMK, the AWS account ID of the CMK owner, the - // key namespace, and then the CMK ID. For example, arn:aws:kms:us-east-1:012345678910:key/abcd1234-a123-456a-a12b-a123b4cd56ef. - // If a KmsKeyId is specified, the Encrypted flag must also be set. - KmsKeyId *string `type:"string"` - - // The size of the volume, in GiBs. - // - // Constraints: 1-1024 for standard volumes, 1-16384 for gp2 volumes, and 4-16384 - // for io1 volumes. If you specify a snapshot, the volume size must be equal - // to or larger than the snapshot size. - // - // Default: If you're creating the volume from a snapshot and don't specify - // a volume size, the default is the snapshot size. - Size *int64 `type:"integer"` - - // The snapshot from which to create the volume. - SnapshotId *string `type:"string"` - - // The volume type. This can be gp2 for General Purpose (SSD) volumes, io1 for - // Provisioned IOPS (SSD) volumes, or standard for Magnetic volumes. - // - // Default: standard - VolumeType *string `type:"string" enum:"VolumeType"` - - metadataCreateVolumeInput `json:"-" xml:"-"` -} - -type metadataCreateVolumeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateVolumeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateVolumeInput) GoString() string { - return s.String() -} - -// Describes the user or group to be added or removed from the permissions for -// a volume. -type CreateVolumePermission struct { - // The specific group that is to be added or removed from a volume's list of - // create volume permissions. - Group *string `locationName:"group" type:"string" enum:"PermissionGroup"` - - // The specific AWS account ID that is to be added or removed from a volume's - // list of create volume permissions. - UserId *string `locationName:"userId" type:"string"` - - metadataCreateVolumePermission `json:"-" xml:"-"` -} - -type metadataCreateVolumePermission struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateVolumePermission) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateVolumePermission) GoString() string { - return s.String() -} - -// Describes modifications to the permissions for a volume. -type CreateVolumePermissionModifications struct { - // Adds a specific AWS account ID or group to a volume's list of create volume - // permissions. - Add []*CreateVolumePermission `locationNameList:"item" type:"list"` - - // Removes a specific AWS account ID or group from a volume's list of create - // volume permissions. - Remove []*CreateVolumePermission `locationNameList:"item" type:"list"` - - metadataCreateVolumePermissionModifications `json:"-" xml:"-"` -} - -type metadataCreateVolumePermissionModifications struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateVolumePermissionModifications) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateVolumePermissionModifications) GoString() string { - return s.String() -} - -type CreateVpcEndpointInput struct { - // Unique, case-sensitive identifier you provide to ensure the idempotency of - // the request. For more information, see How to Ensure Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/APIReference/Run_Instance_Idempotency.html). - ClientToken *string `type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `type:"boolean"` - - // A policy to attach to the endpoint that controls access to the service. The - // policy must be in valid JSON format. If this parameter is not specified, - // we attach a default policy that allows full access to the service. - PolicyDocument *string `type:"string"` - - // One or more route table IDs. - RouteTableIds []*string `locationName:"RouteTableId" locationNameList:"item" type:"list"` - - // The AWS service name, in the form com.amazonaws.region.service. To get a - // list of available services, use the DescribeVpcEndpointServices request. - ServiceName *string `type:"string" required:"true"` - - // The ID of the VPC in which the endpoint will be used. - VpcId *string `type:"string" required:"true"` - - metadataCreateVpcEndpointInput `json:"-" xml:"-"` -} - -type metadataCreateVpcEndpointInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateVpcEndpointInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateVpcEndpointInput) GoString() string { - return s.String() -} - -type CreateVpcEndpointOutput struct { - // Unique, case-sensitive identifier you provide to ensure the idempotency of - // the request. - ClientToken *string `locationName:"clientToken" type:"string"` - - // Information about the endpoint. - VpcEndpoint *VpcEndpoint `locationName:"vpcEndpoint" type:"structure"` - - metadataCreateVpcEndpointOutput `json:"-" xml:"-"` -} - -type metadataCreateVpcEndpointOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateVpcEndpointOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateVpcEndpointOutput) GoString() string { - return s.String() -} - -type CreateVpcInput struct { - // The network range for the VPC, in CIDR notation. For example, 10.0.0.0/16. - CidrBlock *string `type:"string" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The supported tenancy options for instances launched into the VPC. A value - // of default means that instances can be launched with any tenancy; a value - // of dedicated means all instances launched into the VPC are launched as dedicated - // tenancy instances regardless of the tenancy assigned to the instance at launch. - // Dedicated tenancy instances run on single-tenant hardware. - // - // Default: default - InstanceTenancy *string `locationName:"instanceTenancy" type:"string" enum:"Tenancy"` - - metadataCreateVpcInput `json:"-" xml:"-"` -} - -type metadataCreateVpcInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateVpcInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateVpcInput) GoString() string { - return s.String() -} - -type CreateVpcOutput struct { - // Information about the VPC. - Vpc *Vpc `locationName:"vpc" type:"structure"` - - metadataCreateVpcOutput `json:"-" xml:"-"` -} - -type metadataCreateVpcOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateVpcOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateVpcOutput) GoString() string { - return s.String() -} - -type CreateVpcPeeringConnectionInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The AWS account ID of the owner of the peer VPC. - // - // Default: Your AWS account ID - PeerOwnerId *string `locationName:"peerOwnerId" type:"string"` - - // The ID of the VPC with which you are creating the VPC peering connection. - PeerVpcId *string `locationName:"peerVpcId" type:"string"` - - // The ID of the requester VPC. - VpcId *string `locationName:"vpcId" type:"string"` - - metadataCreateVpcPeeringConnectionInput `json:"-" xml:"-"` -} - -type metadataCreateVpcPeeringConnectionInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateVpcPeeringConnectionInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateVpcPeeringConnectionInput) GoString() string { - return s.String() -} - -type CreateVpcPeeringConnectionOutput struct { - // Information about the VPC peering connection. - VpcPeeringConnection *VpcPeeringConnection `locationName:"vpcPeeringConnection" type:"structure"` - - metadataCreateVpcPeeringConnectionOutput `json:"-" xml:"-"` -} - -type metadataCreateVpcPeeringConnectionOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateVpcPeeringConnectionOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateVpcPeeringConnectionOutput) GoString() string { - return s.String() -} - -type CreateVpnConnectionInput struct { - // The ID of the customer gateway. - CustomerGatewayId *string `type:"string" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // Indicates whether the VPN connection requires static routes. If you are creating - // a VPN connection for a device that does not support BGP, you must specify - // true. - // - // Default: false - Options *VpnConnectionOptionsSpecification `locationName:"options" type:"structure"` - - // The type of VPN connection (ipsec.1). - Type *string `type:"string" required:"true"` - - // The ID of the virtual private gateway. - VpnGatewayId *string `type:"string" required:"true"` - - metadataCreateVpnConnectionInput `json:"-" xml:"-"` -} - -type metadataCreateVpnConnectionInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateVpnConnectionInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateVpnConnectionInput) GoString() string { - return s.String() -} - -type CreateVpnConnectionOutput struct { - // Information about the VPN connection. - VpnConnection *VpnConnection `locationName:"vpnConnection" type:"structure"` - - metadataCreateVpnConnectionOutput `json:"-" xml:"-"` -} - -type metadataCreateVpnConnectionOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateVpnConnectionOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateVpnConnectionOutput) GoString() string { - return s.String() -} - -type CreateVpnConnectionRouteInput struct { - // The CIDR block associated with the local subnet of the customer network. - DestinationCidrBlock *string `type:"string" required:"true"` - - // The ID of the VPN connection. - VpnConnectionId *string `type:"string" required:"true"` - - metadataCreateVpnConnectionRouteInput `json:"-" xml:"-"` -} - -type metadataCreateVpnConnectionRouteInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateVpnConnectionRouteInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateVpnConnectionRouteInput) GoString() string { - return s.String() -} - -type CreateVpnConnectionRouteOutput struct { - metadataCreateVpnConnectionRouteOutput `json:"-" xml:"-"` -} - -type metadataCreateVpnConnectionRouteOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateVpnConnectionRouteOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateVpnConnectionRouteOutput) GoString() string { - return s.String() -} - -type CreateVpnGatewayInput struct { - // The Availability Zone for the virtual private gateway. - AvailabilityZone *string `type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The type of VPN connection this virtual private gateway supports. - Type *string `type:"string" required:"true" enum:"GatewayType"` - - metadataCreateVpnGatewayInput `json:"-" xml:"-"` -} - -type metadataCreateVpnGatewayInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateVpnGatewayInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateVpnGatewayInput) GoString() string { - return s.String() -} - -type CreateVpnGatewayOutput struct { - // Information about the virtual private gateway. - VpnGateway *VpnGateway `locationName:"vpnGateway" type:"structure"` - - metadataCreateVpnGatewayOutput `json:"-" xml:"-"` -} - -type metadataCreateVpnGatewayOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CreateVpnGatewayOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CreateVpnGatewayOutput) GoString() string { - return s.String() -} - -// Describes a customer gateway. -type CustomerGateway struct { - // The customer gateway's Border Gateway Protocol (BGP) Autonomous System Number - // (ASN). - BgpAsn *string `locationName:"bgpAsn" type:"string"` - - // The ID of the customer gateway. - CustomerGatewayId *string `locationName:"customerGatewayId" type:"string"` - - // The Internet-routable IP address of the customer gateway's outside interface. - IpAddress *string `locationName:"ipAddress" type:"string"` - - // The current state of the customer gateway (pending | available | deleting - // | deleted). - State *string `locationName:"state" type:"string"` - - // Any tags assigned to the customer gateway. - Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - // The type of VPN connection the customer gateway supports (ipsec.1). - Type *string `locationName:"type" type:"string"` - - metadataCustomerGateway `json:"-" xml:"-"` -} - -type metadataCustomerGateway struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s CustomerGateway) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s CustomerGateway) GoString() string { - return s.String() -} - -type DeleteCustomerGatewayInput struct { - // The ID of the customer gateway. - CustomerGatewayId *string `type:"string" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - metadataDeleteCustomerGatewayInput `json:"-" xml:"-"` -} - -type metadataDeleteCustomerGatewayInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteCustomerGatewayInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteCustomerGatewayInput) GoString() string { - return s.String() -} - -type DeleteCustomerGatewayOutput struct { - metadataDeleteCustomerGatewayOutput `json:"-" xml:"-"` -} - -type metadataDeleteCustomerGatewayOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteCustomerGatewayOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteCustomerGatewayOutput) GoString() string { - return s.String() -} - -type DeleteDhcpOptionsInput struct { - // The ID of the DHCP options set. - DhcpOptionsId *string `type:"string" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - metadataDeleteDhcpOptionsInput `json:"-" xml:"-"` -} - -type metadataDeleteDhcpOptionsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteDhcpOptionsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteDhcpOptionsInput) GoString() string { - return s.String() -} - -type DeleteDhcpOptionsOutput struct { - metadataDeleteDhcpOptionsOutput `json:"-" xml:"-"` -} - -type metadataDeleteDhcpOptionsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteDhcpOptionsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteDhcpOptionsOutput) GoString() string { - return s.String() -} - -type DeleteFlowLogsInput struct { - // One or more flow log IDs. - FlowLogIds []*string `locationName:"FlowLogId" locationNameList:"item" type:"list" required:"true"` - - metadataDeleteFlowLogsInput `json:"-" xml:"-"` -} - -type metadataDeleteFlowLogsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteFlowLogsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteFlowLogsInput) GoString() string { - return s.String() -} - -type DeleteFlowLogsOutput struct { - // Information about the flow logs that could not be deleted successfully. - Unsuccessful []*UnsuccessfulItem `locationName:"unsuccessful" locationNameList:"item" type:"list"` - - metadataDeleteFlowLogsOutput `json:"-" xml:"-"` -} - -type metadataDeleteFlowLogsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteFlowLogsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteFlowLogsOutput) GoString() string { - return s.String() -} - -type DeleteInternetGatewayInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the Internet gateway. - InternetGatewayId *string `locationName:"internetGatewayId" type:"string" required:"true"` - - metadataDeleteInternetGatewayInput `json:"-" xml:"-"` -} - -type metadataDeleteInternetGatewayInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteInternetGatewayInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteInternetGatewayInput) GoString() string { - return s.String() -} - -type DeleteInternetGatewayOutput struct { - metadataDeleteInternetGatewayOutput `json:"-" xml:"-"` -} - -type metadataDeleteInternetGatewayOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteInternetGatewayOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteInternetGatewayOutput) GoString() string { - return s.String() -} - -type DeleteKeyPairInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The name of the key pair. - KeyName *string `type:"string" required:"true"` - - metadataDeleteKeyPairInput `json:"-" xml:"-"` -} - -type metadataDeleteKeyPairInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteKeyPairInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteKeyPairInput) GoString() string { - return s.String() -} - -type DeleteKeyPairOutput struct { - metadataDeleteKeyPairOutput `json:"-" xml:"-"` -} - -type metadataDeleteKeyPairOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteKeyPairOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteKeyPairOutput) GoString() string { - return s.String() -} - -type DeleteNetworkAclEntryInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // Indicates whether the rule is an egress rule. - Egress *bool `locationName:"egress" type:"boolean" required:"true"` - - // The ID of the network ACL. - NetworkAclId *string `locationName:"networkAclId" type:"string" required:"true"` - - // The rule number of the entry to delete. - RuleNumber *int64 `locationName:"ruleNumber" type:"integer" required:"true"` - - metadataDeleteNetworkAclEntryInput `json:"-" xml:"-"` -} - -type metadataDeleteNetworkAclEntryInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteNetworkAclEntryInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteNetworkAclEntryInput) GoString() string { - return s.String() -} - -type DeleteNetworkAclEntryOutput struct { - metadataDeleteNetworkAclEntryOutput `json:"-" xml:"-"` -} - -type metadataDeleteNetworkAclEntryOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteNetworkAclEntryOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteNetworkAclEntryOutput) GoString() string { - return s.String() -} - -type DeleteNetworkAclInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the network ACL. - NetworkAclId *string `locationName:"networkAclId" type:"string" required:"true"` - - metadataDeleteNetworkAclInput `json:"-" xml:"-"` -} - -type metadataDeleteNetworkAclInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteNetworkAclInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteNetworkAclInput) GoString() string { - return s.String() -} - -type DeleteNetworkAclOutput struct { - metadataDeleteNetworkAclOutput `json:"-" xml:"-"` -} - -type metadataDeleteNetworkAclOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteNetworkAclOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteNetworkAclOutput) GoString() string { - return s.String() -} - -type DeleteNetworkInterfaceInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the network interface. - NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string" required:"true"` - - metadataDeleteNetworkInterfaceInput `json:"-" xml:"-"` -} - -type metadataDeleteNetworkInterfaceInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteNetworkInterfaceInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteNetworkInterfaceInput) GoString() string { - return s.String() -} - -type DeleteNetworkInterfaceOutput struct { - metadataDeleteNetworkInterfaceOutput `json:"-" xml:"-"` -} - -type metadataDeleteNetworkInterfaceOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteNetworkInterfaceOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteNetworkInterfaceOutput) GoString() string { - return s.String() -} - -type DeletePlacementGroupInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The name of the placement group. - GroupName *string `locationName:"groupName" type:"string" required:"true"` - - metadataDeletePlacementGroupInput `json:"-" xml:"-"` -} - -type metadataDeletePlacementGroupInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeletePlacementGroupInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeletePlacementGroupInput) GoString() string { - return s.String() -} - -type DeletePlacementGroupOutput struct { - metadataDeletePlacementGroupOutput `json:"-" xml:"-"` -} - -type metadataDeletePlacementGroupOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeletePlacementGroupOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeletePlacementGroupOutput) GoString() string { - return s.String() -} - -type DeleteRouteInput struct { - // The CIDR range for the route. The value you specify must match the CIDR for - // the route exactly. - DestinationCidrBlock *string `locationName:"destinationCidrBlock" type:"string" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the route table. - RouteTableId *string `locationName:"routeTableId" type:"string" required:"true"` - - metadataDeleteRouteInput `json:"-" xml:"-"` -} - -type metadataDeleteRouteInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteRouteInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteRouteInput) GoString() string { - return s.String() -} - -type DeleteRouteOutput struct { - metadataDeleteRouteOutput `json:"-" xml:"-"` -} - -type metadataDeleteRouteOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteRouteOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteRouteOutput) GoString() string { - return s.String() -} - -type DeleteRouteTableInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the route table. - RouteTableId *string `locationName:"routeTableId" type:"string" required:"true"` - - metadataDeleteRouteTableInput `json:"-" xml:"-"` -} - -type metadataDeleteRouteTableInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteRouteTableInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteRouteTableInput) GoString() string { - return s.String() -} - -type DeleteRouteTableOutput struct { - metadataDeleteRouteTableOutput `json:"-" xml:"-"` -} - -type metadataDeleteRouteTableOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteRouteTableOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteRouteTableOutput) GoString() string { - return s.String() -} - -type DeleteSecurityGroupInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the security group. Required for a nondefault VPC. - GroupId *string `type:"string"` - - // [EC2-Classic, default VPC] The name of the security group. You can specify - // either the security group name or the security group ID. - GroupName *string `type:"string"` - - metadataDeleteSecurityGroupInput `json:"-" xml:"-"` -} - -type metadataDeleteSecurityGroupInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteSecurityGroupInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteSecurityGroupInput) GoString() string { - return s.String() -} - -type DeleteSecurityGroupOutput struct { - metadataDeleteSecurityGroupOutput `json:"-" xml:"-"` -} - -type metadataDeleteSecurityGroupOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteSecurityGroupOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteSecurityGroupOutput) GoString() string { - return s.String() -} - -type DeleteSnapshotInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the EBS snapshot. - SnapshotId *string `type:"string" required:"true"` - - metadataDeleteSnapshotInput `json:"-" xml:"-"` -} - -type metadataDeleteSnapshotInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteSnapshotInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteSnapshotInput) GoString() string { - return s.String() -} - -type DeleteSnapshotOutput struct { - metadataDeleteSnapshotOutput `json:"-" xml:"-"` -} - -type metadataDeleteSnapshotOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteSnapshotOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteSnapshotOutput) GoString() string { - return s.String() -} - -// Contains the parameters for DeleteSpotDatafeedSubscription. -type DeleteSpotDatafeedSubscriptionInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - metadataDeleteSpotDatafeedSubscriptionInput `json:"-" xml:"-"` -} - -type metadataDeleteSpotDatafeedSubscriptionInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteSpotDatafeedSubscriptionInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteSpotDatafeedSubscriptionInput) GoString() string { - return s.String() -} - -type DeleteSpotDatafeedSubscriptionOutput struct { - metadataDeleteSpotDatafeedSubscriptionOutput `json:"-" xml:"-"` -} - -type metadataDeleteSpotDatafeedSubscriptionOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteSpotDatafeedSubscriptionOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteSpotDatafeedSubscriptionOutput) GoString() string { - return s.String() -} - -type DeleteSubnetInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the subnet. - SubnetId *string `type:"string" required:"true"` - - metadataDeleteSubnetInput `json:"-" xml:"-"` -} - -type metadataDeleteSubnetInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteSubnetInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteSubnetInput) GoString() string { - return s.String() -} - -type DeleteSubnetOutput struct { - metadataDeleteSubnetOutput `json:"-" xml:"-"` -} - -type metadataDeleteSubnetOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteSubnetOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteSubnetOutput) GoString() string { - return s.String() -} - -type DeleteTagsInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the resource. For example, ami-1a2b3c4d. You can specify more than - // one resource ID. - Resources []*string `locationName:"resourceId" type:"list" required:"true"` - - // One or more tags to delete. If you omit the value parameter, we delete the - // tag regardless of its value. If you specify this parameter with an empty - // string as the value, we delete the key only if its value is an empty string. - Tags []*Tag `locationName:"tag" locationNameList:"item" type:"list"` - - metadataDeleteTagsInput `json:"-" xml:"-"` -} - -type metadataDeleteTagsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteTagsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteTagsInput) GoString() string { - return s.String() -} - -type DeleteTagsOutput struct { - metadataDeleteTagsOutput `json:"-" xml:"-"` -} - -type metadataDeleteTagsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteTagsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteTagsOutput) GoString() string { - return s.String() -} - -type DeleteVolumeInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the volume. - VolumeId *string `type:"string" required:"true"` - - metadataDeleteVolumeInput `json:"-" xml:"-"` -} - -type metadataDeleteVolumeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteVolumeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteVolumeInput) GoString() string { - return s.String() -} - -type DeleteVolumeOutput struct { - metadataDeleteVolumeOutput `json:"-" xml:"-"` -} - -type metadataDeleteVolumeOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteVolumeOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteVolumeOutput) GoString() string { - return s.String() -} - -type DeleteVpcEndpointsInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `type:"boolean"` - - // One or more endpoint IDs. - VpcEndpointIds []*string `locationName:"VpcEndpointId" locationNameList:"item" type:"list" required:"true"` - - metadataDeleteVpcEndpointsInput `json:"-" xml:"-"` -} - -type metadataDeleteVpcEndpointsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteVpcEndpointsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteVpcEndpointsInput) GoString() string { - return s.String() -} - -type DeleteVpcEndpointsOutput struct { - // Information about the endpoints that were not successfully deleted. - Unsuccessful []*UnsuccessfulItem `locationName:"unsuccessful" locationNameList:"item" type:"list"` - - metadataDeleteVpcEndpointsOutput `json:"-" xml:"-"` -} - -type metadataDeleteVpcEndpointsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteVpcEndpointsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteVpcEndpointsOutput) GoString() string { - return s.String() -} - -type DeleteVpcInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the VPC. - VpcId *string `type:"string" required:"true"` - - metadataDeleteVpcInput `json:"-" xml:"-"` -} - -type metadataDeleteVpcInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteVpcInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteVpcInput) GoString() string { - return s.String() -} - -type DeleteVpcOutput struct { - metadataDeleteVpcOutput `json:"-" xml:"-"` -} - -type metadataDeleteVpcOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteVpcOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteVpcOutput) GoString() string { - return s.String() -} - -type DeleteVpcPeeringConnectionInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the VPC peering connection. - VpcPeeringConnectionId *string `locationName:"vpcPeeringConnectionId" type:"string" required:"true"` - - metadataDeleteVpcPeeringConnectionInput `json:"-" xml:"-"` -} - -type metadataDeleteVpcPeeringConnectionInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteVpcPeeringConnectionInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteVpcPeeringConnectionInput) GoString() string { - return s.String() -} - -type DeleteVpcPeeringConnectionOutput struct { - // Returns true if the request succeeds; otherwise, it returns an error. - Return *bool `locationName:"return" type:"boolean"` - - metadataDeleteVpcPeeringConnectionOutput `json:"-" xml:"-"` -} - -type metadataDeleteVpcPeeringConnectionOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteVpcPeeringConnectionOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteVpcPeeringConnectionOutput) GoString() string { - return s.String() -} - -type DeleteVpnConnectionInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the VPN connection. - VpnConnectionId *string `type:"string" required:"true"` - - metadataDeleteVpnConnectionInput `json:"-" xml:"-"` -} - -type metadataDeleteVpnConnectionInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteVpnConnectionInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteVpnConnectionInput) GoString() string { - return s.String() -} - -type DeleteVpnConnectionOutput struct { - metadataDeleteVpnConnectionOutput `json:"-" xml:"-"` -} - -type metadataDeleteVpnConnectionOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteVpnConnectionOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteVpnConnectionOutput) GoString() string { - return s.String() -} - -type DeleteVpnConnectionRouteInput struct { - // The CIDR block associated with the local subnet of the customer network. - DestinationCidrBlock *string `type:"string" required:"true"` - - // The ID of the VPN connection. - VpnConnectionId *string `type:"string" required:"true"` - - metadataDeleteVpnConnectionRouteInput `json:"-" xml:"-"` -} - -type metadataDeleteVpnConnectionRouteInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteVpnConnectionRouteInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteVpnConnectionRouteInput) GoString() string { - return s.String() -} - -type DeleteVpnConnectionRouteOutput struct { - metadataDeleteVpnConnectionRouteOutput `json:"-" xml:"-"` -} - -type metadataDeleteVpnConnectionRouteOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteVpnConnectionRouteOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteVpnConnectionRouteOutput) GoString() string { - return s.String() -} - -type DeleteVpnGatewayInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the virtual private gateway. - VpnGatewayId *string `type:"string" required:"true"` - - metadataDeleteVpnGatewayInput `json:"-" xml:"-"` -} - -type metadataDeleteVpnGatewayInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteVpnGatewayInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteVpnGatewayInput) GoString() string { - return s.String() -} - -type DeleteVpnGatewayOutput struct { - metadataDeleteVpnGatewayOutput `json:"-" xml:"-"` -} - -type metadataDeleteVpnGatewayOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeleteVpnGatewayOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeleteVpnGatewayOutput) GoString() string { - return s.String() -} - -type DeregisterImageInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the AMI. - ImageId *string `type:"string" required:"true"` - - metadataDeregisterImageInput `json:"-" xml:"-"` -} - -type metadataDeregisterImageInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeregisterImageInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeregisterImageInput) GoString() string { - return s.String() -} - -type DeregisterImageOutput struct { - metadataDeregisterImageOutput `json:"-" xml:"-"` -} - -type metadataDeregisterImageOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DeregisterImageOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DeregisterImageOutput) GoString() string { - return s.String() -} - -type DescribeAccountAttributesInput struct { - // One or more account attribute names. - AttributeNames []*string `locationName:"attributeName" locationNameList:"attributeName" type:"list"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - metadataDescribeAccountAttributesInput `json:"-" xml:"-"` -} - -type metadataDescribeAccountAttributesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeAccountAttributesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeAccountAttributesInput) GoString() string { - return s.String() -} - -type DescribeAccountAttributesOutput struct { - // Information about one or more account attributes. - AccountAttributes []*AccountAttribute `locationName:"accountAttributeSet" locationNameList:"item" type:"list"` - - metadataDescribeAccountAttributesOutput `json:"-" xml:"-"` -} - -type metadataDescribeAccountAttributesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeAccountAttributesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeAccountAttributesOutput) GoString() string { - return s.String() -} - -type DescribeAddressesInput struct { - // [EC2-VPC] One or more allocation IDs. - // - // Default: Describes all your Elastic IP addresses. - AllocationIds []*string `locationName:"AllocationId" locationNameList:"AllocationId" type:"list"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. Filter names and values are case-sensitive. - // - // allocation-id - [EC2-VPC] The allocation ID for the address. - // - // association-id - [EC2-VPC] The association ID for the address. - // - // domain - Indicates whether the address is for use in EC2-Classic (standard) - // or in a VPC (vpc). - // - // instance-id - The ID of the instance the address is associated with, if - // any. - // - // network-interface-id - [EC2-VPC] The ID of the network interface that - // the address is associated with, if any. - // - // network-interface-owner-id - The AWS account ID of the owner. - // - // private-ip-address - [EC2-VPC] The private IP address associated with - // the Elastic IP address. - // - // public-ip - The Elastic IP address. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // [EC2-Classic] One or more Elastic IP addresses. - // - // Default: Describes all your Elastic IP addresses. - PublicIps []*string `locationName:"PublicIp" locationNameList:"PublicIp" type:"list"` - - metadataDescribeAddressesInput `json:"-" xml:"-"` -} - -type metadataDescribeAddressesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeAddressesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeAddressesInput) GoString() string { - return s.String() -} - -type DescribeAddressesOutput struct { - // Information about one or more Elastic IP addresses. - Addresses []*Address `locationName:"addressesSet" locationNameList:"item" type:"list"` - - metadataDescribeAddressesOutput `json:"-" xml:"-"` -} - -type metadataDescribeAddressesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeAddressesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeAddressesOutput) GoString() string { - return s.String() -} - -type DescribeAvailabilityZonesInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // message - Information about the Availability Zone. - // - // region-name - The name of the region for the Availability Zone (for example, - // us-east-1). - // - // state - The state of the Availability Zone (available | information | - // impaired | unavailable). - // - // zone-name - The name of the Availability Zone (for example, us-east-1a). - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // The names of one or more Availability Zones. - ZoneNames []*string `locationName:"ZoneName" locationNameList:"ZoneName" type:"list"` - - metadataDescribeAvailabilityZonesInput `json:"-" xml:"-"` -} - -type metadataDescribeAvailabilityZonesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeAvailabilityZonesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeAvailabilityZonesInput) GoString() string { - return s.String() -} - -type DescribeAvailabilityZonesOutput struct { - // Information about one or more Availability Zones. - AvailabilityZones []*AvailabilityZone `locationName:"availabilityZoneInfo" locationNameList:"item" type:"list"` - - metadataDescribeAvailabilityZonesOutput `json:"-" xml:"-"` -} - -type metadataDescribeAvailabilityZonesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeAvailabilityZonesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeAvailabilityZonesOutput) GoString() string { - return s.String() -} - -type DescribeBundleTasksInput struct { - // One or more bundle task IDs. - // - // Default: Describes all your bundle tasks. - BundleIds []*string `locationName:"BundleId" locationNameList:"BundleId" type:"list"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // bundle-id - The ID of the bundle task. - // - // error-code - If the task failed, the error code returned. - // - // error-message - If the task failed, the error message returned. - // - // instance-id - The ID of the instance. - // - // progress - The level of task completion, as a percentage (for example, - // 20%). - // - // s3-bucket - The Amazon S3 bucket to store the AMI. - // - // s3-prefix - The beginning of the AMI name. - // - // start-time - The time the task started (for example, 2013-09-15T17:15:20.000Z). - // - // state - The state of the task (pending | waiting-for-shutdown | bundling - // | storing | cancelling | complete | failed). - // - // update-time - The time of the most recent update for the task. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - metadataDescribeBundleTasksInput `json:"-" xml:"-"` -} - -type metadataDescribeBundleTasksInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeBundleTasksInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeBundleTasksInput) GoString() string { - return s.String() -} - -type DescribeBundleTasksOutput struct { - // Information about one or more bundle tasks. - BundleTasks []*BundleTask `locationName:"bundleInstanceTasksSet" locationNameList:"item" type:"list"` - - metadataDescribeBundleTasksOutput `json:"-" xml:"-"` -} - -type metadataDescribeBundleTasksOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeBundleTasksOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeBundleTasksOutput) GoString() string { - return s.String() -} - -type DescribeClassicLinkInstancesInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // group-id - The ID of a VPC security group that's associated with the instance. - // - // instance-id - The ID of the instance. - // - // tag:key=value - The key/value combination of a tag assigned to the resource. - // - // tag-key - The key of a tag assigned to the resource. This filter is independent - // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" - // and the filter "tag-value=X", you get any resources assigned both the tag - // key Purpose (regardless of what the tag's value is), and the tag value X - // (regardless of what the tag's key is). If you want to list only resources - // where Purpose is X, see the tag:key=value filter. - // - // tag-value - The value of a tag assigned to the resource. This filter is - // independent of the tag-key filter. - // - // vpc-id - The ID of the VPC that the instance is linked to. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // One or more instance IDs. Must be instances linked to a VPC through ClassicLink. - InstanceIds []*string `locationName:"InstanceId" locationNameList:"InstanceId" type:"list"` - - // The maximum number of results to return for the request in a single page. - // The remaining results of the initial request can be seen by sending another - // request with the returned NextToken value. This value can be between 5 and - // 1000; if MaxResults is given a value larger than 1000, only 1000 results - // are returned. You cannot specify this parameter and the instance IDs parameter - // in the same request. - // - // Constraint: If the value is greater than 1000, we return only 1000 items. - MaxResults *int64 `locationName:"maxResults" type:"integer"` - - // The token to retrieve the next page of results. - NextToken *string `locationName:"nextToken" type:"string"` - - metadataDescribeClassicLinkInstancesInput `json:"-" xml:"-"` -} - -type metadataDescribeClassicLinkInstancesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeClassicLinkInstancesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeClassicLinkInstancesInput) GoString() string { - return s.String() -} - -type DescribeClassicLinkInstancesOutput struct { - // Information about one or more linked EC2-Classic instances. - Instances []*ClassicLinkInstance `locationName:"instancesSet" locationNameList:"item" type:"list"` - - // The token to use to retrieve the next page of results. This value is null - // when there are no more results to return. - NextToken *string `locationName:"nextToken" type:"string"` - - metadataDescribeClassicLinkInstancesOutput `json:"-" xml:"-"` -} - -type metadataDescribeClassicLinkInstancesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeClassicLinkInstancesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeClassicLinkInstancesOutput) GoString() string { - return s.String() -} - -type DescribeConversionTasksInput struct { - // One or more conversion task IDs. - ConversionTaskIds []*string `locationName:"conversionTaskId" locationNameList:"item" type:"list"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - Filters []*Filter `locationName:"filter" locationNameList:"Filter" type:"list"` - - metadataDescribeConversionTasksInput `json:"-" xml:"-"` -} - -type metadataDescribeConversionTasksInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeConversionTasksInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeConversionTasksInput) GoString() string { - return s.String() -} - -type DescribeConversionTasksOutput struct { - // Information about the conversion tasks. - ConversionTasks []*ConversionTask `locationName:"conversionTasks" locationNameList:"item" type:"list"` - - metadataDescribeConversionTasksOutput `json:"-" xml:"-"` -} - -type metadataDescribeConversionTasksOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeConversionTasksOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeConversionTasksOutput) GoString() string { - return s.String() -} - -type DescribeCustomerGatewaysInput struct { - // One or more customer gateway IDs. - // - // Default: Describes all your customer gateways. - CustomerGatewayIds []*string `locationName:"CustomerGatewayId" locationNameList:"CustomerGatewayId" type:"list"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // bgp-asn - The customer gateway's Border Gateway Protocol (BGP) Autonomous - // System Number (ASN). - // - // customer-gateway-id - The ID of the customer gateway. - // - // ip-address - The IP address of the customer gateway's Internet-routable - // external interface. - // - // state - The state of the customer gateway (pending | available | deleting - // | deleted). - // - // type - The type of customer gateway. Currently, the only supported type - // is ipsec.1. - // - // tag:key=value - The key/value combination of a tag assigned to the resource. - // - // tag-key - The key of a tag assigned to the resource. This filter is independent - // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" - // and the filter "tag-value=X", you get any resources assigned both the tag - // key Purpose (regardless of what the tag's value is), and the tag value X - // (regardless of what the tag's key is). If you want to list only resources - // where Purpose is X, see the tag:key=value filter. - // - // tag-value - The value of a tag assigned to the resource. This filter is - // independent of the tag-key filter. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - metadataDescribeCustomerGatewaysInput `json:"-" xml:"-"` -} - -type metadataDescribeCustomerGatewaysInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeCustomerGatewaysInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeCustomerGatewaysInput) GoString() string { - return s.String() -} - -type DescribeCustomerGatewaysOutput struct { - // Information about one or more customer gateways. - CustomerGateways []*CustomerGateway `locationName:"customerGatewaySet" locationNameList:"item" type:"list"` - - metadataDescribeCustomerGatewaysOutput `json:"-" xml:"-"` -} - -type metadataDescribeCustomerGatewaysOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeCustomerGatewaysOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeCustomerGatewaysOutput) GoString() string { - return s.String() -} - -type DescribeDhcpOptionsInput struct { - // The IDs of one or more DHCP options sets. - // - // Default: Describes all your DHCP options sets. - DhcpOptionsIds []*string `locationName:"DhcpOptionsId" locationNameList:"DhcpOptionsId" type:"list"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // dhcp-options-id - The ID of a set of DHCP options. - // - // key - The key for one of the options (for example, domain-name). - // - // value - The value for one of the options. - // - // tag:key=value - The key/value combination of a tag assigned to the resource. - // - // tag-key - The key of a tag assigned to the resource. This filter is independent - // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" - // and the filter "tag-value=X", you get any resources assigned both the tag - // key Purpose (regardless of what the tag's value is), and the tag value X - // (regardless of what the tag's key is). If you want to list only resources - // where Purpose is X, see the tag:key=value filter. - // - // tag-value - The value of a tag assigned to the resource. This filter is - // independent of the tag-key filter. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - metadataDescribeDhcpOptionsInput `json:"-" xml:"-"` -} - -type metadataDescribeDhcpOptionsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeDhcpOptionsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeDhcpOptionsInput) GoString() string { - return s.String() -} - -type DescribeDhcpOptionsOutput struct { - // Information about one or more DHCP options sets. - DhcpOptions []*DhcpOptions `locationName:"dhcpOptionsSet" locationNameList:"item" type:"list"` - - metadataDescribeDhcpOptionsOutput `json:"-" xml:"-"` -} - -type metadataDescribeDhcpOptionsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeDhcpOptionsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeDhcpOptionsOutput) GoString() string { - return s.String() -} - -type DescribeExportTasksInput struct { - // One or more export task IDs. - ExportTaskIds []*string `locationName:"exportTaskId" locationNameList:"ExportTaskId" type:"list"` - - metadataDescribeExportTasksInput `json:"-" xml:"-"` -} - -type metadataDescribeExportTasksInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeExportTasksInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeExportTasksInput) GoString() string { - return s.String() -} - -type DescribeExportTasksOutput struct { - // Information about the export tasks. - ExportTasks []*ExportTask `locationName:"exportTaskSet" locationNameList:"item" type:"list"` - - metadataDescribeExportTasksOutput `json:"-" xml:"-"` -} - -type metadataDescribeExportTasksOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeExportTasksOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeExportTasksOutput) GoString() string { - return s.String() -} - -type DescribeFlowLogsInput struct { - // One or more filters. - // - // deliver-log-status - The status of the logs delivery (SUCCESS | FAILED). - // - // flow-log-id - The ID of the flow log. - // - // log-group-name - The name of the log group. - // - // resource-id - The ID of the VPC, subnet, or network interface. - // - // traffic-type - The type of traffic (ACCEPT | REJECT | ALL) - Filter []*Filter `locationNameList:"Filter" type:"list"` - - // One or more flow log IDs. - FlowLogIds []*string `locationName:"FlowLogId" locationNameList:"item" type:"list"` - - // The maximum number of results to return for the request in a single page. - // The remaining results can be seen by sending another request with the returned - // NextToken value. This value can be between 5 and 1000; if MaxResults is given - // a value larger than 1000, only 1000 results are returned. You cannot specify - // this parameter and the flow log IDs parameter in the same request. - MaxResults *int64 `type:"integer"` - - // The token to retrieve the next page of results. - NextToken *string `type:"string"` - - metadataDescribeFlowLogsInput `json:"-" xml:"-"` -} - -type metadataDescribeFlowLogsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeFlowLogsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeFlowLogsInput) GoString() string { - return s.String() -} - -type DescribeFlowLogsOutput struct { - // Information about the flow logs. - FlowLogs []*FlowLog `locationName:"flowLogSet" locationNameList:"item" type:"list"` - - // The token to use to retrieve the next page of results. This value is null - // when there are no more results to return. - NextToken *string `locationName:"nextToken" type:"string"` - - metadataDescribeFlowLogsOutput `json:"-" xml:"-"` -} - -type metadataDescribeFlowLogsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeFlowLogsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeFlowLogsOutput) GoString() string { - return s.String() -} - -type DescribeImageAttributeInput struct { - // The AMI attribute. - // - // Note: Depending on your account privileges, the blockDeviceMapping attribute - // may return a Client.AuthFailure error. If this happens, use DescribeImages - // to get information about the block device mapping for the AMI. - Attribute *string `type:"string" required:"true" enum:"ImageAttributeName"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the AMI. - ImageId *string `type:"string" required:"true"` - - metadataDescribeImageAttributeInput `json:"-" xml:"-"` -} - -type metadataDescribeImageAttributeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeImageAttributeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeImageAttributeInput) GoString() string { - return s.String() -} - -// Describes an image attribute. -type DescribeImageAttributeOutput struct { - // One or more block device mapping entries. - BlockDeviceMappings []*BlockDeviceMapping `locationName:"blockDeviceMapping" locationNameList:"item" type:"list"` - - // A description for the AMI. - Description *AttributeValue `locationName:"description" type:"structure"` - - // The ID of the AMI. - ImageId *string `locationName:"imageId" type:"string"` - - // The kernel ID. - KernelId *AttributeValue `locationName:"kernel" type:"structure"` - - // One or more launch permissions. - LaunchPermissions []*LaunchPermission `locationName:"launchPermission" locationNameList:"item" type:"list"` - - // One or more product codes. - ProductCodes []*ProductCode `locationName:"productCodes" locationNameList:"item" type:"list"` - - // The RAM disk ID. - RamdiskId *AttributeValue `locationName:"ramdisk" type:"structure"` - - // The value to use for a resource attribute. - SriovNetSupport *AttributeValue `locationName:"sriovNetSupport" type:"structure"` - - metadataDescribeImageAttributeOutput `json:"-" xml:"-"` -} - -type metadataDescribeImageAttributeOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeImageAttributeOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeImageAttributeOutput) GoString() string { - return s.String() -} - -type DescribeImagesInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // Scopes the images by users with explicit launch permissions. Specify an AWS - // account ID, self (the sender of the request), or all (public AMIs). - ExecutableUsers []*string `locationName:"ExecutableBy" locationNameList:"ExecutableBy" type:"list"` - - // One or more filters. - // - // architecture - The image architecture (i386 | x86_64). - // - // block-device-mapping.delete-on-termination - A Boolean value that indicates - // whether the Amazon EBS volume is deleted on instance termination. - // - // block-device-mapping.device-name - The device name for the EBS volume - // (for example, /dev/sdh). - // - // block-device-mapping.snapshot-id - The ID of the snapshot used for the - // EBS volume. - // - // block-device-mapping.volume-size - The volume size of the EBS volume, - // in GiB. - // - // block-device-mapping.volume-type - The volume type of the EBS volume (gp2 - // | standard | io1). - // - // description - The description of the image (provided during image creation). - // - // hypervisor - The hypervisor type (ovm | xen). - // - // image-id - The ID of the image. - // - // image-type - The image type (machine | kernel | ramdisk). - // - // is-public - A Boolean that indicates whether the image is public. - // - // kernel-id - The kernel ID. - // - // manifest-location - The location of the image manifest. - // - // name - The name of the AMI (provided during image creation). - // - // owner-alias - The AWS account alias (for example, amazon). - // - // owner-id - The AWS account ID of the image owner. - // - // platform - The platform. To only list Windows-based AMIs, use windows. - // - // product-code - The product code. - // - // product-code.type - The type of the product code (devpay | marketplace). - // - // ramdisk-id - The RAM disk ID. - // - // root-device-name - The name of the root device volume (for example, /dev/sda1). - // - // root-device-type - The type of the root device volume (ebs | instance-store). - // - // state - The state of the image (available | pending | failed). - // - // state-reason-code - The reason code for the state change. - // - // state-reason-message - The message for the state change. - // - // tag:key=value - The key/value combination of a tag assigned to the resource. - // - // tag-key - The key of a tag assigned to the resource. This filter is independent - // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" - // and the filter "tag-value=X", you get any resources assigned both the tag - // key Purpose (regardless of what the tag's value is), and the tag value X - // (regardless of what the tag's key is). If you want to list only resources - // where Purpose is X, see the tag:key=value filter. - // - // tag-value - The value of a tag assigned to the resource. This filter is - // independent of the tag-key filter. - // - // virtualization-type - The virtualization type (paravirtual | hvm). - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // One or more image IDs. - // - // Default: Describes all images available to you. - ImageIds []*string `locationName:"ImageId" locationNameList:"ImageId" type:"list"` - - // Filters the images by the owner. Specify an AWS account ID, amazon (owner - // is Amazon), aws-marketplace (owner is AWS Marketplace), self (owner is the - // sender of the request). Omitting this option returns all images for which - // you have launch permissions, regardless of ownership. - Owners []*string `locationName:"Owner" locationNameList:"Owner" type:"list"` - - metadataDescribeImagesInput `json:"-" xml:"-"` -} - -type metadataDescribeImagesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeImagesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeImagesInput) GoString() string { - return s.String() -} - -type DescribeImagesOutput struct { - // Information about one or more images. - Images []*Image `locationName:"imagesSet" locationNameList:"item" type:"list"` - - metadataDescribeImagesOutput `json:"-" xml:"-"` -} - -type metadataDescribeImagesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeImagesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeImagesOutput) GoString() string { - return s.String() -} - -type DescribeImportImageTasksInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `type:"boolean"` - - // One or more filters. - Filters []*Filter `locationNameList:"Filter" type:"list"` - - // A list of import image task IDs. - ImportTaskIds []*string `locationName:"ImportTaskId" locationNameList:"ImportTaskId" type:"list"` - - // The maximum number of results to return in a single request. - MaxResults *int64 `type:"integer"` - - // A token that indicates the next page of results. - NextToken *string `type:"string"` - - metadataDescribeImportImageTasksInput `json:"-" xml:"-"` -} - -type metadataDescribeImportImageTasksInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeImportImageTasksInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeImportImageTasksInput) GoString() string { - return s.String() -} - -type DescribeImportImageTasksOutput struct { - // A list of zero or more import image tasks that are currently active or were - // completed or canceled in the previous 7 days. - ImportImageTasks []*ImportImageTask `locationName:"importImageTaskSet" locationNameList:"item" type:"list"` - - // The token to use to get the next page of results. This value is null when - // there are no more results to return. - NextToken *string `locationName:"nextToken" type:"string"` - - metadataDescribeImportImageTasksOutput `json:"-" xml:"-"` -} - -type metadataDescribeImportImageTasksOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeImportImageTasksOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeImportImageTasksOutput) GoString() string { - return s.String() -} - -type DescribeImportSnapshotTasksInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `type:"boolean"` - - // One or more filters. - Filters []*Filter `locationNameList:"Filter" type:"list"` - - // A list of import snapshot task IDs. - ImportTaskIds []*string `locationName:"ImportTaskId" locationNameList:"ImportTaskId" type:"list"` - - // The maximum number of results to return in a single request. - MaxResults *int64 `type:"integer"` - - // A token that indicates the next page of results. - NextToken *string `type:"string"` - - metadataDescribeImportSnapshotTasksInput `json:"-" xml:"-"` -} - -type metadataDescribeImportSnapshotTasksInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeImportSnapshotTasksInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeImportSnapshotTasksInput) GoString() string { - return s.String() -} - -type DescribeImportSnapshotTasksOutput struct { - // A list of zero or more import snapshot tasks that are currently active or - // were completed or canceled in the previous 7 days. - ImportSnapshotTasks []*ImportSnapshotTask `locationName:"importSnapshotTaskSet" locationNameList:"item" type:"list"` - - // The token to use to get the next page of results. This value is null when - // there are no more results to return. - NextToken *string `locationName:"nextToken" type:"string"` - - metadataDescribeImportSnapshotTasksOutput `json:"-" xml:"-"` -} - -type metadataDescribeImportSnapshotTasksOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeImportSnapshotTasksOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeImportSnapshotTasksOutput) GoString() string { - return s.String() -} - -type DescribeInstanceAttributeInput struct { - // The instance attribute. - Attribute *string `locationName:"attribute" type:"string" required:"true" enum:"InstanceAttributeName"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the instance. - InstanceId *string `locationName:"instanceId" type:"string" required:"true"` - - metadataDescribeInstanceAttributeInput `json:"-" xml:"-"` -} - -type metadataDescribeInstanceAttributeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeInstanceAttributeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeInstanceAttributeInput) GoString() string { - return s.String() -} - -// Describes an instance attribute. -type DescribeInstanceAttributeOutput struct { - // The block device mapping of the instance. - BlockDeviceMappings []*InstanceBlockDeviceMapping `locationName:"blockDeviceMapping" locationNameList:"item" type:"list"` - - // If the value is true, you can't terminate the instance through the Amazon - // EC2 console, CLI, or API; otherwise, you can. - DisableApiTermination *AttributeBooleanValue `locationName:"disableApiTermination" type:"structure"` - - // Indicates whether the instance is optimized for EBS I/O. - EbsOptimized *AttributeBooleanValue `locationName:"ebsOptimized" type:"structure"` - - // The security groups associated with the instance. - Groups []*GroupIdentifier `locationName:"groupSet" locationNameList:"item" type:"list"` - - // The ID of the instance. - InstanceId *string `locationName:"instanceId" type:"string"` - - // Indicates whether an instance stops or terminates when you initiate shutdown - // from the instance (using the operating system command for system shutdown). - InstanceInitiatedShutdownBehavior *AttributeValue `locationName:"instanceInitiatedShutdownBehavior" type:"structure"` - - // The instance type. - InstanceType *AttributeValue `locationName:"instanceType" type:"structure"` - - // The kernel ID. - KernelId *AttributeValue `locationName:"kernel" type:"structure"` - - // A list of product codes. - ProductCodes []*ProductCode `locationName:"productCodes" locationNameList:"item" type:"list"` - - // The RAM disk ID. - RamdiskId *AttributeValue `locationName:"ramdisk" type:"structure"` - - // The name of the root device (for example, /dev/sda1 or /dev/xvda). - RootDeviceName *AttributeValue `locationName:"rootDeviceName" type:"structure"` - - // Indicates whether source/destination checking is enabled. A value of true - // means checking is enabled, and false means checking is disabled. This value - // must be false for a NAT instance to perform NAT. - SourceDestCheck *AttributeBooleanValue `locationName:"sourceDestCheck" type:"structure"` - - // The value to use for a resource attribute. - SriovNetSupport *AttributeValue `locationName:"sriovNetSupport" type:"structure"` - - // The Base64-encoded MIME user data. - UserData *AttributeValue `locationName:"userData" type:"structure"` - - metadataDescribeInstanceAttributeOutput `json:"-" xml:"-"` -} - -type metadataDescribeInstanceAttributeOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeInstanceAttributeOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeInstanceAttributeOutput) GoString() string { - return s.String() -} - -type DescribeInstanceStatusInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // availability-zone - The Availability Zone of the instance. - // - // event.code - The code for the scheduled event (instance-reboot | system-reboot - // | system-maintenance | instance-retirement | instance-stop). - // - // event.description - A description of the event. - // - // event.not-after - The latest end time for the scheduled event (for example, - // 2014-09-15T17:15:20.000Z). - // - // event.not-before - The earliest start time for the scheduled event (for - // example, 2014-09-15T17:15:20.000Z). - // - // instance-state-code - The code for the instance state, as a 16-bit unsigned - // integer. The high byte is an opaque internal value and should be ignored. - // The low byte is set based on the state represented. The valid values are - // 0 (pending), 16 (running), 32 (shutting-down), 48 (terminated), 64 (stopping), - // and 80 (stopped). - // - // instance-state-name - The state of the instance (pending | running | shutting-down - // | terminated | stopping | stopped). - // - // instance-status.reachability - Filters on instance status where the name - // is reachability (passed | failed | initializing | insufficient-data). - // - // instance-status.status - The status of the instance (ok | impaired | initializing - // | insufficient-data | not-applicable). - // - // system-status.reachability - Filters on system status where the name is - // reachability (passed | failed | initializing | insufficient-data). - // - // system-status.status - The system status of the instance (ok | impaired - // | initializing | insufficient-data | not-applicable). - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // When true, includes the health status for all instances. When false, includes - // the health status for running instances only. - // - // Default: false - IncludeAllInstances *bool `locationName:"includeAllInstances" type:"boolean"` - - // One or more instance IDs. - // - // Default: Describes all your instances. - // - // Constraints: Maximum 100 explicitly specified instance IDs. - InstanceIds []*string `locationName:"InstanceId" locationNameList:"InstanceId" type:"list"` - - // The maximum number of results to return for the request in a single page. - // The remaining results of the initial request can be seen by sending another - // request with the returned NextToken value. This value can be between 5 and - // 1000; if MaxResults is given a value larger than 1000, only 1000 results - // are returned. You cannot specify this parameter and the instance IDs parameter - // in the same request. - MaxResults *int64 `type:"integer"` - - // The token to retrieve the next page of results. - NextToken *string `type:"string"` - - metadataDescribeInstanceStatusInput `json:"-" xml:"-"` -} - -type metadataDescribeInstanceStatusInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeInstanceStatusInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeInstanceStatusInput) GoString() string { - return s.String() -} - -type DescribeInstanceStatusOutput struct { - // One or more instance status descriptions. - InstanceStatuses []*InstanceStatus `locationName:"instanceStatusSet" locationNameList:"item" type:"list"` - - // The token to use to retrieve the next page of results. This value is null - // when there are no more results to return. - NextToken *string `locationName:"nextToken" type:"string"` - - metadataDescribeInstanceStatusOutput `json:"-" xml:"-"` -} - -type metadataDescribeInstanceStatusOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeInstanceStatusOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeInstanceStatusOutput) GoString() string { - return s.String() -} - -type DescribeInstancesInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // architecture - The instance architecture (i386 | x86_64). - // - // availability-zone - The Availability Zone of the instance. - // - // block-device-mapping.attach-time - The attach time for an EBS volume mapped - // to the instance, for example, 2010-09-15T17:15:20.000Z. - // - // block-device-mapping.delete-on-termination - A Boolean that indicates - // whether the EBS volume is deleted on instance termination. - // - // block-device-mapping.device-name - The device name for the EBS volume - // (for example, /dev/sdh or xvdh). - // - // block-device-mapping.status - The status for the EBS volume (attaching - // | attached | detaching | detached). - // - // block-device-mapping.volume-id - The volume ID of the EBS volume. - // - // client-token - The idempotency token you provided when you launched the - // instance. - // - // dns-name - The public DNS name of the instance. - // - // group-id - The ID of the security group for the instance. EC2-Classic - // only. - // - // group-name - The name of the security group for the instance. EC2-Classic - // only. - // - // hypervisor - The hypervisor type of the instance (ovm | xen). - // - // iam-instance-profile.arn - The instance profile associated with the instance. - // Specified as an ARN. - // - // image-id - The ID of the image used to launch the instance. - // - // instance-id - The ID of the instance. - // - // instance-lifecycle - Indicates whether this is a Spot Instance (spot). - // - // instance-state-code - The state of the instance, as a 16-bit unsigned - // integer. The high byte is an opaque internal value and should be ignored. - // The low byte is set based on the state represented. The valid values are: - // 0 (pending), 16 (running), 32 (shutting-down), 48 (terminated), 64 (stopping), - // and 80 (stopped). - // - // instance-state-name - The state of the instance (pending | running | shutting-down - // | terminated | stopping | stopped). - // - // instance-type - The type of instance (for example, t2.micro). - // - // instance.group-id - The ID of the security group for the instance. - // - // instance.group-name - The name of the security group for the instance. - // - // ip-address - The public IP address of the instance. - // - // kernel-id - The kernel ID. - // - // key-name - The name of the key pair used when the instance was launched. - // - // launch-index - When launching multiple instances, this is the index for - // the instance in the launch group (for example, 0, 1, 2, and so on). - // - // launch-time - The time when the instance was launched. - // - // monitoring-state - Indicates whether monitoring is enabled for the instance - // (disabled | enabled). - // - // owner-id - The AWS account ID of the instance owner. - // - // placement-group-name - The name of the placement group for the instance. - // - // platform - The platform. Use windows if you have Windows instances; otherwise, - // leave blank. - // - // private-dns-name - The private DNS name of the instance. - // - // private-ip-address - The private IP address of the instance. - // - // product-code - The product code associated with the AMI used to launch - // the instance. - // - // product-code.type - The type of product code (devpay | marketplace). - // - // ramdisk-id - The RAM disk ID. - // - // reason - The reason for the current state of the instance (for example, - // shows "User Initiated [date]" when you stop or terminate the instance). Similar - // to the state-reason-code filter. - // - // requester-id - The ID of the entity that launched the instance on your - // behalf (for example, AWS Management Console, Auto Scaling, and so on). - // - // reservation-id - The ID of the instance's reservation. A reservation ID - // is created any time you launch an instance. A reservation ID has a one-to-one - // relationship with an instance launch request, but can be associated with - // more than one instance if you launch multiple instances using the same launch - // request. For example, if you launch one instance, you'll get one reservation - // ID. If you launch ten instances using the same launch request, you'll also - // get one reservation ID. - // - // root-device-name - The name of the root device for the instance (for example, - // /dev/sda1 or /dev/xvda). - // - // root-device-type - The type of root device that the instance uses (ebs - // | instance-store). - // - // source-dest-check - Indicates whether the instance performs source/destination - // checking. A value of true means that checking is enabled, and false means - // checking is disabled. The value must be false for the instance to perform - // network address translation (NAT) in your VPC. - // - // spot-instance-request-id - The ID of the Spot Instance request. - // - // state-reason-code - The reason code for the state change. - // - // state-reason-message - A message that describes the state change. - // - // subnet-id - The ID of the subnet for the instance. - // - // tag:key=value - The key/value combination of a tag assigned to the resource, - // where tag:key is the tag's key. - // - // tag-key - The key of a tag assigned to the resource. This filter is independent - // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" - // and the filter "tag-value=X", you get any resources assigned both the tag - // key Purpose (regardless of what the tag's value is), and the tag value X - // (regardless of what the tag's key is). If you want to list only resources - // where Purpose is X, see the tag:key=value filter. - // - // tag-value - The value of a tag assigned to the resource. This filter is - // independent of the tag-key filter. - // - // tenancy - The tenancy of an instance (dedicated | default). - // - // virtualization-type - The virtualization type of the instance (paravirtual - // | hvm). - // - // vpc-id - The ID of the VPC that the instance is running in. - // - // network-interface.description - The description of the network interface. - // - // network-interface.subnet-id - The ID of the subnet for the network interface. - // - // network-interface.vpc-id - The ID of the VPC for the network interface. - // - // network-interface.network-interface-id - The ID of the network interface. - // - // network-interface.owner-id - The ID of the owner of the network interface. - // - // network-interface.availability-zone - The Availability Zone for the network - // interface. - // - // network-interface.requester-id - The requester ID for the network interface. - // - // network-interface.requester-managed - Indicates whether the network interface - // is being managed by AWS. - // - // network-interface.status - The status of the network interface (available) - // | in-use). - // - // network-interface.mac-address - The MAC address of the network interface. - // - // network-interface-private-dns-name - The private DNS name of the network - // interface. - // - // network-interface.source-dest-check - Whether the network interface performs - // source/destination checking. A value of true means checking is enabled, and - // false means checking is disabled. The value must be false for the network - // interface to perform network address translation (NAT) in your VPC. - // - // network-interface.group-id - The ID of a security group associated with - // the network interface. - // - // network-interface.group-name - The name of a security group associated - // with the network interface. - // - // network-interface.attachment.attachment-id - The ID of the interface attachment. - // - // network-interface.attachment.instance-id - The ID of the instance to which - // the network interface is attached. - // - // network-interface.attachment.instance-owner-id - The owner ID of the instance - // to which the network interface is attached. - // - // network-interface.addresses.private-ip-address - The private IP address - // associated with the network interface. - // - // network-interface.attachment.device-index - The device index to which - // the network interface is attached. - // - // network-interface.attachment.status - The status of the attachment (attaching - // | attached | detaching | detached). - // - // network-interface.attachment.attach-time - The time that the network interface - // was attached to an instance. - // - // network-interface.attachment.delete-on-termination - Specifies whether - // the attachment is deleted when an instance is terminated. - // - // network-interface.addresses.primary - Specifies whether the IP address - // of the network interface is the primary private IP address. - // - // network-interface.addresses.association.public-ip - The ID of the association - // of an Elastic IP address with a network interface. - // - // network-interface.addresses.association.ip-owner-id - The owner ID of - // the private IP address associated with the network interface. - // - // association.public-ip - The address of the Elastic IP address bound to - // the network interface. - // - // association.ip-owner-id - The owner of the Elastic IP address associated - // with the network interface. - // - // association.allocation-id - The allocation ID returned when you allocated - // the Elastic IP address for your network interface. - // - // association.association-id - The association ID returned when the network - // interface was associated with an IP address. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // One or more instance IDs. - // - // Default: Describes all your instances. - InstanceIds []*string `locationName:"InstanceId" locationNameList:"InstanceId" type:"list"` - - // The maximum number of results to return for the request in a single page. - // The remaining results of the initial request can be seen by sending another - // request with the returned NextToken value. This value can be between 5 and - // 1000; if MaxResults is given a value larger than 1000, only 1000 results - // are returned. You cannot specify this parameter and the instance IDs parameter - // in the same request. - MaxResults *int64 `locationName:"maxResults" type:"integer"` - - // The token to request the next page of results. - NextToken *string `locationName:"nextToken" type:"string"` - - metadataDescribeInstancesInput `json:"-" xml:"-"` -} - -type metadataDescribeInstancesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeInstancesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeInstancesInput) GoString() string { - return s.String() -} - -type DescribeInstancesOutput struct { - // The token to use to retrieve the next page of results. This value is null - // when there are no more results to return. - NextToken *string `locationName:"nextToken" type:"string"` - - // One or more reservations. - Reservations []*Reservation `locationName:"reservationSet" locationNameList:"item" type:"list"` - - metadataDescribeInstancesOutput `json:"-" xml:"-"` -} - -type metadataDescribeInstancesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeInstancesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeInstancesOutput) GoString() string { - return s.String() -} - -type DescribeInternetGatewaysInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // attachment.state - The current state of the attachment between the gateway - // and the VPC (available). Present only if a VPC is attached. - // - // attachment.vpc-id - The ID of an attached VPC. - // - // internet-gateway-id - The ID of the Internet gateway. - // - // tag:key=value - The key/value combination of a tag assigned to the resource. - // - // tag-key - The key of a tag assigned to the resource. This filter is independent - // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" - // and the filter "tag-value=X", you get any resources assigned both the tag - // key Purpose (regardless of what the tag's value is), and the tag value X - // (regardless of what the tag's key is). If you want to list only resources - // where Purpose is X, see the tag:key=value filter. - // - // tag-value - The value of a tag assigned to the resource. This filter is - // independent of the tag-key filter. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // One or more Internet gateway IDs. - // - // Default: Describes all your Internet gateways. - InternetGatewayIds []*string `locationName:"internetGatewayId" locationNameList:"item" type:"list"` - - metadataDescribeInternetGatewaysInput `json:"-" xml:"-"` -} - -type metadataDescribeInternetGatewaysInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeInternetGatewaysInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeInternetGatewaysInput) GoString() string { - return s.String() -} - -type DescribeInternetGatewaysOutput struct { - // Information about one or more Internet gateways. - InternetGateways []*InternetGateway `locationName:"internetGatewaySet" locationNameList:"item" type:"list"` - - metadataDescribeInternetGatewaysOutput `json:"-" xml:"-"` -} - -type metadataDescribeInternetGatewaysOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeInternetGatewaysOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeInternetGatewaysOutput) GoString() string { - return s.String() -} - -type DescribeKeyPairsInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // fingerprint - The fingerprint of the key pair. - // - // key-name - The name of the key pair. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // One or more key pair names. - // - // Default: Describes all your key pairs. - KeyNames []*string `locationName:"KeyName" locationNameList:"KeyName" type:"list"` - - metadataDescribeKeyPairsInput `json:"-" xml:"-"` -} - -type metadataDescribeKeyPairsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeKeyPairsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeKeyPairsInput) GoString() string { - return s.String() -} - -type DescribeKeyPairsOutput struct { - // Information about one or more key pairs. - KeyPairs []*KeyPairInfo `locationName:"keySet" locationNameList:"item" type:"list"` - - metadataDescribeKeyPairsOutput `json:"-" xml:"-"` -} - -type metadataDescribeKeyPairsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeKeyPairsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeKeyPairsOutput) GoString() string { - return s.String() -} - -type DescribeMovingAddressesInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // moving-status - The status of the Elastic IP address (MovingToVpc | RestoringToClassic). - Filters []*Filter `locationName:"filter" locationNameList:"Filter" type:"list"` - - // The maximum number of results to return for the request in a single page. - // The remaining results of the initial request can be seen by sending another - // request with the returned NextToken value. This value can be between 5 and - // 1000; if MaxResults is given a value outside of this range, an error is returned. - // - // Default: If no value is provided, the default is 1000. - MaxResults *int64 `locationName:"maxResults" type:"integer"` - - // The token to use to retrieve the next page of results. - NextToken *string `locationName:"nextToken" type:"string"` - - // One or more Elastic IP addresses. - PublicIps []*string `locationName:"publicIp" locationNameList:"item" type:"list"` - - metadataDescribeMovingAddressesInput `json:"-" xml:"-"` -} - -type metadataDescribeMovingAddressesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeMovingAddressesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeMovingAddressesInput) GoString() string { - return s.String() -} - -type DescribeMovingAddressesOutput struct { - // The status for each Elastic IP address. - MovingAddressStatuses []*MovingAddressStatus `locationName:"movingAddressStatusSet" locationNameList:"item" type:"list"` - - // The token to use to retrieve the next page of results. This value is null - // when there are no more results to return. - NextToken *string `locationName:"nextToken" type:"string"` - - metadataDescribeMovingAddressesOutput `json:"-" xml:"-"` -} - -type metadataDescribeMovingAddressesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeMovingAddressesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeMovingAddressesOutput) GoString() string { - return s.String() -} - -type DescribeNetworkAclsInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // association.association-id - The ID of an association ID for the ACL. - // - // association.network-acl-id - The ID of the network ACL involved in the - // association. - // - // association.subnet-id - The ID of the subnet involved in the association. - // - // default - Indicates whether the ACL is the default network ACL for the - // VPC. - // - // entry.cidr - The CIDR range specified in the entry. - // - // entry.egress - Indicates whether the entry applies to egress traffic. - // - // entry.icmp.code - The ICMP code specified in the entry, if any. - // - // entry.icmp.type - The ICMP type specified in the entry, if any. - // - // entry.port-range.from - The start of the port range specified in the entry. - // - // entry.port-range.to - The end of the port range specified in the entry. - // - // entry.protocol - The protocol specified in the entry (tcp | udp | icmp - // or a protocol number). - // - // entry.rule-action - Allows or denies the matching traffic (allow | deny). - // - // entry.rule-number - The number of an entry (in other words, rule) in the - // ACL's set of entries. - // - // network-acl-id - The ID of the network ACL. - // - // tag:key=value - The key/value combination of a tag assigned to the resource. - // - // tag-key - The key of a tag assigned to the resource. This filter is independent - // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" - // and the filter "tag-value=X", you get any resources assigned both the tag - // key Purpose (regardless of what the tag's value is), and the tag value X - // (regardless of what the tag's key is). If you want to list only resources - // where Purpose is X, see the tag:key=value filter. - // - // tag-value - The value of a tag assigned to the resource. This filter is - // independent of the tag-key filter. - // - // vpc-id - The ID of the VPC for the network ACL. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // One or more network ACL IDs. - // - // Default: Describes all your network ACLs. - NetworkAclIds []*string `locationName:"NetworkAclId" locationNameList:"item" type:"list"` - - metadataDescribeNetworkAclsInput `json:"-" xml:"-"` -} - -type metadataDescribeNetworkAclsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeNetworkAclsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeNetworkAclsInput) GoString() string { - return s.String() -} - -type DescribeNetworkAclsOutput struct { - // Information about one or more network ACLs. - NetworkAcls []*NetworkAcl `locationName:"networkAclSet" locationNameList:"item" type:"list"` - - metadataDescribeNetworkAclsOutput `json:"-" xml:"-"` -} - -type metadataDescribeNetworkAclsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeNetworkAclsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeNetworkAclsOutput) GoString() string { - return s.String() -} - -type DescribeNetworkInterfaceAttributeInput struct { - // The attribute of the network interface. - Attribute *string `locationName:"attribute" type:"string" enum:"NetworkInterfaceAttribute"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the network interface. - NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string" required:"true"` - - metadataDescribeNetworkInterfaceAttributeInput `json:"-" xml:"-"` -} - -type metadataDescribeNetworkInterfaceAttributeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeNetworkInterfaceAttributeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeNetworkInterfaceAttributeInput) GoString() string { - return s.String() -} - -type DescribeNetworkInterfaceAttributeOutput struct { - // The attachment (if any) of the network interface. - Attachment *NetworkInterfaceAttachment `locationName:"attachment" type:"structure"` - - // The description of the network interface. - Description *AttributeValue `locationName:"description" type:"structure"` - - // The security groups associated with the network interface. - Groups []*GroupIdentifier `locationName:"groupSet" locationNameList:"item" type:"list"` - - // The ID of the network interface. - NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string"` - - // Indicates whether source/destination checking is enabled. - SourceDestCheck *AttributeBooleanValue `locationName:"sourceDestCheck" type:"structure"` - - metadataDescribeNetworkInterfaceAttributeOutput `json:"-" xml:"-"` -} - -type metadataDescribeNetworkInterfaceAttributeOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeNetworkInterfaceAttributeOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeNetworkInterfaceAttributeOutput) GoString() string { - return s.String() -} - -type DescribeNetworkInterfacesInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // addresses.private-ip-address - The private IP addresses associated with - // the network interface. - // - // addresses.primary - Whether the private IP address is the primary IP address - // associated with the network interface. - // - // addresses.association.public-ip - The association ID returned when the - // network interface was associated with the Elastic IP address. - // - // addresses.association.owner-id - The owner ID of the addresses associated - // with the network interface. - // - // association.association-id - The association ID returned when the network - // interface was associated with an IP address. - // - // association.allocation-id - The allocation ID returned when you allocated - // the Elastic IP address for your network interface. - // - // association.ip-owner-id - The owner of the Elastic IP address associated - // with the network interface. - // - // association.public-ip - The address of the Elastic IP address bound to - // the network interface. - // - // association.public-dns-name - The public DNS name for the network interface. - // - // attachment.attachment-id - The ID of the interface attachment. - // - // attachment.instance-id - The ID of the instance to which the network interface - // is attached. - // - // attachment.instance-owner-id - The owner ID of the instance to which the - // network interface is attached. - // - // attachment.device-index - The device index to which the network interface - // is attached. - // - // attachment.status - The status of the attachment (attaching | attached - // | detaching | detached). - // - // attachment.attach.time - The time that the network interface was attached - // to an instance. - // - // attachment.delete-on-termination - Indicates whether the attachment is - // deleted when an instance is terminated. - // - // availability-zone - The Availability Zone of the network interface. - // - // description - The description of the network interface. - // - // group-id - The ID of a security group associated with the network interface. - // - // group-name - The name of a security group associated with the network - // interface. - // - // mac-address - The MAC address of the network interface. - // - // network-interface-id - The ID of the network interface. - // - // owner-id - The AWS account ID of the network interface owner. - // - // private-ip-address - The private IP address or addresses of the network - // interface. - // - // private-dns-name - The private DNS name of the network interface. - // - // requester-id - The ID of the entity that launched the instance on your - // behalf (for example, AWS Management Console, Auto Scaling, and so on). - // - // requester-managed - Indicates whether the network interface is being managed - // by an AWS service (for example, AWS Management Console, Auto Scaling, and - // so on). - // - // source-desk-check - Indicates whether the network interface performs source/destination - // checking. A value of true means checking is enabled, and false means checking - // is disabled. The value must be false for the network interface to perform - // Network Address Translation (NAT) in your VPC. - // - // status - The status of the network interface. If the network interface - // is not attached to an instance, the status is available; if a network interface - // is attached to an instance the status is in-use. - // - // subnet-id - The ID of the subnet for the network interface. - // - // tag:key=value - The key/value combination of a tag assigned to the resource. - // - // tag-key - The key of a tag assigned to the resource. This filter is independent - // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" - // and the filter "tag-value=X", you get any resources assigned both the tag - // key Purpose (regardless of what the tag's value is), and the tag value X - // (regardless of what the tag's key is). If you want to list only resources - // where Purpose is X, see the tag:key=value filter. - // - // tag-value - The value of a tag assigned to the resource. This filter is - // independent of the tag-key filter. - // - // vpc-id - The ID of the VPC for the network interface. - Filters []*Filter `locationName:"filter" locationNameList:"Filter" type:"list"` - - // One or more network interface IDs. - // - // Default: Describes all your network interfaces. - NetworkInterfaceIds []*string `locationName:"NetworkInterfaceId" locationNameList:"item" type:"list"` - - metadataDescribeNetworkInterfacesInput `json:"-" xml:"-"` -} - -type metadataDescribeNetworkInterfacesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeNetworkInterfacesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeNetworkInterfacesInput) GoString() string { - return s.String() -} - -type DescribeNetworkInterfacesOutput struct { - // Information about one or more network interfaces. - NetworkInterfaces []*NetworkInterface `locationName:"networkInterfaceSet" locationNameList:"item" type:"list"` - - metadataDescribeNetworkInterfacesOutput `json:"-" xml:"-"` -} - -type metadataDescribeNetworkInterfacesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeNetworkInterfacesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeNetworkInterfacesOutput) GoString() string { - return s.String() -} - -type DescribePlacementGroupsInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // group-name - The name of the placement group. - // - // state - The state of the placement group (pending | available | deleting - // | deleted). - // - // strategy - The strategy of the placement group (cluster). - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // One or more placement group names. - // - // Default: Describes all your placement groups, or only those otherwise specified. - GroupNames []*string `locationName:"groupName" type:"list"` - - metadataDescribePlacementGroupsInput `json:"-" xml:"-"` -} - -type metadataDescribePlacementGroupsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribePlacementGroupsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribePlacementGroupsInput) GoString() string { - return s.String() -} - -type DescribePlacementGroupsOutput struct { - // One or more placement groups. - PlacementGroups []*PlacementGroup `locationName:"placementGroupSet" locationNameList:"item" type:"list"` - - metadataDescribePlacementGroupsOutput `json:"-" xml:"-"` -} - -type metadataDescribePlacementGroupsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribePlacementGroupsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribePlacementGroupsOutput) GoString() string { - return s.String() -} - -type DescribePrefixListsInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `type:"boolean"` - - // One or more filters. - // - // prefix-list-id: The ID of a prefix list. - // - // prefix-list-name: The name of a prefix list. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // The maximum number of items to return for this request. The request returns - // a token that you can specify in a subsequent call to get the next set of - // results. - // - // Constraint: If the value specified is greater than 1000, we return only - // 1000 items. - MaxResults *int64 `type:"integer"` - - // The token for the next set of items to return. (You received this token from - // a prior call.) - NextToken *string `type:"string"` - - // One or more prefix list IDs. - PrefixListIds []*string `locationName:"PrefixListId" locationNameList:"item" type:"list"` - - metadataDescribePrefixListsInput `json:"-" xml:"-"` -} - -type metadataDescribePrefixListsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribePrefixListsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribePrefixListsInput) GoString() string { - return s.String() -} - -type DescribePrefixListsOutput struct { - // The token to use when requesting the next set of items. If there are no additional - // items to return, the string is empty. - NextToken *string `locationName:"nextToken" type:"string"` - - // All available prefix lists. - PrefixLists []*PrefixList `locationName:"prefixListSet" locationNameList:"item" type:"list"` - - metadataDescribePrefixListsOutput `json:"-" xml:"-"` -} - -type metadataDescribePrefixListsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribePrefixListsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribePrefixListsOutput) GoString() string { - return s.String() -} - -type DescribeRegionsInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // endpoint - The endpoint of the region (for example, ec2.us-east-1.amazonaws.com). - // - // region-name - The name of the region (for example, us-east-1). - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // The names of one or more regions. - RegionNames []*string `locationName:"RegionName" locationNameList:"RegionName" type:"list"` - - metadataDescribeRegionsInput `json:"-" xml:"-"` -} - -type metadataDescribeRegionsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeRegionsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeRegionsInput) GoString() string { - return s.String() -} - -type DescribeRegionsOutput struct { - // Information about one or more regions. - Regions []*Region `locationName:"regionInfo" locationNameList:"item" type:"list"` - - metadataDescribeRegionsOutput `json:"-" xml:"-"` -} - -type metadataDescribeRegionsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeRegionsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeRegionsOutput) GoString() string { - return s.String() -} - -type DescribeReservedInstancesInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // availability-zone - The Availability Zone where the Reserved Instance - // can be used. - // - // duration - The duration of the Reserved Instance (one year or three years), - // in seconds (31536000 | 94608000). - // - // end - The time when the Reserved Instance expires (for example, 2015-08-07T11:54:42.000Z). - // - // fixed-price - The purchase price of the Reserved Instance (for example, - // 9800.0). - // - // instance-type - The instance type on which the Reserved Instance can be - // used. - // - // product-description - The Reserved Instance product platform description. - // Instances that include (Amazon VPC) in the product platform description will - // only be displayed to EC2-Classic account holders and are for use with Amazon - // VPC. (Linux/UNIX | Linux/UNIX (Amazon VPC) | SUSE Linux | SUSE Linux (Amazon - // VPC) | Red Hat Enterprise Linux | Red Hat Enterprise Linux (Amazon VPC) | - // Windows | Windows (Amazon VPC) | Windows with SQL Server Standard | Windows - // with SQL Server Standard (Amazon VPC) | Windows with SQL Server Web | Windows - // with SQL Server Web (Amazon VPC) | Windows with SQL Server Enterprise | Windows - // with SQL Server Enterprise (Amazon VPC)). - // - // reserved-instances-id - The ID of the Reserved Instance. - // - // start - The time at which the Reserved Instance purchase request was placed - // (for example, 2014-08-07T11:54:42.000Z). - // - // state - The state of the Reserved Instance (payment-pending | active | - // payment-failed | retired). - // - // tag:key=value - The key/value combination of a tag assigned to the resource. - // - // tag-key - The key of a tag assigned to the resource. This filter is independent - // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" - // and the filter "tag-value=X", you get any resources assigned both the tag - // key Purpose (regardless of what the tag's value is), and the tag value X - // (regardless of what the tag's key is). If you want to list only resources - // where Purpose is X, see the tag:key=value filter. - // - // tag-value - The value of a tag assigned to the resource. This filter is - // independent of the tag-key filter. - // - // usage-price - The usage price of the Reserved Instance, per hour (for - // example, 0.84). - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // The Reserved Instance offering type. If you are using tools that predate - // the 2011-11-01 API version, you only have access to the Medium Utilization - // Reserved Instance offering type. - OfferingType *string `locationName:"offeringType" type:"string" enum:"OfferingTypeValues"` - - // One or more Reserved Instance IDs. - // - // Default: Describes all your Reserved Instances, or only those otherwise - // specified. - ReservedInstancesIds []*string `locationName:"ReservedInstancesId" locationNameList:"ReservedInstancesId" type:"list"` - - metadataDescribeReservedInstancesInput `json:"-" xml:"-"` -} - -type metadataDescribeReservedInstancesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeReservedInstancesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeReservedInstancesInput) GoString() string { - return s.String() -} - -type DescribeReservedInstancesListingsInput struct { - // One or more filters. - // - // reserved-instances-id - The ID of the Reserved Instances. - // - // reserved-instances-listing-id - The ID of the Reserved Instances listing. - // - // status - The status of the Reserved Instance listing (pending | active - // | cancelled | closed). - // - // status-message - The reason for the status. - Filters []*Filter `locationName:"filters" locationNameList:"Filter" type:"list"` - - // One or more Reserved Instance IDs. - ReservedInstancesId *string `locationName:"reservedInstancesId" type:"string"` - - // One or more Reserved Instance Listing IDs. - ReservedInstancesListingId *string `locationName:"reservedInstancesListingId" type:"string"` - - metadataDescribeReservedInstancesListingsInput `json:"-" xml:"-"` -} - -type metadataDescribeReservedInstancesListingsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeReservedInstancesListingsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeReservedInstancesListingsInput) GoString() string { - return s.String() -} - -type DescribeReservedInstancesListingsOutput struct { - // Information about the Reserved Instance listing. - ReservedInstancesListings []*ReservedInstancesListing `locationName:"reservedInstancesListingsSet" locationNameList:"item" type:"list"` - - metadataDescribeReservedInstancesListingsOutput `json:"-" xml:"-"` -} - -type metadataDescribeReservedInstancesListingsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeReservedInstancesListingsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeReservedInstancesListingsOutput) GoString() string { - return s.String() -} - -type DescribeReservedInstancesModificationsInput struct { - // One or more filters. - // - // client-token - The idempotency token for the modification request. - // - // create-date - The time when the modification request was created. - // - // effective-date - The time when the modification becomes effective. - // - // modification-result.reserved-instances-id - The ID for the Reserved Instances - // created as part of the modification request. This ID is only available when - // the status of the modification is fulfilled. - // - // modification-result.target-configuration.availability-zone - The Availability - // Zone for the new Reserved Instances. - // - // modification-result.target-configuration.instance-count - The number - // of new Reserved Instances. - // - // modification-result.target-configuration.instance-type - The instance - // type of the new Reserved Instances. - // - // modification-result.target-configuration.platform - The network platform - // of the new Reserved Instances (EC2-Classic | EC2-VPC). - // - // reserved-instances-id - The ID of the Reserved Instances modified. - // - // reserved-instances-modification-id - The ID of the modification request. - // - // status - The status of the Reserved Instances modification request (processing - // | fulfilled | failed). - // - // status-message - The reason for the status. - // - // update-date - The time when the modification request was last updated. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // The token to retrieve the next page of results. - NextToken *string `locationName:"nextToken" type:"string"` - - // IDs for the submitted modification request. - ReservedInstancesModificationIds []*string `locationName:"ReservedInstancesModificationId" locationNameList:"ReservedInstancesModificationId" type:"list"` - - metadataDescribeReservedInstancesModificationsInput `json:"-" xml:"-"` -} - -type metadataDescribeReservedInstancesModificationsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeReservedInstancesModificationsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeReservedInstancesModificationsInput) GoString() string { - return s.String() -} - -type DescribeReservedInstancesModificationsOutput struct { - // The token to use to retrieve the next page of results. This value is null - // when there are no more results to return. - NextToken *string `locationName:"nextToken" type:"string"` - - // The Reserved Instance modification information. - ReservedInstancesModifications []*ReservedInstancesModification `locationName:"reservedInstancesModificationsSet" locationNameList:"item" type:"list"` - - metadataDescribeReservedInstancesModificationsOutput `json:"-" xml:"-"` -} - -type metadataDescribeReservedInstancesModificationsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeReservedInstancesModificationsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeReservedInstancesModificationsOutput) GoString() string { - return s.String() -} - -type DescribeReservedInstancesOfferingsInput struct { - // The Availability Zone in which the Reserved Instance can be used. - AvailabilityZone *string `type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // availability-zone - The Availability Zone where the Reserved Instance - // can be used. - // - // duration - The duration of the Reserved Instance (for example, one year - // or three years), in seconds (31536000 | 94608000). - // - // fixed-price - The purchase price of the Reserved Instance (for example, - // 9800.0). - // - // instance-type - The instance type on which the Reserved Instance can be - // used. - // - // marketplace - Set to true to show only Reserved Instance Marketplace offerings. - // When this filter is not used, which is the default behavior, all offerings - // from AWS and Reserved Instance Marketplace are listed. - // - // product-description - The Reserved Instance product platform description. - // Instances that include (Amazon VPC) in the product platform description will - // only be displayed to EC2-Classic account holders and are for use with Amazon - // VPC. (Linux/UNIX | Linux/UNIX (Amazon VPC) | SUSE Linux | SUSE Linux (Amazon - // VPC) | Red Hat Enterprise Linux | Red Hat Enterprise Linux (Amazon VPC) | - // Windows | Windows (Amazon VPC) | Windows with SQL Server Standard | Windows - // with SQL Server Standard (Amazon VPC) | Windows with SQL Server Web | Windows - // with SQL Server Web (Amazon VPC) | Windows with SQL Server Enterprise | Windows - // with SQL Server Enterprise (Amazon VPC)) - // - // reserved-instances-offering-id - The Reserved Instances offering ID. - // - // usage-price - The usage price of the Reserved Instance, per hour (for - // example, 0.84). - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // Include Marketplace offerings in the response. - IncludeMarketplace *bool `type:"boolean"` - - // The tenancy of the Reserved Instance offering. A Reserved Instance with dedicated - // tenancy runs on single-tenant hardware and can only be launched within a - // VPC. - // - // Default: default - InstanceTenancy *string `locationName:"instanceTenancy" type:"string" enum:"Tenancy"` - - // The instance type on which the Reserved Instance can be used. For more information, - // see Instance Types (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html) - // in the Amazon Elastic Compute Cloud User Guide. - InstanceType *string `type:"string" enum:"InstanceType"` - - // The maximum duration (in seconds) to filter when searching for offerings. - // - // Default: 94608000 (3 years) - MaxDuration *int64 `type:"long"` - - // The maximum number of instances to filter when searching for offerings. - // - // Default: 20 - MaxInstanceCount *int64 `type:"integer"` - - // The maximum number of results to return for the request in a single page. - // The remaining results of the initial request can be seen by sending another - // request with the returned NextToken value. The maximum is 100. - // - // Default: 100 - MaxResults *int64 `locationName:"maxResults" type:"integer"` - - // The minimum duration (in seconds) to filter when searching for offerings. - // - // Default: 2592000 (1 month) - MinDuration *int64 `type:"long"` - - // The token to retrieve the next page of results. - NextToken *string `locationName:"nextToken" type:"string"` - - // The Reserved Instance offering type. If you are using tools that predate - // the 2011-11-01 API version, you only have access to the Medium Utilization - // Reserved Instance offering type. - OfferingType *string `locationName:"offeringType" type:"string" enum:"OfferingTypeValues"` - - // The Reserved Instance product platform description. Instances that include - // (Amazon VPC) in the description are for use with Amazon VPC. - ProductDescription *string `type:"string" enum:"RIProductDescription"` - - // One or more Reserved Instances offering IDs. - ReservedInstancesOfferingIds []*string `locationName:"ReservedInstancesOfferingId" type:"list"` - - metadataDescribeReservedInstancesOfferingsInput `json:"-" xml:"-"` -} - -type metadataDescribeReservedInstancesOfferingsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeReservedInstancesOfferingsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeReservedInstancesOfferingsInput) GoString() string { - return s.String() -} - -type DescribeReservedInstancesOfferingsOutput struct { - // The token to use to retrieve the next page of results. This value is null - // when there are no more results to return. - NextToken *string `locationName:"nextToken" type:"string"` - - // A list of Reserved Instances offerings. - ReservedInstancesOfferings []*ReservedInstancesOffering `locationName:"reservedInstancesOfferingsSet" locationNameList:"item" type:"list"` - - metadataDescribeReservedInstancesOfferingsOutput `json:"-" xml:"-"` -} - -type metadataDescribeReservedInstancesOfferingsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeReservedInstancesOfferingsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeReservedInstancesOfferingsOutput) GoString() string { - return s.String() -} - -type DescribeReservedInstancesOutput struct { - // A list of Reserved Instances. - ReservedInstances []*ReservedInstances `locationName:"reservedInstancesSet" locationNameList:"item" type:"list"` - - metadataDescribeReservedInstancesOutput `json:"-" xml:"-"` -} - -type metadataDescribeReservedInstancesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeReservedInstancesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeReservedInstancesOutput) GoString() string { - return s.String() -} - -type DescribeRouteTablesInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // association.route-table-association-id - The ID of an association ID for - // the route table. - // - // association.route-table-id - The ID of the route table involved in the - // association. - // - // association.subnet-id - The ID of the subnet involved in the association. - // - // association.main - Indicates whether the route table is the main route - // table for the VPC. - // - // route-table-id - The ID of the route table. - // - // route.destination-cidr-block - The CIDR range specified in a route in - // the table. - // - // route.destination-prefix-list-id - The ID (prefix) of the AWS service - // specified in a route in the table. - // - // route.gateway-id - The ID of a gateway specified in a route in the table. - // - // route.instance-id - The ID of an instance specified in a route in the - // table. - // - // route.origin - Describes how the route was created. CreateRouteTable indicates - // that the route was automatically created when the route table was created; - // CreateRoute indicates that the route was manually added to the route table; - // EnableVgwRoutePropagation indicates that the route was propagated by route - // propagation. - // - // route.state - The state of a route in the route table (active | blackhole). - // The blackhole state indicates that the route's target isn't available (for - // example, the specified gateway isn't attached to the VPC, the specified NAT - // instance has been terminated, and so on). - // - // route.vpc-peering-connection-id - The ID of a VPC peering connection specified - // in a route in the table. - // - // tag:key=value - The key/value combination of a tag assigned to the resource. - // - // tag-key - The key of a tag assigned to the resource. This filter is independent - // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" - // and the filter "tag-value=X", you get any resources assigned both the tag - // key Purpose (regardless of what the tag's value is), and the tag value X - // (regardless of what the tag's key is). If you want to list only resources - // where Purpose is X, see the tag:key=value filter. - // - // tag-value - The value of a tag assigned to the resource. This filter is - // independent of the tag-key filter. - // - // vpc-id - The ID of the VPC for the route table. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // One or more route table IDs. - // - // Default: Describes all your route tables. - RouteTableIds []*string `locationName:"RouteTableId" locationNameList:"item" type:"list"` - - metadataDescribeRouteTablesInput `json:"-" xml:"-"` -} - -type metadataDescribeRouteTablesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeRouteTablesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeRouteTablesInput) GoString() string { - return s.String() -} - -type DescribeRouteTablesOutput struct { - // Information about one or more route tables. - RouteTables []*RouteTable `locationName:"routeTableSet" locationNameList:"item" type:"list"` - - metadataDescribeRouteTablesOutput `json:"-" xml:"-"` -} - -type metadataDescribeRouteTablesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeRouteTablesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeRouteTablesOutput) GoString() string { - return s.String() -} - -type DescribeSecurityGroupsInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. If using multiple filters for rules, the results include - // security groups for which any combination of rules - not necessarily a single - // rule - match all filters. - // - // description - The description of the security group. - // - // egress.ip-permission.prefix-list-id - The ID (prefix) of the AWS service - // to which the security group allows access. - // - // group-id - The ID of the security group. - // - // group-name - The name of the security group. - // - // ip-permission.cidr - A CIDR range that has been granted permission. - // - // ip-permission.from-port - The start of port range for the TCP and UDP - // protocols, or an ICMP type number. - // - // ip-permission.group-id - The ID of a security group that has been granted - // permission. - // - // ip-permission.group-name - The name of a security group that has been - // granted permission. - // - // ip-permission.protocol - The IP protocol for the permission (tcp | udp - // | icmp or a protocol number). - // - // ip-permission.to-port - The end of port range for the TCP and UDP protocols, - // or an ICMP code. - // - // ip-permission.user-id - The ID of an AWS account that has been granted - // permission. - // - // owner-id - The AWS account ID of the owner of the security group. - // - // tag-key - The key of a tag assigned to the security group. - // - // tag-value - The value of a tag assigned to the security group. - // - // vpc-id - The ID of the VPC specified when the security group was created. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // One or more security group IDs. Required for security groups in a nondefault - // VPC. - // - // Default: Describes all your security groups. - GroupIds []*string `locationName:"GroupId" locationNameList:"groupId" type:"list"` - - // [EC2-Classic and default VPC only] One or more security group names. You - // can specify either the security group name or the security group ID. For - // security groups in a nondefault VPC, use the group-name filter to describe - // security groups by name. - // - // Default: Describes all your security groups. - GroupNames []*string `locationName:"GroupName" locationNameList:"GroupName" type:"list"` - - metadataDescribeSecurityGroupsInput `json:"-" xml:"-"` -} - -type metadataDescribeSecurityGroupsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeSecurityGroupsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeSecurityGroupsInput) GoString() string { - return s.String() -} - -type DescribeSecurityGroupsOutput struct { - // Information about one or more security groups. - SecurityGroups []*SecurityGroup `locationName:"securityGroupInfo" locationNameList:"item" type:"list"` - - metadataDescribeSecurityGroupsOutput `json:"-" xml:"-"` -} - -type metadataDescribeSecurityGroupsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeSecurityGroupsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeSecurityGroupsOutput) GoString() string { - return s.String() -} - -type DescribeSnapshotAttributeInput struct { - // The snapshot attribute you would like to view. - Attribute *string `type:"string" required:"true" enum:"SnapshotAttributeName"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the EBS snapshot. - SnapshotId *string `type:"string" required:"true"` - - metadataDescribeSnapshotAttributeInput `json:"-" xml:"-"` -} - -type metadataDescribeSnapshotAttributeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeSnapshotAttributeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeSnapshotAttributeInput) GoString() string { - return s.String() -} - -type DescribeSnapshotAttributeOutput struct { - // A list of permissions for creating volumes from the snapshot. - CreateVolumePermissions []*CreateVolumePermission `locationName:"createVolumePermission" locationNameList:"item" type:"list"` - - // A list of product codes. - ProductCodes []*ProductCode `locationName:"productCodes" locationNameList:"item" type:"list"` - - // The ID of the EBS snapshot. - SnapshotId *string `locationName:"snapshotId" type:"string"` - - metadataDescribeSnapshotAttributeOutput `json:"-" xml:"-"` -} - -type metadataDescribeSnapshotAttributeOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeSnapshotAttributeOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeSnapshotAttributeOutput) GoString() string { - return s.String() -} - -type DescribeSnapshotsInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // description - A description of the snapshot. - // - // owner-alias - The AWS account alias (for example, amazon) that owns the - // snapshot. - // - // owner-id - The ID of the AWS account that owns the snapshot. - // - // progress - The progress of the snapshot, as a percentage (for example, - // 80%). - // - // snapshot-id - The snapshot ID. - // - // start-time - The time stamp when the snapshot was initiated. - // - // status - The status of the snapshot (pending | completed | error). - // - // tag:key=value - The key/value combination of a tag assigned to the resource. - // - // tag-key - The key of a tag assigned to the resource. This filter is independent - // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" - // and the filter "tag-value=X", you get any resources assigned both the tag - // key Purpose (regardless of what the tag's value is), and the tag value X - // (regardless of what the tag's key is). If you want to list only resources - // where Purpose is X, see the tag:key=value filter. - // - // tag-value - The value of a tag assigned to the resource. This filter is - // independent of the tag-key filter. - // - // volume-id - The ID of the volume the snapshot is for. - // - // volume-size - The size of the volume, in GiB. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // The maximum number of snapshot results returned by DescribeSnapshots in paginated - // output. When this parameter is used, DescribeSnapshots only returns MaxResults - // results in a single page along with a NextToken response element. The remaining - // results of the initial request can be seen by sending another DescribeSnapshots - // request with the returned NextToken value. This value can be between 5 and - // 1000; if MaxResults is given a value larger than 1000, only 1000 results - // are returned. If this parameter is not used, then DescribeSnapshots returns - // all results. You cannot specify this parameter and the snapshot IDs parameter - // in the same request. - MaxResults *int64 `type:"integer"` - - // The NextToken value returned from a previous paginated DescribeSnapshots - // request where MaxResults was used and the results exceeded the value of that - // parameter. Pagination continues from the end of the previous results that - // returned the NextToken value. This value is null when there are no more results - // to return. - NextToken *string `type:"string"` - - // Returns the snapshots owned by the specified owner. Multiple owners can be - // specified. - OwnerIds []*string `locationName:"Owner" locationNameList:"Owner" type:"list"` - - // One or more AWS accounts IDs that can create volumes from the snapshot. - RestorableByUserIds []*string `locationName:"RestorableBy" type:"list"` - - // One or more snapshot IDs. - // - // Default: Describes snapshots for which you have launch permissions. - SnapshotIds []*string `locationName:"SnapshotId" locationNameList:"SnapshotId" type:"list"` - - metadataDescribeSnapshotsInput `json:"-" xml:"-"` -} - -type metadataDescribeSnapshotsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeSnapshotsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeSnapshotsInput) GoString() string { - return s.String() -} - -type DescribeSnapshotsOutput struct { - // The NextToken value to include in a future DescribeSnapshots request. When - // the results of a DescribeSnapshots request exceed MaxResults, this value - // can be used to retrieve the next page of results. This value is null when - // there are no more results to return. - NextToken *string `locationName:"nextToken" type:"string"` - - // Information about the snapshots. - Snapshots []*Snapshot `locationName:"snapshotSet" locationNameList:"item" type:"list"` - - metadataDescribeSnapshotsOutput `json:"-" xml:"-"` -} - -type metadataDescribeSnapshotsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeSnapshotsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeSnapshotsOutput) GoString() string { - return s.String() -} - -// Contains the parameters for DescribeSpotDatafeedSubscription. -type DescribeSpotDatafeedSubscriptionInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - metadataDescribeSpotDatafeedSubscriptionInput `json:"-" xml:"-"` -} - -type metadataDescribeSpotDatafeedSubscriptionInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeSpotDatafeedSubscriptionInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeSpotDatafeedSubscriptionInput) GoString() string { - return s.String() -} - -// Contains the output of DescribeSpotDatafeedSubscription. -type DescribeSpotDatafeedSubscriptionOutput struct { - // The Spot instance data feed subscription. - SpotDatafeedSubscription *SpotDatafeedSubscription `locationName:"spotDatafeedSubscription" type:"structure"` - - metadataDescribeSpotDatafeedSubscriptionOutput `json:"-" xml:"-"` -} - -type metadataDescribeSpotDatafeedSubscriptionOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeSpotDatafeedSubscriptionOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeSpotDatafeedSubscriptionOutput) GoString() string { - return s.String() -} - -// Contains the parameters for DescribeSpotFleetInstances. -type DescribeSpotFleetInstancesInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The maximum number of results to return in a single call. Specify a value - // between 1 and 1000. The default value is 1000. To retrieve the remaining - // results, make another call with the returned NextToken value. - MaxResults *int64 `locationName:"maxResults" type:"integer"` - - // The token for the next set of results. - NextToken *string `locationName:"nextToken" type:"string"` - - // The ID of the Spot fleet request. - SpotFleetRequestId *string `locationName:"spotFleetRequestId" type:"string" required:"true"` - - metadataDescribeSpotFleetInstancesInput `json:"-" xml:"-"` -} - -type metadataDescribeSpotFleetInstancesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeSpotFleetInstancesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeSpotFleetInstancesInput) GoString() string { - return s.String() -} - -// Contains the output of DescribeSpotFleetInstances. -type DescribeSpotFleetInstancesOutput struct { - // The running instances. Note that this list is refreshed periodically and - // might be out of date. - ActiveInstances []*ActiveInstance `locationName:"activeInstanceSet" locationNameList:"item" type:"list" required:"true"` - - // The token required to retrieve the next set of results. This value is null - // when there are no more results to return. - NextToken *string `locationName:"nextToken" type:"string"` - - // The ID of the Spot fleet request. - SpotFleetRequestId *string `locationName:"spotFleetRequestId" type:"string" required:"true"` - - metadataDescribeSpotFleetInstancesOutput `json:"-" xml:"-"` -} - -type metadataDescribeSpotFleetInstancesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeSpotFleetInstancesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeSpotFleetInstancesOutput) GoString() string { - return s.String() -} - -// Contains the parameters for DescribeSpotFleetRequestHistory. -type DescribeSpotFleetRequestHistoryInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The type of events to describe. By default, all events are described. - EventType *string `locationName:"eventType" type:"string" enum:"EventType"` - - // The maximum number of results to return in a single call. Specify a value - // between 1 and 1000. The default value is 1000. To retrieve the remaining - // results, make another call with the returned NextToken value. - MaxResults *int64 `locationName:"maxResults" type:"integer"` - - // The token for the next set of results. - NextToken *string `locationName:"nextToken" type:"string"` - - // The ID of the Spot fleet request. - SpotFleetRequestId *string `locationName:"spotFleetRequestId" type:"string" required:"true"` - - // The starting date and time for the events, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). - StartTime *time.Time `locationName:"startTime" type:"timestamp" timestampFormat:"iso8601" required:"true"` - - metadataDescribeSpotFleetRequestHistoryInput `json:"-" xml:"-"` -} - -type metadataDescribeSpotFleetRequestHistoryInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeSpotFleetRequestHistoryInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeSpotFleetRequestHistoryInput) GoString() string { - return s.String() -} - -// Contains the output of DescribeSpotFleetRequestHistory. -type DescribeSpotFleetRequestHistoryOutput struct { - // Information about the events in the history of the Spot fleet request. - HistoryRecords []*HistoryRecord `locationName:"historyRecordSet" locationNameList:"item" type:"list" required:"true"` - - // The last date and time for the events, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). - // All records up to this time were retrieved. - // - // If nextToken indicates that there are more results, this value is not present. - LastEvaluatedTime *time.Time `locationName:"lastEvaluatedTime" type:"timestamp" timestampFormat:"iso8601" required:"true"` - - // The token required to retrieve the next set of results. This value is null - // when there are no more results to return. - NextToken *string `locationName:"nextToken" type:"string"` - - // The ID of the Spot fleet request. - SpotFleetRequestId *string `locationName:"spotFleetRequestId" type:"string" required:"true"` - - // The starting date and time for the events, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). - StartTime *time.Time `locationName:"startTime" type:"timestamp" timestampFormat:"iso8601" required:"true"` - - metadataDescribeSpotFleetRequestHistoryOutput `json:"-" xml:"-"` -} - -type metadataDescribeSpotFleetRequestHistoryOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeSpotFleetRequestHistoryOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeSpotFleetRequestHistoryOutput) GoString() string { - return s.String() -} - -// Contains the parameters for DescribeSpotFleetRequests. -type DescribeSpotFleetRequestsInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The maximum number of results to return in a single call. Specify a value - // between 1 and 1000. The default value is 1000. To retrieve the remaining - // results, make another call with the returned NextToken value. - MaxResults *int64 `locationName:"maxResults" type:"integer"` - - // The token for the next set of results. - NextToken *string `locationName:"nextToken" type:"string"` - - // The IDs of the Spot fleet requests. - SpotFleetRequestIds []*string `locationName:"spotFleetRequestId" locationNameList:"item" type:"list"` - - metadataDescribeSpotFleetRequestsInput `json:"-" xml:"-"` -} - -type metadataDescribeSpotFleetRequestsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeSpotFleetRequestsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeSpotFleetRequestsInput) GoString() string { - return s.String() -} - -// Contains the output of DescribeSpotFleetRequests. -type DescribeSpotFleetRequestsOutput struct { - // The token required to retrieve the next set of results. This value is null - // when there are no more results to return. - NextToken *string `locationName:"nextToken" type:"string"` - - // Information about the configuration of your Spot fleet. - SpotFleetRequestConfigs []*SpotFleetRequestConfig `locationName:"spotFleetRequestConfigSet" locationNameList:"item" type:"list" required:"true"` - - metadataDescribeSpotFleetRequestsOutput `json:"-" xml:"-"` -} - -type metadataDescribeSpotFleetRequestsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeSpotFleetRequestsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeSpotFleetRequestsOutput) GoString() string { - return s.String() -} - -// Contains the parameters for DescribeSpotInstanceRequests. -type DescribeSpotInstanceRequestsInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // availability-zone-group - The Availability Zone group. - // - // create-time - The time stamp when the Spot instance request was created. - // - // fault-code - The fault code related to the request. - // - // fault-message - The fault message related to the request. - // - // instance-id - The ID of the instance that fulfilled the request. - // - // launch-group - The Spot instance launch group. - // - // launch.block-device-mapping.delete-on-termination - Indicates whether - // the Amazon EBS volume is deleted on instance termination. - // - // launch.block-device-mapping.device-name - The device name for the Amazon - // EBS volume (for example, /dev/sdh). - // - // launch.block-device-mapping.snapshot-id - The ID of the snapshot used - // for the Amazon EBS volume. - // - // launch.block-device-mapping.volume-size - The size of the Amazon EBS volume, - // in GiB. - // - // launch.block-device-mapping.volume-type - The type of the Amazon EBS volume - // (gp2 | standard | io1). - // - // launch.group-id - The security group for the instance. - // - // launch.image-id - The ID of the AMI. - // - // launch.instance-type - The type of instance (for example, m3.medium). - // - // launch.kernel-id - The kernel ID. - // - // launch.key-name - The name of the key pair the instance launched with. - // - // launch.monitoring-enabled - Whether monitoring is enabled for the Spot - // instance. - // - // launch.ramdisk-id - The RAM disk ID. - // - // network-interface.network-interface-id - The ID of the network interface. - // - // network-interface.device-index - The index of the device for the network - // interface attachment on the instance. - // - // network-interface.subnet-id - The ID of the subnet for the instance. - // - // network-interface.description - A description of the network interface. - // - // network-interface.private-ip-address - The primary private IP address - // of the network interface. - // - // network-interface.delete-on-termination - Indicates whether the network - // interface is deleted when the instance is terminated. - // - // network-interface.group-id - The ID of the security group associated with - // the network interface. - // - // network-interface.group-name - The name of the security group associated - // with the network interface. - // - // network-interface.addresses.primary - Indicates whether the IP address - // is the primary private IP address. - // - // product-description - The product description associated with the instance - // (Linux/UNIX | Windows). - // - // spot-instance-request-id - The Spot instance request ID. - // - // spot-price - The maximum hourly price for any Spot instance launched to - // fulfill the request. - // - // state - The state of the Spot instance request (open | active | closed - // | cancelled | failed). Spot bid status information can help you track your - // Amazon EC2 Spot instance requests. For more information, see Spot Bid Status - // (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-bid-status.html) - // in the Amazon Elastic Compute Cloud User Guide. - // - // status-code - The short code describing the most recent evaluation of - // your Spot instance request. - // - // status-message - The message explaining the status of the Spot instance - // request. - // - // tag:key=value - The key/value combination of a tag assigned to the resource. - // - // tag-key - The key of a tag assigned to the resource. This filter is independent - // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" - // and the filter "tag-value=X", you get any resources assigned both the tag - // key Purpose (regardless of what the tag's value is), and the tag value X - // (regardless of what the tag's key is). If you want to list only resources - // where Purpose is X, see the tag:key=value filter. - // - // tag-value - The value of a tag assigned to the resource. This filter is - // independent of the tag-key filter. - // - // type - The type of Spot instance request (one-time | persistent). - // - // launched-availability-zone - The Availability Zone in which the bid is - // launched. - // - // valid-from - The start date of the request. - // - // valid-until - The end date of the request. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // One or more Spot instance request IDs. - SpotInstanceRequestIds []*string `locationName:"SpotInstanceRequestId" locationNameList:"SpotInstanceRequestId" type:"list"` - - metadataDescribeSpotInstanceRequestsInput `json:"-" xml:"-"` -} - -type metadataDescribeSpotInstanceRequestsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeSpotInstanceRequestsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeSpotInstanceRequestsInput) GoString() string { - return s.String() -} - -// Contains the output of DescribeSpotInstanceRequests. -type DescribeSpotInstanceRequestsOutput struct { - // One or more Spot instance requests. - SpotInstanceRequests []*SpotInstanceRequest `locationName:"spotInstanceRequestSet" locationNameList:"item" type:"list"` - - metadataDescribeSpotInstanceRequestsOutput `json:"-" xml:"-"` -} - -type metadataDescribeSpotInstanceRequestsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeSpotInstanceRequestsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeSpotInstanceRequestsOutput) GoString() string { - return s.String() -} - -// Contains the parameters for DescribeSpotPriceHistory. -type DescribeSpotPriceHistoryInput struct { - // Filters the results by the specified Availability Zone. - AvailabilityZone *string `locationName:"availabilityZone" type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The date and time, up to the current date, from which to stop retrieving - // the price history data, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). - EndTime *time.Time `locationName:"endTime" type:"timestamp" timestampFormat:"iso8601"` - - // One or more filters. - // - // availability-zone - The Availability Zone for which prices should be returned. - // - // instance-type - The type of instance (for example, m3.medium). - // - // product-description - The product description for the Spot price (Linux/UNIX - // | SUSE Linux | Windows | Linux/UNIX (Amazon VPC) | SUSE Linux (Amazon VPC) - // | Windows (Amazon VPC)). - // - // spot-price - The Spot price. The value must match exactly (or use wildcards; - // greater than or less than comparison is not supported). - // - // timestamp - The timestamp of the Spot price history, in UTC format (for - // example, YYYY-MM-DDTHH:MM:SSZ). You can use wildcards (* and ?). Greater - // than or less than comparison is not supported. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // Filters the results by the specified instance types. - InstanceTypes []*string `locationName:"InstanceType" type:"list"` - - // The maximum number of results to return in a single call. Specify a value - // between 1 and 1000. The default value is 1000. To retrieve the remaining - // results, make another call with the returned NextToken value. - MaxResults *int64 `locationName:"maxResults" type:"integer"` - - // The token for the next set of results. - NextToken *string `locationName:"nextToken" type:"string"` - - // Filters the results by the specified basic product descriptions. - ProductDescriptions []*string `locationName:"ProductDescription" type:"list"` - - // The date and time, up to the past 90 days, from which to start retrieving - // the price history data, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). - StartTime *time.Time `locationName:"startTime" type:"timestamp" timestampFormat:"iso8601"` - - metadataDescribeSpotPriceHistoryInput `json:"-" xml:"-"` -} - -type metadataDescribeSpotPriceHistoryInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeSpotPriceHistoryInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeSpotPriceHistoryInput) GoString() string { - return s.String() -} - -// Contains the output of DescribeSpotPriceHistory. -type DescribeSpotPriceHistoryOutput struct { - // The token required to retrieve the next set of results. This value is null - // when there are no more results to return. - NextToken *string `locationName:"nextToken" type:"string"` - - // The historical Spot prices. - SpotPriceHistory []*SpotPrice `locationName:"spotPriceHistorySet" locationNameList:"item" type:"list"` - - metadataDescribeSpotPriceHistoryOutput `json:"-" xml:"-"` -} - -type metadataDescribeSpotPriceHistoryOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeSpotPriceHistoryOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeSpotPriceHistoryOutput) GoString() string { - return s.String() -} - -type DescribeSubnetsInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // availabilityZone - The Availability Zone for the subnet. You can also - // use availability-zone as the filter name. - // - // available-ip-address-count - The number of IP addresses in the subnet - // that are available. - // - // cidrBlock - The CIDR block of the subnet. The CIDR block you specify must - // exactly match the subnet's CIDR block for information to be returned for - // the subnet. You can also use cidr or cidr-block as the filter names. - // - // defaultForAz - Indicates whether this is the default subnet for the Availability - // Zone. You can also use default-for-az as the filter name. - // - // state - The state of the subnet (pending | available). - // - // subnet-id - The ID of the subnet. - // - // tag:key=value - The key/value combination of a tag assigned to the resource. - // - // tag-key - The key of a tag assigned to the resource. This filter is independent - // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" - // and the filter "tag-value=X", you get any resources assigned both the tag - // key Purpose (regardless of what the tag's value is), and the tag value X - // (regardless of what the tag's key is). If you want to list only resources - // where Purpose is X, see the tag:key=value filter. - // - // tag-value - The value of a tag assigned to the resource. This filter is - // independent of the tag-key filter. - // - // vpc-id - The ID of the VPC for the subnet. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // One or more subnet IDs. - // - // Default: Describes all your subnets. - SubnetIds []*string `locationName:"SubnetId" locationNameList:"SubnetId" type:"list"` - - metadataDescribeSubnetsInput `json:"-" xml:"-"` -} - -type metadataDescribeSubnetsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeSubnetsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeSubnetsInput) GoString() string { - return s.String() -} - -type DescribeSubnetsOutput struct { - // Information about one or more subnets. - Subnets []*Subnet `locationName:"subnetSet" locationNameList:"item" type:"list"` - - metadataDescribeSubnetsOutput `json:"-" xml:"-"` -} - -type metadataDescribeSubnetsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeSubnetsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeSubnetsOutput) GoString() string { - return s.String() -} - -type DescribeTagsInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // key - The tag key. - // - // resource-id - The resource ID. - // - // resource-type - The resource type (customer-gateway | dhcp-options | image - // | instance | internet-gateway | network-acl | network-interface | reserved-instances - // | route-table | security-group | snapshot | spot-instances-request | subnet - // | volume | vpc | vpn-connection | vpn-gateway). - // - // value - The tag value. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // The maximum number of results to return for the request in a single page. - // The remaining results of the initial request can be seen by sending another - // request with the returned NextToken value. This value can be between 5 and - // 1000; if MaxResults is given a value larger than 1000, only 1000 results - // are returned. - MaxResults *int64 `locationName:"maxResults" type:"integer"` - - // The token to retrieve the next page of results. - NextToken *string `locationName:"nextToken" type:"string"` - - metadataDescribeTagsInput `json:"-" xml:"-"` -} - -type metadataDescribeTagsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeTagsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeTagsInput) GoString() string { - return s.String() -} - -type DescribeTagsOutput struct { - // The token to use to retrieve the next page of results. This value is null - // when there are no more results to return.. - NextToken *string `locationName:"nextToken" type:"string"` - - // A list of tags. - Tags []*TagDescription `locationName:"tagSet" locationNameList:"item" type:"list"` - - metadataDescribeTagsOutput `json:"-" xml:"-"` -} - -type metadataDescribeTagsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeTagsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeTagsOutput) GoString() string { - return s.String() -} - -type DescribeVolumeAttributeInput struct { - // The instance attribute. - Attribute *string `type:"string" enum:"VolumeAttributeName"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the volume. - VolumeId *string `type:"string" required:"true"` - - metadataDescribeVolumeAttributeInput `json:"-" xml:"-"` -} - -type metadataDescribeVolumeAttributeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVolumeAttributeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVolumeAttributeInput) GoString() string { - return s.String() -} - -type DescribeVolumeAttributeOutput struct { - // The state of autoEnableIO attribute. - AutoEnableIO *AttributeBooleanValue `locationName:"autoEnableIO" type:"structure"` - - // A list of product codes. - ProductCodes []*ProductCode `locationName:"productCodes" locationNameList:"item" type:"list"` - - // The ID of the volume. - VolumeId *string `locationName:"volumeId" type:"string"` - - metadataDescribeVolumeAttributeOutput `json:"-" xml:"-"` -} - -type metadataDescribeVolumeAttributeOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVolumeAttributeOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVolumeAttributeOutput) GoString() string { - return s.String() -} - -type DescribeVolumeStatusInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // action.code - The action code for the event (for example, enable-volume-io). - // - // action.description - A description of the action. - // - // action.event-id - The event ID associated with the action. - // - // availability-zone - The Availability Zone of the instance. - // - // event.description - A description of the event. - // - // event.event-id - The event ID. - // - // event.event-type - The event type (for io-enabled: passed | failed; for - // io-performance: io-performance:degraded | io-performance:severely-degraded - // | io-performance:stalled). - // - // event.not-after - The latest end time for the event. - // - // event.not-before - The earliest start time for the event. - // - // volume-status.details-name - The cause for volume-status.status (io-enabled - // | io-performance). - // - // volume-status.details-status - The status of volume-status.details-name - // (for io-enabled: passed | failed; for io-performance: normal | degraded | - // severely-degraded | stalled). - // - // volume-status.status - The status of the volume (ok | impaired | warning - // | insufficient-data). - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // The maximum number of volume results returned by DescribeVolumeStatus in - // paginated output. When this parameter is used, the request only returns MaxResults - // results in a single page along with a NextToken response element. The remaining - // results of the initial request can be seen by sending another request with - // the returned NextToken value. This value can be between 5 and 1000; if MaxResults - // is given a value larger than 1000, only 1000 results are returned. If this - // parameter is not used, then DescribeVolumeStatus returns all results. You - // cannot specify this parameter and the volume IDs parameter in the same request. - MaxResults *int64 `type:"integer"` - - // The NextToken value to include in a future DescribeVolumeStatus request. - // When the results of the request exceed MaxResults, this value can be used - // to retrieve the next page of results. This value is null when there are no - // more results to return. - NextToken *string `type:"string"` - - // One or more volume IDs. - // - // Default: Describes all your volumes. - VolumeIds []*string `locationName:"VolumeId" locationNameList:"VolumeId" type:"list"` - - metadataDescribeVolumeStatusInput `json:"-" xml:"-"` -} - -type metadataDescribeVolumeStatusInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVolumeStatusInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVolumeStatusInput) GoString() string { - return s.String() -} - -type DescribeVolumeStatusOutput struct { - // The token to use to retrieve the next page of results. This value is null - // when there are no more results to return. - NextToken *string `locationName:"nextToken" type:"string"` - - // A list of volumes. - VolumeStatuses []*VolumeStatusItem `locationName:"volumeStatusSet" locationNameList:"item" type:"list"` - - metadataDescribeVolumeStatusOutput `json:"-" xml:"-"` -} - -type metadataDescribeVolumeStatusOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVolumeStatusOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVolumeStatusOutput) GoString() string { - return s.String() -} - -type DescribeVolumesInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // attachment.attach-time - The time stamp when the attachment initiated. - // - // attachment.delete-on-termination - Whether the volume is deleted on instance - // termination. - // - // attachment.device - The device name that is exposed to the instance (for - // example, /dev/sda1). - // - // attachment.instance-id - The ID of the instance the volume is attached - // to. - // - // attachment.status - The attachment state (attaching | attached | detaching - // | detached). - // - // availability-zone - The Availability Zone in which the volume was created. - // - // create-time - The time stamp when the volume was created. - // - // encrypted - The encryption status of the volume. - // - // size - The size of the volume, in GiB. - // - // snapshot-id - The snapshot from which the volume was created. - // - // status - The status of the volume (creating | available | in-use | deleting - // | deleted | error). - // - // tag:key=value - The key/value combination of a tag assigned to the resource. - // - // tag-key - The key of a tag assigned to the resource. This filter is independent - // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" - // and the filter "tag-value=X", you get any resources assigned both the tag - // key Purpose (regardless of what the tag's value is), and the tag value X - // (regardless of what the tag's key is). If you want to list only resources - // where Purpose is X, see the tag:key=value filter. - // - // tag-value - The value of a tag assigned to the resource. This filter is - // independent of the tag-key filter. - // - // volume-id - The volume ID. - // - // volume-type - The Amazon EBS volume type. This can be gp2 for General - // Purpose (SSD) volumes, io1 for Provisioned IOPS (SSD) volumes, or standard - // for Magnetic volumes. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // The maximum number of volume results returned by DescribeVolumes in paginated - // output. When this parameter is used, DescribeVolumes only returns MaxResults - // results in a single page along with a NextToken response element. The remaining - // results of the initial request can be seen by sending another DescribeVolumes - // request with the returned NextToken value. This value can be between 5 and - // 1000; if MaxResults is given a value larger than 1000, only 1000 results - // are returned. If this parameter is not used, then DescribeVolumes returns - // all results. You cannot specify this parameter and the volume IDs parameter - // in the same request. - MaxResults *int64 `locationName:"maxResults" type:"integer"` - - // The NextToken value returned from a previous paginated DescribeVolumes request - // where MaxResults was used and the results exceeded the value of that parameter. - // Pagination continues from the end of the previous results that returned the - // NextToken value. This value is null when there are no more results to return. - NextToken *string `locationName:"nextToken" type:"string"` - - // One or more volume IDs. - VolumeIds []*string `locationName:"VolumeId" locationNameList:"VolumeId" type:"list"` - - metadataDescribeVolumesInput `json:"-" xml:"-"` -} - -type metadataDescribeVolumesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVolumesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVolumesInput) GoString() string { - return s.String() -} - -type DescribeVolumesOutput struct { - // The NextToken value to include in a future DescribeVolumes request. When - // the results of a DescribeVolumes request exceed MaxResults, this value can - // be used to retrieve the next page of results. This value is null when there - // are no more results to return. - NextToken *string `locationName:"nextToken" type:"string"` - - // Information about the volumes. - Volumes []*Volume `locationName:"volumeSet" locationNameList:"item" type:"list"` - - metadataDescribeVolumesOutput `json:"-" xml:"-"` -} - -type metadataDescribeVolumesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVolumesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVolumesOutput) GoString() string { - return s.String() -} - -type DescribeVpcAttributeInput struct { - // The VPC attribute. - Attribute *string `type:"string" enum:"VpcAttributeName"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the VPC. - VpcId *string `type:"string" required:"true"` - - metadataDescribeVpcAttributeInput `json:"-" xml:"-"` -} - -type metadataDescribeVpcAttributeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVpcAttributeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVpcAttributeInput) GoString() string { - return s.String() -} - -type DescribeVpcAttributeOutput struct { - // Indicates whether the instances launched in the VPC get DNS hostnames. If - // this attribute is true, instances in the VPC get DNS hostnames; otherwise, - // they do not. - EnableDnsHostnames *AttributeBooleanValue `locationName:"enableDnsHostnames" type:"structure"` - - // Indicates whether DNS resolution is enabled for the VPC. If this attribute - // is true, the Amazon DNS server resolves DNS hostnames for your instances - // to their corresponding IP addresses; otherwise, it does not. - EnableDnsSupport *AttributeBooleanValue `locationName:"enableDnsSupport" type:"structure"` - - // The ID of the VPC. - VpcId *string `locationName:"vpcId" type:"string"` - - metadataDescribeVpcAttributeOutput `json:"-" xml:"-"` -} - -type metadataDescribeVpcAttributeOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVpcAttributeOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVpcAttributeOutput) GoString() string { - return s.String() -} - -type DescribeVpcClassicLinkInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // is-classic-link-enabled - Whether the VPC is enabled for ClassicLink (true - // | false). - // - // tag:key=value - The key/value combination of a tag assigned to the resource. - // - // tag-key - The key of a tag assigned to the resource. This filter is independent - // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" - // and the filter "tag-value=X", you get any resources assigned both the tag - // key Purpose (regardless of what the tag's value is), and the tag value X - // (regardless of what the tag's key is). If you want to list only resources - // where Purpose is X, see the tag:key=value filter. - // - // tag-value - The value of a tag assigned to the resource. This filter is - // independent of the tag-key filter. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // One or more VPCs for which you want to describe the ClassicLink status. - VpcIds []*string `locationName:"VpcId" locationNameList:"VpcId" type:"list"` - - metadataDescribeVpcClassicLinkInput `json:"-" xml:"-"` -} - -type metadataDescribeVpcClassicLinkInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVpcClassicLinkInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVpcClassicLinkInput) GoString() string { - return s.String() -} - -type DescribeVpcClassicLinkOutput struct { - // The ClassicLink status of one or more VPCs. - Vpcs []*VpcClassicLink `locationName:"vpcSet" locationNameList:"item" type:"list"` - - metadataDescribeVpcClassicLinkOutput `json:"-" xml:"-"` -} - -type metadataDescribeVpcClassicLinkOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVpcClassicLinkOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVpcClassicLinkOutput) GoString() string { - return s.String() -} - -type DescribeVpcEndpointServicesInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `type:"boolean"` - - // The maximum number of items to return for this request. The request returns - // a token that you can specify in a subsequent call to get the next set of - // results. - // - // Constraint: If the value is greater than 1000, we return only 1000 items. - MaxResults *int64 `type:"integer"` - - // The token for the next set of items to return. (You received this token from - // a prior call.) - NextToken *string `type:"string"` - - metadataDescribeVpcEndpointServicesInput `json:"-" xml:"-"` -} - -type metadataDescribeVpcEndpointServicesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVpcEndpointServicesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVpcEndpointServicesInput) GoString() string { - return s.String() -} - -type DescribeVpcEndpointServicesOutput struct { - // The token to use when requesting the next set of items. If there are no additional - // items to return, the string is empty. - NextToken *string `locationName:"nextToken" type:"string"` - - // A list of supported AWS services. - ServiceNames []*string `locationName:"serviceNameSet" locationNameList:"item" type:"list"` - - metadataDescribeVpcEndpointServicesOutput `json:"-" xml:"-"` -} - -type metadataDescribeVpcEndpointServicesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVpcEndpointServicesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVpcEndpointServicesOutput) GoString() string { - return s.String() -} - -type DescribeVpcEndpointsInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `type:"boolean"` - - // One or more filters. - // - // service-name: The name of the AWS service. - // - // vpc-id: The ID of the VPC in which the endpoint resides. - // - // vpc-endpoint-id: The ID of the endpoint. - // - // vpc-endpoint-state: The state of the endpoint. (pending | available | - // deleting | deleted) - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // The maximum number of items to return for this request. The request returns - // a token that you can specify in a subsequent call to get the next set of - // results. - // - // Constraint: If the value is greater than 1000, we return only 1000 items. - MaxResults *int64 `type:"integer"` - - // The token for the next set of items to return. (You received this token from - // a prior call.) - NextToken *string `type:"string"` - - // One or more endpoint IDs. - VpcEndpointIds []*string `locationName:"VpcEndpointId" locationNameList:"item" type:"list"` - - metadataDescribeVpcEndpointsInput `json:"-" xml:"-"` -} - -type metadataDescribeVpcEndpointsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVpcEndpointsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVpcEndpointsInput) GoString() string { - return s.String() -} - -type DescribeVpcEndpointsOutput struct { - // The token to use when requesting the next set of items. If there are no additional - // items to return, the string is empty. - NextToken *string `locationName:"nextToken" type:"string"` - - // Information about the endpoints. - VpcEndpoints []*VpcEndpoint `locationName:"vpcEndpointSet" locationNameList:"item" type:"list"` - - metadataDescribeVpcEndpointsOutput `json:"-" xml:"-"` -} - -type metadataDescribeVpcEndpointsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVpcEndpointsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVpcEndpointsOutput) GoString() string { - return s.String() -} - -type DescribeVpcPeeringConnectionsInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // accepter-vpc-info.cidr-block - The CIDR block of the peer VPC. - // - // accepter-vpc-info.owner-id - The AWS account ID of the owner of the peer - // VPC. - // - // accepter-vpc-info.vpc-id - The ID of the peer VPC. - // - // expiration-time - The expiration date and time for the VPC peering connection. - // - // requester-vpc-info.cidr-block - The CIDR block of the requester's VPC. - // - // requester-vpc-info.owner-id - The AWS account ID of the owner of the requester - // VPC. - // - // requester-vpc-info.vpc-id - The ID of the requester VPC. - // - // status-code - The status of the VPC peering connection (pending-acceptance - // | failed | expired | provisioning | active | deleted | rejected). - // - // status-message - A message that provides more information about the status - // of the VPC peering connection, if applicable. - // - // tag:key=value - The key/value combination of a tag assigned to the resource. - // - // tag-key - The key of a tag assigned to the resource. This filter is independent - // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" - // and the filter "tag-value=X", you get any resources assigned both the tag - // key Purpose (regardless of what the tag's value is), and the tag value X - // (regardless of what the tag's key is). If you want to list only resources - // where Purpose is X, see the tag:key=value filter. - // - // tag-value - The value of a tag assigned to the resource. This filter is - // independent of the tag-key filter. - // - // vpc-peering-connection-id - The ID of the VPC peering connection. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // One or more VPC peering connection IDs. - // - // Default: Describes all your VPC peering connections. - VpcPeeringConnectionIds []*string `locationName:"VpcPeeringConnectionId" locationNameList:"item" type:"list"` - - metadataDescribeVpcPeeringConnectionsInput `json:"-" xml:"-"` -} - -type metadataDescribeVpcPeeringConnectionsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVpcPeeringConnectionsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVpcPeeringConnectionsInput) GoString() string { - return s.String() -} - -type DescribeVpcPeeringConnectionsOutput struct { - // Information about the VPC peering connections. - VpcPeeringConnections []*VpcPeeringConnection `locationName:"vpcPeeringConnectionSet" locationNameList:"item" type:"list"` - - metadataDescribeVpcPeeringConnectionsOutput `json:"-" xml:"-"` -} - -type metadataDescribeVpcPeeringConnectionsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVpcPeeringConnectionsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVpcPeeringConnectionsOutput) GoString() string { - return s.String() -} - -type DescribeVpcsInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // cidr - The CIDR block of the VPC. The CIDR block you specify must exactly - // match the VPC's CIDR block for information to be returned for the VPC. Must - // contain the slash followed by one or two digits (for example, /28). - // - // dhcp-options-id - The ID of a set of DHCP options. - // - // isDefault - Indicates whether the VPC is the default VPC. - // - // state - The state of the VPC (pending | available). - // - // tag:key=value - The key/value combination of a tag assigned to the resource. - // - // tag-key - The key of a tag assigned to the resource. This filter is independent - // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" - // and the filter "tag-value=X", you get any resources assigned both the tag - // key Purpose (regardless of what the tag's value is), and the tag value X - // (regardless of what the tag's key is). If you want to list only resources - // where Purpose is X, see the tag:key=value filter. - // - // tag-value - The value of a tag assigned to the resource. This filter is - // independent of the tag-key filter. - // - // vpc-id - The ID of the VPC. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // One or more VPC IDs. - // - // Default: Describes all your VPCs. - VpcIds []*string `locationName:"VpcId" locationNameList:"VpcId" type:"list"` - - metadataDescribeVpcsInput `json:"-" xml:"-"` -} - -type metadataDescribeVpcsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVpcsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVpcsInput) GoString() string { - return s.String() -} - -type DescribeVpcsOutput struct { - // Information about one or more VPCs. - Vpcs []*Vpc `locationName:"vpcSet" locationNameList:"item" type:"list"` - - metadataDescribeVpcsOutput `json:"-" xml:"-"` -} - -type metadataDescribeVpcsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVpcsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVpcsOutput) GoString() string { - return s.String() -} - -type DescribeVpnConnectionsInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // customer-gateway-configuration - The configuration information for the - // customer gateway. - // - // customer-gateway-id - The ID of a customer gateway associated with the - // VPN connection. - // - // state - The state of the VPN connection (pending | available | deleting - // | deleted). - // - // option.static-routes-only - Indicates whether the connection has static - // routes only. Used for devices that do not support Border Gateway Protocol - // (BGP). - // - // route.destination-cidr-block - The destination CIDR block. This corresponds - // to the subnet used in a customer data center. - // - // bgp-asn - The BGP Autonomous System Number (ASN) associated with a BGP - // device. - // - // tag:key=value - The key/value combination of a tag assigned to the resource. - // - // tag-key - The key of a tag assigned to the resource. This filter is independent - // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" - // and the filter "tag-value=X", you get any resources assigned both the tag - // key Purpose (regardless of what the tag's value is), and the tag value X - // (regardless of what the tag's key is). If you want to list only resources - // where Purpose is X, see the tag:key=value filter. - // - // tag-value - The value of a tag assigned to the resource. This filter is - // independent of the tag-key filter. - // - // type - The type of VPN connection. Currently the only supported type is - // ipsec.1. - // - // vpn-connection-id - The ID of the VPN connection. - // - // vpn-gateway-id - The ID of a virtual private gateway associated with the - // VPN connection. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // One or more VPN connection IDs. - // - // Default: Describes your VPN connections. - VpnConnectionIds []*string `locationName:"VpnConnectionId" locationNameList:"VpnConnectionId" type:"list"` - - metadataDescribeVpnConnectionsInput `json:"-" xml:"-"` -} - -type metadataDescribeVpnConnectionsInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVpnConnectionsInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVpnConnectionsInput) GoString() string { - return s.String() -} - -type DescribeVpnConnectionsOutput struct { - // Information about one or more VPN connections. - VpnConnections []*VpnConnection `locationName:"vpnConnectionSet" locationNameList:"item" type:"list"` - - metadataDescribeVpnConnectionsOutput `json:"-" xml:"-"` -} - -type metadataDescribeVpnConnectionsOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVpnConnectionsOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVpnConnectionsOutput) GoString() string { - return s.String() -} - -type DescribeVpnGatewaysInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more filters. - // - // attachment.state - The current state of the attachment between the gateway - // and the VPC (attaching | attached | detaching | detached). - // - // attachment.vpc-id - The ID of an attached VPC. - // - // availability-zone - The Availability Zone for the virtual private gateway. - // - // state - The state of the virtual private gateway (pending | available - // | deleting | deleted). - // - // tag:key=value - The key/value combination of a tag assigned to the resource. - // - // tag-key - The key of a tag assigned to the resource. This filter is independent - // of the tag-value filter. For example, if you use both the filter "tag-key=Purpose" - // and the filter "tag-value=X", you get any resources assigned both the tag - // key Purpose (regardless of what the tag's value is), and the tag value X - // (regardless of what the tag's key is). If you want to list only resources - // where Purpose is X, see the tag:key=value filter. - // - // tag-value - The value of a tag assigned to the resource. This filter is - // independent of the tag-key filter. - // - // type - The type of virtual private gateway. Currently the only supported - // type is ipsec.1. - // - // vpn-gateway-id - The ID of the virtual private gateway. - Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"` - - // One or more virtual private gateway IDs. - // - // Default: Describes all your virtual private gateways. - VpnGatewayIds []*string `locationName:"VpnGatewayId" locationNameList:"VpnGatewayId" type:"list"` - - metadataDescribeVpnGatewaysInput `json:"-" xml:"-"` -} - -type metadataDescribeVpnGatewaysInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVpnGatewaysInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVpnGatewaysInput) GoString() string { - return s.String() -} - -type DescribeVpnGatewaysOutput struct { - // Information about one or more virtual private gateways. - VpnGateways []*VpnGateway `locationName:"vpnGatewaySet" locationNameList:"item" type:"list"` - - metadataDescribeVpnGatewaysOutput `json:"-" xml:"-"` -} - -type metadataDescribeVpnGatewaysOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DescribeVpnGatewaysOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DescribeVpnGatewaysOutput) GoString() string { - return s.String() -} - -type DetachClassicLinkVpcInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the instance to unlink from the VPC. - InstanceId *string `locationName:"instanceId" type:"string" required:"true"` - - // The ID of the VPC to which the instance is linked. - VpcId *string `locationName:"vpcId" type:"string" required:"true"` - - metadataDetachClassicLinkVpcInput `json:"-" xml:"-"` -} - -type metadataDetachClassicLinkVpcInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DetachClassicLinkVpcInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DetachClassicLinkVpcInput) GoString() string { - return s.String() -} - -type DetachClassicLinkVpcOutput struct { - // Returns true if the request succeeds; otherwise, it returns an error. - Return *bool `locationName:"return" type:"boolean"` - - metadataDetachClassicLinkVpcOutput `json:"-" xml:"-"` -} - -type metadataDetachClassicLinkVpcOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DetachClassicLinkVpcOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DetachClassicLinkVpcOutput) GoString() string { - return s.String() -} - -type DetachInternetGatewayInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the Internet gateway. - InternetGatewayId *string `locationName:"internetGatewayId" type:"string" required:"true"` - - // The ID of the VPC. - VpcId *string `locationName:"vpcId" type:"string" required:"true"` - - metadataDetachInternetGatewayInput `json:"-" xml:"-"` -} - -type metadataDetachInternetGatewayInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DetachInternetGatewayInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DetachInternetGatewayInput) GoString() string { - return s.String() -} - -type DetachInternetGatewayOutput struct { - metadataDetachInternetGatewayOutput `json:"-" xml:"-"` -} - -type metadataDetachInternetGatewayOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DetachInternetGatewayOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DetachInternetGatewayOutput) GoString() string { - return s.String() -} - -type DetachNetworkInterfaceInput struct { - // The ID of the attachment. - AttachmentId *string `locationName:"attachmentId" type:"string" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // Specifies whether to force a detachment. - Force *bool `locationName:"force" type:"boolean"` - - metadataDetachNetworkInterfaceInput `json:"-" xml:"-"` -} - -type metadataDetachNetworkInterfaceInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DetachNetworkInterfaceInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DetachNetworkInterfaceInput) GoString() string { - return s.String() -} - -type DetachNetworkInterfaceOutput struct { - metadataDetachNetworkInterfaceOutput `json:"-" xml:"-"` -} - -type metadataDetachNetworkInterfaceOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DetachNetworkInterfaceOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DetachNetworkInterfaceOutput) GoString() string { - return s.String() -} - -type DetachVolumeInput struct { - // The device name. - Device *string `type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // Forces detachment if the previous detachment attempt did not occur cleanly - // (for example, logging into an instance, unmounting the volume, and detaching - // normally). This option can lead to data loss or a corrupted file system. - // Use this option only as a last resort to detach a volume from a failed instance. - // The instance won't have an opportunity to flush file system caches or file - // system metadata. If you use this option, you must perform file system check - // and repair procedures. - Force *bool `type:"boolean"` - - // The ID of the instance. - InstanceId *string `type:"string"` - - // The ID of the volume. - VolumeId *string `type:"string" required:"true"` - - metadataDetachVolumeInput `json:"-" xml:"-"` -} - -type metadataDetachVolumeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DetachVolumeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DetachVolumeInput) GoString() string { - return s.String() -} - -type DetachVpnGatewayInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the VPC. - VpcId *string `type:"string" required:"true"` - - // The ID of the virtual private gateway. - VpnGatewayId *string `type:"string" required:"true"` - - metadataDetachVpnGatewayInput `json:"-" xml:"-"` -} - -type metadataDetachVpnGatewayInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DetachVpnGatewayInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DetachVpnGatewayInput) GoString() string { - return s.String() -} - -type DetachVpnGatewayOutput struct { - metadataDetachVpnGatewayOutput `json:"-" xml:"-"` -} - -type metadataDetachVpnGatewayOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DetachVpnGatewayOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DetachVpnGatewayOutput) GoString() string { - return s.String() -} - -// Describes a DHCP configuration option. -type DhcpConfiguration struct { - // The name of a DHCP option. - Key *string `locationName:"key" type:"string"` - - // One or more values for the DHCP option. - Values []*AttributeValue `locationName:"valueSet" locationNameList:"item" type:"list"` - - metadataDhcpConfiguration `json:"-" xml:"-"` -} - -type metadataDhcpConfiguration struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DhcpConfiguration) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DhcpConfiguration) GoString() string { - return s.String() -} - -// Describes a set of DHCP options. -type DhcpOptions struct { - // One or more DHCP options in the set. - DhcpConfigurations []*DhcpConfiguration `locationName:"dhcpConfigurationSet" locationNameList:"item" type:"list"` - - // The ID of the set of DHCP options. - DhcpOptionsId *string `locationName:"dhcpOptionsId" type:"string"` - - // Any tags assigned to the DHCP options set. - Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - metadataDhcpOptions `json:"-" xml:"-"` -} - -type metadataDhcpOptions struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DhcpOptions) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DhcpOptions) GoString() string { - return s.String() -} - -type DisableVgwRoutePropagationInput struct { - // The ID of the virtual private gateway. - GatewayId *string `type:"string" required:"true"` - - // The ID of the route table. - RouteTableId *string `type:"string" required:"true"` - - metadataDisableVgwRoutePropagationInput `json:"-" xml:"-"` -} - -type metadataDisableVgwRoutePropagationInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DisableVgwRoutePropagationInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DisableVgwRoutePropagationInput) GoString() string { - return s.String() -} - -type DisableVgwRoutePropagationOutput struct { - metadataDisableVgwRoutePropagationOutput `json:"-" xml:"-"` -} - -type metadataDisableVgwRoutePropagationOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DisableVgwRoutePropagationOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DisableVgwRoutePropagationOutput) GoString() string { - return s.String() -} - -type DisableVpcClassicLinkInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the VPC. - VpcId *string `locationName:"vpcId" type:"string" required:"true"` - - metadataDisableVpcClassicLinkInput `json:"-" xml:"-"` -} - -type metadataDisableVpcClassicLinkInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DisableVpcClassicLinkInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DisableVpcClassicLinkInput) GoString() string { - return s.String() -} - -type DisableVpcClassicLinkOutput struct { - // Returns true if the request succeeds; otherwise, it returns an error. - Return *bool `locationName:"return" type:"boolean"` - - metadataDisableVpcClassicLinkOutput `json:"-" xml:"-"` -} - -type metadataDisableVpcClassicLinkOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DisableVpcClassicLinkOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DisableVpcClassicLinkOutput) GoString() string { - return s.String() -} - -type DisassociateAddressInput struct { - // [EC2-VPC] The association ID. Required for EC2-VPC. - AssociationId *string `type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // [EC2-Classic] The Elastic IP address. Required for EC2-Classic. - PublicIp *string `type:"string"` - - metadataDisassociateAddressInput `json:"-" xml:"-"` -} - -type metadataDisassociateAddressInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DisassociateAddressInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DisassociateAddressInput) GoString() string { - return s.String() -} - -type DisassociateAddressOutput struct { - metadataDisassociateAddressOutput `json:"-" xml:"-"` -} - -type metadataDisassociateAddressOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DisassociateAddressOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DisassociateAddressOutput) GoString() string { - return s.String() -} - -type DisassociateRouteTableInput struct { - // The association ID representing the current association between the route - // table and subnet. - AssociationId *string `locationName:"associationId" type:"string" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - metadataDisassociateRouteTableInput `json:"-" xml:"-"` -} - -type metadataDisassociateRouteTableInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DisassociateRouteTableInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DisassociateRouteTableInput) GoString() string { - return s.String() -} - -type DisassociateRouteTableOutput struct { - metadataDisassociateRouteTableOutput `json:"-" xml:"-"` -} - -type metadataDisassociateRouteTableOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DisassociateRouteTableOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DisassociateRouteTableOutput) GoString() string { - return s.String() -} - -// Describes a disk image. -type DiskImage struct { - // A description of the disk image. - Description *string `type:"string"` - - // Information about the disk image. - Image *DiskImageDetail `type:"structure"` - - // Information about the volume. - Volume *VolumeDetail `type:"structure"` - - metadataDiskImage `json:"-" xml:"-"` -} - -type metadataDiskImage struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DiskImage) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DiskImage) GoString() string { - return s.String() -} - -// Describes a disk image. -type DiskImageDescription struct { - // The checksum computed for the disk image. - Checksum *string `locationName:"checksum" type:"string"` - - // The disk image format. - Format *string `locationName:"format" type:"string" required:"true" enum:"DiskImageFormat"` - - // A presigned URL for the import manifest stored in Amazon S3. For information - // about creating a presigned URL for an Amazon S3 object, read the "Query String - // Request Authentication Alternative" section of the Authenticating REST Requests - // (http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html) - // topic in the Amazon Simple Storage Service Developer Guide. - ImportManifestUrl *string `locationName:"importManifestUrl" type:"string" required:"true"` - - // The size of the disk image, in GiB. - Size *int64 `locationName:"size" type:"long" required:"true"` - - metadataDiskImageDescription `json:"-" xml:"-"` -} - -type metadataDiskImageDescription struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DiskImageDescription) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DiskImageDescription) GoString() string { - return s.String() -} - -// Describes a disk image. -type DiskImageDetail struct { - // The size of the disk image, in GiB. - Bytes *int64 `locationName:"bytes" type:"long" required:"true"` - - // The disk image format. - Format *string `locationName:"format" type:"string" required:"true" enum:"DiskImageFormat"` - - // A presigned URL for the import manifest stored in Amazon S3 and presented - // here as an Amazon S3 presigned URL. For information about creating a presigned - // URL for an Amazon S3 object, read the "Query String Request Authentication - // Alternative" section of the Authenticating REST Requests (http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html) - // topic in the Amazon Simple Storage Service Developer Guide. - ImportManifestUrl *string `locationName:"importManifestUrl" type:"string" required:"true"` - - metadataDiskImageDetail `json:"-" xml:"-"` -} - -type metadataDiskImageDetail struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DiskImageDetail) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DiskImageDetail) GoString() string { - return s.String() -} - -// Describes a disk image volume. -type DiskImageVolumeDescription struct { - // The volume identifier. - Id *string `locationName:"id" type:"string" required:"true"` - - // The size of the volume, in GiB. - Size *int64 `locationName:"size" type:"long"` - - metadataDiskImageVolumeDescription `json:"-" xml:"-"` -} - -type metadataDiskImageVolumeDescription struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s DiskImageVolumeDescription) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s DiskImageVolumeDescription) GoString() string { - return s.String() -} - -// Describes a block device for an EBS volume. -type EbsBlockDevice struct { - // Indicates whether the EBS volume is deleted on instance termination. - DeleteOnTermination *bool `locationName:"deleteOnTermination" type:"boolean"` - - // Indicates whether the EBS volume is encrypted. Encrypted Amazon EBS volumes - // may only be attached to instances that support Amazon EBS encryption. - Encrypted *bool `locationName:"encrypted" type:"boolean"` - - // The number of I/O operations per second (IOPS) that the volume supports. - // For Provisioned IOPS (SSD) volumes, this represents the number of IOPS that - // are provisioned for the volume. For General Purpose (SSD) volumes, this represents - // the baseline performance of the volume and the rate at which the volume accumulates - // I/O credits for bursting. For more information on General Purpose (SSD) baseline - // performance, I/O credits, and bursting, see Amazon EBS Volume Types (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html) - // in the Amazon Elastic Compute Cloud User Guide. - // - // Constraint: Range is 100 to 20000 for Provisioned IOPS (SSD) volumes and - // 3 to 10000 for General Purpose (SSD) volumes. - // - // Condition: This parameter is required for requests to create io1 volumes; - // it is not used in requests to create standard or gp2 volumes. - Iops *int64 `locationName:"iops" type:"integer"` - - // The ID of the snapshot. - SnapshotId *string `locationName:"snapshotId" type:"string"` - - // The size of the volume, in GiB. - // - // Constraints: 1-1024 for standard volumes, 1-16384 for gp2 volumes, and 4-16384 - // for io1 volumes. If you specify a snapshot, the volume size must be equal - // to or larger than the snapshot size. - // - // Default: If you're creating the volume from a snapshot and don't specify - // a volume size, the default is the snapshot size. - VolumeSize *int64 `locationName:"volumeSize" type:"integer"` - - // The volume type. gp2 for General Purpose (SSD) volumes, io1 for Provisioned - // IOPS (SSD) volumes, and standard for Magnetic volumes. - // - // Default: standard - VolumeType *string `locationName:"volumeType" type:"string" enum:"VolumeType"` - - metadataEbsBlockDevice `json:"-" xml:"-"` -} - -type metadataEbsBlockDevice struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s EbsBlockDevice) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s EbsBlockDevice) GoString() string { - return s.String() -} - -// Describes a parameter used to set up an EBS volume in a block device mapping. -type EbsInstanceBlockDevice struct { - // The time stamp when the attachment initiated. - AttachTime *time.Time `locationName:"attachTime" type:"timestamp" timestampFormat:"iso8601"` - - // Indicates whether the volume is deleted on instance termination. - DeleteOnTermination *bool `locationName:"deleteOnTermination" type:"boolean"` - - // The attachment state. - Status *string `locationName:"status" type:"string" enum:"AttachmentStatus"` - - // The ID of the EBS volume. - VolumeId *string `locationName:"volumeId" type:"string"` - - metadataEbsInstanceBlockDevice `json:"-" xml:"-"` -} - -type metadataEbsInstanceBlockDevice struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s EbsInstanceBlockDevice) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s EbsInstanceBlockDevice) GoString() string { - return s.String() -} - -type EbsInstanceBlockDeviceSpecification struct { - // Indicates whether the volume is deleted on instance termination. - DeleteOnTermination *bool `locationName:"deleteOnTermination" type:"boolean"` - - // The ID of the EBS volume. - VolumeId *string `locationName:"volumeId" type:"string"` - - metadataEbsInstanceBlockDeviceSpecification `json:"-" xml:"-"` -} - -type metadataEbsInstanceBlockDeviceSpecification struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s EbsInstanceBlockDeviceSpecification) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s EbsInstanceBlockDeviceSpecification) GoString() string { - return s.String() -} - -type EnableVgwRoutePropagationInput struct { - // The ID of the virtual private gateway. - GatewayId *string `type:"string" required:"true"` - - // The ID of the route table. - RouteTableId *string `type:"string" required:"true"` - - metadataEnableVgwRoutePropagationInput `json:"-" xml:"-"` -} - -type metadataEnableVgwRoutePropagationInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s EnableVgwRoutePropagationInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s EnableVgwRoutePropagationInput) GoString() string { - return s.String() -} - -type EnableVgwRoutePropagationOutput struct { - metadataEnableVgwRoutePropagationOutput `json:"-" xml:"-"` -} - -type metadataEnableVgwRoutePropagationOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s EnableVgwRoutePropagationOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s EnableVgwRoutePropagationOutput) GoString() string { - return s.String() -} - -type EnableVolumeIOInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the volume. - VolumeId *string `locationName:"volumeId" type:"string" required:"true"` - - metadataEnableVolumeIOInput `json:"-" xml:"-"` -} - -type metadataEnableVolumeIOInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s EnableVolumeIOInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s EnableVolumeIOInput) GoString() string { - return s.String() -} - -type EnableVolumeIOOutput struct { - metadataEnableVolumeIOOutput `json:"-" xml:"-"` -} - -type metadataEnableVolumeIOOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s EnableVolumeIOOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s EnableVolumeIOOutput) GoString() string { - return s.String() -} - -type EnableVpcClassicLinkInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the VPC. - VpcId *string `locationName:"vpcId" type:"string" required:"true"` - - metadataEnableVpcClassicLinkInput `json:"-" xml:"-"` -} - -type metadataEnableVpcClassicLinkInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s EnableVpcClassicLinkInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s EnableVpcClassicLinkInput) GoString() string { - return s.String() -} - -type EnableVpcClassicLinkOutput struct { - // Returns true if the request succeeds; otherwise, it returns an error. - Return *bool `locationName:"return" type:"boolean"` - - metadataEnableVpcClassicLinkOutput `json:"-" xml:"-"` -} - -type metadataEnableVpcClassicLinkOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s EnableVpcClassicLinkOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s EnableVpcClassicLinkOutput) GoString() string { - return s.String() -} - -// Describes a Spot fleet event. -type EventInformation struct { - // The description of the event. - EventDescription *string `locationName:"eventDescription" type:"string"` - - // The event. - // - // The following are the error events. - // - // iamFleetRoleInvalid - The Spot fleet did not have the required permissions - // either to launch or terminate an instance. - // - // launchSpecTemporarilyBlacklisted - The configuration is not valid and - // several attempts to launch instances have failed. For more information, see - // the description of the event. - // - // spotFleetRequestConfigurationInvalid - The configuration is not valid. - // For more information, see the description of the event. - // - // spotInstanceCountLimitExceeded - You've reached the limit on the number - // of Spot instances that you can launch. - // - // The following are the fleetRequestChange events. - // - // active - The Spot fleet has been validated and Amazon EC2 is attempting - // to maintain the target number of running Spot instances. - // - // cancelled - The Spot fleet is canceled and has no running Spot instances. - // The Spot fleet will be deleted two days after its instances were terminated. - // - // cancelled_running - The Spot fleet is canceled and will not launch additional - // Spot instances, but its existing Spot instances continue to run until they - // are interrupted or terminated. - // - // cancelled_terminating - The Spot fleet is canceled and its Spot instances - // are terminating. - // - // expired - The Spot fleet request has expired. A subsequent event indicates - // that the instances were terminated, if the request was created with TerminateInstancesWithExpiration - // set. - // - // modify_in_progress - A request to modify the Spot fleet request was accepted - // and is in progress. - // - // modify_successful - The Spot fleet request was modified. - // - // price_update - The bid price for a launch configuration was adjusted because - // it was too high. This change is permanent. - // - // submitted - The Spot fleet request is being evaluated and Amazon EC2 is - // preparing to launch the target number of Spot instances. - // - // The following are the instanceChange events. - // - // launched - A bid was fulfilled and a new instance was launched. - // - // terminated - An instance was terminated by the user. - EventSubType *string `locationName:"eventSubType" type:"string"` - - // The ID of the instance. This information is available only for instanceChange - // events. - InstanceId *string `locationName:"instanceId" type:"string"` - - metadataEventInformation `json:"-" xml:"-"` -} - -type metadataEventInformation struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s EventInformation) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s EventInformation) GoString() string { - return s.String() -} - -// Describes an instance export task. -type ExportTask struct { - // A description of the resource being exported. - Description *string `locationName:"description" type:"string"` - - // The ID of the export task. - ExportTaskId *string `locationName:"exportTaskId" type:"string"` - - // Information about the export task. - ExportToS3Task *ExportToS3Task `locationName:"exportToS3" type:"structure"` - - // Information about the instance to export. - InstanceExportDetails *InstanceExportDetails `locationName:"instanceExport" type:"structure"` - - // The state of the export task. - State *string `locationName:"state" type:"string" enum:"ExportTaskState"` - - // The status message related to the export task. - StatusMessage *string `locationName:"statusMessage" type:"string"` - - metadataExportTask `json:"-" xml:"-"` -} - -type metadataExportTask struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ExportTask) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ExportTask) GoString() string { - return s.String() -} - -// Describes the format and location for an instance export task. -type ExportToS3Task struct { - // The container format used to combine disk images with metadata (such as OVF). - // If absent, only the disk image is exported. - ContainerFormat *string `locationName:"containerFormat" type:"string" enum:"ContainerFormat"` - - // The format for the exported image. - DiskImageFormat *string `locationName:"diskImageFormat" type:"string" enum:"DiskImageFormat"` - - // The S3 bucket for the destination image. The destination bucket must exist - // and grant WRITE and READ_ACP permissions to the AWS account vm-import-export@amazon.com. - S3Bucket *string `locationName:"s3Bucket" type:"string"` - - // The encryption key for your S3 bucket. - S3Key *string `locationName:"s3Key" type:"string"` - - metadataExportToS3Task `json:"-" xml:"-"` -} - -type metadataExportToS3Task struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ExportToS3Task) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ExportToS3Task) GoString() string { - return s.String() -} - -// Describes an instance export task. -type ExportToS3TaskSpecification struct { - // The container format used to combine disk images with metadata (such as OVF). - // If absent, only the disk image is exported. - ContainerFormat *string `locationName:"containerFormat" type:"string" enum:"ContainerFormat"` - - // The format for the exported image. - DiskImageFormat *string `locationName:"diskImageFormat" type:"string" enum:"DiskImageFormat"` - - // The S3 bucket for the destination image. The destination bucket must exist - // and grant WRITE and READ_ACP permissions to the AWS account vm-import-export@amazon.com. - S3Bucket *string `locationName:"s3Bucket" type:"string"` - - // The image is written to a single object in the S3 bucket at the S3 key s3prefix - // + exportTaskId + '.' + diskImageFormat. - S3Prefix *string `locationName:"s3Prefix" type:"string"` - - metadataExportToS3TaskSpecification `json:"-" xml:"-"` -} - -type metadataExportToS3TaskSpecification struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ExportToS3TaskSpecification) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ExportToS3TaskSpecification) GoString() string { - return s.String() -} - -// A filter name and value pair that is used to return a more specific list -// of results. Filters can be used to match a set of resources by various criteria, -// such as tags, attributes, or IDs. -type Filter struct { - // The name of the filter. Filter names are case-sensitive. - Name *string `type:"string"` - - // One or more filter values. Filter values are case-sensitive. - Values []*string `locationName:"Value" locationNameList:"item" type:"list"` - - metadataFilter `json:"-" xml:"-"` -} - -type metadataFilter struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s Filter) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s Filter) GoString() string { - return s.String() -} - -// Describes a flow log. -type FlowLog struct { - // The date and time the flow log was created. - CreationTime *time.Time `locationName:"creationTime" type:"timestamp" timestampFormat:"iso8601"` - - // Information about the error that occurred. Rate limited indicates that CloudWatch - // logs throttling has been applied for one or more network interfaces. Access - // error indicates that the IAM role associated with the flow log does not have - // sufficient permissions to publish to CloudWatch Logs. Unknown error indicates - // an internal error. - DeliverLogsErrorMessage *string `locationName:"deliverLogsErrorMessage" type:"string"` - - // The ARN of the IAM role that posts logs to CloudWatch Logs. - DeliverLogsPermissionArn *string `locationName:"deliverLogsPermissionArn" type:"string"` - - // The status of the logs delivery (SUCCESS | FAILED). - DeliverLogsStatus *string `locationName:"deliverLogsStatus" type:"string"` - - // The flow log ID. - FlowLogId *string `locationName:"flowLogId" type:"string"` - - // The status of the flow log (ACTIVE). - FlowLogStatus *string `locationName:"flowLogStatus" type:"string"` - - // The name of the flow log group. - LogGroupName *string `locationName:"logGroupName" type:"string"` - - // The ID of the resource on which the flow log was created. - ResourceId *string `locationName:"resourceId" type:"string"` - - // The type of traffic captured for the flow log. - TrafficType *string `locationName:"trafficType" type:"string" enum:"TrafficType"` - - metadataFlowLog `json:"-" xml:"-"` -} - -type metadataFlowLog struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s FlowLog) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s FlowLog) GoString() string { - return s.String() -} - -type GetConsoleOutputInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the instance. - InstanceId *string `type:"string" required:"true"` - - metadataGetConsoleOutputInput `json:"-" xml:"-"` -} - -type metadataGetConsoleOutputInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s GetConsoleOutputInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s GetConsoleOutputInput) GoString() string { - return s.String() -} - -type GetConsoleOutputOutput struct { - // The ID of the instance. - InstanceId *string `locationName:"instanceId" type:"string"` - - // The console output, Base64 encoded. - Output *string `locationName:"output" type:"string"` - - // The time the output was last updated. - Timestamp *time.Time `locationName:"timestamp" type:"timestamp" timestampFormat:"iso8601"` - - metadataGetConsoleOutputOutput `json:"-" xml:"-"` -} - -type metadataGetConsoleOutputOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s GetConsoleOutputOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s GetConsoleOutputOutput) GoString() string { - return s.String() -} - -type GetPasswordDataInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the Windows instance. - InstanceId *string `type:"string" required:"true"` - - metadataGetPasswordDataInput `json:"-" xml:"-"` -} - -type metadataGetPasswordDataInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s GetPasswordDataInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s GetPasswordDataInput) GoString() string { - return s.String() -} - -type GetPasswordDataOutput struct { - // The ID of the Windows instance. - InstanceId *string `locationName:"instanceId" type:"string"` - - // The password of the instance. - PasswordData *string `locationName:"passwordData" type:"string"` - - // The time the data was last updated. - Timestamp *time.Time `locationName:"timestamp" type:"timestamp" timestampFormat:"iso8601"` - - metadataGetPasswordDataOutput `json:"-" xml:"-"` -} - -type metadataGetPasswordDataOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s GetPasswordDataOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s GetPasswordDataOutput) GoString() string { - return s.String() -} - -// Describes a security group. -type GroupIdentifier struct { - // The ID of the security group. - GroupId *string `locationName:"groupId" type:"string"` - - // The name of the security group. - GroupName *string `locationName:"groupName" type:"string"` - - metadataGroupIdentifier `json:"-" xml:"-"` -} - -type metadataGroupIdentifier struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s GroupIdentifier) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s GroupIdentifier) GoString() string { - return s.String() -} - -// Describes an event in the history of the Spot fleet request. -type HistoryRecord struct { - // Information about the event. - EventInformation *EventInformation `locationName:"eventInformation" type:"structure" required:"true"` - - // The event type. - // - // error - Indicates an error with the Spot fleet request. - // - // fleetRequestChange - Indicates a change in the status or configuration - // of the Spot fleet request. - // - // instanceChange - Indicates that an instance was launched or terminated. - EventType *string `locationName:"eventType" type:"string" required:"true" enum:"EventType"` - - // The date and time of the event, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). - Timestamp *time.Time `locationName:"timestamp" type:"timestamp" timestampFormat:"iso8601" required:"true"` - - metadataHistoryRecord `json:"-" xml:"-"` -} - -type metadataHistoryRecord struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s HistoryRecord) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s HistoryRecord) GoString() string { - return s.String() -} - -// Describes an IAM instance profile. -type IamInstanceProfile struct { - // The Amazon Resource Name (ARN) of the instance profile. - Arn *string `locationName:"arn" type:"string"` - - // The ID of the instance profile. - Id *string `locationName:"id" type:"string"` - - metadataIamInstanceProfile `json:"-" xml:"-"` -} - -type metadataIamInstanceProfile struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s IamInstanceProfile) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s IamInstanceProfile) GoString() string { - return s.String() -} - -// Describes an IAM instance profile. -type IamInstanceProfileSpecification struct { - // The Amazon Resource Name (ARN) of the instance profile. - Arn *string `locationName:"arn" type:"string"` - - // The name of the instance profile. - Name *string `locationName:"name" type:"string"` - - metadataIamInstanceProfileSpecification `json:"-" xml:"-"` -} - -type metadataIamInstanceProfileSpecification struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s IamInstanceProfileSpecification) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s IamInstanceProfileSpecification) GoString() string { - return s.String() -} - -// Describes the ICMP type and code. -type IcmpTypeCode struct { - // The ICMP type. A value of -1 means all types. - Code *int64 `locationName:"code" type:"integer"` - - // The ICMP code. A value of -1 means all codes for the specified ICMP type. - Type *int64 `locationName:"type" type:"integer"` - - metadataIcmpTypeCode `json:"-" xml:"-"` -} - -type metadataIcmpTypeCode struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s IcmpTypeCode) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s IcmpTypeCode) GoString() string { - return s.String() -} - -// Describes an image. -type Image struct { - // The architecture of the image. - Architecture *string `locationName:"architecture" type:"string" enum:"ArchitectureValues"` - - // Any block device mapping entries. - BlockDeviceMappings []*BlockDeviceMapping `locationName:"blockDeviceMapping" locationNameList:"item" type:"list"` - - // The date and time the image was created. - CreationDate *string `locationName:"creationDate" type:"string"` - - // The description of the AMI that was provided during image creation. - Description *string `locationName:"description" type:"string"` - - // The hypervisor type of the image. - Hypervisor *string `locationName:"hypervisor" type:"string" enum:"HypervisorType"` - - // The ID of the AMI. - ImageId *string `locationName:"imageId" type:"string"` - - // The location of the AMI. - ImageLocation *string `locationName:"imageLocation" type:"string"` - - // The AWS account alias (for example, amazon, self) or the AWS account ID of - // the AMI owner. - ImageOwnerAlias *string `locationName:"imageOwnerAlias" type:"string"` - - // The type of image. - ImageType *string `locationName:"imageType" type:"string" enum:"ImageTypeValues"` - - // The kernel associated with the image, if any. Only applicable for machine - // images. - KernelId *string `locationName:"kernelId" type:"string"` - - // The name of the AMI that was provided during image creation. - Name *string `locationName:"name" type:"string"` - - // The AWS account ID of the image owner. - OwnerId *string `locationName:"imageOwnerId" type:"string"` - - // The value is Windows for Windows AMIs; otherwise blank. - Platform *string `locationName:"platform" type:"string" enum:"PlatformValues"` - - // Any product codes associated with the AMI. - ProductCodes []*ProductCode `locationName:"productCodes" locationNameList:"item" type:"list"` - - // Indicates whether the image has public launch permissions. The value is true - // if this image has public launch permissions or false if it has only implicit - // and explicit launch permissions. - Public *bool `locationName:"isPublic" type:"boolean"` - - // The RAM disk associated with the image, if any. Only applicable for machine - // images. - RamdiskId *string `locationName:"ramdiskId" type:"string"` - - // The device name of the root device (for example, /dev/sda1 or /dev/xvda). - RootDeviceName *string `locationName:"rootDeviceName" type:"string"` - - // The type of root device used by the AMI. The AMI can use an EBS volume or - // an instance store volume. - RootDeviceType *string `locationName:"rootDeviceType" type:"string" enum:"DeviceType"` - - // Specifies whether enhanced networking is enabled. - SriovNetSupport *string `locationName:"sriovNetSupport" type:"string"` - - // The current state of the AMI. If the state is available, the image is successfully - // registered and can be used to launch an instance. - State *string `locationName:"imageState" type:"string" enum:"ImageState"` - - // The reason for the state change. - StateReason *StateReason `locationName:"stateReason" type:"structure"` - - // Any tags assigned to the image. - Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - // The type of virtualization of the AMI. - VirtualizationType *string `locationName:"virtualizationType" type:"string" enum:"VirtualizationType"` - - metadataImage `json:"-" xml:"-"` -} - -type metadataImage struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s Image) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s Image) GoString() string { - return s.String() -} - -// Describes the disk container object for an import image task. -type ImageDiskContainer struct { - // The description of the disk image. - Description *string `type:"string"` - - // The block device mapping for the disk. - DeviceName *string `type:"string"` - - // The format of the disk image being imported. - // - // Valid values: RAW | VHD | VMDK | OVA - Format *string `type:"string"` - - // The ID of the EBS snapshot to be used for importing the snapshot. - SnapshotId *string `type:"string"` - - // The URL to the Amazon S3-based disk image being imported. The URL can either - // be a https URL (https://..) or an Amazon S3 URL (s3://..) - Url *string `type:"string"` - - // The S3 bucket for the disk image. - UserBucket *UserBucket `type:"structure"` - - metadataImageDiskContainer `json:"-" xml:"-"` -} - -type metadataImageDiskContainer struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ImageDiskContainer) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ImageDiskContainer) GoString() string { - return s.String() -} - -type ImportImageInput struct { - // The architecture of the virtual machine. - // - // Valid values: i386 | x86_64 - Architecture *string `type:"string"` - - // The client-specific data. - ClientData *ClientData `type:"structure"` - - // The token to enable idempotency for VM import requests. - ClientToken *string `type:"string"` - - // A description string for the import image task. - Description *string `type:"string"` - - // Information about the disk containers. - DiskContainers []*ImageDiskContainer `locationName:"DiskContainer" locationNameList:"item" type:"list"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `type:"boolean"` - - // The target hypervisor platform. - // - // Valid values: xen - Hypervisor *string `type:"string"` - - // The license type to be used for the Amazon Machine Image (AMI) after importing. - // - // Note: You may only use BYOL if you have existing licenses with rights to - // use these licenses in a third party cloud like AWS. For more information, - // see VM Import/Export Prerequisites (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/VMImportPrerequisites.html) - // in the Amazon Elastic Compute Cloud User Guide. - // - // Valid values: AWS | BYOL - LicenseType *string `type:"string"` - - // The operating system of the virtual machine. - // - // Valid values: Windows | Linux - Platform *string `type:"string"` - - // The name of the role to use when not using the default role, 'vmimport'. - RoleName *string `type:"string"` - - metadataImportImageInput `json:"-" xml:"-"` -} - -type metadataImportImageInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ImportImageInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ImportImageInput) GoString() string { - return s.String() -} - -type ImportImageOutput struct { - // The architecture of the virtual machine. - Architecture *string `locationName:"architecture" type:"string"` - - // A description of the import task. - Description *string `locationName:"description" type:"string"` - - // The target hypervisor of the import task. - Hypervisor *string `locationName:"hypervisor" type:"string"` - - // The ID of the Amazon Machine Image (AMI) created by the import task. - ImageId *string `locationName:"imageId" type:"string"` - - // The task ID of the import image task. - ImportTaskId *string `locationName:"importTaskId" type:"string"` - - // The license type of the virtual machine. - LicenseType *string `locationName:"licenseType" type:"string"` - - // The operating system of the virtual machine. - Platform *string `locationName:"platform" type:"string"` - - // The progress of the task. - Progress *string `locationName:"progress" type:"string"` - - // Information about the snapshots. - SnapshotDetails []*SnapshotDetail `locationName:"snapshotDetailSet" locationNameList:"item" type:"list"` - - // A brief status of the task. - Status *string `locationName:"status" type:"string"` - - // A detailed status message of the import task. - StatusMessage *string `locationName:"statusMessage" type:"string"` - - metadataImportImageOutput `json:"-" xml:"-"` -} - -type metadataImportImageOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ImportImageOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ImportImageOutput) GoString() string { - return s.String() -} - -// Describes an import image task. -type ImportImageTask struct { - // The architecture of the virtual machine. - // - // Valid values: i386 | x86_64 - Architecture *string `locationName:"architecture" type:"string"` - - // A description of the import task. - Description *string `locationName:"description" type:"string"` - - // The target hypervisor for the import task. - // - // Valid values: xen - Hypervisor *string `locationName:"hypervisor" type:"string"` - - // The ID of the Amazon Machine Image (AMI) of the imported virtual machine. - ImageId *string `locationName:"imageId" type:"string"` - - // The ID of the import image task. - ImportTaskId *string `locationName:"importTaskId" type:"string"` - - // The license type of the virtual machine. - LicenseType *string `locationName:"licenseType" type:"string"` - - // The description string for the import image task. - Platform *string `locationName:"platform" type:"string"` - - // The percentage of progress of the import image task. - Progress *string `locationName:"progress" type:"string"` - - // Information about the snapshots. - SnapshotDetails []*SnapshotDetail `locationName:"snapshotDetailSet" locationNameList:"item" type:"list"` - - // A brief status for the import image task. - Status *string `locationName:"status" type:"string"` - - // A descriptive status message for the import image task. - StatusMessage *string `locationName:"statusMessage" type:"string"` - - metadataImportImageTask `json:"-" xml:"-"` -} - -type metadataImportImageTask struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ImportImageTask) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ImportImageTask) GoString() string { - return s.String() -} - -type ImportInstanceInput struct { - // A description for the instance being imported. - Description *string `locationName:"description" type:"string"` - - // The disk image. - DiskImages []*DiskImage `locationName:"diskImage" type:"list"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The launch specification. - LaunchSpecification *ImportInstanceLaunchSpecification `locationName:"launchSpecification" type:"structure"` - - // The instance operating system. - Platform *string `locationName:"platform" type:"string" required:"true" enum:"PlatformValues"` - - metadataImportInstanceInput `json:"-" xml:"-"` -} - -type metadataImportInstanceInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ImportInstanceInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ImportInstanceInput) GoString() string { - return s.String() -} - -// Describes the launch specification for VM import. -type ImportInstanceLaunchSpecification struct { - // Reserved. - AdditionalInfo *string `locationName:"additionalInfo" type:"string"` - - // The architecture of the instance. - Architecture *string `locationName:"architecture" type:"string" enum:"ArchitectureValues"` - - // One or more security group IDs. - GroupIds []*string `locationName:"GroupId" locationNameList:"SecurityGroupId" type:"list"` - - // One or more security group names. - GroupNames []*string `locationName:"GroupName" locationNameList:"SecurityGroup" type:"list"` - - // Indicates whether an instance stops or terminates when you initiate shutdown - // from the instance (using the operating system command for system shutdown). - InstanceInitiatedShutdownBehavior *string `locationName:"instanceInitiatedShutdownBehavior" type:"string" enum:"ShutdownBehavior"` - - // The instance type. For more information about the instance types that you - // can import, see Before You Get Started (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/VMImportPrerequisites.html) - // in the Amazon Elastic Compute Cloud User Guide. - InstanceType *string `locationName:"instanceType" type:"string" enum:"InstanceType"` - - // Indicates whether monitoring is enabled. - Monitoring *bool `locationName:"monitoring" type:"boolean"` - - // The placement information for the instance. - Placement *Placement `locationName:"placement" type:"structure"` - - // [EC2-VPC] An available IP address from the IP address range of the subnet. - PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` - - // [EC2-VPC] The ID of the subnet in which to launch the instance. - SubnetId *string `locationName:"subnetId" type:"string"` - - // The Base64-encoded MIME user data to be made available to the instance. - UserData *UserData `locationName:"userData" type:"structure"` - - metadataImportInstanceLaunchSpecification `json:"-" xml:"-"` -} - -type metadataImportInstanceLaunchSpecification struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ImportInstanceLaunchSpecification) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ImportInstanceLaunchSpecification) GoString() string { - return s.String() -} - -type ImportInstanceOutput struct { - // Information about the conversion task. - ConversionTask *ConversionTask `locationName:"conversionTask" type:"structure"` - - metadataImportInstanceOutput `json:"-" xml:"-"` -} - -type metadataImportInstanceOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ImportInstanceOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ImportInstanceOutput) GoString() string { - return s.String() -} - -// Describes an import instance task. -type ImportInstanceTaskDetails struct { - // A description of the task. - Description *string `locationName:"description" type:"string"` - - // The ID of the instance. - InstanceId *string `locationName:"instanceId" type:"string"` - - // The instance operating system. - Platform *string `locationName:"platform" type:"string" enum:"PlatformValues"` - - // One or more volumes. - Volumes []*ImportInstanceVolumeDetailItem `locationName:"volumes" locationNameList:"item" type:"list" required:"true"` - - metadataImportInstanceTaskDetails `json:"-" xml:"-"` -} - -type metadataImportInstanceTaskDetails struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ImportInstanceTaskDetails) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ImportInstanceTaskDetails) GoString() string { - return s.String() -} - -// Describes an import volume task. -type ImportInstanceVolumeDetailItem struct { - // The Availability Zone where the resulting instance will reside. - AvailabilityZone *string `locationName:"availabilityZone" type:"string" required:"true"` - - // The number of bytes converted so far. - BytesConverted *int64 `locationName:"bytesConverted" type:"long" required:"true"` - - // A description of the task. - Description *string `locationName:"description" type:"string"` - - // The image. - Image *DiskImageDescription `locationName:"image" type:"structure" required:"true"` - - // The status of the import of this particular disk image. - Status *string `locationName:"status" type:"string" required:"true"` - - // The status information or errors related to the disk image. - StatusMessage *string `locationName:"statusMessage" type:"string"` - - // The volume. - Volume *DiskImageVolumeDescription `locationName:"volume" type:"structure" required:"true"` - - metadataImportInstanceVolumeDetailItem `json:"-" xml:"-"` -} - -type metadataImportInstanceVolumeDetailItem struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ImportInstanceVolumeDetailItem) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ImportInstanceVolumeDetailItem) GoString() string { - return s.String() -} - -type ImportKeyPairInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // A unique name for the key pair. - KeyName *string `locationName:"keyName" type:"string" required:"true"` - - // The public key. You must base64 encode the public key material before sending - // it to AWS. - PublicKeyMaterial []byte `locationName:"publicKeyMaterial" type:"blob" required:"true"` - - metadataImportKeyPairInput `json:"-" xml:"-"` -} - -type metadataImportKeyPairInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ImportKeyPairInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ImportKeyPairInput) GoString() string { - return s.String() -} - -type ImportKeyPairOutput struct { - // The MD5 public key fingerprint as specified in section 4 of RFC 4716. - KeyFingerprint *string `locationName:"keyFingerprint" type:"string"` - - // The key pair name you provided. - KeyName *string `locationName:"keyName" type:"string"` - - metadataImportKeyPairOutput `json:"-" xml:"-"` -} - -type metadataImportKeyPairOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ImportKeyPairOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ImportKeyPairOutput) GoString() string { - return s.String() -} - -type ImportSnapshotInput struct { - // The client-specific data. - ClientData *ClientData `type:"structure"` - - // Token to enable idempotency for VM import requests. - ClientToken *string `type:"string"` - - // The description string for the import snapshot task. - Description *string `type:"string"` - - // Information about the disk container. - DiskContainer *SnapshotDiskContainer `type:"structure"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `type:"boolean"` - - // The name of the role to use when not using the default role, 'vmimport'. - RoleName *string `type:"string"` - - metadataImportSnapshotInput `json:"-" xml:"-"` -} - -type metadataImportSnapshotInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ImportSnapshotInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ImportSnapshotInput) GoString() string { - return s.String() -} - -type ImportSnapshotOutput struct { - // A description of the import snapshot task. - Description *string `locationName:"description" type:"string"` - - // The ID of the import snapshot task. - ImportTaskId *string `locationName:"importTaskId" type:"string"` - - // Information about the import snapshot task. - SnapshotTaskDetail *SnapshotTaskDetail `locationName:"snapshotTaskDetail" type:"structure"` - - metadataImportSnapshotOutput `json:"-" xml:"-"` -} - -type metadataImportSnapshotOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ImportSnapshotOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ImportSnapshotOutput) GoString() string { - return s.String() -} - -// Describes an import snapshot task. -type ImportSnapshotTask struct { - // A description of the import snapshot task. - Description *string `locationName:"description" type:"string"` - - // The ID of the import snapshot task. - ImportTaskId *string `locationName:"importTaskId" type:"string"` - - // Describes an import snapshot task. - SnapshotTaskDetail *SnapshotTaskDetail `locationName:"snapshotTaskDetail" type:"structure"` - - metadataImportSnapshotTask `json:"-" xml:"-"` -} - -type metadataImportSnapshotTask struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ImportSnapshotTask) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ImportSnapshotTask) GoString() string { - return s.String() -} - -type ImportVolumeInput struct { - // The Availability Zone for the resulting EBS volume. - AvailabilityZone *string `locationName:"availabilityZone" type:"string" required:"true"` - - // A description of the volume. - Description *string `locationName:"description" type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The disk image. - Image *DiskImageDetail `locationName:"image" type:"structure" required:"true"` - - // The volume size. - Volume *VolumeDetail `locationName:"volume" type:"structure" required:"true"` - - metadataImportVolumeInput `json:"-" xml:"-"` -} - -type metadataImportVolumeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ImportVolumeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ImportVolumeInput) GoString() string { - return s.String() -} - -type ImportVolumeOutput struct { - // Information about the conversion task. - ConversionTask *ConversionTask `locationName:"conversionTask" type:"structure"` - - metadataImportVolumeOutput `json:"-" xml:"-"` -} - -type metadataImportVolumeOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ImportVolumeOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ImportVolumeOutput) GoString() string { - return s.String() -} - -// Describes an import volume task. -type ImportVolumeTaskDetails struct { - // The Availability Zone where the resulting volume will reside. - AvailabilityZone *string `locationName:"availabilityZone" type:"string" required:"true"` - - // The number of bytes converted so far. - BytesConverted *int64 `locationName:"bytesConverted" type:"long" required:"true"` - - // The description you provided when starting the import volume task. - Description *string `locationName:"description" type:"string"` - - // The image. - Image *DiskImageDescription `locationName:"image" type:"structure" required:"true"` - - // The volume. - Volume *DiskImageVolumeDescription `locationName:"volume" type:"structure" required:"true"` - - metadataImportVolumeTaskDetails `json:"-" xml:"-"` -} - -type metadataImportVolumeTaskDetails struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ImportVolumeTaskDetails) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ImportVolumeTaskDetails) GoString() string { - return s.String() -} - -// Describes an instance. -type Instance struct { - // The AMI launch index, which can be used to find this instance in the launch - // group. - AmiLaunchIndex *int64 `locationName:"amiLaunchIndex" type:"integer"` - - // The architecture of the image. - Architecture *string `locationName:"architecture" type:"string" enum:"ArchitectureValues"` - - // Any block device mapping entries for the instance. - BlockDeviceMappings []*InstanceBlockDeviceMapping `locationName:"blockDeviceMapping" locationNameList:"item" type:"list"` - - // The idempotency token you provided when you launched the instance, if applicable. - ClientToken *string `locationName:"clientToken" type:"string"` - - // Indicates whether the instance is optimized for EBS I/O. This optimization - // provides dedicated throughput to Amazon EBS and an optimized configuration - // stack to provide optimal I/O performance. This optimization isn't available - // with all instance types. Additional usage charges apply when using an EBS - // Optimized instance. - EbsOptimized *bool `locationName:"ebsOptimized" type:"boolean"` - - // The hypervisor type of the instance. - Hypervisor *string `locationName:"hypervisor" type:"string" enum:"HypervisorType"` - - // The IAM instance profile associated with the instance, if applicable. - IamInstanceProfile *IamInstanceProfile `locationName:"iamInstanceProfile" type:"structure"` - - // The ID of the AMI used to launch the instance. - ImageId *string `locationName:"imageId" type:"string"` - - // The ID of the instance. - InstanceId *string `locationName:"instanceId" type:"string"` - - // Indicates whether this is a Spot Instance. - InstanceLifecycle *string `locationName:"instanceLifecycle" type:"string" enum:"InstanceLifecycleType"` - - // The instance type. - InstanceType *string `locationName:"instanceType" type:"string" enum:"InstanceType"` - - // The kernel associated with this instance, if applicable. - KernelId *string `locationName:"kernelId" type:"string"` - - // The name of the key pair, if this instance was launched with an associated - // key pair. - KeyName *string `locationName:"keyName" type:"string"` - - // The time the instance was launched. - LaunchTime *time.Time `locationName:"launchTime" type:"timestamp" timestampFormat:"iso8601"` - - // The monitoring information for the instance. - Monitoring *Monitoring `locationName:"monitoring" type:"structure"` - - // [EC2-VPC] One or more network interfaces for the instance. - NetworkInterfaces []*InstanceNetworkInterface `locationName:"networkInterfaceSet" locationNameList:"item" type:"list"` - - // The location where the instance launched, if applicable. - Placement *Placement `locationName:"placement" type:"structure"` - - // The value is Windows for Windows instances; otherwise blank. - Platform *string `locationName:"platform" type:"string" enum:"PlatformValues"` - - // The private DNS name assigned to the instance. This DNS name can only be - // used inside the Amazon EC2 network. This name is not available until the - // instance enters the running state. For EC2-VPC, this name is only available - // if you've enabled DNS hostnames for your VPC. - PrivateDnsName *string `locationName:"privateDnsName" type:"string"` - - // The private IP address assigned to the instance. - PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` - - // The product codes attached to this instance, if applicable. - ProductCodes []*ProductCode `locationName:"productCodes" locationNameList:"item" type:"list"` - - // The public DNS name assigned to the instance. This name is not available - // until the instance enters the running state. For EC2-VPC, this name is only - // available if you've enabled DNS hostnames for your VPC. - PublicDnsName *string `locationName:"dnsName" type:"string"` - - // The public IP address assigned to the instance, if applicable. - PublicIpAddress *string `locationName:"ipAddress" type:"string"` - - // The RAM disk associated with this instance, if applicable. - RamdiskId *string `locationName:"ramdiskId" type:"string"` - - // The root device name (for example, /dev/sda1 or /dev/xvda). - RootDeviceName *string `locationName:"rootDeviceName" type:"string"` - - // The root device type used by the AMI. The AMI can use an EBS volume or an - // instance store volume. - RootDeviceType *string `locationName:"rootDeviceType" type:"string" enum:"DeviceType"` - - // One or more security groups for the instance. - SecurityGroups []*GroupIdentifier `locationName:"groupSet" locationNameList:"item" type:"list"` - - // Specifies whether to enable an instance launched in a VPC to perform NAT. - // This controls whether source/destination checking is enabled on the instance. - // A value of true means checking is enabled, and false means checking is disabled. - // The value must be false for the instance to perform NAT. For more information, - // see NAT Instances (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_NAT_Instance.html) - // in the Amazon Virtual Private Cloud User Guide. - SourceDestCheck *bool `locationName:"sourceDestCheck" type:"boolean"` - - // If the request is a Spot instance request, the ID of the request. - SpotInstanceRequestId *string `locationName:"spotInstanceRequestId" type:"string"` - - // Specifies whether enhanced networking is enabled. - SriovNetSupport *string `locationName:"sriovNetSupport" type:"string"` - - // The current state of the instance. - State *InstanceState `locationName:"instanceState" type:"structure"` - - // The reason for the most recent state transition. - StateReason *StateReason `locationName:"stateReason" type:"structure"` - - // The reason for the most recent state transition. This might be an empty string. - StateTransitionReason *string `locationName:"reason" type:"string"` - - // [EC2-VPC] The ID of the subnet in which the instance is running. - SubnetId *string `locationName:"subnetId" type:"string"` - - // Any tags assigned to the instance. - Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - // The virtualization type of the instance. - VirtualizationType *string `locationName:"virtualizationType" type:"string" enum:"VirtualizationType"` - - // [EC2-VPC] The ID of the VPC in which the instance is running. - VpcId *string `locationName:"vpcId" type:"string"` - - metadataInstance `json:"-" xml:"-"` -} - -type metadataInstance struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s Instance) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s Instance) GoString() string { - return s.String() -} - -// Describes a block device mapping. -type InstanceBlockDeviceMapping struct { - // The device name exposed to the instance (for example, /dev/sdh or xvdh). - DeviceName *string `locationName:"deviceName" type:"string"` - - // Parameters used to automatically set up EBS volumes when the instance is - // launched. - Ebs *EbsInstanceBlockDevice `locationName:"ebs" type:"structure"` - - metadataInstanceBlockDeviceMapping `json:"-" xml:"-"` -} - -type metadataInstanceBlockDeviceMapping struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s InstanceBlockDeviceMapping) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s InstanceBlockDeviceMapping) GoString() string { - return s.String() -} - -// Describes a block device mapping entry. -type InstanceBlockDeviceMappingSpecification struct { - // The device name exposed to the instance (for example, /dev/sdh or xvdh). - DeviceName *string `locationName:"deviceName" type:"string"` - - // Parameters used to automatically set up EBS volumes when the instance is - // launched. - Ebs *EbsInstanceBlockDeviceSpecification `locationName:"ebs" type:"structure"` - - // suppress the specified device included in the block device mapping. - NoDevice *string `locationName:"noDevice" type:"string"` - - // The virtual device name. - VirtualName *string `locationName:"virtualName" type:"string"` - - metadataInstanceBlockDeviceMappingSpecification `json:"-" xml:"-"` -} - -type metadataInstanceBlockDeviceMappingSpecification struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s InstanceBlockDeviceMappingSpecification) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s InstanceBlockDeviceMappingSpecification) GoString() string { - return s.String() -} - -// Describes a Reserved Instance listing state. -type InstanceCount struct { - // The number of listed Reserved Instances in the state specified by the state. - InstanceCount *int64 `locationName:"instanceCount" type:"integer"` - - // The states of the listed Reserved Instances. - State *string `locationName:"state" type:"string" enum:"ListingState"` - - metadataInstanceCount `json:"-" xml:"-"` -} - -type metadataInstanceCount struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s InstanceCount) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s InstanceCount) GoString() string { - return s.String() -} - -// Describes an instance to export. -type InstanceExportDetails struct { - // The ID of the resource being exported. - InstanceId *string `locationName:"instanceId" type:"string"` - - // The target virtualization environment. - TargetEnvironment *string `locationName:"targetEnvironment" type:"string" enum:"ExportEnvironment"` - - metadataInstanceExportDetails `json:"-" xml:"-"` -} - -type metadataInstanceExportDetails struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s InstanceExportDetails) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s InstanceExportDetails) GoString() string { - return s.String() -} - -// Describes the monitoring information of the instance. -type InstanceMonitoring struct { - // The ID of the instance. - InstanceId *string `locationName:"instanceId" type:"string"` - - // The monitoring information. - Monitoring *Monitoring `locationName:"monitoring" type:"structure"` - - metadataInstanceMonitoring `json:"-" xml:"-"` -} - -type metadataInstanceMonitoring struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s InstanceMonitoring) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s InstanceMonitoring) GoString() string { - return s.String() -} - -// Describes a network interface. -type InstanceNetworkInterface struct { - // The association information for an Elastic IP associated with the network - // interface. - Association *InstanceNetworkInterfaceAssociation `locationName:"association" type:"structure"` - - // The network interface attachment. - Attachment *InstanceNetworkInterfaceAttachment `locationName:"attachment" type:"structure"` - - // The description. - Description *string `locationName:"description" type:"string"` - - // One or more security groups. - Groups []*GroupIdentifier `locationName:"groupSet" locationNameList:"item" type:"list"` - - // The MAC address. - MacAddress *string `locationName:"macAddress" type:"string"` - - // The ID of the network interface. - NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string"` - - // The ID of the AWS account that created the network interface. - OwnerId *string `locationName:"ownerId" type:"string"` - - // The private DNS name. - PrivateDnsName *string `locationName:"privateDnsName" type:"string"` - - // The IP address of the network interface within the subnet. - PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` - - // The private IP addresses associated with the network interface. - PrivateIpAddresses []*InstancePrivateIpAddress `locationName:"privateIpAddressesSet" locationNameList:"item" type:"list"` - - // Indicates whether to validate network traffic to or from this network interface. - SourceDestCheck *bool `locationName:"sourceDestCheck" type:"boolean"` - - // The status of the network interface. - Status *string `locationName:"status" type:"string" enum:"NetworkInterfaceStatus"` - - // The ID of the subnet. - SubnetId *string `locationName:"subnetId" type:"string"` - - // The ID of the VPC. - VpcId *string `locationName:"vpcId" type:"string"` - - metadataInstanceNetworkInterface `json:"-" xml:"-"` -} - -type metadataInstanceNetworkInterface struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s InstanceNetworkInterface) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s InstanceNetworkInterface) GoString() string { - return s.String() -} - -// Describes association information for an Elastic IP address. -type InstanceNetworkInterfaceAssociation struct { - // The ID of the owner of the Elastic IP address. - IpOwnerId *string `locationName:"ipOwnerId" type:"string"` - - // The public DNS name. - PublicDnsName *string `locationName:"publicDnsName" type:"string"` - - // The public IP address or Elastic IP address bound to the network interface. - PublicIp *string `locationName:"publicIp" type:"string"` - - metadataInstanceNetworkInterfaceAssociation `json:"-" xml:"-"` -} - -type metadataInstanceNetworkInterfaceAssociation struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s InstanceNetworkInterfaceAssociation) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s InstanceNetworkInterfaceAssociation) GoString() string { - return s.String() -} - -// Describes a network interface attachment. -type InstanceNetworkInterfaceAttachment struct { - // The time stamp when the attachment initiated. - AttachTime *time.Time `locationName:"attachTime" type:"timestamp" timestampFormat:"iso8601"` - - // The ID of the network interface attachment. - AttachmentId *string `locationName:"attachmentId" type:"string"` - - // Indicates whether the network interface is deleted when the instance is terminated. - DeleteOnTermination *bool `locationName:"deleteOnTermination" type:"boolean"` - - // The index of the device on the instance for the network interface attachment. - DeviceIndex *int64 `locationName:"deviceIndex" type:"integer"` - - // The attachment state. - Status *string `locationName:"status" type:"string" enum:"AttachmentStatus"` - - metadataInstanceNetworkInterfaceAttachment `json:"-" xml:"-"` -} - -type metadataInstanceNetworkInterfaceAttachment struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s InstanceNetworkInterfaceAttachment) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s InstanceNetworkInterfaceAttachment) GoString() string { - return s.String() -} - -// Describes a network interface. -type InstanceNetworkInterfaceSpecification struct { - // Indicates whether to assign a public IP address to an instance you launch - // in a VPC. The public IP address can only be assigned to a network interface - // for eth0, and can only be assigned to a new network interface, not an existing - // one. You cannot specify more than one network interface in the request. If - // launching into a default subnet, the default value is true. - AssociatePublicIpAddress *bool `locationName:"associatePublicIpAddress" type:"boolean"` - - // If set to true, the interface is deleted when the instance is terminated. - // You can specify true only if creating a new network interface when launching - // an instance. - DeleteOnTermination *bool `locationName:"deleteOnTermination" type:"boolean"` - - // The description of the network interface. Applies only if creating a network - // interface when launching an instance. - Description *string `locationName:"description" type:"string"` - - // The index of the device on the instance for the network interface attachment. - // If you are specifying a network interface in a RunInstances request, you - // must provide the device index. - DeviceIndex *int64 `locationName:"deviceIndex" type:"integer"` - - // The IDs of the security groups for the network interface. Applies only if - // creating a network interface when launching an instance. - Groups []*string `locationName:"SecurityGroupId" locationNameList:"SecurityGroupId" type:"list"` - - // The ID of the network interface. - NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string"` - - // The private IP address of the network interface. Applies only if creating - // a network interface when launching an instance. - PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` - - // One or more private IP addresses to assign to the network interface. Only - // one private IP address can be designated as primary. - PrivateIpAddresses []*PrivateIpAddressSpecification `locationName:"privateIpAddressesSet" queryName:"PrivateIpAddresses" locationNameList:"item" type:"list"` - - // The number of secondary private IP addresses. You can't specify this option - // and specify more than one private IP address using the private IP addresses - // option. - SecondaryPrivateIpAddressCount *int64 `locationName:"secondaryPrivateIpAddressCount" type:"integer"` - - // The ID of the subnet associated with the network string. Applies only if - // creating a network interface when launching an instance. - SubnetId *string `locationName:"subnetId" type:"string"` - - metadataInstanceNetworkInterfaceSpecification `json:"-" xml:"-"` -} - -type metadataInstanceNetworkInterfaceSpecification struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s InstanceNetworkInterfaceSpecification) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s InstanceNetworkInterfaceSpecification) GoString() string { - return s.String() -} - -// Describes a private IP address. -type InstancePrivateIpAddress struct { - // The association information for an Elastic IP address for the network interface. - Association *InstanceNetworkInterfaceAssociation `locationName:"association" type:"structure"` - - // Indicates whether this IP address is the primary private IP address of the - // network interface. - Primary *bool `locationName:"primary" type:"boolean"` - - // The private DNS name. - PrivateDnsName *string `locationName:"privateDnsName" type:"string"` - - // The private IP address of the network interface. - PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` - - metadataInstancePrivateIpAddress `json:"-" xml:"-"` -} - -type metadataInstancePrivateIpAddress struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s InstancePrivateIpAddress) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s InstancePrivateIpAddress) GoString() string { - return s.String() -} - -// Describes the current state of the instance. -type InstanceState struct { - // The low byte represents the state. The high byte is an opaque internal value - // and should be ignored. - // - // 0 : pending - // - // 16 : running - // - // 32 : shutting-down - // - // 48 : terminated - // - // 64 : stopping - // - // 80 : stopped - Code *int64 `locationName:"code" type:"integer"` - - // The current state of the instance. - Name *string `locationName:"name" type:"string" enum:"InstanceStateName"` - - metadataInstanceState `json:"-" xml:"-"` -} - -type metadataInstanceState struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s InstanceState) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s InstanceState) GoString() string { - return s.String() -} - -// Describes an instance state change. -type InstanceStateChange struct { - // The current state of the instance. - CurrentState *InstanceState `locationName:"currentState" type:"structure"` - - // The ID of the instance. - InstanceId *string `locationName:"instanceId" type:"string"` - - // The previous state of the instance. - PreviousState *InstanceState `locationName:"previousState" type:"structure"` - - metadataInstanceStateChange `json:"-" xml:"-"` -} - -type metadataInstanceStateChange struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s InstanceStateChange) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s InstanceStateChange) GoString() string { - return s.String() -} - -// Describes the status of an instance. -type InstanceStatus struct { - // The Availability Zone of the instance. - AvailabilityZone *string `locationName:"availabilityZone" type:"string"` - - // Any scheduled events associated with the instance. - Events []*InstanceStatusEvent `locationName:"eventsSet" locationNameList:"item" type:"list"` - - // The ID of the instance. - InstanceId *string `locationName:"instanceId" type:"string"` - - // The intended state of the instance. DescribeInstanceStatus requires that - // an instance be in the running state. - InstanceState *InstanceState `locationName:"instanceState" type:"structure"` - - // Reports impaired functionality that stems from issues internal to the instance, - // such as impaired reachability. - InstanceStatus *InstanceStatusSummary `locationName:"instanceStatus" type:"structure"` - - // Reports impaired functionality that stems from issues related to the systems - // that support an instance, such as hardware failures and network connectivity - // problems. - SystemStatus *InstanceStatusSummary `locationName:"systemStatus" type:"structure"` - - metadataInstanceStatus `json:"-" xml:"-"` -} - -type metadataInstanceStatus struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s InstanceStatus) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s InstanceStatus) GoString() string { - return s.String() -} - -// Describes the instance status. -type InstanceStatusDetails struct { - // The time when a status check failed. For an instance that was launched and - // impaired, this is the time when the instance was launched. - ImpairedSince *time.Time `locationName:"impairedSince" type:"timestamp" timestampFormat:"iso8601"` - - // The type of instance status. - Name *string `locationName:"name" type:"string" enum:"StatusName"` - - // The status. - Status *string `locationName:"status" type:"string" enum:"StatusType"` - - metadataInstanceStatusDetails `json:"-" xml:"-"` -} - -type metadataInstanceStatusDetails struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s InstanceStatusDetails) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s InstanceStatusDetails) GoString() string { - return s.String() -} - -// Describes a scheduled event for an instance. -type InstanceStatusEvent struct { - // The event code. - Code *string `locationName:"code" type:"string" enum:"EventCode"` - - // A description of the event. - // - // After a scheduled event is completed, it can still be described for up to - // a week. If the event has been completed, this description starts with the - // following text: [Completed]. - Description *string `locationName:"description" type:"string"` - - // The latest scheduled end time for the event. - NotAfter *time.Time `locationName:"notAfter" type:"timestamp" timestampFormat:"iso8601"` - - // The earliest scheduled start time for the event. - NotBefore *time.Time `locationName:"notBefore" type:"timestamp" timestampFormat:"iso8601"` - - metadataInstanceStatusEvent `json:"-" xml:"-"` -} - -type metadataInstanceStatusEvent struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s InstanceStatusEvent) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s InstanceStatusEvent) GoString() string { - return s.String() -} - -// Describes the status of an instance. -type InstanceStatusSummary struct { - // The system instance health or application instance health. - Details []*InstanceStatusDetails `locationName:"details" locationNameList:"item" type:"list"` - - // The status. - Status *string `locationName:"status" type:"string" enum:"SummaryStatus"` - - metadataInstanceStatusSummary `json:"-" xml:"-"` -} - -type metadataInstanceStatusSummary struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s InstanceStatusSummary) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s InstanceStatusSummary) GoString() string { - return s.String() -} - -// Describes an Internet gateway. -type InternetGateway struct { - // Any VPCs attached to the Internet gateway. - Attachments []*InternetGatewayAttachment `locationName:"attachmentSet" locationNameList:"item" type:"list"` - - // The ID of the Internet gateway. - InternetGatewayId *string `locationName:"internetGatewayId" type:"string"` - - // Any tags assigned to the Internet gateway. - Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - metadataInternetGateway `json:"-" xml:"-"` -} - -type metadataInternetGateway struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s InternetGateway) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s InternetGateway) GoString() string { - return s.String() -} - -// Describes the attachment of a VPC to an Internet gateway. -type InternetGatewayAttachment struct { - // The current state of the attachment. - State *string `locationName:"state" type:"string" enum:"AttachmentStatus"` - - // The ID of the VPC. - VpcId *string `locationName:"vpcId" type:"string"` - - metadataInternetGatewayAttachment `json:"-" xml:"-"` -} - -type metadataInternetGatewayAttachment struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s InternetGatewayAttachment) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s InternetGatewayAttachment) GoString() string { - return s.String() -} - -// Describes a security group rule. -type IpPermission struct { - // The start of port range for the TCP and UDP protocols, or an ICMP type number. - // A value of -1 indicates all ICMP types. - FromPort *int64 `locationName:"fromPort" type:"integer"` - - // The protocol. - // - // When you call DescribeSecurityGroups, the protocol value returned is the - // number. Exception: For TCP, UDP, and ICMP, the value returned is the name - // (for example, tcp, udp, or icmp). For a list of protocol numbers, see Protocol - // Numbers (http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml). - // (VPC only) When you call AuthorizeSecurityGroupIngress, you can use -1 to - // specify all. - IpProtocol *string `locationName:"ipProtocol" type:"string"` - - // One or more IP ranges. - IpRanges []*IpRange `locationName:"ipRanges" locationNameList:"item" type:"list"` - - // (Valid for AuthorizeSecurityGroupEgress, RevokeSecurityGroupEgress and DescribeSecurityGroups - // only) One or more prefix list IDs for an AWS service. In an AuthorizeSecurityGroupEgress - // request, this is the AWS service that you want to access through a VPC endpoint - // from instances associated with the security group. - PrefixListIds []*PrefixListId `locationName:"prefixListIds" locationNameList:"item" type:"list"` - - // The end of port range for the TCP and UDP protocols, or an ICMP code. A value - // of -1 indicates all ICMP codes for the specified ICMP type. - ToPort *int64 `locationName:"toPort" type:"integer"` - - // One or more security group and AWS account ID pairs. - UserIdGroupPairs []*UserIdGroupPair `locationName:"groups" locationNameList:"item" type:"list"` - - metadataIpPermission `json:"-" xml:"-"` -} - -type metadataIpPermission struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s IpPermission) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s IpPermission) GoString() string { - return s.String() -} - -// Describes an IP range. -type IpRange struct { - // The CIDR range. You can either specify a CIDR range or a source security - // group, not both. - CidrIp *string `locationName:"cidrIp" type:"string"` - - metadataIpRange `json:"-" xml:"-"` -} - -type metadataIpRange struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s IpRange) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s IpRange) GoString() string { - return s.String() -} - -// Describes a key pair. -type KeyPairInfo struct { - // If you used CreateKeyPair to create the key pair, this is the SHA-1 digest - // of the DER encoded private key. If you used ImportKeyPair to provide AWS - // the public key, this is the MD5 public key fingerprint as specified in section - // 4 of RFC4716. - KeyFingerprint *string `locationName:"keyFingerprint" type:"string"` - - // The name of the key pair. - KeyName *string `locationName:"keyName" type:"string"` - - metadataKeyPairInfo `json:"-" xml:"-"` -} - -type metadataKeyPairInfo struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s KeyPairInfo) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s KeyPairInfo) GoString() string { - return s.String() -} - -// Describes a launch permission. -type LaunchPermission struct { - // The name of the group. - Group *string `locationName:"group" type:"string" enum:"PermissionGroup"` - - // The AWS account ID. - UserId *string `locationName:"userId" type:"string"` - - metadataLaunchPermission `json:"-" xml:"-"` -} - -type metadataLaunchPermission struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s LaunchPermission) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s LaunchPermission) GoString() string { - return s.String() -} - -// Describes a launch permission modification. -type LaunchPermissionModifications struct { - // The AWS account ID to add to the list of launch permissions for the AMI. - Add []*LaunchPermission `locationNameList:"item" type:"list"` - - // The AWS account ID to remove from the list of launch permissions for the - // AMI. - Remove []*LaunchPermission `locationNameList:"item" type:"list"` - - metadataLaunchPermissionModifications `json:"-" xml:"-"` -} - -type metadataLaunchPermissionModifications struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s LaunchPermissionModifications) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s LaunchPermissionModifications) GoString() string { - return s.String() -} - -// Describes the launch specification for an instance. -type LaunchSpecification struct { - // Deprecated. - AddressingType *string `locationName:"addressingType" type:"string"` - - // One or more block device mapping entries. - BlockDeviceMappings []*BlockDeviceMapping `locationName:"blockDeviceMapping" locationNameList:"item" type:"list"` - - // Indicates whether the instance is optimized for EBS I/O. This optimization - // provides dedicated throughput to Amazon EBS and an optimized configuration - // stack to provide optimal EBS I/O performance. This optimization isn't available - // with all instance types. Additional usage charges apply when using an EBS - // Optimized instance. - // - // Default: false - EbsOptimized *bool `locationName:"ebsOptimized" type:"boolean"` - - // The IAM instance profile. - IamInstanceProfile *IamInstanceProfileSpecification `locationName:"iamInstanceProfile" type:"structure"` - - // The ID of the AMI. - ImageId *string `locationName:"imageId" type:"string"` - - // The instance type. - InstanceType *string `locationName:"instanceType" type:"string" enum:"InstanceType"` - - // The ID of the kernel. - KernelId *string `locationName:"kernelId" type:"string"` - - // The name of the key pair. - KeyName *string `locationName:"keyName" type:"string"` - - // Describes the monitoring for the instance. - Monitoring *RunInstancesMonitoringEnabled `locationName:"monitoring" type:"structure"` - - // One or more network interfaces. - NetworkInterfaces []*InstanceNetworkInterfaceSpecification `locationName:"networkInterfaceSet" locationNameList:"item" type:"list"` - - // The placement information for the instance. - Placement *SpotPlacement `locationName:"placement" type:"structure"` - - // The ID of the RAM disk. - RamdiskId *string `locationName:"ramdiskId" type:"string"` - - // One or more security groups. When requesting instances in a VPC, you must - // specify the IDs of the security groups. When requesting instances in EC2-Classic, - // you can specify the names or the IDs of the security groups. - SecurityGroups []*GroupIdentifier `locationName:"groupSet" locationNameList:"item" type:"list"` - - // The ID of the subnet in which to launch the instance. - SubnetId *string `locationName:"subnetId" type:"string"` - - // The Base64-encoded MIME user data to make available to the instances. - UserData *string `locationName:"userData" type:"string"` - - metadataLaunchSpecification `json:"-" xml:"-"` -} - -type metadataLaunchSpecification struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s LaunchSpecification) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s LaunchSpecification) GoString() string { - return s.String() -} - -type ModifyImageAttributeInput struct { - // The name of the attribute to modify. - Attribute *string `type:"string"` - - // A description for the AMI. - Description *AttributeValue `type:"structure"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the AMI. - ImageId *string `type:"string" required:"true"` - - // A launch permission modification. - LaunchPermission *LaunchPermissionModifications `type:"structure"` - - // The operation type. - OperationType *string `type:"string" enum:"OperationType"` - - // One or more product codes. After you add a product code to an AMI, it can't - // be removed. This is only valid when modifying the productCodes attribute. - ProductCodes []*string `locationName:"ProductCode" locationNameList:"ProductCode" type:"list"` - - // One or more user groups. This is only valid when modifying the launchPermission - // attribute. - UserGroups []*string `locationName:"UserGroup" locationNameList:"UserGroup" type:"list"` - - // One or more AWS account IDs. This is only valid when modifying the launchPermission - // attribute. - UserIds []*string `locationName:"UserId" locationNameList:"UserId" type:"list"` - - // The value of the attribute being modified. This is only valid when modifying - // the description attribute. - Value *string `type:"string"` - - metadataModifyImageAttributeInput `json:"-" xml:"-"` -} - -type metadataModifyImageAttributeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ModifyImageAttributeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ModifyImageAttributeInput) GoString() string { - return s.String() -} - -type ModifyImageAttributeOutput struct { - metadataModifyImageAttributeOutput `json:"-" xml:"-"` -} - -type metadataModifyImageAttributeOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ModifyImageAttributeOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ModifyImageAttributeOutput) GoString() string { - return s.String() -} - -type ModifyInstanceAttributeInput struct { - // The name of the attribute. - Attribute *string `locationName:"attribute" type:"string" enum:"InstanceAttributeName"` - - // Modifies the DeleteOnTermination attribute for volumes that are currently - // attached. The volume must be owned by the caller. If no value is specified - // for DeleteOnTermination, the default is true and the volume is deleted when - // the instance is terminated. - // - // To add instance store volumes to an Amazon EBS-backed instance, you must - // add them when you launch the instance. For more information, see Updating - // the Block Device Mapping when Launching an Instance (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concepts.html#Using_OverridingAMIBDM) - // in the Amazon Elastic Compute Cloud User Guide. - BlockDeviceMappings []*InstanceBlockDeviceMappingSpecification `locationName:"blockDeviceMapping" locationNameList:"item" type:"list"` - - // If the value is true, you can't terminate the instance using the Amazon EC2 - // console, CLI, or API; otherwise, you can. You cannot use this paramater for - // Spot Instances. - DisableApiTermination *AttributeBooleanValue `locationName:"disableApiTermination" type:"structure"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // Specifies whether the instance is optimized for EBS I/O. This optimization - // provides dedicated throughput to Amazon EBS and an optimized configuration - // stack to provide optimal EBS I/O performance. This optimization isn't available - // with all instance types. Additional usage charges apply when using an EBS - // Optimized instance. - EbsOptimized *AttributeBooleanValue `locationName:"ebsOptimized" type:"structure"` - - // [EC2-VPC] Changes the security groups of the instance. You must specify at - // least one security group, even if it's just the default security group for - // the VPC. You must specify the security group ID, not the security group name. - Groups []*string `locationName:"GroupId" locationNameList:"groupId" type:"list"` - - // The ID of the instance. - InstanceId *string `locationName:"instanceId" type:"string" required:"true"` - - // Specifies whether an instance stops or terminates when you initiate shutdown - // from the instance (using the operating system command for system shutdown). - InstanceInitiatedShutdownBehavior *AttributeValue `locationName:"instanceInitiatedShutdownBehavior" type:"structure"` - - // Changes the instance type to the specified value. For more information, see - // Instance Types (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html). - // If the instance type is not valid, the error returned is InvalidInstanceAttributeValue. - InstanceType *AttributeValue `locationName:"instanceType" type:"structure"` - - // Changes the instance's kernel to the specified value. We recommend that you - // use PV-GRUB instead of kernels and RAM disks. For more information, see PV-GRUB - // (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/UserProvidedKernels.html). - Kernel *AttributeValue `locationName:"kernel" type:"structure"` - - // Changes the instance's RAM disk to the specified value. We recommend that - // you use PV-GRUB instead of kernels and RAM disks. For more information, see - // PV-GRUB (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/UserProvidedKernels.html). - Ramdisk *AttributeValue `locationName:"ramdisk" type:"structure"` - - // Specifies whether source/destination checking is enabled. A value of true - // means that checking is enabled, and false means checking is disabled. This - // value must be false for a NAT instance to perform NAT. - SourceDestCheck *AttributeBooleanValue `type:"structure"` - - // Set to simple to enable enhanced networking for the instance. - // - // There is no way to disable enhanced networking at this time. - // - // This option is supported only for HVM instances. Specifying this option - // with a PV instance can make it unreachable. - SriovNetSupport *AttributeValue `locationName:"sriovNetSupport" type:"structure"` - - // Changes the instance's user data to the specified value. - UserData *BlobAttributeValue `locationName:"userData" type:"structure"` - - // A new value for the attribute. Use only with the kernel, ramdisk, userData, - // disableApiTermination, or instanceInitiatedShutdownBehavior attribute. - Value *string `locationName:"value" type:"string"` - - metadataModifyInstanceAttributeInput `json:"-" xml:"-"` -} - -type metadataModifyInstanceAttributeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ModifyInstanceAttributeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ModifyInstanceAttributeInput) GoString() string { - return s.String() -} - -type ModifyInstanceAttributeOutput struct { - metadataModifyInstanceAttributeOutput `json:"-" xml:"-"` -} - -type metadataModifyInstanceAttributeOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ModifyInstanceAttributeOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ModifyInstanceAttributeOutput) GoString() string { - return s.String() -} - -type ModifyNetworkInterfaceAttributeInput struct { - // Information about the interface attachment. If modifying the 'delete on termination' - // attribute, you must specify the ID of the interface attachment. - Attachment *NetworkInterfaceAttachmentChanges `locationName:"attachment" type:"structure"` - - // A description for the network interface. - Description *AttributeValue `locationName:"description" type:"structure"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // Changes the security groups for the network interface. The new set of groups - // you specify replaces the current set. You must specify at least one group, - // even if it's just the default security group in the VPC. You must specify - // the ID of the security group, not the name. - Groups []*string `locationName:"SecurityGroupId" locationNameList:"SecurityGroupId" type:"list"` - - // The ID of the network interface. - NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string" required:"true"` - - // Indicates whether source/destination checking is enabled. A value of true - // means checking is enabled, and false means checking is disabled. This value - // must be false for a NAT instance to perform NAT. For more information, see - // NAT Instances (http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_NAT_Instance.html) - // in the Amazon Virtual Private Cloud User Guide. - SourceDestCheck *AttributeBooleanValue `locationName:"sourceDestCheck" type:"structure"` - - metadataModifyNetworkInterfaceAttributeInput `json:"-" xml:"-"` -} - -type metadataModifyNetworkInterfaceAttributeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ModifyNetworkInterfaceAttributeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ModifyNetworkInterfaceAttributeInput) GoString() string { - return s.String() -} - -type ModifyNetworkInterfaceAttributeOutput struct { - metadataModifyNetworkInterfaceAttributeOutput `json:"-" xml:"-"` -} - -type metadataModifyNetworkInterfaceAttributeOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ModifyNetworkInterfaceAttributeOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ModifyNetworkInterfaceAttributeOutput) GoString() string { - return s.String() -} - -type ModifyReservedInstancesInput struct { - // A unique, case-sensitive token you provide to ensure idempotency of your - // modification request. For more information, see Ensuring Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/APIReference/Run_Instance_Idempotency.html). - ClientToken *string `locationName:"clientToken" type:"string"` - - // The IDs of the Reserved Instances to modify. - ReservedInstancesIds []*string `locationName:"ReservedInstancesId" locationNameList:"ReservedInstancesId" type:"list" required:"true"` - - // The configuration settings for the Reserved Instances to modify. - TargetConfigurations []*ReservedInstancesConfiguration `locationName:"ReservedInstancesConfigurationSetItemType" locationNameList:"item" type:"list" required:"true"` - - metadataModifyReservedInstancesInput `json:"-" xml:"-"` -} - -type metadataModifyReservedInstancesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ModifyReservedInstancesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ModifyReservedInstancesInput) GoString() string { - return s.String() -} - -type ModifyReservedInstancesOutput struct { - // The ID for the modification. - ReservedInstancesModificationId *string `locationName:"reservedInstancesModificationId" type:"string"` - - metadataModifyReservedInstancesOutput `json:"-" xml:"-"` -} - -type metadataModifyReservedInstancesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ModifyReservedInstancesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ModifyReservedInstancesOutput) GoString() string { - return s.String() -} - -type ModifySnapshotAttributeInput struct { - // The snapshot attribute to modify. - // - // Only volume creation permissions may be modified at the customer level. - Attribute *string `type:"string" enum:"SnapshotAttributeName"` - - // A JSON representation of the snapshot attribute modification. - CreateVolumePermission *CreateVolumePermissionModifications `type:"structure"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The group to modify for the snapshot. - GroupNames []*string `locationName:"UserGroup" locationNameList:"GroupName" type:"list"` - - // The type of operation to perform to the attribute. - OperationType *string `type:"string" enum:"OperationType"` - - // The ID of the snapshot. - SnapshotId *string `type:"string" required:"true"` - - // The account ID to modify for the snapshot. - UserIds []*string `locationName:"UserId" locationNameList:"UserId" type:"list"` - - metadataModifySnapshotAttributeInput `json:"-" xml:"-"` -} - -type metadataModifySnapshotAttributeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ModifySnapshotAttributeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ModifySnapshotAttributeInput) GoString() string { - return s.String() -} - -type ModifySnapshotAttributeOutput struct { - metadataModifySnapshotAttributeOutput `json:"-" xml:"-"` -} - -type metadataModifySnapshotAttributeOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ModifySnapshotAttributeOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ModifySnapshotAttributeOutput) GoString() string { - return s.String() -} - -// Contains the parameters for ModifySpotFleetRequest. -type ModifySpotFleetRequestInput struct { - // Indicates whether running Spot instances should be terminated if the target - // capacity of the Spot fleet request is decreased below the current size of - // the Spot fleet. - ExcessCapacityTerminationPolicy *string `locationName:"excessCapacityTerminationPolicy" type:"string" enum:"ExcessCapacityTerminationPolicy"` - - // The ID of the Spot fleet request. - SpotFleetRequestId *string `locationName:"spotFleetRequestId" type:"string" required:"true"` - - // The size of the fleet. - TargetCapacity *int64 `locationName:"targetCapacity" type:"integer"` - - metadataModifySpotFleetRequestInput `json:"-" xml:"-"` -} - -type metadataModifySpotFleetRequestInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ModifySpotFleetRequestInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ModifySpotFleetRequestInput) GoString() string { - return s.String() -} - -// Contains the output of ModifySpotFleetRequest. -type ModifySpotFleetRequestOutput struct { - // Is true if the request succeeds, and an error otherwise. - Return *bool `locationName:"return" type:"boolean"` - - metadataModifySpotFleetRequestOutput `json:"-" xml:"-"` -} - -type metadataModifySpotFleetRequestOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ModifySpotFleetRequestOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ModifySpotFleetRequestOutput) GoString() string { - return s.String() -} - -type ModifySubnetAttributeInput struct { - // Specify true to indicate that instances launched into the specified subnet - // should be assigned public IP address. - MapPublicIpOnLaunch *AttributeBooleanValue `type:"structure"` - - // The ID of the subnet. - SubnetId *string `locationName:"subnetId" type:"string" required:"true"` - - metadataModifySubnetAttributeInput `json:"-" xml:"-"` -} - -type metadataModifySubnetAttributeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ModifySubnetAttributeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ModifySubnetAttributeInput) GoString() string { - return s.String() -} - -type ModifySubnetAttributeOutput struct { - metadataModifySubnetAttributeOutput `json:"-" xml:"-"` -} - -type metadataModifySubnetAttributeOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ModifySubnetAttributeOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ModifySubnetAttributeOutput) GoString() string { - return s.String() -} - -type ModifyVolumeAttributeInput struct { - // Indicates whether the volume should be auto-enabled for I/O operations. - AutoEnableIO *AttributeBooleanValue `type:"structure"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the volume. - VolumeId *string `type:"string" required:"true"` - - metadataModifyVolumeAttributeInput `json:"-" xml:"-"` -} - -type metadataModifyVolumeAttributeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ModifyVolumeAttributeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ModifyVolumeAttributeInput) GoString() string { - return s.String() -} - -type ModifyVolumeAttributeOutput struct { - metadataModifyVolumeAttributeOutput `json:"-" xml:"-"` -} - -type metadataModifyVolumeAttributeOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ModifyVolumeAttributeOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ModifyVolumeAttributeOutput) GoString() string { - return s.String() -} - -type ModifyVpcAttributeInput struct { - // Indicates whether the instances launched in the VPC get DNS hostnames. If - // enabled, instances in the VPC get DNS hostnames; otherwise, they do not. - // - // You cannot modify the DNS resolution and DNS hostnames attributes in the - // same request. Use separate requests for each attribute. You can only enable - // DNS hostnames if you've enabled DNS support. - EnableDnsHostnames *AttributeBooleanValue `type:"structure"` - - // Indicates whether the DNS resolution is supported for the VPC. If enabled, - // queries to the Amazon provided DNS server at the 169.254.169.253 IP address, - // or the reserved IP address at the base of the VPC network range "plus two" - // will succeed. If disabled, the Amazon provided DNS service in the VPC that - // resolves public DNS hostnames to IP addresses is not enabled. - // - // You cannot modify the DNS resolution and DNS hostnames attributes in the - // same request. Use separate requests for each attribute. - EnableDnsSupport *AttributeBooleanValue `type:"structure"` - - // The ID of the VPC. - VpcId *string `locationName:"vpcId" type:"string" required:"true"` - - metadataModifyVpcAttributeInput `json:"-" xml:"-"` -} - -type metadataModifyVpcAttributeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ModifyVpcAttributeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ModifyVpcAttributeInput) GoString() string { - return s.String() -} - -type ModifyVpcAttributeOutput struct { - metadataModifyVpcAttributeOutput `json:"-" xml:"-"` -} - -type metadataModifyVpcAttributeOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ModifyVpcAttributeOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ModifyVpcAttributeOutput) GoString() string { - return s.String() -} - -type ModifyVpcEndpointInput struct { - // One or more route tables IDs to associate with the endpoint. - AddRouteTableIds []*string `locationName:"AddRouteTableId" locationNameList:"item" type:"list"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `type:"boolean"` - - // A policy document to attach to the endpoint. The policy must be in valid - // JSON format. - PolicyDocument *string `type:"string"` - - // One or more route table IDs to disassociate from the endpoint. - RemoveRouteTableIds []*string `locationName:"RemoveRouteTableId" locationNameList:"item" type:"list"` - - // Specify true to reset the policy document to the default policy. The default - // policy allows access to the service. - ResetPolicy *bool `type:"boolean"` - - // The ID of the endpoint. - VpcEndpointId *string `type:"string" required:"true"` - - metadataModifyVpcEndpointInput `json:"-" xml:"-"` -} - -type metadataModifyVpcEndpointInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ModifyVpcEndpointInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ModifyVpcEndpointInput) GoString() string { - return s.String() -} - -type ModifyVpcEndpointOutput struct { - // Returns true if the request succeeds; otherwise, it returns an error. - Return *bool `locationName:"return" type:"boolean"` - - metadataModifyVpcEndpointOutput `json:"-" xml:"-"` -} - -type metadataModifyVpcEndpointOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ModifyVpcEndpointOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ModifyVpcEndpointOutput) GoString() string { - return s.String() -} - -type MonitorInstancesInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more instance IDs. - InstanceIds []*string `locationName:"InstanceId" locationNameList:"InstanceId" type:"list" required:"true"` - - metadataMonitorInstancesInput `json:"-" xml:"-"` -} - -type metadataMonitorInstancesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s MonitorInstancesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s MonitorInstancesInput) GoString() string { - return s.String() -} - -type MonitorInstancesOutput struct { - // Monitoring information for one or more instances. - InstanceMonitorings []*InstanceMonitoring `locationName:"instancesSet" locationNameList:"item" type:"list"` - - metadataMonitorInstancesOutput `json:"-" xml:"-"` -} - -type metadataMonitorInstancesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s MonitorInstancesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s MonitorInstancesOutput) GoString() string { - return s.String() -} - -// Describes the monitoring for the instance. -type Monitoring struct { - // Indicates whether monitoring is enabled for the instance. - State *string `locationName:"state" type:"string" enum:"MonitoringState"` - - metadataMonitoring `json:"-" xml:"-"` -} - -type metadataMonitoring struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s Monitoring) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s Monitoring) GoString() string { - return s.String() -} - -type MoveAddressToVpcInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The Elastic IP address. - PublicIp *string `locationName:"publicIp" type:"string" required:"true"` - - metadataMoveAddressToVpcInput `json:"-" xml:"-"` -} - -type metadataMoveAddressToVpcInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s MoveAddressToVpcInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s MoveAddressToVpcInput) GoString() string { - return s.String() -} - -type MoveAddressToVpcOutput struct { - // The allocation ID for the Elastic IP address. - AllocationId *string `locationName:"allocationId" type:"string"` - - // The status of the move of the IP address. - Status *string `locationName:"status" type:"string" enum:"Status"` - - metadataMoveAddressToVpcOutput `json:"-" xml:"-"` -} - -type metadataMoveAddressToVpcOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s MoveAddressToVpcOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s MoveAddressToVpcOutput) GoString() string { - return s.String() -} - -// Describes the status of a moving Elastic IP address. -type MovingAddressStatus struct { - // The status of the Elastic IP address that's being moved to the EC2-VPC platform, - // or restored to the EC2-Classic platform. - MoveStatus *string `locationName:"moveStatus" type:"string" enum:"MoveStatus"` - - // The Elastic IP address. - PublicIp *string `locationName:"publicIp" type:"string"` - - metadataMovingAddressStatus `json:"-" xml:"-"` -} - -type metadataMovingAddressStatus struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s MovingAddressStatus) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s MovingAddressStatus) GoString() string { - return s.String() -} - -// Describes a network ACL. -type NetworkAcl struct { - // Any associations between the network ACL and one or more subnets - Associations []*NetworkAclAssociation `locationName:"associationSet" locationNameList:"item" type:"list"` - - // One or more entries (rules) in the network ACL. - Entries []*NetworkAclEntry `locationName:"entrySet" locationNameList:"item" type:"list"` - - // Indicates whether this is the default network ACL for the VPC. - IsDefault *bool `locationName:"default" type:"boolean"` - - // The ID of the network ACL. - NetworkAclId *string `locationName:"networkAclId" type:"string"` - - // Any tags assigned to the network ACL. - Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - // The ID of the VPC for the network ACL. - VpcId *string `locationName:"vpcId" type:"string"` - - metadataNetworkAcl `json:"-" xml:"-"` -} - -type metadataNetworkAcl struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s NetworkAcl) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s NetworkAcl) GoString() string { - return s.String() -} - -// Describes an association between a network ACL and a subnet. -type NetworkAclAssociation struct { - // The ID of the association between a network ACL and a subnet. - NetworkAclAssociationId *string `locationName:"networkAclAssociationId" type:"string"` - - // The ID of the network ACL. - NetworkAclId *string `locationName:"networkAclId" type:"string"` - - // The ID of the subnet. - SubnetId *string `locationName:"subnetId" type:"string"` - - metadataNetworkAclAssociation `json:"-" xml:"-"` -} - -type metadataNetworkAclAssociation struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s NetworkAclAssociation) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s NetworkAclAssociation) GoString() string { - return s.String() -} - -// Describes an entry in a network ACL. -type NetworkAclEntry struct { - // The network range to allow or deny, in CIDR notation. - CidrBlock *string `locationName:"cidrBlock" type:"string"` - - // Indicates whether the rule is an egress rule (applied to traffic leaving - // the subnet). - Egress *bool `locationName:"egress" type:"boolean"` - - // ICMP protocol: The ICMP type and code. - IcmpTypeCode *IcmpTypeCode `locationName:"icmpTypeCode" type:"structure"` - - // TCP or UDP protocols: The range of ports the rule applies to. - PortRange *PortRange `locationName:"portRange" type:"structure"` - - // The protocol. A value of -1 means all protocols. - Protocol *string `locationName:"protocol" type:"string"` - - // Indicates whether to allow or deny the traffic that matches the rule. - RuleAction *string `locationName:"ruleAction" type:"string" enum:"RuleAction"` - - // The rule number for the entry. ACL entries are processed in ascending order - // by rule number. - RuleNumber *int64 `locationName:"ruleNumber" type:"integer"` - - metadataNetworkAclEntry `json:"-" xml:"-"` -} - -type metadataNetworkAclEntry struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s NetworkAclEntry) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s NetworkAclEntry) GoString() string { - return s.String() -} - -// Describes a network interface. -type NetworkInterface struct { - // The association information for an Elastic IP associated with the network - // interface. - Association *NetworkInterfaceAssociation `locationName:"association" type:"structure"` - - // The network interface attachment. - Attachment *NetworkInterfaceAttachment `locationName:"attachment" type:"structure"` - - // The Availability Zone. - AvailabilityZone *string `locationName:"availabilityZone" type:"string"` - - // A description. - Description *string `locationName:"description" type:"string"` - - // Any security groups for the network interface. - Groups []*GroupIdentifier `locationName:"groupSet" locationNameList:"item" type:"list"` - - // The MAC address. - MacAddress *string `locationName:"macAddress" type:"string"` - - // The ID of the network interface. - NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string"` - - // The AWS account ID of the owner of the network interface. - OwnerId *string `locationName:"ownerId" type:"string"` - - // The private DNS name. - PrivateDnsName *string `locationName:"privateDnsName" type:"string"` - - // The IP address of the network interface within the subnet. - PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` - - // The private IP addresses associated with the network interface. - PrivateIpAddresses []*NetworkInterfacePrivateIpAddress `locationName:"privateIpAddressesSet" locationNameList:"item" type:"list"` - - // The ID of the entity that launched the instance on your behalf (for example, - // AWS Management Console or Auto Scaling). - RequesterId *string `locationName:"requesterId" type:"string"` - - // Indicates whether the network interface is being managed by AWS. - RequesterManaged *bool `locationName:"requesterManaged" type:"boolean"` - - // Indicates whether traffic to or from the instance is validated. - SourceDestCheck *bool `locationName:"sourceDestCheck" type:"boolean"` - - // The status of the network interface. - Status *string `locationName:"status" type:"string" enum:"NetworkInterfaceStatus"` - - // The ID of the subnet. - SubnetId *string `locationName:"subnetId" type:"string"` - - // Any tags assigned to the network interface. - TagSet []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - // The ID of the VPC. - VpcId *string `locationName:"vpcId" type:"string"` - - metadataNetworkInterface `json:"-" xml:"-"` -} - -type metadataNetworkInterface struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s NetworkInterface) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s NetworkInterface) GoString() string { - return s.String() -} - -// Describes association information for an Elastic IP address. -type NetworkInterfaceAssociation struct { - // The allocation ID. - AllocationId *string `locationName:"allocationId" type:"string"` - - // The association ID. - AssociationId *string `locationName:"associationId" type:"string"` - - // The ID of the Elastic IP address owner. - IpOwnerId *string `locationName:"ipOwnerId" type:"string"` - - // The public DNS name. - PublicDnsName *string `locationName:"publicDnsName" type:"string"` - - // The address of the Elastic IP address bound to the network interface. - PublicIp *string `locationName:"publicIp" type:"string"` - - metadataNetworkInterfaceAssociation `json:"-" xml:"-"` -} - -type metadataNetworkInterfaceAssociation struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s NetworkInterfaceAssociation) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s NetworkInterfaceAssociation) GoString() string { - return s.String() -} - -// Describes a network interface attachment. -type NetworkInterfaceAttachment struct { - // The timestamp indicating when the attachment initiated. - AttachTime *time.Time `locationName:"attachTime" type:"timestamp" timestampFormat:"iso8601"` - - // The ID of the network interface attachment. - AttachmentId *string `locationName:"attachmentId" type:"string"` - - // Indicates whether the network interface is deleted when the instance is terminated. - DeleteOnTermination *bool `locationName:"deleteOnTermination" type:"boolean"` - - // The device index of the network interface attachment on the instance. - DeviceIndex *int64 `locationName:"deviceIndex" type:"integer"` - - // The ID of the instance. - InstanceId *string `locationName:"instanceId" type:"string"` - - // The AWS account ID of the owner of the instance. - InstanceOwnerId *string `locationName:"instanceOwnerId" type:"string"` - - // The attachment state. - Status *string `locationName:"status" type:"string" enum:"AttachmentStatus"` - - metadataNetworkInterfaceAttachment `json:"-" xml:"-"` -} - -type metadataNetworkInterfaceAttachment struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s NetworkInterfaceAttachment) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s NetworkInterfaceAttachment) GoString() string { - return s.String() -} - -// Describes an attachment change. -type NetworkInterfaceAttachmentChanges struct { - // The ID of the network interface attachment. - AttachmentId *string `locationName:"attachmentId" type:"string"` - - // Indicates whether the network interface is deleted when the instance is terminated. - DeleteOnTermination *bool `locationName:"deleteOnTermination" type:"boolean"` - - metadataNetworkInterfaceAttachmentChanges `json:"-" xml:"-"` -} - -type metadataNetworkInterfaceAttachmentChanges struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s NetworkInterfaceAttachmentChanges) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s NetworkInterfaceAttachmentChanges) GoString() string { - return s.String() -} - -// Describes the private IP address of a network interface. -type NetworkInterfacePrivateIpAddress struct { - // The association information for an Elastic IP address associated with the - // network interface. - Association *NetworkInterfaceAssociation `locationName:"association" type:"structure"` - - // Indicates whether this IP address is the primary private IP address of the - // network interface. - Primary *bool `locationName:"primary" type:"boolean"` - - // The private DNS name. - PrivateDnsName *string `locationName:"privateDnsName" type:"string"` - - // The private IP address. - PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` - - metadataNetworkInterfacePrivateIpAddress `json:"-" xml:"-"` -} - -type metadataNetworkInterfacePrivateIpAddress struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s NetworkInterfacePrivateIpAddress) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s NetworkInterfacePrivateIpAddress) GoString() string { - return s.String() -} - -type NewDhcpConfiguration struct { - Key *string `locationName:"key" type:"string"` - - Values []*string `locationName:"Value" locationNameList:"item" type:"list"` - - metadataNewDhcpConfiguration `json:"-" xml:"-"` -} - -type metadataNewDhcpConfiguration struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s NewDhcpConfiguration) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s NewDhcpConfiguration) GoString() string { - return s.String() -} - -// Describes the placement for the instance. -type Placement struct { - // The Availability Zone of the instance. - AvailabilityZone *string `locationName:"availabilityZone" type:"string"` - - // The name of the placement group the instance is in (for cluster compute instances). - GroupName *string `locationName:"groupName" type:"string"` - - // The tenancy of the instance (if the instance is running in a VPC). An instance - // with a tenancy of dedicated runs on single-tenant hardware. - Tenancy *string `locationName:"tenancy" type:"string" enum:"Tenancy"` - - metadataPlacement `json:"-" xml:"-"` -} - -type metadataPlacement struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s Placement) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s Placement) GoString() string { - return s.String() -} - -// Describes a placement group. -type PlacementGroup struct { - // The name of the placement group. - GroupName *string `locationName:"groupName" type:"string"` - - // The state of the placement group. - State *string `locationName:"state" type:"string" enum:"PlacementGroupState"` - - // The placement strategy. - Strategy *string `locationName:"strategy" type:"string" enum:"PlacementStrategy"` - - metadataPlacementGroup `json:"-" xml:"-"` -} - -type metadataPlacementGroup struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s PlacementGroup) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s PlacementGroup) GoString() string { - return s.String() -} - -// Describes a range of ports. -type PortRange struct { - // The first port in the range. - From *int64 `locationName:"from" type:"integer"` - - // The last port in the range. - To *int64 `locationName:"to" type:"integer"` - - metadataPortRange `json:"-" xml:"-"` -} - -type metadataPortRange struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s PortRange) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s PortRange) GoString() string { - return s.String() -} - -// Describes prefixes for AWS services. -type PrefixList struct { - // The IP address range of the AWS service. - Cidrs []*string `locationName:"cidrSet" locationNameList:"item" type:"list"` - - // The ID of the prefix. - PrefixListId *string `locationName:"prefixListId" type:"string"` - - // The name of the prefix. - PrefixListName *string `locationName:"prefixListName" type:"string"` - - metadataPrefixList `json:"-" xml:"-"` -} - -type metadataPrefixList struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s PrefixList) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s PrefixList) GoString() string { - return s.String() -} - -// The ID of the prefix. -type PrefixListId struct { - // The ID of the prefix. - PrefixListId *string `locationName:"prefixListId" type:"string"` - - metadataPrefixListId `json:"-" xml:"-"` -} - -type metadataPrefixListId struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s PrefixListId) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s PrefixListId) GoString() string { - return s.String() -} - -// Describes the price for a Reserved Instance. -type PriceSchedule struct { - // The current price schedule, as determined by the term remaining for the Reserved - // Instance in the listing. - // - // A specific price schedule is always in effect, but only one price schedule - // can be active at any time. Take, for example, a Reserved Instance listing - // that has five months remaining in its term. When you specify price schedules - // for five months and two months, this means that schedule 1, covering the - // first three months of the remaining term, will be active during months 5, - // 4, and 3. Then schedule 2, covering the last two months of the term, will - // be active for months 2 and 1. - Active *bool `locationName:"active" type:"boolean"` - - // The currency for transacting the Reserved Instance resale. At this time, - // the only supported currency is USD. - CurrencyCode *string `locationName:"currencyCode" type:"string" enum:"CurrencyCodeValues"` - - // The fixed price for the term. - Price *float64 `locationName:"price" type:"double"` - - // The number of months remaining in the reservation. For example, 2 is the - // second to the last month before the capacity reservation expires. - Term *int64 `locationName:"term" type:"long"` - - metadataPriceSchedule `json:"-" xml:"-"` -} - -type metadataPriceSchedule struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s PriceSchedule) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s PriceSchedule) GoString() string { - return s.String() -} - -// Describes the price for a Reserved Instance. -type PriceScheduleSpecification struct { - // The currency for transacting the Reserved Instance resale. At this time, - // the only supported currency is USD. - CurrencyCode *string `locationName:"currencyCode" type:"string" enum:"CurrencyCodeValues"` - - // The fixed price for the term. - Price *float64 `locationName:"price" type:"double"` - - // The number of months remaining in the reservation. For example, 2 is the - // second to the last month before the capacity reservation expires. - Term *int64 `locationName:"term" type:"long"` - - metadataPriceScheduleSpecification `json:"-" xml:"-"` -} - -type metadataPriceScheduleSpecification struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s PriceScheduleSpecification) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s PriceScheduleSpecification) GoString() string { - return s.String() -} - -// Describes a Reserved Instance offering. -type PricingDetail struct { - // The number of instances available for the price. - Count *int64 `locationName:"count" type:"integer"` - - // The price per instance. - Price *float64 `locationName:"price" type:"double"` - - metadataPricingDetail `json:"-" xml:"-"` -} - -type metadataPricingDetail struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s PricingDetail) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s PricingDetail) GoString() string { - return s.String() -} - -// Describes a secondary private IP address for a network interface. -type PrivateIpAddressSpecification struct { - // Indicates whether the private IP address is the primary private IP address. - // Only one IP address can be designated as primary. - Primary *bool `locationName:"primary" type:"boolean"` - - // The private IP addresses. - PrivateIpAddress *string `locationName:"privateIpAddress" type:"string" required:"true"` - - metadataPrivateIpAddressSpecification `json:"-" xml:"-"` -} - -type metadataPrivateIpAddressSpecification struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s PrivateIpAddressSpecification) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s PrivateIpAddressSpecification) GoString() string { - return s.String() -} - -// Describes a product code. -type ProductCode struct { - // The product code. - ProductCodeId *string `locationName:"productCode" type:"string"` - - // The type of product code. - ProductCodeType *string `locationName:"type" type:"string" enum:"ProductCodeValues"` - - metadataProductCode `json:"-" xml:"-"` -} - -type metadataProductCode struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ProductCode) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ProductCode) GoString() string { - return s.String() -} - -// Describes a virtual private gateway propagating route. -type PropagatingVgw struct { - // The ID of the virtual private gateway (VGW). - GatewayId *string `locationName:"gatewayId" type:"string"` - - metadataPropagatingVgw `json:"-" xml:"-"` -} - -type metadataPropagatingVgw struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s PropagatingVgw) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s PropagatingVgw) GoString() string { - return s.String() -} - -type PurchaseReservedInstancesOfferingInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The number of Reserved Instances to purchase. - InstanceCount *int64 `type:"integer" required:"true"` - - // Specified for Reserved Instance Marketplace offerings to limit the total - // order and ensure that the Reserved Instances are not purchased at unexpected - // prices. - LimitPrice *ReservedInstanceLimitPrice `locationName:"limitPrice" type:"structure"` - - // The ID of the Reserved Instance offering to purchase. - ReservedInstancesOfferingId *string `type:"string" required:"true"` - - metadataPurchaseReservedInstancesOfferingInput `json:"-" xml:"-"` -} - -type metadataPurchaseReservedInstancesOfferingInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s PurchaseReservedInstancesOfferingInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s PurchaseReservedInstancesOfferingInput) GoString() string { - return s.String() -} - -type PurchaseReservedInstancesOfferingOutput struct { - // The IDs of the purchased Reserved Instances. - ReservedInstancesId *string `locationName:"reservedInstancesId" type:"string"` - - metadataPurchaseReservedInstancesOfferingOutput `json:"-" xml:"-"` -} - -type metadataPurchaseReservedInstancesOfferingOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s PurchaseReservedInstancesOfferingOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s PurchaseReservedInstancesOfferingOutput) GoString() string { - return s.String() -} - -type RebootInstancesInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more instance IDs. - InstanceIds []*string `locationName:"InstanceId" locationNameList:"InstanceId" type:"list" required:"true"` - - metadataRebootInstancesInput `json:"-" xml:"-"` -} - -type metadataRebootInstancesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RebootInstancesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RebootInstancesInput) GoString() string { - return s.String() -} - -type RebootInstancesOutput struct { - metadataRebootInstancesOutput `json:"-" xml:"-"` -} - -type metadataRebootInstancesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RebootInstancesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RebootInstancesOutput) GoString() string { - return s.String() -} - -// Describes a recurring charge. -type RecurringCharge struct { - // The amount of the recurring charge. - Amount *float64 `locationName:"amount" type:"double"` - - // The frequency of the recurring charge. - Frequency *string `locationName:"frequency" type:"string" enum:"RecurringChargeFrequency"` - - metadataRecurringCharge `json:"-" xml:"-"` -} - -type metadataRecurringCharge struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RecurringCharge) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RecurringCharge) GoString() string { - return s.String() -} - -// Describes a region. -type Region struct { - // The region service endpoint. - Endpoint *string `locationName:"regionEndpoint" type:"string"` - - // The name of the region. - RegionName *string `locationName:"regionName" type:"string"` - - metadataRegion `json:"-" xml:"-"` -} - -type metadataRegion struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s Region) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s Region) GoString() string { - return s.String() -} - -type RegisterImageInput struct { - // The architecture of the AMI. - // - // Default: For Amazon EBS-backed AMIs, i386. For instance store-backed AMIs, - // the architecture specified in the manifest file. - Architecture *string `locationName:"architecture" type:"string" enum:"ArchitectureValues"` - - // One or more block device mapping entries. - BlockDeviceMappings []*BlockDeviceMapping `locationName:"BlockDeviceMapping" locationNameList:"BlockDeviceMapping" type:"list"` - - // A description for your AMI. - Description *string `locationName:"description" type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The full path to your AMI manifest in Amazon S3 storage. - ImageLocation *string `type:"string"` - - // The ID of the kernel. - KernelId *string `locationName:"kernelId" type:"string"` - - // A name for your AMI. - // - // Constraints: 3-128 alphanumeric characters, parentheses (()), square brackets - // ([]), spaces ( ), periods (.), slashes (/), dashes (-), single quotes ('), - // at-signs (@), or underscores(_) - Name *string `locationName:"name" type:"string" required:"true"` - - // The ID of the RAM disk. - RamdiskId *string `locationName:"ramdiskId" type:"string"` - - // The name of the root device (for example, /dev/sda1, or /dev/xvda). - RootDeviceName *string `locationName:"rootDeviceName" type:"string"` - - // Set to simple to enable enhanced networking for the AMI and any instances - // that you launch from the AMI. - // - // There is no way to disable enhanced networking at this time. - // - // This option is supported only for HVM AMIs. Specifying this option with - // a PV AMI can make instances launched from the AMI unreachable. - SriovNetSupport *string `locationName:"sriovNetSupport" type:"string"` - - // The type of virtualization. - // - // Default: paravirtual - VirtualizationType *string `locationName:"virtualizationType" type:"string"` - - metadataRegisterImageInput `json:"-" xml:"-"` -} - -type metadataRegisterImageInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RegisterImageInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RegisterImageInput) GoString() string { - return s.String() -} - -type RegisterImageOutput struct { - // The ID of the newly registered AMI. - ImageId *string `locationName:"imageId" type:"string"` - - metadataRegisterImageOutput `json:"-" xml:"-"` -} - -type metadataRegisterImageOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RegisterImageOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RegisterImageOutput) GoString() string { - return s.String() -} - -type RejectVpcPeeringConnectionInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the VPC peering connection. - VpcPeeringConnectionId *string `locationName:"vpcPeeringConnectionId" type:"string" required:"true"` - - metadataRejectVpcPeeringConnectionInput `json:"-" xml:"-"` -} - -type metadataRejectVpcPeeringConnectionInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RejectVpcPeeringConnectionInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RejectVpcPeeringConnectionInput) GoString() string { - return s.String() -} - -type RejectVpcPeeringConnectionOutput struct { - // Returns true if the request succeeds; otherwise, it returns an error. - Return *bool `locationName:"return" type:"boolean"` - - metadataRejectVpcPeeringConnectionOutput `json:"-" xml:"-"` -} - -type metadataRejectVpcPeeringConnectionOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RejectVpcPeeringConnectionOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RejectVpcPeeringConnectionOutput) GoString() string { - return s.String() -} - -type ReleaseAddressInput struct { - // [EC2-VPC] The allocation ID. Required for EC2-VPC. - AllocationId *string `type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // [EC2-Classic] The Elastic IP address. Required for EC2-Classic. - PublicIp *string `type:"string"` - - metadataReleaseAddressInput `json:"-" xml:"-"` -} - -type metadataReleaseAddressInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ReleaseAddressInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ReleaseAddressInput) GoString() string { - return s.String() -} - -type ReleaseAddressOutput struct { - metadataReleaseAddressOutput `json:"-" xml:"-"` -} - -type metadataReleaseAddressOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ReleaseAddressOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ReleaseAddressOutput) GoString() string { - return s.String() -} - -type ReplaceNetworkAclAssociationInput struct { - // The ID of the current association between the original network ACL and the - // subnet. - AssociationId *string `locationName:"associationId" type:"string" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the new network ACL to associate with the subnet. - NetworkAclId *string `locationName:"networkAclId" type:"string" required:"true"` - - metadataReplaceNetworkAclAssociationInput `json:"-" xml:"-"` -} - -type metadataReplaceNetworkAclAssociationInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ReplaceNetworkAclAssociationInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ReplaceNetworkAclAssociationInput) GoString() string { - return s.String() -} - -type ReplaceNetworkAclAssociationOutput struct { - // The ID of the new association. - NewAssociationId *string `locationName:"newAssociationId" type:"string"` - - metadataReplaceNetworkAclAssociationOutput `json:"-" xml:"-"` -} - -type metadataReplaceNetworkAclAssociationOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ReplaceNetworkAclAssociationOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ReplaceNetworkAclAssociationOutput) GoString() string { - return s.String() -} - -type ReplaceNetworkAclEntryInput struct { - // The network range to allow or deny, in CIDR notation. - CidrBlock *string `locationName:"cidrBlock" type:"string" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // Indicates whether to replace the egress rule. - // - // Default: If no value is specified, we replace the ingress rule. - Egress *bool `locationName:"egress" type:"boolean" required:"true"` - - // ICMP protocol: The ICMP type and code. Required if specifying 1 (ICMP) for - // the protocol. - IcmpTypeCode *IcmpTypeCode `locationName:"Icmp" type:"structure"` - - // The ID of the ACL. - NetworkAclId *string `locationName:"networkAclId" type:"string" required:"true"` - - // TCP or UDP protocols: The range of ports the rule applies to. Required if - // specifying 6 (TCP) or 17 (UDP) for the protocol. - PortRange *PortRange `locationName:"portRange" type:"structure"` - - // The IP protocol. You can specify all or -1 to mean all protocols. - Protocol *string `locationName:"protocol" type:"string" required:"true"` - - // Indicates whether to allow or deny the traffic that matches the rule. - RuleAction *string `locationName:"ruleAction" type:"string" required:"true" enum:"RuleAction"` - - // The rule number of the entry to replace. - RuleNumber *int64 `locationName:"ruleNumber" type:"integer" required:"true"` - - metadataReplaceNetworkAclEntryInput `json:"-" xml:"-"` -} - -type metadataReplaceNetworkAclEntryInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ReplaceNetworkAclEntryInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ReplaceNetworkAclEntryInput) GoString() string { - return s.String() -} - -type ReplaceNetworkAclEntryOutput struct { - metadataReplaceNetworkAclEntryOutput `json:"-" xml:"-"` -} - -type metadataReplaceNetworkAclEntryOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ReplaceNetworkAclEntryOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ReplaceNetworkAclEntryOutput) GoString() string { - return s.String() -} - -type ReplaceRouteInput struct { - // The CIDR address block used for the destination match. The value you provide - // must match the CIDR of an existing route in the table. - DestinationCidrBlock *string `locationName:"destinationCidrBlock" type:"string" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of an Internet gateway or virtual private gateway. - GatewayId *string `locationName:"gatewayId" type:"string"` - - // The ID of a NAT instance in your VPC. - InstanceId *string `locationName:"instanceId" type:"string"` - - // The ID of a network interface. - NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string"` - - // The ID of the route table. - RouteTableId *string `locationName:"routeTableId" type:"string" required:"true"` - - // The ID of a VPC peering connection. - VpcPeeringConnectionId *string `locationName:"vpcPeeringConnectionId" type:"string"` - - metadataReplaceRouteInput `json:"-" xml:"-"` -} - -type metadataReplaceRouteInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ReplaceRouteInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ReplaceRouteInput) GoString() string { - return s.String() -} - -type ReplaceRouteOutput struct { - metadataReplaceRouteOutput `json:"-" xml:"-"` -} - -type metadataReplaceRouteOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ReplaceRouteOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ReplaceRouteOutput) GoString() string { - return s.String() -} - -type ReplaceRouteTableAssociationInput struct { - // The association ID. - AssociationId *string `locationName:"associationId" type:"string" required:"true"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the new route table to associate with the subnet. - RouteTableId *string `locationName:"routeTableId" type:"string" required:"true"` - - metadataReplaceRouteTableAssociationInput `json:"-" xml:"-"` -} - -type metadataReplaceRouteTableAssociationInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ReplaceRouteTableAssociationInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ReplaceRouteTableAssociationInput) GoString() string { - return s.String() -} - -type ReplaceRouteTableAssociationOutput struct { - // The ID of the new association. - NewAssociationId *string `locationName:"newAssociationId" type:"string"` - - metadataReplaceRouteTableAssociationOutput `json:"-" xml:"-"` -} - -type metadataReplaceRouteTableAssociationOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ReplaceRouteTableAssociationOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ReplaceRouteTableAssociationOutput) GoString() string { - return s.String() -} - -type ReportInstanceStatusInput struct { - // Descriptive text about the health state of your instance. - Description *string `locationName:"description" type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The time at which the reported instance health state ended. - EndTime *time.Time `locationName:"endTime" type:"timestamp" timestampFormat:"iso8601"` - - // One or more instances. - Instances []*string `locationName:"instanceId" locationNameList:"InstanceId" type:"list" required:"true"` - - // One or more reason codes that describes the health state of your instance. - // - // instance-stuck-in-state: My instance is stuck in a state. - // - // unresponsive: My instance is unresponsive. - // - // not-accepting-credentials: My instance is not accepting my credentials. - // - // password-not-available: A password is not available for my instance. - // - // performance-network: My instance is experiencing performance problems which - // I believe are network related. - // - // performance-instance-store: My instance is experiencing performance problems - // which I believe are related to the instance stores. - // - // performance-ebs-volume: My instance is experiencing performance problems - // which I believe are related to an EBS volume. - // - // performance-other: My instance is experiencing performance problems. - // - // other: [explain using the description parameter] - ReasonCodes []*string `locationName:"reasonCode" locationNameList:"item" type:"list" required:"true"` - - // The time at which the reported instance health state began. - StartTime *time.Time `locationName:"startTime" type:"timestamp" timestampFormat:"iso8601"` - - // The status of all instances listed. - Status *string `locationName:"status" type:"string" required:"true" enum:"ReportStatusType"` - - metadataReportInstanceStatusInput `json:"-" xml:"-"` -} - -type metadataReportInstanceStatusInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ReportInstanceStatusInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ReportInstanceStatusInput) GoString() string { - return s.String() -} - -type ReportInstanceStatusOutput struct { - metadataReportInstanceStatusOutput `json:"-" xml:"-"` -} - -type metadataReportInstanceStatusOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ReportInstanceStatusOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ReportInstanceStatusOutput) GoString() string { - return s.String() -} - -// Contains the parameters for RequestSpotFleet. -type RequestSpotFleetInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The configuration for the Spot fleet request. - SpotFleetRequestConfig *SpotFleetRequestConfigData `locationName:"spotFleetRequestConfig" type:"structure" required:"true"` - - metadataRequestSpotFleetInput `json:"-" xml:"-"` -} - -type metadataRequestSpotFleetInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RequestSpotFleetInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RequestSpotFleetInput) GoString() string { - return s.String() -} - -// Contains the output of RequestSpotFleet. -type RequestSpotFleetOutput struct { - // The ID of the Spot fleet request. - SpotFleetRequestId *string `locationName:"spotFleetRequestId" type:"string" required:"true"` - - metadataRequestSpotFleetOutput `json:"-" xml:"-"` -} - -type metadataRequestSpotFleetOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RequestSpotFleetOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RequestSpotFleetOutput) GoString() string { - return s.String() -} - -// Contains the parameters for RequestSpotInstances. -type RequestSpotInstancesInput struct { - // The user-specified name for a logical grouping of bids. - // - // When you specify an Availability Zone group in a Spot Instance request, - // all Spot instances in the request are launched in the same Availability Zone. - // Instance proximity is maintained with this parameter, but the choice of Availability - // Zone is not. The group applies only to bids for Spot Instances of the same - // instance type. Any additional Spot instance requests that are specified with - // the same Availability Zone group name are launched in that same Availability - // Zone, as long as at least one instance from the group is still active. - // - // If there is no active instance running in the Availability Zone group that - // you specify for a new Spot instance request (all instances are terminated, - // the bid is expired, or the bid falls below current market), then Amazon EC2 - // launches the instance in any Availability Zone where the constraint can be - // met. Consequently, the subsequent set of Spot instances could be placed in - // a different zone from the original request, even if you specified the same - // Availability Zone group. - // - // Default: Instances are launched in any available Availability Zone. - AvailabilityZoneGroup *string `locationName:"availabilityZoneGroup" type:"string"` - - // The required duration for the Spot instances, in minutes. This value must - // be a multiple of 60 (60, 120, 180, 240, 300, or 360). - // - // The duration period starts as soon as your Spot instance receives its instance - // ID. At the end of the duration period, Amazon EC2 marks the Spot instance - // for termination and provides a Spot instance termination notice, which gives - // the instance a two-minute warning before it terminates. - // - // Note that you can't specify an Availability Zone group or a launch group - // if you specify a duration. - BlockDurationMinutes *int64 `locationName:"blockDurationMinutes" type:"integer"` - - // Unique, case-sensitive identifier that you provide to ensure the idempotency - // of the request. For more information, see How to Ensure Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Run_Instance_Idempotency.html) - // in the Amazon Elastic Compute Cloud User Guide. - ClientToken *string `locationName:"clientToken" type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The maximum number of Spot instances to launch. - // - // Default: 1 - InstanceCount *int64 `locationName:"instanceCount" type:"integer"` - - // The instance launch group. Launch groups are Spot instances that launch together - // and terminate together. - // - // Default: Instances are launched and terminated individually - LaunchGroup *string `locationName:"launchGroup" type:"string"` - - // Describes the launch specification for an instance. - LaunchSpecification *RequestSpotLaunchSpecification `type:"structure"` - - // The maximum hourly price (bid) for any Spot instance launched to fulfill - // the request. - SpotPrice *string `locationName:"spotPrice" type:"string" required:"true"` - - // The Spot instance request type. - // - // Default: one-time - Type *string `locationName:"type" type:"string" enum:"SpotInstanceType"` - - // The start date of the request. If this is a one-time request, the request - // becomes active at this date and time and remains active until all instances - // launch, the request expires, or the request is canceled. If the request is - // persistent, the request becomes active at this date and time and remains - // active until it expires or is canceled. - // - // Default: The request is effective indefinitely. - ValidFrom *time.Time `locationName:"validFrom" type:"timestamp" timestampFormat:"iso8601"` - - // The end date of the request. If this is a one-time request, the request remains - // active until all instances launch, the request is canceled, or this date - // is reached. If the request is persistent, it remains active until it is canceled - // or this date and time is reached. - // - // Default: The request is effective indefinitely. - ValidUntil *time.Time `locationName:"validUntil" type:"timestamp" timestampFormat:"iso8601"` - - metadataRequestSpotInstancesInput `json:"-" xml:"-"` -} - -type metadataRequestSpotInstancesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RequestSpotInstancesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RequestSpotInstancesInput) GoString() string { - return s.String() -} - -// Contains the output of RequestSpotInstances. -type RequestSpotInstancesOutput struct { - // One or more Spot instance requests. - SpotInstanceRequests []*SpotInstanceRequest `locationName:"spotInstanceRequestSet" locationNameList:"item" type:"list"` - - metadataRequestSpotInstancesOutput `json:"-" xml:"-"` -} - -type metadataRequestSpotInstancesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RequestSpotInstancesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RequestSpotInstancesOutput) GoString() string { - return s.String() -} - -// Describes the launch specification for an instance. -type RequestSpotLaunchSpecification struct { - // Deprecated. - AddressingType *string `locationName:"addressingType" type:"string"` - - // One or more block device mapping entries. - BlockDeviceMappings []*BlockDeviceMapping `locationName:"blockDeviceMapping" locationNameList:"item" type:"list"` - - // Indicates whether the instance is optimized for EBS I/O. This optimization - // provides dedicated throughput to Amazon EBS and an optimized configuration - // stack to provide optimal EBS I/O performance. This optimization isn't available - // with all instance types. Additional usage charges apply when using an EBS - // Optimized instance. - // - // Default: false - EbsOptimized *bool `locationName:"ebsOptimized" type:"boolean"` - - // The IAM instance profile. - IamInstanceProfile *IamInstanceProfileSpecification `locationName:"iamInstanceProfile" type:"structure"` - - // The ID of the AMI. - ImageId *string `locationName:"imageId" type:"string"` - - // The instance type. - InstanceType *string `locationName:"instanceType" type:"string" enum:"InstanceType"` - - // The ID of the kernel. - KernelId *string `locationName:"kernelId" type:"string"` - - // The name of the key pair. - KeyName *string `locationName:"keyName" type:"string"` - - // Describes the monitoring for the instance. - Monitoring *RunInstancesMonitoringEnabled `locationName:"monitoring" type:"structure"` - - // One or more network interfaces. - NetworkInterfaces []*InstanceNetworkInterfaceSpecification `locationName:"NetworkInterface" locationNameList:"item" type:"list"` - - // The placement information for the instance. - Placement *SpotPlacement `locationName:"placement" type:"structure"` - - // The ID of the RAM disk. - RamdiskId *string `locationName:"ramdiskId" type:"string"` - - SecurityGroupIds []*string `locationName:"SecurityGroupId" locationNameList:"item" type:"list"` - - SecurityGroups []*string `locationName:"SecurityGroup" locationNameList:"item" type:"list"` - - // The ID of the subnet in which to launch the instance. - SubnetId *string `locationName:"subnetId" type:"string"` - - // The Base64-encoded MIME user data to make available to the instances. - UserData *string `locationName:"userData" type:"string"` - - metadataRequestSpotLaunchSpecification `json:"-" xml:"-"` -} - -type metadataRequestSpotLaunchSpecification struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RequestSpotLaunchSpecification) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RequestSpotLaunchSpecification) GoString() string { - return s.String() -} - -// Describes a reservation. -type Reservation struct { - // One or more security groups. - Groups []*GroupIdentifier `locationName:"groupSet" locationNameList:"item" type:"list"` - - // One or more instances. - Instances []*Instance `locationName:"instancesSet" locationNameList:"item" type:"list"` - - // The ID of the AWS account that owns the reservation. - OwnerId *string `locationName:"ownerId" type:"string"` - - // The ID of the requester that launched the instances on your behalf (for example, - // AWS Management Console or Auto Scaling). - RequesterId *string `locationName:"requesterId" type:"string"` - - // The ID of the reservation. - ReservationId *string `locationName:"reservationId" type:"string"` - - metadataReservation `json:"-" xml:"-"` -} - -type metadataReservation struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s Reservation) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s Reservation) GoString() string { - return s.String() -} - -// Describes the limit price of a Reserved Instance offering. -type ReservedInstanceLimitPrice struct { - // Used for Reserved Instance Marketplace offerings. Specifies the limit price - // on the total order (instanceCount * price). - Amount *float64 `locationName:"amount" type:"double"` - - // The currency in which the limitPrice amount is specified. At this time, the - // only supported currency is USD. - CurrencyCode *string `locationName:"currencyCode" type:"string" enum:"CurrencyCodeValues"` - - metadataReservedInstanceLimitPrice `json:"-" xml:"-"` -} - -type metadataReservedInstanceLimitPrice struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ReservedInstanceLimitPrice) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ReservedInstanceLimitPrice) GoString() string { - return s.String() -} - -// Describes a Reserved Instance. -type ReservedInstances struct { - // The Availability Zone in which the Reserved Instance can be used. - AvailabilityZone *string `locationName:"availabilityZone" type:"string"` - - // The currency of the Reserved Instance. It's specified using ISO 4217 standard - // currency codes. At this time, the only supported currency is USD. - CurrencyCode *string `locationName:"currencyCode" type:"string" enum:"CurrencyCodeValues"` - - // The duration of the Reserved Instance, in seconds. - Duration *int64 `locationName:"duration" type:"long"` - - // The time when the Reserved Instance expires. - End *time.Time `locationName:"end" type:"timestamp" timestampFormat:"iso8601"` - - // The purchase price of the Reserved Instance. - FixedPrice *float64 `locationName:"fixedPrice" type:"float"` - - // The number of Reserved Instances purchased. - InstanceCount *int64 `locationName:"instanceCount" type:"integer"` - - // The tenancy of the reserved instance. - InstanceTenancy *string `locationName:"instanceTenancy" type:"string" enum:"Tenancy"` - - // The instance type on which the Reserved Instance can be used. - InstanceType *string `locationName:"instanceType" type:"string" enum:"InstanceType"` - - // The Reserved Instance offering type. - OfferingType *string `locationName:"offeringType" type:"string" enum:"OfferingTypeValues"` - - // The Reserved Instance product platform description. - ProductDescription *string `locationName:"productDescription" type:"string" enum:"RIProductDescription"` - - // The recurring charge tag assigned to the resource. - RecurringCharges []*RecurringCharge `locationName:"recurringCharges" locationNameList:"item" type:"list"` - - // The ID of the Reserved Instance. - ReservedInstancesId *string `locationName:"reservedInstancesId" type:"string"` - - // The date and time the Reserved Instance started. - Start *time.Time `locationName:"start" type:"timestamp" timestampFormat:"iso8601"` - - // The state of the Reserved Instance purchase. - State *string `locationName:"state" type:"string" enum:"ReservedInstanceState"` - - // Any tags assigned to the resource. - Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - // The usage price of the Reserved Instance, per hour. - UsagePrice *float64 `locationName:"usagePrice" type:"float"` - - metadataReservedInstances `json:"-" xml:"-"` -} - -type metadataReservedInstances struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ReservedInstances) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ReservedInstances) GoString() string { - return s.String() -} - -// Describes the configuration settings for the modified Reserved Instances. -type ReservedInstancesConfiguration struct { - // The Availability Zone for the modified Reserved Instances. - AvailabilityZone *string `locationName:"availabilityZone" type:"string"` - - // The number of modified Reserved Instances. - InstanceCount *int64 `locationName:"instanceCount" type:"integer"` - - // The instance type for the modified Reserved Instances. - InstanceType *string `locationName:"instanceType" type:"string" enum:"InstanceType"` - - // The network platform of the modified Reserved Instances, which is either - // EC2-Classic or EC2-VPC. - Platform *string `locationName:"platform" type:"string"` - - metadataReservedInstancesConfiguration `json:"-" xml:"-"` -} - -type metadataReservedInstancesConfiguration struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ReservedInstancesConfiguration) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ReservedInstancesConfiguration) GoString() string { - return s.String() -} - -// Describes the ID of a Reserved Instance. -type ReservedInstancesId struct { - // The ID of the Reserved Instance. - ReservedInstancesId *string `locationName:"reservedInstancesId" type:"string"` - - metadataReservedInstancesId `json:"-" xml:"-"` -} - -type metadataReservedInstancesId struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ReservedInstancesId) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ReservedInstancesId) GoString() string { - return s.String() -} - -// Describes a Reserved Instance listing. -type ReservedInstancesListing struct { - // A unique, case-sensitive key supplied by the client to ensure that the request - // is idempotent. For more information, see Ensuring Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/APIReference/Run_Instance_Idempotency.html). - ClientToken *string `locationName:"clientToken" type:"string"` - - // The time the listing was created. - CreateDate *time.Time `locationName:"createDate" type:"timestamp" timestampFormat:"iso8601"` - - // The number of instances in this state. - InstanceCounts []*InstanceCount `locationName:"instanceCounts" locationNameList:"item" type:"list"` - - // The price of the Reserved Instance listing. - PriceSchedules []*PriceSchedule `locationName:"priceSchedules" locationNameList:"item" type:"list"` - - // The ID of the Reserved Instance. - ReservedInstancesId *string `locationName:"reservedInstancesId" type:"string"` - - // The ID of the Reserved Instance listing. - ReservedInstancesListingId *string `locationName:"reservedInstancesListingId" type:"string"` - - // The status of the Reserved Instance listing. - Status *string `locationName:"status" type:"string" enum:"ListingStatus"` - - // The reason for the current status of the Reserved Instance listing. The response - // can be blank. - StatusMessage *string `locationName:"statusMessage" type:"string"` - - // Any tags assigned to the resource. - Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - // The last modified timestamp of the listing. - UpdateDate *time.Time `locationName:"updateDate" type:"timestamp" timestampFormat:"iso8601"` - - metadataReservedInstancesListing `json:"-" xml:"-"` -} - -type metadataReservedInstancesListing struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ReservedInstancesListing) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ReservedInstancesListing) GoString() string { - return s.String() -} - -// Describes a Reserved Instance modification. -type ReservedInstancesModification struct { - // A unique, case-sensitive key supplied by the client to ensure that the request - // is idempotent. For more information, see Ensuring Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/APIReference/Run_Instance_Idempotency.html). - ClientToken *string `locationName:"clientToken" type:"string"` - - // The time when the modification request was created. - CreateDate *time.Time `locationName:"createDate" type:"timestamp" timestampFormat:"iso8601"` - - // The time for the modification to become effective. - EffectiveDate *time.Time `locationName:"effectiveDate" type:"timestamp" timestampFormat:"iso8601"` - - // Contains target configurations along with their corresponding new Reserved - // Instance IDs. - ModificationResults []*ReservedInstancesModificationResult `locationName:"modificationResultSet" locationNameList:"item" type:"list"` - - // The IDs of one or more Reserved Instances. - ReservedInstancesIds []*ReservedInstancesId `locationName:"reservedInstancesSet" locationNameList:"item" type:"list"` - - // A unique ID for the Reserved Instance modification. - ReservedInstancesModificationId *string `locationName:"reservedInstancesModificationId" type:"string"` - - // The status of the Reserved Instances modification request. - Status *string `locationName:"status" type:"string"` - - // The reason for the status. - StatusMessage *string `locationName:"statusMessage" type:"string"` - - // The time when the modification request was last updated. - UpdateDate *time.Time `locationName:"updateDate" type:"timestamp" timestampFormat:"iso8601"` - - metadataReservedInstancesModification `json:"-" xml:"-"` -} - -type metadataReservedInstancesModification struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ReservedInstancesModification) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ReservedInstancesModification) GoString() string { - return s.String() -} - -type ReservedInstancesModificationResult struct { - // The ID for the Reserved Instances that were created as part of the modification - // request. This field is only available when the modification is fulfilled. - ReservedInstancesId *string `locationName:"reservedInstancesId" type:"string"` - - // The target Reserved Instances configurations supplied as part of the modification - // request. - TargetConfiguration *ReservedInstancesConfiguration `locationName:"targetConfiguration" type:"structure"` - - metadataReservedInstancesModificationResult `json:"-" xml:"-"` -} - -type metadataReservedInstancesModificationResult struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ReservedInstancesModificationResult) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ReservedInstancesModificationResult) GoString() string { - return s.String() -} - -// Describes a Reserved Instance offering. -type ReservedInstancesOffering struct { - // The Availability Zone in which the Reserved Instance can be used. - AvailabilityZone *string `locationName:"availabilityZone" type:"string"` - - // The currency of the Reserved Instance offering you are purchasing. It's specified - // using ISO 4217 standard currency codes. At this time, the only supported - // currency is USD. - CurrencyCode *string `locationName:"currencyCode" type:"string" enum:"CurrencyCodeValues"` - - // The duration of the Reserved Instance, in seconds. - Duration *int64 `locationName:"duration" type:"long"` - - // The purchase price of the Reserved Instance. - FixedPrice *float64 `locationName:"fixedPrice" type:"float"` - - // The tenancy of the reserved instance. - InstanceTenancy *string `locationName:"instanceTenancy" type:"string" enum:"Tenancy"` - - // The instance type on which the Reserved Instance can be used. - InstanceType *string `locationName:"instanceType" type:"string" enum:"InstanceType"` - - // Indicates whether the offering is available through the Reserved Instance - // Marketplace (resale) or AWS. If it's a Reserved Instance Marketplace offering, - // this is true. - Marketplace *bool `locationName:"marketplace" type:"boolean"` - - // The Reserved Instance offering type. - OfferingType *string `locationName:"offeringType" type:"string" enum:"OfferingTypeValues"` - - // The pricing details of the Reserved Instance offering. - PricingDetails []*PricingDetail `locationName:"pricingDetailsSet" locationNameList:"item" type:"list"` - - // The Reserved Instance product platform description. - ProductDescription *string `locationName:"productDescription" type:"string" enum:"RIProductDescription"` - - // The recurring charge tag assigned to the resource. - RecurringCharges []*RecurringCharge `locationName:"recurringCharges" locationNameList:"item" type:"list"` - - // The ID of the Reserved Instance offering. - ReservedInstancesOfferingId *string `locationName:"reservedInstancesOfferingId" type:"string"` - - // The usage price of the Reserved Instance, per hour. - UsagePrice *float64 `locationName:"usagePrice" type:"float"` - - metadataReservedInstancesOffering `json:"-" xml:"-"` -} - -type metadataReservedInstancesOffering struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ReservedInstancesOffering) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ReservedInstancesOffering) GoString() string { - return s.String() -} - -type ResetImageAttributeInput struct { - // The attribute to reset (currently you can only reset the launch permission - // attribute). - Attribute *string `type:"string" required:"true" enum:"ResetImageAttributeName"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the AMI. - ImageId *string `type:"string" required:"true"` - - metadataResetImageAttributeInput `json:"-" xml:"-"` -} - -type metadataResetImageAttributeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ResetImageAttributeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ResetImageAttributeInput) GoString() string { - return s.String() -} - -type ResetImageAttributeOutput struct { - metadataResetImageAttributeOutput `json:"-" xml:"-"` -} - -type metadataResetImageAttributeOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ResetImageAttributeOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ResetImageAttributeOutput) GoString() string { - return s.String() -} - -type ResetInstanceAttributeInput struct { - // The attribute to reset. - Attribute *string `locationName:"attribute" type:"string" required:"true" enum:"InstanceAttributeName"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the instance. - InstanceId *string `locationName:"instanceId" type:"string" required:"true"` - - metadataResetInstanceAttributeInput `json:"-" xml:"-"` -} - -type metadataResetInstanceAttributeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ResetInstanceAttributeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ResetInstanceAttributeInput) GoString() string { - return s.String() -} - -type ResetInstanceAttributeOutput struct { - metadataResetInstanceAttributeOutput `json:"-" xml:"-"` -} - -type metadataResetInstanceAttributeOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ResetInstanceAttributeOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ResetInstanceAttributeOutput) GoString() string { - return s.String() -} - -type ResetNetworkInterfaceAttributeInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the network interface. - NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string" required:"true"` - - // The source/destination checking attribute. Resets the value to true. - SourceDestCheck *string `locationName:"sourceDestCheck" type:"string"` - - metadataResetNetworkInterfaceAttributeInput `json:"-" xml:"-"` -} - -type metadataResetNetworkInterfaceAttributeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ResetNetworkInterfaceAttributeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ResetNetworkInterfaceAttributeInput) GoString() string { - return s.String() -} - -type ResetNetworkInterfaceAttributeOutput struct { - metadataResetNetworkInterfaceAttributeOutput `json:"-" xml:"-"` -} - -type metadataResetNetworkInterfaceAttributeOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ResetNetworkInterfaceAttributeOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ResetNetworkInterfaceAttributeOutput) GoString() string { - return s.String() -} - -type ResetSnapshotAttributeInput struct { - // The attribute to reset. Currently, only the attribute for permission to create - // volumes can be reset. - Attribute *string `type:"string" required:"true" enum:"SnapshotAttributeName"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The ID of the snapshot. - SnapshotId *string `type:"string" required:"true"` - - metadataResetSnapshotAttributeInput `json:"-" xml:"-"` -} - -type metadataResetSnapshotAttributeInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ResetSnapshotAttributeInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ResetSnapshotAttributeInput) GoString() string { - return s.String() -} - -type ResetSnapshotAttributeOutput struct { - metadataResetSnapshotAttributeOutput `json:"-" xml:"-"` -} - -type metadataResetSnapshotAttributeOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s ResetSnapshotAttributeOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s ResetSnapshotAttributeOutput) GoString() string { - return s.String() -} - -type RestoreAddressToClassicInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The Elastic IP address. - PublicIp *string `locationName:"publicIp" type:"string" required:"true"` - - metadataRestoreAddressToClassicInput `json:"-" xml:"-"` -} - -type metadataRestoreAddressToClassicInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RestoreAddressToClassicInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RestoreAddressToClassicInput) GoString() string { - return s.String() -} - -type RestoreAddressToClassicOutput struct { - // The Elastic IP address. - PublicIp *string `locationName:"publicIp" type:"string"` - - // The move status for the IP address. - Status *string `locationName:"status" type:"string" enum:"Status"` - - metadataRestoreAddressToClassicOutput `json:"-" xml:"-"` -} - -type metadataRestoreAddressToClassicOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RestoreAddressToClassicOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RestoreAddressToClassicOutput) GoString() string { - return s.String() -} - -type RevokeSecurityGroupEgressInput struct { - // The CIDR IP address range. You can't specify this parameter when specifying - // a source security group. - CidrIp *string `locationName:"cidrIp" type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The start of port range for the TCP and UDP protocols, or an ICMP type number. - // For the ICMP type number, use -1 to specify all ICMP types. - FromPort *int64 `locationName:"fromPort" type:"integer"` - - // The ID of the security group. - GroupId *string `locationName:"groupId" type:"string" required:"true"` - - // A set of IP permissions. You can't specify a destination security group and - // a CIDR IP address range. - IpPermissions []*IpPermission `locationName:"ipPermissions" locationNameList:"item" type:"list"` - - // The IP protocol name (tcp, udp, icmp) or number (see Protocol Numbers (http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml)). - // Use -1 to specify all. - IpProtocol *string `locationName:"ipProtocol" type:"string"` - - // The name of a destination security group. To revoke outbound access to a - // destination security group, we recommend that you use a set of IP permissions - // instead. - SourceSecurityGroupName *string `locationName:"sourceSecurityGroupName" type:"string"` - - // The AWS account number for a destination security group. To revoke outbound - // access to a destination security group, we recommend that you use a set of - // IP permissions instead. - SourceSecurityGroupOwnerId *string `locationName:"sourceSecurityGroupOwnerId" type:"string"` - - // The end of port range for the TCP and UDP protocols, or an ICMP code number. - // For the ICMP code number, use -1 to specify all ICMP codes for the ICMP type. - ToPort *int64 `locationName:"toPort" type:"integer"` - - metadataRevokeSecurityGroupEgressInput `json:"-" xml:"-"` -} - -type metadataRevokeSecurityGroupEgressInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RevokeSecurityGroupEgressInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RevokeSecurityGroupEgressInput) GoString() string { - return s.String() -} - -type RevokeSecurityGroupEgressOutput struct { - metadataRevokeSecurityGroupEgressOutput `json:"-" xml:"-"` -} - -type metadataRevokeSecurityGroupEgressOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RevokeSecurityGroupEgressOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RevokeSecurityGroupEgressOutput) GoString() string { - return s.String() -} - -type RevokeSecurityGroupIngressInput struct { - // The CIDR IP address range. You can't specify this parameter when specifying - // a source security group. - CidrIp *string `type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // The start of port range for the TCP and UDP protocols, or an ICMP type number. - // For the ICMP type number, use -1 to specify all ICMP types. - FromPort *int64 `type:"integer"` - - // The ID of the security group. Required for a security group in a nondefault - // VPC. - GroupId *string `type:"string"` - - // [EC2-Classic, default VPC] The name of the security group. - GroupName *string `type:"string"` - - // A set of IP permissions. You can't specify a source security group and a - // CIDR IP address range. - IpPermissions []*IpPermission `locationNameList:"item" type:"list"` - - // The IP protocol name (tcp, udp, icmp) or number (see Protocol Numbers (http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml)). - // Use -1 to specify all. - IpProtocol *string `type:"string"` - - // [EC2-Classic, default VPC] The name of the source security group. You can't - // specify this parameter in combination with the following parameters: the - // CIDR IP address range, the start of the port range, the IP protocol, and - // the end of the port range. For EC2-VPC, the source security group must be - // in the same VPC. - SourceSecurityGroupName *string `type:"string"` - - // [EC2-Classic, default VPC] The AWS account ID of the source security group. - // For EC2-VPC, the source security group must be in the same VPC. You can't - // specify this parameter in combination with the following parameters: the - // CIDR IP address range, the IP protocol, the start of the port range, and - // the end of the port range. To revoke a specific rule for an IP protocol and - // port range, use a set of IP permissions instead. - SourceSecurityGroupOwnerId *string `type:"string"` - - // The end of port range for the TCP and UDP protocols, or an ICMP code number. - // For the ICMP code number, use -1 to specify all ICMP codes for the ICMP type. - ToPort *int64 `type:"integer"` - - metadataRevokeSecurityGroupIngressInput `json:"-" xml:"-"` -} - -type metadataRevokeSecurityGroupIngressInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RevokeSecurityGroupIngressInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RevokeSecurityGroupIngressInput) GoString() string { - return s.String() -} - -type RevokeSecurityGroupIngressOutput struct { - metadataRevokeSecurityGroupIngressOutput `json:"-" xml:"-"` -} - -type metadataRevokeSecurityGroupIngressOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RevokeSecurityGroupIngressOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RevokeSecurityGroupIngressOutput) GoString() string { - return s.String() -} - -// Describes a route in a route table. -type Route struct { - // The CIDR block used for the destination match. - DestinationCidrBlock *string `locationName:"destinationCidrBlock" type:"string"` - - // The prefix of the AWS service. - DestinationPrefixListId *string `locationName:"destinationPrefixListId" type:"string"` - - // The ID of a gateway attached to your VPC. - GatewayId *string `locationName:"gatewayId" type:"string"` - - // The ID of a NAT instance in your VPC. - InstanceId *string `locationName:"instanceId" type:"string"` - - // The AWS account ID of the owner of the instance. - InstanceOwnerId *string `locationName:"instanceOwnerId" type:"string"` - - // The ID of the network interface. - NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string"` - - // Describes how the route was created. - // - // CreateRouteTable indicates that route was automatically created when the - // route table was created. CreateRoute indicates that the route was manually - // added to the route table. EnableVgwRoutePropagation indicates that the route - // was propagated by route propagation. - Origin *string `locationName:"origin" type:"string" enum:"RouteOrigin"` - - // The state of the route. The blackhole state indicates that the route's target - // isn't available (for example, the specified gateway isn't attached to the - // VPC, or the specified NAT instance has been terminated). - State *string `locationName:"state" type:"string" enum:"RouteState"` - - // The ID of the VPC peering connection. - VpcPeeringConnectionId *string `locationName:"vpcPeeringConnectionId" type:"string"` - - metadataRoute `json:"-" xml:"-"` -} - -type metadataRoute struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s Route) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s Route) GoString() string { - return s.String() -} - -// Describes a route table. -type RouteTable struct { - // The associations between the route table and one or more subnets. - Associations []*RouteTableAssociation `locationName:"associationSet" locationNameList:"item" type:"list"` - - // Any virtual private gateway (VGW) propagating routes. - PropagatingVgws []*PropagatingVgw `locationName:"propagatingVgwSet" locationNameList:"item" type:"list"` - - // The ID of the route table. - RouteTableId *string `locationName:"routeTableId" type:"string"` - - // The routes in the route table. - Routes []*Route `locationName:"routeSet" locationNameList:"item" type:"list"` - - // Any tags assigned to the route table. - Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - // The ID of the VPC. - VpcId *string `locationName:"vpcId" type:"string"` - - metadataRouteTable `json:"-" xml:"-"` -} - -type metadataRouteTable struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RouteTable) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RouteTable) GoString() string { - return s.String() -} - -// Describes an association between a route table and a subnet. -type RouteTableAssociation struct { - // Indicates whether this is the main route table. - Main *bool `locationName:"main" type:"boolean"` - - // The ID of the association between a route table and a subnet. - RouteTableAssociationId *string `locationName:"routeTableAssociationId" type:"string"` - - // The ID of the route table. - RouteTableId *string `locationName:"routeTableId" type:"string"` - - // The ID of the subnet. A subnet ID is not returned for an implicit association. - SubnetId *string `locationName:"subnetId" type:"string"` - - metadataRouteTableAssociation `json:"-" xml:"-"` -} - -type metadataRouteTableAssociation struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RouteTableAssociation) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RouteTableAssociation) GoString() string { - return s.String() -} - -type RunInstancesInput struct { - // Reserved. - AdditionalInfo *string `locationName:"additionalInfo" type:"string"` - - // The block device mapping. - BlockDeviceMappings []*BlockDeviceMapping `locationName:"BlockDeviceMapping" locationNameList:"BlockDeviceMapping" type:"list"` - - // Unique, case-sensitive identifier you provide to ensure the idempotency of - // the request. For more information, see Ensuring Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/APIReference/Run_Instance_Idempotency.html). - // - // Constraints: Maximum 64 ASCII characters - ClientToken *string `locationName:"clientToken" type:"string"` - - // If you set this parameter to true, you can't terminate the instance using - // the Amazon EC2 console, CLI, or API; otherwise, you can. If you set this - // parameter to true and then later want to be able to terminate the instance, - // you must first change the value of the disableApiTermination attribute to - // false using ModifyInstanceAttribute. Alternatively, if you set InstanceInitiatedShutdownBehavior - // to terminate, you can terminate the instance by running the shutdown command - // from the instance. - // - // Default: false - DisableApiTermination *bool `locationName:"disableApiTermination" type:"boolean"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // Indicates whether the instance is optimized for EBS I/O. This optimization - // provides dedicated throughput to Amazon EBS and an optimized configuration - // stack to provide optimal EBS I/O performance. This optimization isn't available - // with all instance types. Additional usage charges apply when using an EBS-optimized - // instance. - // - // Default: false - EbsOptimized *bool `locationName:"ebsOptimized" type:"boolean"` - - // The IAM instance profile. - IamInstanceProfile *IamInstanceProfileSpecification `locationName:"iamInstanceProfile" type:"structure"` - - // The ID of the AMI, which you can get by calling DescribeImages. - ImageId *string `type:"string" required:"true"` - - // Indicates whether an instance stops or terminates when you initiate shutdown - // from the instance (using the operating system command for system shutdown). - // - // Default: stop - InstanceInitiatedShutdownBehavior *string `locationName:"instanceInitiatedShutdownBehavior" type:"string" enum:"ShutdownBehavior"` - - // The instance type. For more information, see Instance Types (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html) - // in the Amazon Elastic Compute Cloud User Guide. - // - // Default: m1.small - InstanceType *string `type:"string" enum:"InstanceType"` - - // The ID of the kernel. - // - // We recommend that you use PV-GRUB instead of kernels and RAM disks. For - // more information, see PV-GRUB (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/UserProvidedkernels.html) - // in the Amazon Elastic Compute Cloud User Guide. - KernelId *string `type:"string"` - - // The name of the key pair. You can create a key pair using CreateKeyPair or - // ImportKeyPair. - // - // If you do not specify a key pair, you can't connect to the instance unless - // you choose an AMI that is configured to allow users another way to log in. - KeyName *string `type:"string"` - - // The maximum number of instances to launch. If you specify more instances - // than Amazon EC2 can launch in the target Availability Zone, Amazon EC2 launches - // the largest possible number of instances above MinCount. - // - // Constraints: Between 1 and the maximum number you're allowed for the specified - // instance type. For more information about the default limits, and how to - // request an increase, see How many instances can I run in Amazon EC2 (http://aws.amazon.com/ec2/faqs/#How_many_instances_can_I_run_in_Amazon_EC2) - // in the Amazon EC2 General FAQ. - MaxCount *int64 `type:"integer" required:"true"` - - // The minimum number of instances to launch. If you specify a minimum that - // is more instances than Amazon EC2 can launch in the target Availability Zone, - // Amazon EC2 launches no instances. - // - // Constraints: Between 1 and the maximum number you're allowed for the specified - // instance type. For more information about the default limits, and how to - // request an increase, see How many instances can I run in Amazon EC2 (http://aws.amazon.com/ec2/faqs/#How_many_instances_can_I_run_in_Amazon_EC2) - // in the Amazon EC2 General FAQ. - MinCount *int64 `type:"integer" required:"true"` - - // The monitoring for the instance. - Monitoring *RunInstancesMonitoringEnabled `type:"structure"` - - // One or more network interfaces. - NetworkInterfaces []*InstanceNetworkInterfaceSpecification `locationName:"networkInterface" locationNameList:"item" type:"list"` - - // The placement for the instance. - Placement *Placement `type:"structure"` - - // [EC2-VPC] The primary IP address. You must specify a value from the IP address - // range of the subnet. - // - // Only one private IP address can be designated as primary. Therefore, you - // can't specify this parameter if PrivateIpAddresses.n.Primary is set to true - // and PrivateIpAddresses.n.PrivateIpAddress is set to an IP address. - // - // Default: We select an IP address from the IP address range of the subnet. - PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"` - - // The ID of the RAM disk. - // - // We recommend that you use PV-GRUB instead of kernels and RAM disks. For - // more information, see PV-GRUB (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/UserProvidedkernels.html) - // in the Amazon Elastic Compute Cloud User Guide. - RamdiskId *string `type:"string"` - - // One or more security group IDs. You can create a security group using CreateSecurityGroup. - // - // Default: Amazon EC2 uses the default security group. - SecurityGroupIds []*string `locationName:"SecurityGroupId" locationNameList:"SecurityGroupId" type:"list"` - - // [EC2-Classic, default VPC] One or more security group names. For a nondefault - // VPC, you must use security group IDs instead. - // - // Default: Amazon EC2 uses the default security group. - SecurityGroups []*string `locationName:"SecurityGroup" locationNameList:"SecurityGroup" type:"list"` - - // [EC2-VPC] The ID of the subnet to launch the instance into. - SubnetId *string `type:"string"` - - // The Base64-encoded MIME user data for the instances. - UserData *string `type:"string"` - - metadataRunInstancesInput `json:"-" xml:"-"` -} - -type metadataRunInstancesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RunInstancesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RunInstancesInput) GoString() string { - return s.String() -} - -// Describes the monitoring for the instance. -type RunInstancesMonitoringEnabled struct { - // Indicates whether monitoring is enabled for the instance. - Enabled *bool `locationName:"enabled" type:"boolean" required:"true"` - - metadataRunInstancesMonitoringEnabled `json:"-" xml:"-"` -} - -type metadataRunInstancesMonitoringEnabled struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s RunInstancesMonitoringEnabled) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s RunInstancesMonitoringEnabled) GoString() string { - return s.String() -} - -// Describes the storage parameters for S3 and S3 buckets for an instance store-backed -// AMI. -type S3Storage struct { - // The access key ID of the owner of the bucket. Before you specify a value - // for your access key ID, review and follow the guidance in Best Practices - // for Managing AWS Access Keys (http://docs.aws.amazon.com/general/latest/gr/aws-access-keys-best-practices.html). - AWSAccessKeyId *string `type:"string"` - - // The bucket in which to store the AMI. You can specify a bucket that you already - // own or a new bucket that Amazon EC2 creates on your behalf. If you specify - // a bucket that belongs to someone else, Amazon EC2 returns an error. - Bucket *string `locationName:"bucket" type:"string"` - - // The beginning of the file name of the AMI. - Prefix *string `locationName:"prefix" type:"string"` - - // A Base64-encoded Amazon S3 upload policy that gives Amazon EC2 permission - // to upload items into Amazon S3 on your behalf. - UploadPolicy []byte `locationName:"uploadPolicy" type:"blob"` - - // The signature of the Base64 encoded JSON document. - UploadPolicySignature *string `locationName:"uploadPolicySignature" type:"string"` - - metadataS3Storage `json:"-" xml:"-"` -} - -type metadataS3Storage struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s S3Storage) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s S3Storage) GoString() string { - return s.String() -} - -// Describes a security group -type SecurityGroup struct { - // A description of the security group. - Description *string `locationName:"groupDescription" type:"string"` - - // The ID of the security group. - GroupId *string `locationName:"groupId" type:"string"` - - // The name of the security group. - GroupName *string `locationName:"groupName" type:"string"` - - // One or more inbound rules associated with the security group. - IpPermissions []*IpPermission `locationName:"ipPermissions" locationNameList:"item" type:"list"` - - // [EC2-VPC] One or more outbound rules associated with the security group. - IpPermissionsEgress []*IpPermission `locationName:"ipPermissionsEgress" locationNameList:"item" type:"list"` - - // The AWS account ID of the owner of the security group. - OwnerId *string `locationName:"ownerId" type:"string"` - - // Any tags assigned to the security group. - Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - // [EC2-VPC] The ID of the VPC for the security group. - VpcId *string `locationName:"vpcId" type:"string"` - - metadataSecurityGroup `json:"-" xml:"-"` -} - -type metadataSecurityGroup struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s SecurityGroup) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s SecurityGroup) GoString() string { - return s.String() -} - -// Describes a snapshot. -type Snapshot struct { - // The data encryption key identifier for the snapshot. This value is a unique - // identifier that corresponds to the data encryption key that was used to encrypt - // the original volume or snapshot copy. Because data encryption keys are inherited - // by volumes created from snapshots, and vice versa, if snapshots share the - // same data encryption key identifier, then they belong to the same volume/snapshot - // lineage. This parameter is only returned by the DescribeSnapshots API operation. - DataEncryptionKeyId *string `locationName:"dataEncryptionKeyId" type:"string"` - - // The description for the snapshot. - Description *string `locationName:"description" type:"string"` - - // Indicates whether the snapshot is encrypted. - Encrypted *bool `locationName:"encrypted" type:"boolean"` - - // The full ARN of the AWS Key Management Service (AWS KMS) customer master - // key (CMK) that was used to protect the volume encryption key for the parent - // volume. - KmsKeyId *string `locationName:"kmsKeyId" type:"string"` - - // The AWS account alias (for example, amazon, self) or AWS account ID that - // owns the snapshot. - OwnerAlias *string `locationName:"ownerAlias" type:"string"` - - // The AWS account ID of the EBS snapshot owner. - OwnerId *string `locationName:"ownerId" type:"string"` - - // The progress of the snapshot, as a percentage. - Progress *string `locationName:"progress" type:"string"` - - // The ID of the snapshot. Each snapshot receives a unique identifier when it - // is created. - SnapshotId *string `locationName:"snapshotId" type:"string"` - - // The time stamp when the snapshot was initiated. - StartTime *time.Time `locationName:"startTime" type:"timestamp" timestampFormat:"iso8601"` - - // The snapshot state. - State *string `locationName:"status" type:"string" enum:"SnapshotState"` - - // Encrypted Amazon EBS snapshots are copied asynchronously. If a snapshot copy - // operation fails (for example, if the proper AWS Key Management Service (AWS - // KMS) permissions are not obtained) this field displays error state details - // to help you diagnose why the error occurred. This parameter is only returned - // by the DescribeSnapshots API operation. - StateMessage *string `locationName:"statusMessage" type:"string"` - - // Any tags assigned to the snapshot. - Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - // The ID of the volume that was used to create the snapshot. - VolumeId *string `locationName:"volumeId" type:"string"` - - // The size of the volume, in GiB. - VolumeSize *int64 `locationName:"volumeSize" type:"integer"` - - metadataSnapshot `json:"-" xml:"-"` -} - -type metadataSnapshot struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s Snapshot) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s Snapshot) GoString() string { - return s.String() -} - -// Describes the snapshot created from the imported disk. -type SnapshotDetail struct { - // A description for the snapshot. - Description *string `locationName:"description" type:"string"` - - // The block device mapping for the snapshot. - DeviceName *string `locationName:"deviceName" type:"string"` - - // The size of the disk in the snapshot, in GiB. - DiskImageSize *float64 `locationName:"diskImageSize" type:"double"` - - // The format of the disk image from which the snapshot is created. - Format *string `locationName:"format" type:"string"` - - // The percentage of progress for the task. - Progress *string `locationName:"progress" type:"string"` - - // The snapshot ID of the disk being imported. - SnapshotId *string `locationName:"snapshotId" type:"string"` - - // A brief status of the snapshot creation. - Status *string `locationName:"status" type:"string"` - - // A detailed status message for the snapshot creation. - StatusMessage *string `locationName:"statusMessage" type:"string"` - - // The URL used to access the disk image. - Url *string `locationName:"url" type:"string"` - - // Describes the S3 bucket for the disk image. - UserBucket *UserBucketDetails `locationName:"userBucket" type:"structure"` - - metadataSnapshotDetail `json:"-" xml:"-"` -} - -type metadataSnapshotDetail struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s SnapshotDetail) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s SnapshotDetail) GoString() string { - return s.String() -} - -// The disk container object for the import snapshot request. -type SnapshotDiskContainer struct { - // The description of the disk image being imported. - Description *string `type:"string"` - - // The format of the disk image being imported. - // - // Valid values: RAW | VHD | VMDK | OVA - Format *string `type:"string"` - - // The URL to the Amazon S3-based disk image being imported. It can either be - // a https URL (https://..) or an Amazon S3 URL (s3://..). - Url *string `type:"string"` - - // Describes the S3 bucket for the disk image. - UserBucket *UserBucket `type:"structure"` - - metadataSnapshotDiskContainer `json:"-" xml:"-"` -} - -type metadataSnapshotDiskContainer struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s SnapshotDiskContainer) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s SnapshotDiskContainer) GoString() string { - return s.String() -} - -// Details about the import snapshot task. -type SnapshotTaskDetail struct { - // The description of the snapshot. - Description *string `locationName:"description" type:"string"` - - // The size of the disk in the snapshot, in GiB. - DiskImageSize *float64 `locationName:"diskImageSize" type:"double"` - - // The format of the disk image from which the snapshot is created. - Format *string `locationName:"format" type:"string"` - - // The percentage of completion for the import snapshot task. - Progress *string `locationName:"progress" type:"string"` - - // The snapshot ID of the disk being imported. - SnapshotId *string `locationName:"snapshotId" type:"string"` - - // A brief status for the import snapshot task. - Status *string `locationName:"status" type:"string"` - - // A detailed status message for the import snapshot task. - StatusMessage *string `locationName:"statusMessage" type:"string"` - - // The URL of the disk image from which the snapshot is created. - Url *string `locationName:"url" type:"string"` - - // The S3 bucket for the disk image. - UserBucket *UserBucketDetails `locationName:"userBucket" type:"structure"` - - metadataSnapshotTaskDetail `json:"-" xml:"-"` -} - -type metadataSnapshotTaskDetail struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s SnapshotTaskDetail) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s SnapshotTaskDetail) GoString() string { - return s.String() -} - -// Describes the data feed for a Spot instance. -type SpotDatafeedSubscription struct { - // The Amazon S3 bucket where the Spot instance data feed is located. - Bucket *string `locationName:"bucket" type:"string"` - - // The fault codes for the Spot instance request, if any. - Fault *SpotInstanceStateFault `locationName:"fault" type:"structure"` - - // The AWS account ID of the account. - OwnerId *string `locationName:"ownerId" type:"string"` - - // The prefix that is prepended to data feed files. - Prefix *string `locationName:"prefix" type:"string"` - - // The state of the Spot instance data feed subscription. - State *string `locationName:"state" type:"string" enum:"DatafeedSubscriptionState"` - - metadataSpotDatafeedSubscription `json:"-" xml:"-"` -} - -type metadataSpotDatafeedSubscription struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s SpotDatafeedSubscription) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s SpotDatafeedSubscription) GoString() string { - return s.String() -} - -// Describes the launch specification for one or more Spot instances. -type SpotFleetLaunchSpecification struct { - // Deprecated. - AddressingType *string `locationName:"addressingType" type:"string"` - - // One or more block device mapping entries. - BlockDeviceMappings []*BlockDeviceMapping `locationName:"blockDeviceMapping" locationNameList:"item" type:"list"` - - // Indicates whether the instances are optimized for EBS I/O. This optimization - // provides dedicated throughput to Amazon EBS and an optimized configuration - // stack to provide optimal EBS I/O performance. This optimization isn't available - // with all instance types. Additional usage charges apply when using an EBS - // Optimized instance. - // - // Default: false - EbsOptimized *bool `locationName:"ebsOptimized" type:"boolean"` - - // The IAM instance profile. - IamInstanceProfile *IamInstanceProfileSpecification `locationName:"iamInstanceProfile" type:"structure"` - - // The ID of the AMI. - ImageId *string `locationName:"imageId" type:"string"` - - // The instance type. - InstanceType *string `locationName:"instanceType" type:"string" enum:"InstanceType"` - - // The ID of the kernel. - KernelId *string `locationName:"kernelId" type:"string"` - - // The name of the key pair. - KeyName *string `locationName:"keyName" type:"string"` - - // Enable or disable monitoring for the instances. - Monitoring *SpotFleetMonitoring `locationName:"monitoring" type:"structure"` - - // One or more network interfaces. - NetworkInterfaces []*InstanceNetworkInterfaceSpecification `locationName:"networkInterfaceSet" locationNameList:"item" type:"list"` - - // The placement information. - Placement *SpotPlacement `locationName:"placement" type:"structure"` - - // The ID of the RAM disk. - RamdiskId *string `locationName:"ramdiskId" type:"string"` - - // One or more security groups. When requesting instances in a VPC, you must - // specify the IDs of the security groups. When requesting instances in EC2-Classic, - // you can specify the names or the IDs of the security groups. - SecurityGroups []*GroupIdentifier `locationName:"groupSet" locationNameList:"item" type:"list"` - - // The bid price per unit hour for the specified instance type. If this value - // is not specified, the default is the Spot bid price specified for the fleet. - // To determine the bid price per unit hour, divide the Spot bid price by the - // value of WeightedCapacity. - SpotPrice *string `locationName:"spotPrice" type:"string"` - - // The ID of the subnet in which to launch the instances. - SubnetId *string `locationName:"subnetId" type:"string"` - - // The Base64-encoded MIME user data to make available to the instances. - UserData *string `locationName:"userData" type:"string"` - - // The number of units provided by the specified instance type. These are the - // same units that you chose to set the target capacity in terms (instances - // or a performance characteristic such as vCPUs, memory, or I/O). - // - // If the target capacity divided by this value is not a whole number, we round - // the number of instances to the next whole number. If this value is not specified, - // the default is 1. - WeightedCapacity *float64 `locationName:"weightedCapacity" type:"double"` - - metadataSpotFleetLaunchSpecification `json:"-" xml:"-"` -} - -type metadataSpotFleetLaunchSpecification struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s SpotFleetLaunchSpecification) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s SpotFleetLaunchSpecification) GoString() string { - return s.String() -} - -// Describes whether monitoring is enabled. -type SpotFleetMonitoring struct { - // Enables monitoring for the instance. - // - // Default: false - Enabled *bool `locationName:"enabled" type:"boolean"` - - metadataSpotFleetMonitoring `json:"-" xml:"-"` -} - -type metadataSpotFleetMonitoring struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s SpotFleetMonitoring) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s SpotFleetMonitoring) GoString() string { - return s.String() -} - -// Describes a Spot fleet request. -type SpotFleetRequestConfig struct { - // The creation date and time of the request. - CreateTime *time.Time `locationName:"createTime" type:"timestamp" timestampFormat:"iso8601" required:"true"` - - // Information about the configuration of the Spot fleet request. - SpotFleetRequestConfig *SpotFleetRequestConfigData `locationName:"spotFleetRequestConfig" type:"structure" required:"true"` - - // The ID of the Spot fleet request. - SpotFleetRequestId *string `locationName:"spotFleetRequestId" type:"string" required:"true"` - - // The state of the Spot fleet request. - SpotFleetRequestState *string `locationName:"spotFleetRequestState" type:"string" required:"true" enum:"BatchState"` - - metadataSpotFleetRequestConfig `json:"-" xml:"-"` -} - -type metadataSpotFleetRequestConfig struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s SpotFleetRequestConfig) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s SpotFleetRequestConfig) GoString() string { - return s.String() -} - -// Describes the configuration of a Spot fleet request. -type SpotFleetRequestConfigData struct { - // Indicates how to allocate the target capacity across the Spot pools specified - // by the Spot fleet request. The default is lowestPrice. - AllocationStrategy *string `locationName:"allocationStrategy" type:"string" enum:"AllocationStrategy"` - - // A unique, case-sensitive identifier you provide to ensure idempotency of - // your listings. This helps avoid duplicate listings. For more information, - // see Ensuring Idempotency (http://docs.aws.amazon.com/AWSEC2/latest/APIReference/Run_Instance_Idempotency.html). - ClientToken *string `locationName:"clientToken" type:"string"` - - // Indicates whether running Spot instances should be terminated if the target - // capacity of the Spot fleet request is decreased below the current size of - // the Spot fleet. - ExcessCapacityTerminationPolicy *string `locationName:"excessCapacityTerminationPolicy" type:"string" enum:"ExcessCapacityTerminationPolicy"` - - // Grants the Spot fleet permission to terminate Spot instances on your behalf - // when you cancel its Spot fleet request using CancelSpotFleetRequests or when - // the Spot fleet request expires, if you set terminateInstancesWithExpiration. - IamFleetRole *string `locationName:"iamFleetRole" type:"string" required:"true"` - - // Information about the launch specifications for the Spot fleet request. - LaunchSpecifications []*SpotFleetLaunchSpecification `locationName:"launchSpecifications" locationNameList:"item" min:"1" type:"list" required:"true"` - - // The bid price per unit hour. - SpotPrice *string `locationName:"spotPrice" type:"string" required:"true"` - - // The number of units to request. You can choose to set the target capacity - // in terms of instances or a performance characteristic that is important to - // your application workload, such as vCPUs, memory, or I/O. - TargetCapacity *int64 `locationName:"targetCapacity" type:"integer" required:"true"` - - // Indicates whether running Spot instances should be terminated when the Spot - // fleet request expires. - TerminateInstancesWithExpiration *bool `locationName:"terminateInstancesWithExpiration" type:"boolean"` - - // The start date and time of the request, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). - // The default is to start fulfilling the request immediately. - ValidFrom *time.Time `locationName:"validFrom" type:"timestamp" timestampFormat:"iso8601"` - - // The end date and time of the request, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). - // At this point, no new Spot instance requests are placed or enabled to fulfill - // the request. - ValidUntil *time.Time `locationName:"validUntil" type:"timestamp" timestampFormat:"iso8601"` - - metadataSpotFleetRequestConfigData `json:"-" xml:"-"` -} - -type metadataSpotFleetRequestConfigData struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s SpotFleetRequestConfigData) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s SpotFleetRequestConfigData) GoString() string { - return s.String() -} - -// Describes a Spot instance request. -type SpotInstanceRequest struct { - // If you specified a duration and your Spot instance request was fulfilled, - // this is the fixed hourly price in effect for the Spot instance while it runs. - ActualBlockHourlyPrice *string `locationName:"actualBlockHourlyPrice" type:"string"` - - // The Availability Zone group. If you specify the same Availability Zone group - // for all Spot instance requests, all Spot instances are launched in the same - // Availability Zone. - AvailabilityZoneGroup *string `locationName:"availabilityZoneGroup" type:"string"` - - // The duration for the Spot instance, in minutes. - BlockDurationMinutes *int64 `locationName:"blockDurationMinutes" type:"integer"` - - // The date and time when the Spot instance request was created, in UTC format - // (for example, YYYY-MM-DDTHH:MM:SSZ). - CreateTime *time.Time `locationName:"createTime" type:"timestamp" timestampFormat:"iso8601"` - - // The fault codes for the Spot instance request, if any. - Fault *SpotInstanceStateFault `locationName:"fault" type:"structure"` - - // The instance ID, if an instance has been launched to fulfill the Spot instance - // request. - InstanceId *string `locationName:"instanceId" type:"string"` - - // The instance launch group. Launch groups are Spot instances that launch together - // and terminate together. - LaunchGroup *string `locationName:"launchGroup" type:"string"` - - // Additional information for launching instances. - LaunchSpecification *LaunchSpecification `locationName:"launchSpecification" type:"structure"` - - // The Availability Zone in which the bid is launched. - LaunchedAvailabilityZone *string `locationName:"launchedAvailabilityZone" type:"string"` - - // The product description associated with the Spot instance. - ProductDescription *string `locationName:"productDescription" type:"string" enum:"RIProductDescription"` - - // The ID of the Spot instance request. - SpotInstanceRequestId *string `locationName:"spotInstanceRequestId" type:"string"` - - // The maximum hourly price (bid) for the Spot instance launched to fulfill - // the request. - SpotPrice *string `locationName:"spotPrice" type:"string"` - - // The state of the Spot instance request. Spot bid status information can help - // you track your Spot instance requests. For more information, see Spot Bid - // Status (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-bid-status.html) - // in the Amazon Elastic Compute Cloud User Guide. - State *string `locationName:"state" type:"string" enum:"SpotInstanceState"` - - // The status code and status message describing the Spot instance request. - Status *SpotInstanceStatus `locationName:"status" type:"structure"` - - // Any tags assigned to the resource. - Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - // The Spot instance request type. - Type *string `locationName:"type" type:"string" enum:"SpotInstanceType"` - - // The start date of the request, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). - // The request becomes active at this date and time. - ValidFrom *time.Time `locationName:"validFrom" type:"timestamp" timestampFormat:"iso8601"` - - // The end date of the request, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). - // If this is a one-time request, it remains active until all instances launch, - // the request is canceled, or this date is reached. If the request is persistent, - // it remains active until it is canceled or this date is reached. - ValidUntil *time.Time `locationName:"validUntil" type:"timestamp" timestampFormat:"iso8601"` - - metadataSpotInstanceRequest `json:"-" xml:"-"` -} - -type metadataSpotInstanceRequest struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s SpotInstanceRequest) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s SpotInstanceRequest) GoString() string { - return s.String() -} - -// Describes a Spot instance state change. -type SpotInstanceStateFault struct { - // The reason code for the Spot instance state change. - Code *string `locationName:"code" type:"string"` - - // The message for the Spot instance state change. - Message *string `locationName:"message" type:"string"` - - metadataSpotInstanceStateFault `json:"-" xml:"-"` -} - -type metadataSpotInstanceStateFault struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s SpotInstanceStateFault) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s SpotInstanceStateFault) GoString() string { - return s.String() -} - -// Describes the status of a Spot instance request. -type SpotInstanceStatus struct { - // The status code. For a list of status codes, see Spot Bid Status Codes (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-bid-status.html#spot-instance-bid-status-understand) - // in the Amazon Elastic Compute Cloud User Guide. - Code *string `locationName:"code" type:"string"` - - // The description for the status code. - Message *string `locationName:"message" type:"string"` - - // The date and time of the most recent status update, in UTC format (for example, - // YYYY-MM-DDTHH:MM:SSZ). - UpdateTime *time.Time `locationName:"updateTime" type:"timestamp" timestampFormat:"iso8601"` - - metadataSpotInstanceStatus `json:"-" xml:"-"` -} - -type metadataSpotInstanceStatus struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s SpotInstanceStatus) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s SpotInstanceStatus) GoString() string { - return s.String() -} - -// Describes Spot instance placement. -type SpotPlacement struct { - // The Availability Zone. - AvailabilityZone *string `locationName:"availabilityZone" type:"string"` - - // The name of the placement group (for cluster instances). - GroupName *string `locationName:"groupName" type:"string"` - - metadataSpotPlacement `json:"-" xml:"-"` -} - -type metadataSpotPlacement struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s SpotPlacement) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s SpotPlacement) GoString() string { - return s.String() -} - -// Describes the maximum hourly price (bid) for any Spot instance launched to -// fulfill the request. -type SpotPrice struct { - // The Availability Zone. - AvailabilityZone *string `locationName:"availabilityZone" type:"string"` - - // The instance type. - InstanceType *string `locationName:"instanceType" type:"string" enum:"InstanceType"` - - // A general description of the AMI. - ProductDescription *string `locationName:"productDescription" type:"string" enum:"RIProductDescription"` - - // The maximum price (bid) that you are willing to pay for a Spot instance. - SpotPrice *string `locationName:"spotPrice" type:"string"` - - // The date and time the request was created, in UTC format (for example, YYYY-MM-DDTHH:MM:SSZ). - Timestamp *time.Time `locationName:"timestamp" type:"timestamp" timestampFormat:"iso8601"` - - metadataSpotPrice `json:"-" xml:"-"` -} - -type metadataSpotPrice struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s SpotPrice) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s SpotPrice) GoString() string { - return s.String() -} - -type StartInstancesInput struct { - // Reserved. - AdditionalInfo *string `locationName:"additionalInfo" type:"string"` - - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more instance IDs. - InstanceIds []*string `locationName:"InstanceId" locationNameList:"InstanceId" type:"list" required:"true"` - - metadataStartInstancesInput `json:"-" xml:"-"` -} - -type metadataStartInstancesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s StartInstancesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s StartInstancesInput) GoString() string { - return s.String() -} - -type StartInstancesOutput struct { - // Information about one or more started instances. - StartingInstances []*InstanceStateChange `locationName:"instancesSet" locationNameList:"item" type:"list"` - - metadataStartInstancesOutput `json:"-" xml:"-"` -} - -type metadataStartInstancesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s StartInstancesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s StartInstancesOutput) GoString() string { - return s.String() -} - -// Describes a state change. -type StateReason struct { - // The reason code for the state change. - Code *string `locationName:"code" type:"string"` - - // The message for the state change. - // - // Server.SpotInstanceTermination: A Spot Instance was terminated due to an - // increase in the market price. - // - // Server.InternalError: An internal error occurred during instance launch, - // resulting in termination. - // - // Server.InsufficientInstanceCapacity: There was insufficient instance capacity - // to satisfy the launch request. - // - // Client.InternalError: A client error caused the instance to terminate on - // launch. - // - // Client.InstanceInitiatedShutdown: The instance was shut down using the shutdown - // -h command from the instance. - // - // Client.UserInitiatedShutdown: The instance was shut down using the Amazon - // EC2 API. - // - // Client.VolumeLimitExceeded: The volume limit was exceeded. - // - // Client.InvalidSnapshot.NotFound: The specified snapshot was not found. - Message *string `locationName:"message" type:"string"` - - metadataStateReason `json:"-" xml:"-"` -} - -type metadataStateReason struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s StateReason) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s StateReason) GoString() string { - return s.String() -} - -type StopInstancesInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // Forces the instances to stop. The instances do not have an opportunity to - // flush file system caches or file system metadata. If you use this option, - // you must perform file system check and repair procedures. This option is - // not recommended for Windows instances. - // - // Default: false - Force *bool `locationName:"force" type:"boolean"` - - // One or more instance IDs. - InstanceIds []*string `locationName:"InstanceId" locationNameList:"InstanceId" type:"list" required:"true"` - - metadataStopInstancesInput `json:"-" xml:"-"` -} - -type metadataStopInstancesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s StopInstancesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s StopInstancesInput) GoString() string { - return s.String() -} - -type StopInstancesOutput struct { - // Information about one or more stopped instances. - StoppingInstances []*InstanceStateChange `locationName:"instancesSet" locationNameList:"item" type:"list"` - - metadataStopInstancesOutput `json:"-" xml:"-"` -} - -type metadataStopInstancesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s StopInstancesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s StopInstancesOutput) GoString() string { - return s.String() -} - -// Describes the storage location for an instance store-backed AMI. -type Storage struct { - // An Amazon S3 storage location. - S3 *S3Storage `type:"structure"` - - metadataStorage `json:"-" xml:"-"` -} - -type metadataStorage struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s Storage) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s Storage) GoString() string { - return s.String() -} - -// Describes a subnet. -type Subnet struct { - // The Availability Zone of the subnet. - AvailabilityZone *string `locationName:"availabilityZone" type:"string"` - - // The number of unused IP addresses in the subnet. Note that the IP addresses - // for any stopped instances are considered unavailable. - AvailableIpAddressCount *int64 `locationName:"availableIpAddressCount" type:"integer"` - - // The CIDR block assigned to the subnet. - CidrBlock *string `locationName:"cidrBlock" type:"string"` - - // Indicates whether this is the default subnet for the Availability Zone. - DefaultForAz *bool `locationName:"defaultForAz" type:"boolean"` - - // Indicates whether instances launched in this subnet receive a public IP address. - MapPublicIpOnLaunch *bool `locationName:"mapPublicIpOnLaunch" type:"boolean"` - - // The current state of the subnet. - State *string `locationName:"state" type:"string" enum:"SubnetState"` - - // The ID of the subnet. - SubnetId *string `locationName:"subnetId" type:"string"` - - // Any tags assigned to the subnet. - Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - // The ID of the VPC the subnet is in. - VpcId *string `locationName:"vpcId" type:"string"` - - metadataSubnet `json:"-" xml:"-"` -} - -type metadataSubnet struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s Subnet) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s Subnet) GoString() string { - return s.String() -} - -// Describes a tag. -type Tag struct { - // The key of the tag. - // - // Constraints: Tag keys are case-sensitive and accept a maximum of 127 Unicode - // characters. May not begin with aws: - Key *string `locationName:"key" type:"string"` - - // The value of the tag. - // - // Constraints: Tag values are case-sensitive and accept a maximum of 255 Unicode - // characters. - Value *string `locationName:"value" type:"string"` - - metadataTag `json:"-" xml:"-"` -} - -type metadataTag struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s Tag) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s Tag) GoString() string { - return s.String() -} - -// Describes a tag. -type TagDescription struct { - // The tag key. - Key *string `locationName:"key" type:"string"` - - // The ID of the resource. For example, ami-1a2b3c4d. - ResourceId *string `locationName:"resourceId" type:"string"` - - // The resource type. - ResourceType *string `locationName:"resourceType" type:"string" enum:"ResourceType"` - - // The tag value. - Value *string `locationName:"value" type:"string"` - - metadataTagDescription `json:"-" xml:"-"` -} - -type metadataTagDescription struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s TagDescription) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s TagDescription) GoString() string { - return s.String() -} - -type TerminateInstancesInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more instance IDs. - InstanceIds []*string `locationName:"InstanceId" locationNameList:"InstanceId" type:"list" required:"true"` - - metadataTerminateInstancesInput `json:"-" xml:"-"` -} - -type metadataTerminateInstancesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s TerminateInstancesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s TerminateInstancesInput) GoString() string { - return s.String() -} - -type TerminateInstancesOutput struct { - // Information about one or more terminated instances. - TerminatingInstances []*InstanceStateChange `locationName:"instancesSet" locationNameList:"item" type:"list"` - - metadataTerminateInstancesOutput `json:"-" xml:"-"` -} - -type metadataTerminateInstancesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s TerminateInstancesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s TerminateInstancesOutput) GoString() string { - return s.String() -} - -type UnassignPrivateIpAddressesInput struct { - // The ID of the network interface. - NetworkInterfaceId *string `locationName:"networkInterfaceId" type:"string" required:"true"` - - // The secondary private IP addresses to unassign from the network interface. - // You can specify this option multiple times to unassign more than one IP address. - PrivateIpAddresses []*string `locationName:"privateIpAddress" locationNameList:"PrivateIpAddress" type:"list" required:"true"` - - metadataUnassignPrivateIpAddressesInput `json:"-" xml:"-"` -} - -type metadataUnassignPrivateIpAddressesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s UnassignPrivateIpAddressesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s UnassignPrivateIpAddressesInput) GoString() string { - return s.String() -} - -type UnassignPrivateIpAddressesOutput struct { - metadataUnassignPrivateIpAddressesOutput `json:"-" xml:"-"` -} - -type metadataUnassignPrivateIpAddressesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s UnassignPrivateIpAddressesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s UnassignPrivateIpAddressesOutput) GoString() string { - return s.String() -} - -type UnmonitorInstancesInput struct { - // Checks whether you have the required permissions for the action, without - // actually making the request, and provides an error response. If you have - // the required permissions, the error response is DryRunOperation. Otherwise, - // it is UnauthorizedOperation. - DryRun *bool `locationName:"dryRun" type:"boolean"` - - // One or more instance IDs. - InstanceIds []*string `locationName:"InstanceId" locationNameList:"InstanceId" type:"list" required:"true"` - - metadataUnmonitorInstancesInput `json:"-" xml:"-"` -} - -type metadataUnmonitorInstancesInput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s UnmonitorInstancesInput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s UnmonitorInstancesInput) GoString() string { - return s.String() -} - -type UnmonitorInstancesOutput struct { - // Monitoring information for one or more instances. - InstanceMonitorings []*InstanceMonitoring `locationName:"instancesSet" locationNameList:"item" type:"list"` - - metadataUnmonitorInstancesOutput `json:"-" xml:"-"` -} - -type metadataUnmonitorInstancesOutput struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s UnmonitorInstancesOutput) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s UnmonitorInstancesOutput) GoString() string { - return s.String() -} - -// Information about items that were not successfully processed in a batch call. -type UnsuccessfulItem struct { - // Information about the error. - Error *UnsuccessfulItemError `locationName:"error" type:"structure" required:"true"` - - // The ID of the resource. - ResourceId *string `locationName:"resourceId" type:"string"` - - metadataUnsuccessfulItem `json:"-" xml:"-"` -} - -type metadataUnsuccessfulItem struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s UnsuccessfulItem) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s UnsuccessfulItem) GoString() string { - return s.String() -} - -// Information about the error that occurred. For more information about errors, -// see Error Codes (http://docs.aws.amazon.com/AWSEC2/latest/APIReference/errors-overview.html). -type UnsuccessfulItemError struct { - // The error code. - Code *string `locationName:"code" type:"string" required:"true"` - - // The error message accompanying the error code. - Message *string `locationName:"message" type:"string" required:"true"` - - metadataUnsuccessfulItemError `json:"-" xml:"-"` -} - -type metadataUnsuccessfulItemError struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s UnsuccessfulItemError) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s UnsuccessfulItemError) GoString() string { - return s.String() -} - -// Describes the S3 bucket for the disk image. -type UserBucket struct { - // The name of the S3 bucket where the disk image is located. - S3Bucket *string `type:"string"` - - // The key for the disk image. - S3Key *string `type:"string"` - - metadataUserBucket `json:"-" xml:"-"` -} - -type metadataUserBucket struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s UserBucket) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s UserBucket) GoString() string { - return s.String() -} - -// Describes the S3 bucket for the disk image. -type UserBucketDetails struct { - // The S3 bucket from which the disk image was created. - S3Bucket *string `locationName:"s3Bucket" type:"string"` - - // The key from which the disk image was created. - S3Key *string `locationName:"s3Key" type:"string"` - - metadataUserBucketDetails `json:"-" xml:"-"` -} - -type metadataUserBucketDetails struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s UserBucketDetails) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s UserBucketDetails) GoString() string { - return s.String() -} - -// Describes the user data to be made available to an instance. -type UserData struct { - // The Base64-encoded MIME user data for the instance. - Data *string `locationName:"data" type:"string"` - - metadataUserData `json:"-" xml:"-"` -} - -type metadataUserData struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s UserData) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s UserData) GoString() string { - return s.String() -} - -// Describes a security group and AWS account ID pair. -type UserIdGroupPair struct { - // The ID of the security group. - GroupId *string `locationName:"groupId" type:"string"` - - // The name of the security group. In a request, use this parameter for a security - // group in EC2-Classic or a default VPC only. For a security group in a nondefault - // VPC, use GroupId. - GroupName *string `locationName:"groupName" type:"string"` - - // The ID of an AWS account. EC2-Classic only. - UserId *string `locationName:"userId" type:"string"` - - metadataUserIdGroupPair `json:"-" xml:"-"` -} - -type metadataUserIdGroupPair struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s UserIdGroupPair) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s UserIdGroupPair) GoString() string { - return s.String() -} - -// Describes telemetry for a VPN tunnel. -type VgwTelemetry struct { - // The number of accepted routes. - AcceptedRouteCount *int64 `locationName:"acceptedRouteCount" type:"integer"` - - // The date and time of the last change in status. - LastStatusChange *time.Time `locationName:"lastStatusChange" type:"timestamp" timestampFormat:"iso8601"` - - // The Internet-routable IP address of the virtual private gateway's outside - // interface. - OutsideIpAddress *string `locationName:"outsideIpAddress" type:"string"` - - // The status of the VPN tunnel. - Status *string `locationName:"status" type:"string" enum:"TelemetryStatus"` - - // If an error occurs, a description of the error. - StatusMessage *string `locationName:"statusMessage" type:"string"` - - metadataVgwTelemetry `json:"-" xml:"-"` -} - -type metadataVgwTelemetry struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s VgwTelemetry) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s VgwTelemetry) GoString() string { - return s.String() -} - -// Describes a volume. -type Volume struct { - // Information about the volume attachments. - Attachments []*VolumeAttachment `locationName:"attachmentSet" locationNameList:"item" type:"list"` - - // The Availability Zone for the volume. - AvailabilityZone *string `locationName:"availabilityZone" type:"string"` - - // The time stamp when volume creation was initiated. - CreateTime *time.Time `locationName:"createTime" type:"timestamp" timestampFormat:"iso8601"` - - // Indicates whether the volume will be encrypted. - Encrypted *bool `locationName:"encrypted" type:"boolean"` - - // The number of I/O operations per second (IOPS) that the volume supports. - // For Provisioned IOPS (SSD) volumes, this represents the number of IOPS that - // are provisioned for the volume. For General Purpose (SSD) volumes, this represents - // the baseline performance of the volume and the rate at which the volume accumulates - // I/O credits for bursting. For more information on General Purpose (SSD) baseline - // performance, I/O credits, and bursting, see Amazon EBS Volume Types (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html) - // in the Amazon Elastic Compute Cloud User Guide. - // - // Constraint: Range is 100 to 20000 for Provisioned IOPS (SSD) volumes and - // 3 to 10000 for General Purpose (SSD) volumes. - // - // Condition: This parameter is required for requests to create io1 volumes; - // it is not used in requests to create standard or gp2 volumes. - Iops *int64 `locationName:"iops" type:"integer"` - - // The full ARN of the AWS Key Management Service (AWS KMS) customer master - // key (CMK) that was used to protect the volume encryption key for the volume. - KmsKeyId *string `locationName:"kmsKeyId" type:"string"` - - // The size of the volume, in GiBs. - Size *int64 `locationName:"size" type:"integer"` - - // The snapshot from which the volume was created, if applicable. - SnapshotId *string `locationName:"snapshotId" type:"string"` - - // The volume state. - State *string `locationName:"status" type:"string" enum:"VolumeState"` - - // Any tags assigned to the volume. - Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - // The ID of the volume. - VolumeId *string `locationName:"volumeId" type:"string"` - - // The volume type. This can be gp2 for General Purpose (SSD) volumes, io1 for - // Provisioned IOPS (SSD) volumes, or standard for Magnetic volumes. - VolumeType *string `locationName:"volumeType" type:"string" enum:"VolumeType"` - - metadataVolume `json:"-" xml:"-"` -} - -type metadataVolume struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s Volume) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s Volume) GoString() string { - return s.String() -} - -// Describes volume attachment details. -type VolumeAttachment struct { - // The time stamp when the attachment initiated. - AttachTime *time.Time `locationName:"attachTime" type:"timestamp" timestampFormat:"iso8601"` - - // Indicates whether the EBS volume is deleted on instance termination. - DeleteOnTermination *bool `locationName:"deleteOnTermination" type:"boolean"` - - // The device name. - Device *string `locationName:"device" type:"string"` - - // The ID of the instance. - InstanceId *string `locationName:"instanceId" type:"string"` - - // The attachment state of the volume. - State *string `locationName:"status" type:"string" enum:"VolumeAttachmentState"` - - // The ID of the volume. - VolumeId *string `locationName:"volumeId" type:"string"` - - metadataVolumeAttachment `json:"-" xml:"-"` -} - -type metadataVolumeAttachment struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s VolumeAttachment) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s VolumeAttachment) GoString() string { - return s.String() -} - -// Describes an EBS volume. -type VolumeDetail struct { - // The size of the volume, in GiB. - Size *int64 `locationName:"size" type:"long" required:"true"` - - metadataVolumeDetail `json:"-" xml:"-"` -} - -type metadataVolumeDetail struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s VolumeDetail) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s VolumeDetail) GoString() string { - return s.String() -} - -// Describes a volume status operation code. -type VolumeStatusAction struct { - // The code identifying the operation, for example, enable-volume-io. - Code *string `locationName:"code" type:"string"` - - // A description of the operation. - Description *string `locationName:"description" type:"string"` - - // The ID of the event associated with this operation. - EventId *string `locationName:"eventId" type:"string"` - - // The event type associated with this operation. - EventType *string `locationName:"eventType" type:"string"` - - metadataVolumeStatusAction `json:"-" xml:"-"` -} - -type metadataVolumeStatusAction struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s VolumeStatusAction) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s VolumeStatusAction) GoString() string { - return s.String() -} - -// Describes a volume status. -type VolumeStatusDetails struct { - // The name of the volume status. - Name *string `locationName:"name" type:"string" enum:"VolumeStatusName"` - - // The intended status of the volume status. - Status *string `locationName:"status" type:"string"` - - metadataVolumeStatusDetails `json:"-" xml:"-"` -} - -type metadataVolumeStatusDetails struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s VolumeStatusDetails) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s VolumeStatusDetails) GoString() string { - return s.String() -} - -// Describes a volume status event. -type VolumeStatusEvent struct { - // A description of the event. - Description *string `locationName:"description" type:"string"` - - // The ID of this event. - EventId *string `locationName:"eventId" type:"string"` - - // The type of this event. - EventType *string `locationName:"eventType" type:"string"` - - // The latest end time of the event. - NotAfter *time.Time `locationName:"notAfter" type:"timestamp" timestampFormat:"iso8601"` - - // The earliest start time of the event. - NotBefore *time.Time `locationName:"notBefore" type:"timestamp" timestampFormat:"iso8601"` - - metadataVolumeStatusEvent `json:"-" xml:"-"` -} - -type metadataVolumeStatusEvent struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s VolumeStatusEvent) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s VolumeStatusEvent) GoString() string { - return s.String() -} - -// Describes the status of a volume. -type VolumeStatusInfo struct { - // The details of the volume status. - Details []*VolumeStatusDetails `locationName:"details" locationNameList:"item" type:"list"` - - // The status of the volume. - Status *string `locationName:"status" type:"string" enum:"VolumeStatusInfoStatus"` - - metadataVolumeStatusInfo `json:"-" xml:"-"` -} - -type metadataVolumeStatusInfo struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s VolumeStatusInfo) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s VolumeStatusInfo) GoString() string { - return s.String() -} - -// Describes the volume status. -type VolumeStatusItem struct { - // The details of the operation. - Actions []*VolumeStatusAction `locationName:"actionsSet" locationNameList:"item" type:"list"` - - // The Availability Zone of the volume. - AvailabilityZone *string `locationName:"availabilityZone" type:"string"` - - // A list of events associated with the volume. - Events []*VolumeStatusEvent `locationName:"eventsSet" locationNameList:"item" type:"list"` - - // The volume ID. - VolumeId *string `locationName:"volumeId" type:"string"` - - // The volume status. - VolumeStatus *VolumeStatusInfo `locationName:"volumeStatus" type:"structure"` - - metadataVolumeStatusItem `json:"-" xml:"-"` -} - -type metadataVolumeStatusItem struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s VolumeStatusItem) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s VolumeStatusItem) GoString() string { - return s.String() -} - -// Describes a VPC. -type Vpc struct { - // The CIDR block for the VPC. - CidrBlock *string `locationName:"cidrBlock" type:"string"` - - // The ID of the set of DHCP options you've associated with the VPC (or default - // if the default options are associated with the VPC). - DhcpOptionsId *string `locationName:"dhcpOptionsId" type:"string"` - - // The allowed tenancy of instances launched into the VPC. - InstanceTenancy *string `locationName:"instanceTenancy" type:"string" enum:"Tenancy"` - - // Indicates whether the VPC is the default VPC. - IsDefault *bool `locationName:"isDefault" type:"boolean"` - - // The current state of the VPC. - State *string `locationName:"state" type:"string" enum:"VpcState"` - - // Any tags assigned to the VPC. - Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - // The ID of the VPC. - VpcId *string `locationName:"vpcId" type:"string"` - - metadataVpc `json:"-" xml:"-"` -} - -type metadataVpc struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s Vpc) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s Vpc) GoString() string { - return s.String() -} - -// Describes an attachment between a virtual private gateway and a VPC. -type VpcAttachment struct { - // The current state of the attachment. - State *string `locationName:"state" type:"string" enum:"AttachmentStatus"` - - // The ID of the VPC. - VpcId *string `locationName:"vpcId" type:"string"` - - metadataVpcAttachment `json:"-" xml:"-"` -} - -type metadataVpcAttachment struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s VpcAttachment) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s VpcAttachment) GoString() string { - return s.String() -} - -// Describes whether a VPC is enabled for ClassicLink. -type VpcClassicLink struct { - // Indicates whether the VPC is enabled for ClassicLink. - ClassicLinkEnabled *bool `locationName:"classicLinkEnabled" type:"boolean"` - - // Any tags assigned to the VPC. - Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - // The ID of the VPC. - VpcId *string `locationName:"vpcId" type:"string"` - - metadataVpcClassicLink `json:"-" xml:"-"` -} - -type metadataVpcClassicLink struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s VpcClassicLink) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s VpcClassicLink) GoString() string { - return s.String() -} - -// Describes a VPC endpoint. -type VpcEndpoint struct { - // The date and time the VPC endpoint was created. - CreationTimestamp *time.Time `locationName:"creationTimestamp" type:"timestamp" timestampFormat:"iso8601"` - - // The policy document associated with the endpoint. - PolicyDocument *string `locationName:"policyDocument" type:"string"` - - // One or more route tables associated with the endpoint. - RouteTableIds []*string `locationName:"routeTableIdSet" locationNameList:"item" type:"list"` - - // The name of the AWS service to which the endpoint is associated. - ServiceName *string `locationName:"serviceName" type:"string"` - - // The state of the VPC endpoint. - State *string `locationName:"state" type:"string" enum:"State"` - - // The ID of the VPC endpoint. - VpcEndpointId *string `locationName:"vpcEndpointId" type:"string"` - - // The ID of the VPC to which the endpoint is associated. - VpcId *string `locationName:"vpcId" type:"string"` - - metadataVpcEndpoint `json:"-" xml:"-"` -} - -type metadataVpcEndpoint struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s VpcEndpoint) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s VpcEndpoint) GoString() string { - return s.String() -} - -// Describes a VPC peering connection. -type VpcPeeringConnection struct { - // The information of the peer VPC. - AccepterVpcInfo *VpcPeeringConnectionVpcInfo `locationName:"accepterVpcInfo" type:"structure"` - - // The time that an unaccepted VPC peering connection will expire. - ExpirationTime *time.Time `locationName:"expirationTime" type:"timestamp" timestampFormat:"iso8601"` - - // The information of the requester VPC. - RequesterVpcInfo *VpcPeeringConnectionVpcInfo `locationName:"requesterVpcInfo" type:"structure"` - - // The status of the VPC peering connection. - Status *VpcPeeringConnectionStateReason `locationName:"status" type:"structure"` - - // Any tags assigned to the resource. - Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - // The ID of the VPC peering connection. - VpcPeeringConnectionId *string `locationName:"vpcPeeringConnectionId" type:"string"` - - metadataVpcPeeringConnection `json:"-" xml:"-"` -} - -type metadataVpcPeeringConnection struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s VpcPeeringConnection) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s VpcPeeringConnection) GoString() string { - return s.String() -} - -// Describes the status of a VPC peering connection. -type VpcPeeringConnectionStateReason struct { - // The status of the VPC peering connection. - Code *string `locationName:"code" type:"string" enum:"VpcPeeringConnectionStateReasonCode"` - - // A message that provides more information about the status, if applicable. - Message *string `locationName:"message" type:"string"` - - metadataVpcPeeringConnectionStateReason `json:"-" xml:"-"` -} - -type metadataVpcPeeringConnectionStateReason struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s VpcPeeringConnectionStateReason) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s VpcPeeringConnectionStateReason) GoString() string { - return s.String() -} - -// Describes a VPC in a VPC peering connection. -type VpcPeeringConnectionVpcInfo struct { - // The CIDR block for the VPC. - CidrBlock *string `locationName:"cidrBlock" type:"string"` - - // The AWS account ID of the VPC owner. - OwnerId *string `locationName:"ownerId" type:"string"` - - // The ID of the VPC. - VpcId *string `locationName:"vpcId" type:"string"` - - metadataVpcPeeringConnectionVpcInfo `json:"-" xml:"-"` -} - -type metadataVpcPeeringConnectionVpcInfo struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s VpcPeeringConnectionVpcInfo) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s VpcPeeringConnectionVpcInfo) GoString() string { - return s.String() -} - -// Describes a VPN connection. -type VpnConnection struct { - // The configuration information for the VPN connection's customer gateway (in - // the native XML format). This element is always present in the CreateVpnConnection - // response; however, it's present in the DescribeVpnConnections response only - // if the VPN connection is in the pending or available state. - CustomerGatewayConfiguration *string `locationName:"customerGatewayConfiguration" type:"string"` - - // The ID of the customer gateway at your end of the VPN connection. - CustomerGatewayId *string `locationName:"customerGatewayId" type:"string"` - - // The VPN connection options. - Options *VpnConnectionOptions `locationName:"options" type:"structure"` - - // The static routes associated with the VPN connection. - Routes []*VpnStaticRoute `locationName:"routes" locationNameList:"item" type:"list"` - - // The current state of the VPN connection. - State *string `locationName:"state" type:"string" enum:"VpnState"` - - // Any tags assigned to the VPN connection. - Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - // The type of VPN connection. - Type *string `locationName:"type" type:"string" enum:"GatewayType"` - - // Information about the VPN tunnel. - VgwTelemetry []*VgwTelemetry `locationName:"vgwTelemetry" locationNameList:"item" type:"list"` - - // The ID of the VPN connection. - VpnConnectionId *string `locationName:"vpnConnectionId" type:"string"` - - // The ID of the virtual private gateway at the AWS side of the VPN connection. - VpnGatewayId *string `locationName:"vpnGatewayId" type:"string"` - - metadataVpnConnection `json:"-" xml:"-"` -} - -type metadataVpnConnection struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s VpnConnection) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s VpnConnection) GoString() string { - return s.String() -} - -// Describes VPN connection options. -type VpnConnectionOptions struct { - // Indicates whether the VPN connection uses static routes only. Static routes - // must be used for devices that don't support BGP. - StaticRoutesOnly *bool `locationName:"staticRoutesOnly" type:"boolean"` - - metadataVpnConnectionOptions `json:"-" xml:"-"` -} - -type metadataVpnConnectionOptions struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s VpnConnectionOptions) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s VpnConnectionOptions) GoString() string { - return s.String() -} - -// Describes VPN connection options. -type VpnConnectionOptionsSpecification struct { - // Indicates whether the VPN connection uses static routes only. Static routes - // must be used for devices that don't support BGP. - StaticRoutesOnly *bool `locationName:"staticRoutesOnly" type:"boolean"` - - metadataVpnConnectionOptionsSpecification `json:"-" xml:"-"` -} - -type metadataVpnConnectionOptionsSpecification struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s VpnConnectionOptionsSpecification) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s VpnConnectionOptionsSpecification) GoString() string { - return s.String() -} - -// Describes a virtual private gateway. -type VpnGateway struct { - // The Availability Zone where the virtual private gateway was created. - AvailabilityZone *string `locationName:"availabilityZone" type:"string"` - - // The current state of the virtual private gateway. - State *string `locationName:"state" type:"string" enum:"VpnState"` - - // Any tags assigned to the virtual private gateway. - Tags []*Tag `locationName:"tagSet" locationNameList:"item" type:"list"` - - // The type of VPN connection the virtual private gateway supports. - Type *string `locationName:"type" type:"string" enum:"GatewayType"` - - // Any VPCs attached to the virtual private gateway. - VpcAttachments []*VpcAttachment `locationName:"attachments" locationNameList:"item" type:"list"` - - // The ID of the virtual private gateway. - VpnGatewayId *string `locationName:"vpnGatewayId" type:"string"` - - metadataVpnGateway `json:"-" xml:"-"` -} - -type metadataVpnGateway struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s VpnGateway) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s VpnGateway) GoString() string { - return s.String() -} - -// Describes a static route for a VPN connection. -type VpnStaticRoute struct { - // The CIDR block associated with the local subnet of the customer data center. - DestinationCidrBlock *string `locationName:"destinationCidrBlock" type:"string"` - - // Indicates how the routes were provided. - Source *string `locationName:"source" type:"string" enum:"VpnStaticRouteSource"` - - // The current state of the static route. - State *string `locationName:"state" type:"string" enum:"VpnState"` - - metadataVpnStaticRoute `json:"-" xml:"-"` -} - -type metadataVpnStaticRoute struct { - SDKShapeTraits bool `type:"structure"` -} - -// String returns the string representation -func (s VpnStaticRoute) String() string { - return awsutil.Prettify(s) -} - -// GoString returns the string representation -func (s VpnStaticRoute) GoString() string { - return s.String() -} - -const ( - // @enum AccountAttributeName - AccountAttributeNameSupportedPlatforms = "supported-platforms" - // @enum AccountAttributeName - AccountAttributeNameDefaultVpc = "default-vpc" -) - -const ( - // @enum AllocationStrategy - AllocationStrategyLowestPrice = "lowestPrice" - // @enum AllocationStrategy - AllocationStrategyDiversified = "diversified" -) - -const ( - // @enum ArchitectureValues - ArchitectureValuesI386 = "i386" - // @enum ArchitectureValues - ArchitectureValuesX8664 = "x86_64" -) - -const ( - // @enum AttachmentStatus - AttachmentStatusAttaching = "attaching" - // @enum AttachmentStatus - AttachmentStatusAttached = "attached" - // @enum AttachmentStatus - AttachmentStatusDetaching = "detaching" - // @enum AttachmentStatus - AttachmentStatusDetached = "detached" -) - -const ( - // @enum AvailabilityZoneState - AvailabilityZoneStateAvailable = "available" - // @enum AvailabilityZoneState - AvailabilityZoneStateInformation = "information" - // @enum AvailabilityZoneState - AvailabilityZoneStateImpaired = "impaired" - // @enum AvailabilityZoneState - AvailabilityZoneStateUnavailable = "unavailable" -) - -const ( - // @enum BatchState - BatchStateSubmitted = "submitted" - // @enum BatchState - BatchStateActive = "active" - // @enum BatchState - BatchStateCancelled = "cancelled" - // @enum BatchState - BatchStateFailed = "failed" - // @enum BatchState - BatchStateCancelledRunning = "cancelled_running" - // @enum BatchState - BatchStateCancelledTerminating = "cancelled_terminating" - // @enum BatchState - BatchStateModifying = "modifying" -) - -const ( - // @enum BundleTaskState - BundleTaskStatePending = "pending" - // @enum BundleTaskState - BundleTaskStateWaitingForShutdown = "waiting-for-shutdown" - // @enum BundleTaskState - BundleTaskStateBundling = "bundling" - // @enum BundleTaskState - BundleTaskStateStoring = "storing" - // @enum BundleTaskState - BundleTaskStateCancelling = "cancelling" - // @enum BundleTaskState - BundleTaskStateComplete = "complete" - // @enum BundleTaskState - BundleTaskStateFailed = "failed" -) - -const ( - // @enum CancelBatchErrorCode - CancelBatchErrorCodeFleetRequestIdDoesNotExist = "fleetRequestIdDoesNotExist" - // @enum CancelBatchErrorCode - CancelBatchErrorCodeFleetRequestIdMalformed = "fleetRequestIdMalformed" - // @enum CancelBatchErrorCode - CancelBatchErrorCodeFleetRequestNotInCancellableState = "fleetRequestNotInCancellableState" - // @enum CancelBatchErrorCode - CancelBatchErrorCodeUnexpectedError = "unexpectedError" -) - -const ( - // @enum CancelSpotInstanceRequestState - CancelSpotInstanceRequestStateActive = "active" - // @enum CancelSpotInstanceRequestState - CancelSpotInstanceRequestStateOpen = "open" - // @enum CancelSpotInstanceRequestState - CancelSpotInstanceRequestStateClosed = "closed" - // @enum CancelSpotInstanceRequestState - CancelSpotInstanceRequestStateCancelled = "cancelled" - // @enum CancelSpotInstanceRequestState - CancelSpotInstanceRequestStateCompleted = "completed" -) - -const ( - // @enum ContainerFormat - ContainerFormatOva = "ova" -) - -const ( - // @enum ConversionTaskState - ConversionTaskStateActive = "active" - // @enum ConversionTaskState - ConversionTaskStateCancelling = "cancelling" - // @enum ConversionTaskState - ConversionTaskStateCancelled = "cancelled" - // @enum ConversionTaskState - ConversionTaskStateCompleted = "completed" -) - -const ( - // @enum CurrencyCodeValues - CurrencyCodeValuesUsd = "USD" -) - -const ( - // @enum DatafeedSubscriptionState - DatafeedSubscriptionStateActive = "Active" - // @enum DatafeedSubscriptionState - DatafeedSubscriptionStateInactive = "Inactive" -) - -const ( - // @enum DeviceType - DeviceTypeEbs = "ebs" - // @enum DeviceType - DeviceTypeInstanceStore = "instance-store" -) - -const ( - // @enum DiskImageFormat - DiskImageFormatVmdk = "VMDK" - // @enum DiskImageFormat - DiskImageFormatRaw = "RAW" - // @enum DiskImageFormat - DiskImageFormatVhd = "VHD" -) - -const ( - // @enum DomainType - DomainTypeVpc = "vpc" - // @enum DomainType - DomainTypeStandard = "standard" -) - -const ( - // @enum EventCode - EventCodeInstanceReboot = "instance-reboot" - // @enum EventCode - EventCodeSystemReboot = "system-reboot" - // @enum EventCode - EventCodeSystemMaintenance = "system-maintenance" - // @enum EventCode - EventCodeInstanceRetirement = "instance-retirement" - // @enum EventCode - EventCodeInstanceStop = "instance-stop" -) - -const ( - // @enum EventType - EventTypeInstanceChange = "instanceChange" - // @enum EventType - EventTypeFleetRequestChange = "fleetRequestChange" - // @enum EventType - EventTypeError = "error" -) - -const ( - // @enum ExcessCapacityTerminationPolicy - ExcessCapacityTerminationPolicyNoTermination = "noTermination" - // @enum ExcessCapacityTerminationPolicy - ExcessCapacityTerminationPolicyDefault = "default" -) - -const ( - // @enum ExportEnvironment - ExportEnvironmentCitrix = "citrix" - // @enum ExportEnvironment - ExportEnvironmentVmware = "vmware" - // @enum ExportEnvironment - ExportEnvironmentMicrosoft = "microsoft" -) - -const ( - // @enum ExportTaskState - ExportTaskStateActive = "active" - // @enum ExportTaskState - ExportTaskStateCancelling = "cancelling" - // @enum ExportTaskState - ExportTaskStateCancelled = "cancelled" - // @enum ExportTaskState - ExportTaskStateCompleted = "completed" -) - -const ( - // @enum FlowLogsResourceType - FlowLogsResourceTypeVpc = "VPC" - // @enum FlowLogsResourceType - FlowLogsResourceTypeSubnet = "Subnet" - // @enum FlowLogsResourceType - FlowLogsResourceTypeNetworkInterface = "NetworkInterface" -) - -const ( - // @enum GatewayType - GatewayTypeIpsec1 = "ipsec.1" -) - -const ( - // @enum HypervisorType - HypervisorTypeOvm = "ovm" - // @enum HypervisorType - HypervisorTypeXen = "xen" -) - -const ( - // @enum ImageAttributeName - ImageAttributeNameDescription = "description" - // @enum ImageAttributeName - ImageAttributeNameKernel = "kernel" - // @enum ImageAttributeName - ImageAttributeNameRamdisk = "ramdisk" - // @enum ImageAttributeName - ImageAttributeNameLaunchPermission = "launchPermission" - // @enum ImageAttributeName - ImageAttributeNameProductCodes = "productCodes" - // @enum ImageAttributeName - ImageAttributeNameBlockDeviceMapping = "blockDeviceMapping" - // @enum ImageAttributeName - ImageAttributeNameSriovNetSupport = "sriovNetSupport" -) - -const ( - // @enum ImageState - ImageStatePending = "pending" - // @enum ImageState - ImageStateAvailable = "available" - // @enum ImageState - ImageStateInvalid = "invalid" - // @enum ImageState - ImageStateDeregistered = "deregistered" - // @enum ImageState - ImageStateTransient = "transient" - // @enum ImageState - ImageStateFailed = "failed" - // @enum ImageState - ImageStateError = "error" -) - -const ( - // @enum ImageTypeValues - ImageTypeValuesMachine = "machine" - // @enum ImageTypeValues - ImageTypeValuesKernel = "kernel" - // @enum ImageTypeValues - ImageTypeValuesRamdisk = "ramdisk" -) - -const ( - // @enum InstanceAttributeName - InstanceAttributeNameInstanceType = "instanceType" - // @enum InstanceAttributeName - InstanceAttributeNameKernel = "kernel" - // @enum InstanceAttributeName - InstanceAttributeNameRamdisk = "ramdisk" - // @enum InstanceAttributeName - InstanceAttributeNameUserData = "userData" - // @enum InstanceAttributeName - InstanceAttributeNameDisableApiTermination = "disableApiTermination" - // @enum InstanceAttributeName - InstanceAttributeNameInstanceInitiatedShutdownBehavior = "instanceInitiatedShutdownBehavior" - // @enum InstanceAttributeName - InstanceAttributeNameRootDeviceName = "rootDeviceName" - // @enum InstanceAttributeName - InstanceAttributeNameBlockDeviceMapping = "blockDeviceMapping" - // @enum InstanceAttributeName - InstanceAttributeNameProductCodes = "productCodes" - // @enum InstanceAttributeName - InstanceAttributeNameSourceDestCheck = "sourceDestCheck" - // @enum InstanceAttributeName - InstanceAttributeNameGroupSet = "groupSet" - // @enum InstanceAttributeName - InstanceAttributeNameEbsOptimized = "ebsOptimized" - // @enum InstanceAttributeName - InstanceAttributeNameSriovNetSupport = "sriovNetSupport" -) - -const ( - // @enum InstanceLifecycleType - InstanceLifecycleTypeSpot = "spot" -) - -const ( - // @enum InstanceStateName - InstanceStateNamePending = "pending" - // @enum InstanceStateName - InstanceStateNameRunning = "running" - // @enum InstanceStateName - InstanceStateNameShuttingDown = "shutting-down" - // @enum InstanceStateName - InstanceStateNameTerminated = "terminated" - // @enum InstanceStateName - InstanceStateNameStopping = "stopping" - // @enum InstanceStateName - InstanceStateNameStopped = "stopped" -) - -const ( - // @enum InstanceType - InstanceTypeT1Micro = "t1.micro" - // @enum InstanceType - InstanceTypeM1Small = "m1.small" - // @enum InstanceType - InstanceTypeM1Medium = "m1.medium" - // @enum InstanceType - InstanceTypeM1Large = "m1.large" - // @enum InstanceType - InstanceTypeM1Xlarge = "m1.xlarge" - // @enum InstanceType - InstanceTypeM3Medium = "m3.medium" - // @enum InstanceType - InstanceTypeM3Large = "m3.large" - // @enum InstanceType - InstanceTypeM3Xlarge = "m3.xlarge" - // @enum InstanceType - InstanceTypeM32xlarge = "m3.2xlarge" - // @enum InstanceType - InstanceTypeM4Large = "m4.large" - // @enum InstanceType - InstanceTypeM4Xlarge = "m4.xlarge" - // @enum InstanceType - InstanceTypeM42xlarge = "m4.2xlarge" - // @enum InstanceType - InstanceTypeM44xlarge = "m4.4xlarge" - // @enum InstanceType - InstanceTypeM410xlarge = "m4.10xlarge" - // @enum InstanceType - InstanceTypeT2Micro = "t2.micro" - // @enum InstanceType - InstanceTypeT2Small = "t2.small" - // @enum InstanceType - InstanceTypeT2Medium = "t2.medium" - // @enum InstanceType - InstanceTypeT2Large = "t2.large" - // @enum InstanceType - InstanceTypeM2Xlarge = "m2.xlarge" - // @enum InstanceType - InstanceTypeM22xlarge = "m2.2xlarge" - // @enum InstanceType - InstanceTypeM24xlarge = "m2.4xlarge" - // @enum InstanceType - InstanceTypeCr18xlarge = "cr1.8xlarge" - // @enum InstanceType - InstanceTypeI2Xlarge = "i2.xlarge" - // @enum InstanceType - InstanceTypeI22xlarge = "i2.2xlarge" - // @enum InstanceType - InstanceTypeI24xlarge = "i2.4xlarge" - // @enum InstanceType - InstanceTypeI28xlarge = "i2.8xlarge" - // @enum InstanceType - InstanceTypeHi14xlarge = "hi1.4xlarge" - // @enum InstanceType - InstanceTypeHs18xlarge = "hs1.8xlarge" - // @enum InstanceType - InstanceTypeC1Medium = "c1.medium" - // @enum InstanceType - InstanceTypeC1Xlarge = "c1.xlarge" - // @enum InstanceType - InstanceTypeC3Large = "c3.large" - // @enum InstanceType - InstanceTypeC3Xlarge = "c3.xlarge" - // @enum InstanceType - InstanceTypeC32xlarge = "c3.2xlarge" - // @enum InstanceType - InstanceTypeC34xlarge = "c3.4xlarge" - // @enum InstanceType - InstanceTypeC38xlarge = "c3.8xlarge" - // @enum InstanceType - InstanceTypeC4Large = "c4.large" - // @enum InstanceType - InstanceTypeC4Xlarge = "c4.xlarge" - // @enum InstanceType - InstanceTypeC42xlarge = "c4.2xlarge" - // @enum InstanceType - InstanceTypeC44xlarge = "c4.4xlarge" - // @enum InstanceType - InstanceTypeC48xlarge = "c4.8xlarge" - // @enum InstanceType - InstanceTypeCc14xlarge = "cc1.4xlarge" - // @enum InstanceType - InstanceTypeCc28xlarge = "cc2.8xlarge" - // @enum InstanceType - InstanceTypeG22xlarge = "g2.2xlarge" - // @enum InstanceType - InstanceTypeCg14xlarge = "cg1.4xlarge" - // @enum InstanceType - InstanceTypeR3Large = "r3.large" - // @enum InstanceType - InstanceTypeR3Xlarge = "r3.xlarge" - // @enum InstanceType - InstanceTypeR32xlarge = "r3.2xlarge" - // @enum InstanceType - InstanceTypeR34xlarge = "r3.4xlarge" - // @enum InstanceType - InstanceTypeR38xlarge = "r3.8xlarge" - // @enum InstanceType - InstanceTypeD2Xlarge = "d2.xlarge" - // @enum InstanceType - InstanceTypeD22xlarge = "d2.2xlarge" - // @enum InstanceType - InstanceTypeD24xlarge = "d2.4xlarge" - // @enum InstanceType - InstanceTypeD28xlarge = "d2.8xlarge" -) - -const ( - // @enum ListingState - ListingStateAvailable = "available" - // @enum ListingState - ListingStateSold = "sold" - // @enum ListingState - ListingStateCancelled = "cancelled" - // @enum ListingState - ListingStatePending = "pending" -) - -const ( - // @enum ListingStatus - ListingStatusActive = "active" - // @enum ListingStatus - ListingStatusPending = "pending" - // @enum ListingStatus - ListingStatusCancelled = "cancelled" - // @enum ListingStatus - ListingStatusClosed = "closed" -) - -const ( - // @enum MonitoringState - MonitoringStateDisabled = "disabled" - // @enum MonitoringState - MonitoringStateDisabling = "disabling" - // @enum MonitoringState - MonitoringStateEnabled = "enabled" - // @enum MonitoringState - MonitoringStatePending = "pending" -) - -const ( - // @enum MoveStatus - MoveStatusMovingToVpc = "movingToVpc" - // @enum MoveStatus - MoveStatusRestoringToClassic = "restoringToClassic" -) - -const ( - // @enum NetworkInterfaceAttribute - NetworkInterfaceAttributeDescription = "description" - // @enum NetworkInterfaceAttribute - NetworkInterfaceAttributeGroupSet = "groupSet" - // @enum NetworkInterfaceAttribute - NetworkInterfaceAttributeSourceDestCheck = "sourceDestCheck" - // @enum NetworkInterfaceAttribute - NetworkInterfaceAttributeAttachment = "attachment" -) - -const ( - // @enum NetworkInterfaceStatus - NetworkInterfaceStatusAvailable = "available" - // @enum NetworkInterfaceStatus - NetworkInterfaceStatusAttaching = "attaching" - // @enum NetworkInterfaceStatus - NetworkInterfaceStatusInUse = "in-use" - // @enum NetworkInterfaceStatus - NetworkInterfaceStatusDetaching = "detaching" -) - -const ( - // @enum OfferingTypeValues - OfferingTypeValuesHeavyUtilization = "Heavy Utilization" - // @enum OfferingTypeValues - OfferingTypeValuesMediumUtilization = "Medium Utilization" - // @enum OfferingTypeValues - OfferingTypeValuesLightUtilization = "Light Utilization" - // @enum OfferingTypeValues - OfferingTypeValuesNoUpfront = "No Upfront" - // @enum OfferingTypeValues - OfferingTypeValuesPartialUpfront = "Partial Upfront" - // @enum OfferingTypeValues - OfferingTypeValuesAllUpfront = "All Upfront" -) - -const ( - // @enum OperationType - OperationTypeAdd = "add" - // @enum OperationType - OperationTypeRemove = "remove" -) - -const ( - // @enum PermissionGroup - PermissionGroupAll = "all" -) - -const ( - // @enum PlacementGroupState - PlacementGroupStatePending = "pending" - // @enum PlacementGroupState - PlacementGroupStateAvailable = "available" - // @enum PlacementGroupState - PlacementGroupStateDeleting = "deleting" - // @enum PlacementGroupState - PlacementGroupStateDeleted = "deleted" -) - -const ( - // @enum PlacementStrategy - PlacementStrategyCluster = "cluster" -) - -const ( - // @enum PlatformValues - PlatformValuesWindows = "Windows" -) - -const ( - // @enum ProductCodeValues - ProductCodeValuesDevpay = "devpay" - // @enum ProductCodeValues - ProductCodeValuesMarketplace = "marketplace" -) - -const ( - // @enum RIProductDescription - RIProductDescriptionLinuxUnix = "Linux/UNIX" - // @enum RIProductDescription - RIProductDescriptionLinuxUnixamazonVpc = "Linux/UNIX (Amazon VPC)" - // @enum RIProductDescription - RIProductDescriptionWindows = "Windows" - // @enum RIProductDescription - RIProductDescriptionWindowsAmazonVpc = "Windows (Amazon VPC)" -) - -const ( - // @enum RecurringChargeFrequency - RecurringChargeFrequencyHourly = "Hourly" -) - -const ( - // @enum ReportInstanceReasonCodes - ReportInstanceReasonCodesInstanceStuckInState = "instance-stuck-in-state" - // @enum ReportInstanceReasonCodes - ReportInstanceReasonCodesUnresponsive = "unresponsive" - // @enum ReportInstanceReasonCodes - ReportInstanceReasonCodesNotAcceptingCredentials = "not-accepting-credentials" - // @enum ReportInstanceReasonCodes - ReportInstanceReasonCodesPasswordNotAvailable = "password-not-available" - // @enum ReportInstanceReasonCodes - ReportInstanceReasonCodesPerformanceNetwork = "performance-network" - // @enum ReportInstanceReasonCodes - ReportInstanceReasonCodesPerformanceInstanceStore = "performance-instance-store" - // @enum ReportInstanceReasonCodes - ReportInstanceReasonCodesPerformanceEbsVolume = "performance-ebs-volume" - // @enum ReportInstanceReasonCodes - ReportInstanceReasonCodesPerformanceOther = "performance-other" - // @enum ReportInstanceReasonCodes - ReportInstanceReasonCodesOther = "other" -) - -const ( - // @enum ReportStatusType - ReportStatusTypeOk = "ok" - // @enum ReportStatusType - ReportStatusTypeImpaired = "impaired" -) - -const ( - // @enum ReservedInstanceState - ReservedInstanceStatePaymentPending = "payment-pending" - // @enum ReservedInstanceState - ReservedInstanceStateActive = "active" - // @enum ReservedInstanceState - ReservedInstanceStatePaymentFailed = "payment-failed" - // @enum ReservedInstanceState - ReservedInstanceStateRetired = "retired" -) - -const ( - // @enum ResetImageAttributeName - ResetImageAttributeNameLaunchPermission = "launchPermission" -) - -const ( - // @enum ResourceType - ResourceTypeCustomerGateway = "customer-gateway" - // @enum ResourceType - ResourceTypeDhcpOptions = "dhcp-options" - // @enum ResourceType - ResourceTypeImage = "image" - // @enum ResourceType - ResourceTypeInstance = "instance" - // @enum ResourceType - ResourceTypeInternetGateway = "internet-gateway" - // @enum ResourceType - ResourceTypeNetworkAcl = "network-acl" - // @enum ResourceType - ResourceTypeNetworkInterface = "network-interface" - // @enum ResourceType - ResourceTypeReservedInstances = "reserved-instances" - // @enum ResourceType - ResourceTypeRouteTable = "route-table" - // @enum ResourceType - ResourceTypeSnapshot = "snapshot" - // @enum ResourceType - ResourceTypeSpotInstancesRequest = "spot-instances-request" - // @enum ResourceType - ResourceTypeSubnet = "subnet" - // @enum ResourceType - ResourceTypeSecurityGroup = "security-group" - // @enum ResourceType - ResourceTypeVolume = "volume" - // @enum ResourceType - ResourceTypeVpc = "vpc" - // @enum ResourceType - ResourceTypeVpnConnection = "vpn-connection" - // @enum ResourceType - ResourceTypeVpnGateway = "vpn-gateway" -) - -const ( - // @enum RouteOrigin - RouteOriginCreateRouteTable = "CreateRouteTable" - // @enum RouteOrigin - RouteOriginCreateRoute = "CreateRoute" - // @enum RouteOrigin - RouteOriginEnableVgwRoutePropagation = "EnableVgwRoutePropagation" -) - -const ( - // @enum RouteState - RouteStateActive = "active" - // @enum RouteState - RouteStateBlackhole = "blackhole" -) - -const ( - // @enum RuleAction - RuleActionAllow = "allow" - // @enum RuleAction - RuleActionDeny = "deny" -) - -const ( - // @enum ShutdownBehavior - ShutdownBehaviorStop = "stop" - // @enum ShutdownBehavior - ShutdownBehaviorTerminate = "terminate" -) - -const ( - // @enum SnapshotAttributeName - SnapshotAttributeNameProductCodes = "productCodes" - // @enum SnapshotAttributeName - SnapshotAttributeNameCreateVolumePermission = "createVolumePermission" -) - -const ( - // @enum SnapshotState - SnapshotStatePending = "pending" - // @enum SnapshotState - SnapshotStateCompleted = "completed" - // @enum SnapshotState - SnapshotStateError = "error" -) - -const ( - // @enum SpotInstanceState - SpotInstanceStateOpen = "open" - // @enum SpotInstanceState - SpotInstanceStateActive = "active" - // @enum SpotInstanceState - SpotInstanceStateClosed = "closed" - // @enum SpotInstanceState - SpotInstanceStateCancelled = "cancelled" - // @enum SpotInstanceState - SpotInstanceStateFailed = "failed" -) - -const ( - // @enum SpotInstanceType - SpotInstanceTypeOneTime = "one-time" - // @enum SpotInstanceType - SpotInstanceTypePersistent = "persistent" -) - -const ( - // @enum State - StatePending = "Pending" - // @enum State - StateAvailable = "Available" - // @enum State - StateDeleting = "Deleting" - // @enum State - StateDeleted = "Deleted" -) - -const ( - // @enum Status - StatusMoveInProgress = "MoveInProgress" - // @enum Status - StatusInVpc = "InVpc" - // @enum Status - StatusInClassic = "InClassic" -) - -const ( - // @enum StatusName - StatusNameReachability = "reachability" -) - -const ( - // @enum StatusType - StatusTypePassed = "passed" - // @enum StatusType - StatusTypeFailed = "failed" - // @enum StatusType - StatusTypeInsufficientData = "insufficient-data" - // @enum StatusType - StatusTypeInitializing = "initializing" -) - -const ( - // @enum SubnetState - SubnetStatePending = "pending" - // @enum SubnetState - SubnetStateAvailable = "available" -) - -const ( - // @enum SummaryStatus - SummaryStatusOk = "ok" - // @enum SummaryStatus - SummaryStatusImpaired = "impaired" - // @enum SummaryStatus - SummaryStatusInsufficientData = "insufficient-data" - // @enum SummaryStatus - SummaryStatusNotApplicable = "not-applicable" - // @enum SummaryStatus - SummaryStatusInitializing = "initializing" -) - -const ( - // @enum TelemetryStatus - TelemetryStatusUp = "UP" - // @enum TelemetryStatus - TelemetryStatusDown = "DOWN" -) - -const ( - // @enum Tenancy - TenancyDefault = "default" - // @enum Tenancy - TenancyDedicated = "dedicated" -) - -const ( - // @enum TrafficType - TrafficTypeAccept = "ACCEPT" - // @enum TrafficType - TrafficTypeReject = "REJECT" - // @enum TrafficType - TrafficTypeAll = "ALL" -) - -const ( - // @enum VirtualizationType - VirtualizationTypeHvm = "hvm" - // @enum VirtualizationType - VirtualizationTypeParavirtual = "paravirtual" -) - -const ( - // @enum VolumeAttachmentState - VolumeAttachmentStateAttaching = "attaching" - // @enum VolumeAttachmentState - VolumeAttachmentStateAttached = "attached" - // @enum VolumeAttachmentState - VolumeAttachmentStateDetaching = "detaching" - // @enum VolumeAttachmentState - VolumeAttachmentStateDetached = "detached" -) - -const ( - // @enum VolumeAttributeName - VolumeAttributeNameAutoEnableIo = "autoEnableIO" - // @enum VolumeAttributeName - VolumeAttributeNameProductCodes = "productCodes" -) - -const ( - // @enum VolumeState - VolumeStateCreating = "creating" - // @enum VolumeState - VolumeStateAvailable = "available" - // @enum VolumeState - VolumeStateInUse = "in-use" - // @enum VolumeState - VolumeStateDeleting = "deleting" - // @enum VolumeState - VolumeStateDeleted = "deleted" - // @enum VolumeState - VolumeStateError = "error" -) - -const ( - // @enum VolumeStatusInfoStatus - VolumeStatusInfoStatusOk = "ok" - // @enum VolumeStatusInfoStatus - VolumeStatusInfoStatusImpaired = "impaired" - // @enum VolumeStatusInfoStatus - VolumeStatusInfoStatusInsufficientData = "insufficient-data" -) - -const ( - // @enum VolumeStatusName - VolumeStatusNameIoEnabled = "io-enabled" - // @enum VolumeStatusName - VolumeStatusNameIoPerformance = "io-performance" -) - -const ( - // @enum VolumeType - VolumeTypeStandard = "standard" - // @enum VolumeType - VolumeTypeIo1 = "io1" - // @enum VolumeType - VolumeTypeGp2 = "gp2" -) - -const ( - // @enum VpcAttributeName - VpcAttributeNameEnableDnsSupport = "enableDnsSupport" - // @enum VpcAttributeName - VpcAttributeNameEnableDnsHostnames = "enableDnsHostnames" -) - -const ( - // @enum VpcPeeringConnectionStateReasonCode - VpcPeeringConnectionStateReasonCodeInitiatingRequest = "initiating-request" - // @enum VpcPeeringConnectionStateReasonCode - VpcPeeringConnectionStateReasonCodePendingAcceptance = "pending-acceptance" - // @enum VpcPeeringConnectionStateReasonCode - VpcPeeringConnectionStateReasonCodeActive = "active" - // @enum VpcPeeringConnectionStateReasonCode - VpcPeeringConnectionStateReasonCodeDeleted = "deleted" - // @enum VpcPeeringConnectionStateReasonCode - VpcPeeringConnectionStateReasonCodeRejected = "rejected" - // @enum VpcPeeringConnectionStateReasonCode - VpcPeeringConnectionStateReasonCodeFailed = "failed" - // @enum VpcPeeringConnectionStateReasonCode - VpcPeeringConnectionStateReasonCodeExpired = "expired" - // @enum VpcPeeringConnectionStateReasonCode - VpcPeeringConnectionStateReasonCodeProvisioning = "provisioning" - // @enum VpcPeeringConnectionStateReasonCode - VpcPeeringConnectionStateReasonCodeDeleting = "deleting" -) - -const ( - // @enum VpcState - VpcStatePending = "pending" - // @enum VpcState - VpcStateAvailable = "available" -) - -const ( - // @enum VpnState - VpnStatePending = "pending" - // @enum VpnState - VpnStateAvailable = "available" - // @enum VpnState - VpnStateDeleting = "deleting" - // @enum VpnState - VpnStateDeleted = "deleted" -) - -const ( - // @enum VpnStaticRouteSource - VpnStaticRouteSourceStatic = "Static" -) diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/customizations_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/customizations_test.go deleted file mode 100644 index 195d9b55b8d..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/customizations_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package ec2_test - -import ( - "io/ioutil" - "net/url" - "testing" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/awstesting/unit" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/stretchr/testify/assert" -) - -func TestCopySnapshotPresignedURL(t *testing.T) { - svc := ec2.New(unit.Session, &aws.Config{Region: aws.String("us-west-2")}) - - assert.NotPanics(t, func() { - // Doesn't panic on nil input - req, _ := svc.CopySnapshotRequest(nil) - req.Sign() - }) - - req, _ := svc.CopySnapshotRequest(&ec2.CopySnapshotInput{ - SourceRegion: aws.String("us-west-1"), - SourceSnapshotId: aws.String("snap-id"), - }) - req.Sign() - - b, _ := ioutil.ReadAll(req.HTTPRequest.Body) - q, _ := url.ParseQuery(string(b)) - u, _ := url.QueryUnescape(q.Get("PresignedUrl")) - assert.Equal(t, "us-west-2", q.Get("DestinationRegion")) - assert.Equal(t, "us-west-1", q.Get("SourceRegion")) - assert.Regexp(t, `^https://ec2\.us-west-1\.amazonaws\.com/.+&DestinationRegion=us-west-2`, u) -} diff --git a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/examples_test.go b/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/examples_test.go deleted file mode 100644 index 86557fc15d0..00000000000 --- a/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/examples_test.go +++ /dev/null @@ -1,5188 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. - -package ec2_test - -import ( - "bytes" - "fmt" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/ec2" -) - -var _ time.Duration -var _ bytes.Buffer - -func ExampleEC2_AcceptVpcPeeringConnection() { - svc := ec2.New(session.New()) - - params := &ec2.AcceptVpcPeeringConnectionInput{ - DryRun: aws.Bool(true), - VpcPeeringConnectionId: aws.String("String"), - } - resp, err := svc.AcceptVpcPeeringConnection(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_AllocateAddress() { - svc := ec2.New(session.New()) - - params := &ec2.AllocateAddressInput{ - Domain: aws.String("DomainType"), - DryRun: aws.Bool(true), - } - resp, err := svc.AllocateAddress(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_AssignPrivateIpAddresses() { - svc := ec2.New(session.New()) - - params := &ec2.AssignPrivateIpAddressesInput{ - NetworkInterfaceId: aws.String("String"), // Required - AllowReassignment: aws.Bool(true), - PrivateIpAddresses: []*string{ - aws.String("String"), // Required - // More values... - }, - SecondaryPrivateIpAddressCount: aws.Int64(1), - } - resp, err := svc.AssignPrivateIpAddresses(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_AssociateAddress() { - svc := ec2.New(session.New()) - - params := &ec2.AssociateAddressInput{ - AllocationId: aws.String("String"), - AllowReassociation: aws.Bool(true), - DryRun: aws.Bool(true), - InstanceId: aws.String("String"), - NetworkInterfaceId: aws.String("String"), - PrivateIpAddress: aws.String("String"), - PublicIp: aws.String("String"), - } - resp, err := svc.AssociateAddress(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_AssociateDhcpOptions() { - svc := ec2.New(session.New()) - - params := &ec2.AssociateDhcpOptionsInput{ - DhcpOptionsId: aws.String("String"), // Required - VpcId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.AssociateDhcpOptions(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_AssociateRouteTable() { - svc := ec2.New(session.New()) - - params := &ec2.AssociateRouteTableInput{ - RouteTableId: aws.String("String"), // Required - SubnetId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.AssociateRouteTable(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_AttachClassicLinkVpc() { - svc := ec2.New(session.New()) - - params := &ec2.AttachClassicLinkVpcInput{ - Groups: []*string{ // Required - aws.String("String"), // Required - // More values... - }, - InstanceId: aws.String("String"), // Required - VpcId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.AttachClassicLinkVpc(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_AttachInternetGateway() { - svc := ec2.New(session.New()) - - params := &ec2.AttachInternetGatewayInput{ - InternetGatewayId: aws.String("String"), // Required - VpcId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.AttachInternetGateway(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_AttachNetworkInterface() { - svc := ec2.New(session.New()) - - params := &ec2.AttachNetworkInterfaceInput{ - DeviceIndex: aws.Int64(1), // Required - InstanceId: aws.String("String"), // Required - NetworkInterfaceId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.AttachNetworkInterface(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_AttachVolume() { - svc := ec2.New(session.New()) - - params := &ec2.AttachVolumeInput{ - Device: aws.String("String"), // Required - InstanceId: aws.String("String"), // Required - VolumeId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.AttachVolume(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_AttachVpnGateway() { - svc := ec2.New(session.New()) - - params := &ec2.AttachVpnGatewayInput{ - VpcId: aws.String("String"), // Required - VpnGatewayId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.AttachVpnGateway(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_AuthorizeSecurityGroupEgress() { - svc := ec2.New(session.New()) - - params := &ec2.AuthorizeSecurityGroupEgressInput{ - GroupId: aws.String("String"), // Required - CidrIp: aws.String("String"), - DryRun: aws.Bool(true), - FromPort: aws.Int64(1), - IpPermissions: []*ec2.IpPermission{ - { // Required - FromPort: aws.Int64(1), - IpProtocol: aws.String("String"), - IpRanges: []*ec2.IpRange{ - { // Required - CidrIp: aws.String("String"), - }, - // More values... - }, - PrefixListIds: []*ec2.PrefixListId{ - { // Required - PrefixListId: aws.String("String"), - }, - // More values... - }, - ToPort: aws.Int64(1), - UserIdGroupPairs: []*ec2.UserIdGroupPair{ - { // Required - GroupId: aws.String("String"), - GroupName: aws.String("String"), - UserId: aws.String("String"), - }, - // More values... - }, - }, - // More values... - }, - IpProtocol: aws.String("String"), - SourceSecurityGroupName: aws.String("String"), - SourceSecurityGroupOwnerId: aws.String("String"), - ToPort: aws.Int64(1), - } - resp, err := svc.AuthorizeSecurityGroupEgress(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_AuthorizeSecurityGroupIngress() { - svc := ec2.New(session.New()) - - params := &ec2.AuthorizeSecurityGroupIngressInput{ - CidrIp: aws.String("String"), - DryRun: aws.Bool(true), - FromPort: aws.Int64(1), - GroupId: aws.String("String"), - GroupName: aws.String("String"), - IpPermissions: []*ec2.IpPermission{ - { // Required - FromPort: aws.Int64(1), - IpProtocol: aws.String("String"), - IpRanges: []*ec2.IpRange{ - { // Required - CidrIp: aws.String("String"), - }, - // More values... - }, - PrefixListIds: []*ec2.PrefixListId{ - { // Required - PrefixListId: aws.String("String"), - }, - // More values... - }, - ToPort: aws.Int64(1), - UserIdGroupPairs: []*ec2.UserIdGroupPair{ - { // Required - GroupId: aws.String("String"), - GroupName: aws.String("String"), - UserId: aws.String("String"), - }, - // More values... - }, - }, - // More values... - }, - IpProtocol: aws.String("String"), - SourceSecurityGroupName: aws.String("String"), - SourceSecurityGroupOwnerId: aws.String("String"), - ToPort: aws.Int64(1), - } - resp, err := svc.AuthorizeSecurityGroupIngress(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_BundleInstance() { - svc := ec2.New(session.New()) - - params := &ec2.BundleInstanceInput{ - InstanceId: aws.String("String"), // Required - Storage: &ec2.Storage{ // Required - S3: &ec2.S3Storage{ - AWSAccessKeyId: aws.String("String"), - Bucket: aws.String("String"), - Prefix: aws.String("String"), - UploadPolicy: []byte("PAYLOAD"), - UploadPolicySignature: aws.String("String"), - }, - }, - DryRun: aws.Bool(true), - } - resp, err := svc.BundleInstance(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CancelBundleTask() { - svc := ec2.New(session.New()) - - params := &ec2.CancelBundleTaskInput{ - BundleId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.CancelBundleTask(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CancelConversionTask() { - svc := ec2.New(session.New()) - - params := &ec2.CancelConversionTaskInput{ - ConversionTaskId: aws.String("String"), // Required - DryRun: aws.Bool(true), - ReasonMessage: aws.String("String"), - } - resp, err := svc.CancelConversionTask(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CancelExportTask() { - svc := ec2.New(session.New()) - - params := &ec2.CancelExportTaskInput{ - ExportTaskId: aws.String("String"), // Required - } - resp, err := svc.CancelExportTask(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CancelImportTask() { - svc := ec2.New(session.New()) - - params := &ec2.CancelImportTaskInput{ - CancelReason: aws.String("String"), - DryRun: aws.Bool(true), - ImportTaskId: aws.String("String"), - } - resp, err := svc.CancelImportTask(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CancelReservedInstancesListing() { - svc := ec2.New(session.New()) - - params := &ec2.CancelReservedInstancesListingInput{ - ReservedInstancesListingId: aws.String("String"), // Required - } - resp, err := svc.CancelReservedInstancesListing(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CancelSpotFleetRequests() { - svc := ec2.New(session.New()) - - params := &ec2.CancelSpotFleetRequestsInput{ - SpotFleetRequestIds: []*string{ // Required - aws.String("String"), // Required - // More values... - }, - TerminateInstances: aws.Bool(true), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.CancelSpotFleetRequests(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CancelSpotInstanceRequests() { - svc := ec2.New(session.New()) - - params := &ec2.CancelSpotInstanceRequestsInput{ - SpotInstanceRequestIds: []*string{ // Required - aws.String("String"), // Required - // More values... - }, - DryRun: aws.Bool(true), - } - resp, err := svc.CancelSpotInstanceRequests(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ConfirmProductInstance() { - svc := ec2.New(session.New()) - - params := &ec2.ConfirmProductInstanceInput{ - InstanceId: aws.String("String"), // Required - ProductCode: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.ConfirmProductInstance(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CopyImage() { - svc := ec2.New(session.New()) - - params := &ec2.CopyImageInput{ - Name: aws.String("String"), // Required - SourceImageId: aws.String("String"), // Required - SourceRegion: aws.String("String"), // Required - ClientToken: aws.String("String"), - Description: aws.String("String"), - DryRun: aws.Bool(true), - } - resp, err := svc.CopyImage(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CopySnapshot() { - svc := ec2.New(session.New()) - - params := &ec2.CopySnapshotInput{ - SourceRegion: aws.String("String"), // Required - SourceSnapshotId: aws.String("String"), // Required - Description: aws.String("String"), - DestinationRegion: aws.String("String"), - DryRun: aws.Bool(true), - Encrypted: aws.Bool(true), - KmsKeyId: aws.String("String"), - PresignedUrl: aws.String("String"), - } - resp, err := svc.CopySnapshot(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateCustomerGateway() { - svc := ec2.New(session.New()) - - params := &ec2.CreateCustomerGatewayInput{ - BgpAsn: aws.Int64(1), // Required - PublicIp: aws.String("String"), // Required - Type: aws.String("GatewayType"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.CreateCustomerGateway(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateDhcpOptions() { - svc := ec2.New(session.New()) - - params := &ec2.CreateDhcpOptionsInput{ - DhcpConfigurations: []*ec2.NewDhcpConfiguration{ // Required - { // Required - Key: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - DryRun: aws.Bool(true), - } - resp, err := svc.CreateDhcpOptions(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateFlowLogs() { - svc := ec2.New(session.New()) - - params := &ec2.CreateFlowLogsInput{ - DeliverLogsPermissionArn: aws.String("String"), // Required - LogGroupName: aws.String("String"), // Required - ResourceIds: []*string{ // Required - aws.String("String"), // Required - // More values... - }, - ResourceType: aws.String("FlowLogsResourceType"), // Required - TrafficType: aws.String("TrafficType"), // Required - ClientToken: aws.String("String"), - } - resp, err := svc.CreateFlowLogs(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateImage() { - svc := ec2.New(session.New()) - - params := &ec2.CreateImageInput{ - InstanceId: aws.String("String"), // Required - Name: aws.String("String"), // Required - BlockDeviceMappings: []*ec2.BlockDeviceMapping{ - { // Required - DeviceName: aws.String("String"), - Ebs: &ec2.EbsBlockDevice{ - DeleteOnTermination: aws.Bool(true), - Encrypted: aws.Bool(true), - Iops: aws.Int64(1), - SnapshotId: aws.String("String"), - VolumeSize: aws.Int64(1), - VolumeType: aws.String("VolumeType"), - }, - NoDevice: aws.String("String"), - VirtualName: aws.String("String"), - }, - // More values... - }, - Description: aws.String("String"), - DryRun: aws.Bool(true), - NoReboot: aws.Bool(true), - } - resp, err := svc.CreateImage(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateInstanceExportTask() { - svc := ec2.New(session.New()) - - params := &ec2.CreateInstanceExportTaskInput{ - InstanceId: aws.String("String"), // Required - Description: aws.String("String"), - ExportToS3Task: &ec2.ExportToS3TaskSpecification{ - ContainerFormat: aws.String("ContainerFormat"), - DiskImageFormat: aws.String("DiskImageFormat"), - S3Bucket: aws.String("String"), - S3Prefix: aws.String("String"), - }, - TargetEnvironment: aws.String("ExportEnvironment"), - } - resp, err := svc.CreateInstanceExportTask(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateInternetGateway() { - svc := ec2.New(session.New()) - - params := &ec2.CreateInternetGatewayInput{ - DryRun: aws.Bool(true), - } - resp, err := svc.CreateInternetGateway(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateKeyPair() { - svc := ec2.New(session.New()) - - params := &ec2.CreateKeyPairInput{ - KeyName: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.CreateKeyPair(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateNetworkAcl() { - svc := ec2.New(session.New()) - - params := &ec2.CreateNetworkAclInput{ - VpcId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.CreateNetworkAcl(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateNetworkAclEntry() { - svc := ec2.New(session.New()) - - params := &ec2.CreateNetworkAclEntryInput{ - CidrBlock: aws.String("String"), // Required - Egress: aws.Bool(true), // Required - NetworkAclId: aws.String("String"), // Required - Protocol: aws.String("String"), // Required - RuleAction: aws.String("RuleAction"), // Required - RuleNumber: aws.Int64(1), // Required - DryRun: aws.Bool(true), - IcmpTypeCode: &ec2.IcmpTypeCode{ - Code: aws.Int64(1), - Type: aws.Int64(1), - }, - PortRange: &ec2.PortRange{ - From: aws.Int64(1), - To: aws.Int64(1), - }, - } - resp, err := svc.CreateNetworkAclEntry(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateNetworkInterface() { - svc := ec2.New(session.New()) - - params := &ec2.CreateNetworkInterfaceInput{ - SubnetId: aws.String("String"), // Required - Description: aws.String("String"), - DryRun: aws.Bool(true), - Groups: []*string{ - aws.String("String"), // Required - // More values... - }, - PrivateIpAddress: aws.String("String"), - PrivateIpAddresses: []*ec2.PrivateIpAddressSpecification{ - { // Required - PrivateIpAddress: aws.String("String"), // Required - Primary: aws.Bool(true), - }, - // More values... - }, - SecondaryPrivateIpAddressCount: aws.Int64(1), - } - resp, err := svc.CreateNetworkInterface(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreatePlacementGroup() { - svc := ec2.New(session.New()) - - params := &ec2.CreatePlacementGroupInput{ - GroupName: aws.String("String"), // Required - Strategy: aws.String("PlacementStrategy"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.CreatePlacementGroup(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateReservedInstancesListing() { - svc := ec2.New(session.New()) - - params := &ec2.CreateReservedInstancesListingInput{ - ClientToken: aws.String("String"), // Required - InstanceCount: aws.Int64(1), // Required - PriceSchedules: []*ec2.PriceScheduleSpecification{ // Required - { // Required - CurrencyCode: aws.String("CurrencyCodeValues"), - Price: aws.Float64(1.0), - Term: aws.Int64(1), - }, - // More values... - }, - ReservedInstancesId: aws.String("String"), // Required - } - resp, err := svc.CreateReservedInstancesListing(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateRoute() { - svc := ec2.New(session.New()) - - params := &ec2.CreateRouteInput{ - DestinationCidrBlock: aws.String("String"), // Required - RouteTableId: aws.String("String"), // Required - DryRun: aws.Bool(true), - GatewayId: aws.String("String"), - InstanceId: aws.String("String"), - NetworkInterfaceId: aws.String("String"), - VpcPeeringConnectionId: aws.String("String"), - } - resp, err := svc.CreateRoute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateRouteTable() { - svc := ec2.New(session.New()) - - params := &ec2.CreateRouteTableInput{ - VpcId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.CreateRouteTable(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateSecurityGroup() { - svc := ec2.New(session.New()) - - params := &ec2.CreateSecurityGroupInput{ - Description: aws.String("String"), // Required - GroupName: aws.String("String"), // Required - DryRun: aws.Bool(true), - VpcId: aws.String("String"), - } - resp, err := svc.CreateSecurityGroup(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateSnapshot() { - svc := ec2.New(session.New()) - - params := &ec2.CreateSnapshotInput{ - VolumeId: aws.String("String"), // Required - Description: aws.String("String"), - DryRun: aws.Bool(true), - } - resp, err := svc.CreateSnapshot(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateSpotDatafeedSubscription() { - svc := ec2.New(session.New()) - - params := &ec2.CreateSpotDatafeedSubscriptionInput{ - Bucket: aws.String("String"), // Required - DryRun: aws.Bool(true), - Prefix: aws.String("String"), - } - resp, err := svc.CreateSpotDatafeedSubscription(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateSubnet() { - svc := ec2.New(session.New()) - - params := &ec2.CreateSubnetInput{ - CidrBlock: aws.String("String"), // Required - VpcId: aws.String("String"), // Required - AvailabilityZone: aws.String("String"), - DryRun: aws.Bool(true), - } - resp, err := svc.CreateSubnet(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateTags() { - svc := ec2.New(session.New()) - - params := &ec2.CreateTagsInput{ - Resources: []*string{ // Required - aws.String("String"), // Required - // More values... - }, - Tags: []*ec2.Tag{ // Required - { // Required - Key: aws.String("String"), - Value: aws.String("String"), - }, - // More values... - }, - DryRun: aws.Bool(true), - } - resp, err := svc.CreateTags(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateVolume() { - svc := ec2.New(session.New()) - - params := &ec2.CreateVolumeInput{ - AvailabilityZone: aws.String("String"), // Required - DryRun: aws.Bool(true), - Encrypted: aws.Bool(true), - Iops: aws.Int64(1), - KmsKeyId: aws.String("String"), - Size: aws.Int64(1), - SnapshotId: aws.String("String"), - VolumeType: aws.String("VolumeType"), - } - resp, err := svc.CreateVolume(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateVpc() { - svc := ec2.New(session.New()) - - params := &ec2.CreateVpcInput{ - CidrBlock: aws.String("String"), // Required - DryRun: aws.Bool(true), - InstanceTenancy: aws.String("Tenancy"), - } - resp, err := svc.CreateVpc(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateVpcEndpoint() { - svc := ec2.New(session.New()) - - params := &ec2.CreateVpcEndpointInput{ - ServiceName: aws.String("String"), // Required - VpcId: aws.String("String"), // Required - ClientToken: aws.String("String"), - DryRun: aws.Bool(true), - PolicyDocument: aws.String("String"), - RouteTableIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.CreateVpcEndpoint(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateVpcPeeringConnection() { - svc := ec2.New(session.New()) - - params := &ec2.CreateVpcPeeringConnectionInput{ - DryRun: aws.Bool(true), - PeerOwnerId: aws.String("String"), - PeerVpcId: aws.String("String"), - VpcId: aws.String("String"), - } - resp, err := svc.CreateVpcPeeringConnection(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateVpnConnection() { - svc := ec2.New(session.New()) - - params := &ec2.CreateVpnConnectionInput{ - CustomerGatewayId: aws.String("String"), // Required - Type: aws.String("String"), // Required - VpnGatewayId: aws.String("String"), // Required - DryRun: aws.Bool(true), - Options: &ec2.VpnConnectionOptionsSpecification{ - StaticRoutesOnly: aws.Bool(true), - }, - } - resp, err := svc.CreateVpnConnection(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateVpnConnectionRoute() { - svc := ec2.New(session.New()) - - params := &ec2.CreateVpnConnectionRouteInput{ - DestinationCidrBlock: aws.String("String"), // Required - VpnConnectionId: aws.String("String"), // Required - } - resp, err := svc.CreateVpnConnectionRoute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_CreateVpnGateway() { - svc := ec2.New(session.New()) - - params := &ec2.CreateVpnGatewayInput{ - Type: aws.String("GatewayType"), // Required - AvailabilityZone: aws.String("String"), - DryRun: aws.Bool(true), - } - resp, err := svc.CreateVpnGateway(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteCustomerGateway() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteCustomerGatewayInput{ - CustomerGatewayId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DeleteCustomerGateway(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteDhcpOptions() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteDhcpOptionsInput{ - DhcpOptionsId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DeleteDhcpOptions(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteFlowLogs() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteFlowLogsInput{ - FlowLogIds: []*string{ // Required - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DeleteFlowLogs(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteInternetGateway() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteInternetGatewayInput{ - InternetGatewayId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DeleteInternetGateway(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteKeyPair() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteKeyPairInput{ - KeyName: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DeleteKeyPair(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteNetworkAcl() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteNetworkAclInput{ - NetworkAclId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DeleteNetworkAcl(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteNetworkAclEntry() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteNetworkAclEntryInput{ - Egress: aws.Bool(true), // Required - NetworkAclId: aws.String("String"), // Required - RuleNumber: aws.Int64(1), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DeleteNetworkAclEntry(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteNetworkInterface() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteNetworkInterfaceInput{ - NetworkInterfaceId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DeleteNetworkInterface(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeletePlacementGroup() { - svc := ec2.New(session.New()) - - params := &ec2.DeletePlacementGroupInput{ - GroupName: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DeletePlacementGroup(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteRoute() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteRouteInput{ - DestinationCidrBlock: aws.String("String"), // Required - RouteTableId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DeleteRoute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteRouteTable() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteRouteTableInput{ - RouteTableId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DeleteRouteTable(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteSecurityGroup() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteSecurityGroupInput{ - DryRun: aws.Bool(true), - GroupId: aws.String("String"), - GroupName: aws.String("String"), - } - resp, err := svc.DeleteSecurityGroup(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteSnapshot() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteSnapshotInput{ - SnapshotId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DeleteSnapshot(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteSpotDatafeedSubscription() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteSpotDatafeedSubscriptionInput{ - DryRun: aws.Bool(true), - } - resp, err := svc.DeleteSpotDatafeedSubscription(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteSubnet() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteSubnetInput{ - SubnetId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DeleteSubnet(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteTags() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteTagsInput{ - Resources: []*string{ // Required - aws.String("String"), // Required - // More values... - }, - DryRun: aws.Bool(true), - Tags: []*ec2.Tag{ - { // Required - Key: aws.String("String"), - Value: aws.String("String"), - }, - // More values... - }, - } - resp, err := svc.DeleteTags(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteVolume() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteVolumeInput{ - VolumeId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DeleteVolume(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteVpc() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteVpcInput{ - VpcId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DeleteVpc(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteVpcEndpoints() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteVpcEndpointsInput{ - VpcEndpointIds: []*string{ // Required - aws.String("String"), // Required - // More values... - }, - DryRun: aws.Bool(true), - } - resp, err := svc.DeleteVpcEndpoints(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteVpcPeeringConnection() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteVpcPeeringConnectionInput{ - VpcPeeringConnectionId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DeleteVpcPeeringConnection(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteVpnConnection() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteVpnConnectionInput{ - VpnConnectionId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DeleteVpnConnection(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteVpnConnectionRoute() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteVpnConnectionRouteInput{ - DestinationCidrBlock: aws.String("String"), // Required - VpnConnectionId: aws.String("String"), // Required - } - resp, err := svc.DeleteVpnConnectionRoute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeleteVpnGateway() { - svc := ec2.New(session.New()) - - params := &ec2.DeleteVpnGatewayInput{ - VpnGatewayId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DeleteVpnGateway(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DeregisterImage() { - svc := ec2.New(session.New()) - - params := &ec2.DeregisterImageInput{ - ImageId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DeregisterImage(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeAccountAttributes() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeAccountAttributesInput{ - AttributeNames: []*string{ - aws.String("AccountAttributeName"), // Required - // More values... - }, - DryRun: aws.Bool(true), - } - resp, err := svc.DescribeAccountAttributes(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeAddresses() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeAddressesInput{ - AllocationIds: []*string{ - aws.String("String"), // Required - // More values... - }, - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - PublicIps: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeAddresses(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeAvailabilityZones() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeAvailabilityZonesInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - ZoneNames: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeAvailabilityZones(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeBundleTasks() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeBundleTasksInput{ - BundleIds: []*string{ - aws.String("String"), // Required - // More values... - }, - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - } - resp, err := svc.DescribeBundleTasks(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeClassicLinkInstances() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeClassicLinkInstancesInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - InstanceIds: []*string{ - aws.String("String"), // Required - // More values... - }, - MaxResults: aws.Int64(1), - NextToken: aws.String("String"), - } - resp, err := svc.DescribeClassicLinkInstances(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeConversionTasks() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeConversionTasksInput{ - ConversionTaskIds: []*string{ - aws.String("String"), // Required - // More values... - }, - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - } - resp, err := svc.DescribeConversionTasks(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeCustomerGateways() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeCustomerGatewaysInput{ - CustomerGatewayIds: []*string{ - aws.String("String"), // Required - // More values... - }, - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - } - resp, err := svc.DescribeCustomerGateways(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeDhcpOptions() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeDhcpOptionsInput{ - DhcpOptionsIds: []*string{ - aws.String("String"), // Required - // More values... - }, - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - } - resp, err := svc.DescribeDhcpOptions(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeExportTasks() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeExportTasksInput{ - ExportTaskIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeExportTasks(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeFlowLogs() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeFlowLogsInput{ - Filter: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - FlowLogIds: []*string{ - aws.String("String"), // Required - // More values... - }, - MaxResults: aws.Int64(1), - NextToken: aws.String("String"), - } - resp, err := svc.DescribeFlowLogs(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeImageAttribute() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeImageAttributeInput{ - Attribute: aws.String("ImageAttributeName"), // Required - ImageId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DescribeImageAttribute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeImages() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeImagesInput{ - DryRun: aws.Bool(true), - ExecutableUsers: []*string{ - aws.String("String"), // Required - // More values... - }, - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - ImageIds: []*string{ - aws.String("String"), // Required - // More values... - }, - Owners: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeImages(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeImportImageTasks() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeImportImageTasksInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - ImportTaskIds: []*string{ - aws.String("String"), // Required - // More values... - }, - MaxResults: aws.Int64(1), - NextToken: aws.String("String"), - } - resp, err := svc.DescribeImportImageTasks(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeImportSnapshotTasks() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeImportSnapshotTasksInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - ImportTaskIds: []*string{ - aws.String("String"), // Required - // More values... - }, - MaxResults: aws.Int64(1), - NextToken: aws.String("String"), - } - resp, err := svc.DescribeImportSnapshotTasks(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeInstanceAttribute() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeInstanceAttributeInput{ - Attribute: aws.String("InstanceAttributeName"), // Required - InstanceId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DescribeInstanceAttribute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeInstanceStatus() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeInstanceStatusInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - IncludeAllInstances: aws.Bool(true), - InstanceIds: []*string{ - aws.String("String"), // Required - // More values... - }, - MaxResults: aws.Int64(1), - NextToken: aws.String("String"), - } - resp, err := svc.DescribeInstanceStatus(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeInstances() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeInstancesInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - InstanceIds: []*string{ - aws.String("String"), // Required - // More values... - }, - MaxResults: aws.Int64(1), - NextToken: aws.String("String"), - } - resp, err := svc.DescribeInstances(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeInternetGateways() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeInternetGatewaysInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - InternetGatewayIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeInternetGateways(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeKeyPairs() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeKeyPairsInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - KeyNames: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeKeyPairs(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeMovingAddresses() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeMovingAddressesInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - MaxResults: aws.Int64(1), - NextToken: aws.String("String"), - PublicIps: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeMovingAddresses(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeNetworkAcls() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeNetworkAclsInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - NetworkAclIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeNetworkAcls(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeNetworkInterfaceAttribute() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeNetworkInterfaceAttributeInput{ - NetworkInterfaceId: aws.String("String"), // Required - Attribute: aws.String("NetworkInterfaceAttribute"), - DryRun: aws.Bool(true), - } - resp, err := svc.DescribeNetworkInterfaceAttribute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeNetworkInterfaces() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeNetworkInterfacesInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - NetworkInterfaceIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeNetworkInterfaces(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribePlacementGroups() { - svc := ec2.New(session.New()) - - params := &ec2.DescribePlacementGroupsInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - GroupNames: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribePlacementGroups(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribePrefixLists() { - svc := ec2.New(session.New()) - - params := &ec2.DescribePrefixListsInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - MaxResults: aws.Int64(1), - NextToken: aws.String("String"), - PrefixListIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribePrefixLists(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeRegions() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeRegionsInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - RegionNames: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeRegions(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeReservedInstances() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeReservedInstancesInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - OfferingType: aws.String("OfferingTypeValues"), - ReservedInstancesIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeReservedInstances(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeReservedInstancesListings() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeReservedInstancesListingsInput{ - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - ReservedInstancesId: aws.String("String"), - ReservedInstancesListingId: aws.String("String"), - } - resp, err := svc.DescribeReservedInstancesListings(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeReservedInstancesModifications() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeReservedInstancesModificationsInput{ - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - NextToken: aws.String("String"), - ReservedInstancesModificationIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeReservedInstancesModifications(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeReservedInstancesOfferings() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeReservedInstancesOfferingsInput{ - AvailabilityZone: aws.String("String"), - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - IncludeMarketplace: aws.Bool(true), - InstanceTenancy: aws.String("Tenancy"), - InstanceType: aws.String("InstanceType"), - MaxDuration: aws.Int64(1), - MaxInstanceCount: aws.Int64(1), - MaxResults: aws.Int64(1), - MinDuration: aws.Int64(1), - NextToken: aws.String("String"), - OfferingType: aws.String("OfferingTypeValues"), - ProductDescription: aws.String("RIProductDescription"), - ReservedInstancesOfferingIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeReservedInstancesOfferings(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeRouteTables() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeRouteTablesInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - RouteTableIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeRouteTables(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeSecurityGroups() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeSecurityGroupsInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - GroupIds: []*string{ - aws.String("String"), // Required - // More values... - }, - GroupNames: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeSecurityGroups(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeSnapshotAttribute() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeSnapshotAttributeInput{ - Attribute: aws.String("SnapshotAttributeName"), // Required - SnapshotId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DescribeSnapshotAttribute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeSnapshots() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeSnapshotsInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - MaxResults: aws.Int64(1), - NextToken: aws.String("String"), - OwnerIds: []*string{ - aws.String("String"), // Required - // More values... - }, - RestorableByUserIds: []*string{ - aws.String("String"), // Required - // More values... - }, - SnapshotIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeSnapshots(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeSpotDatafeedSubscription() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeSpotDatafeedSubscriptionInput{ - DryRun: aws.Bool(true), - } - resp, err := svc.DescribeSpotDatafeedSubscription(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeSpotFleetInstances() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeSpotFleetInstancesInput{ - SpotFleetRequestId: aws.String("String"), // Required - DryRun: aws.Bool(true), - MaxResults: aws.Int64(1), - NextToken: aws.String("String"), - } - resp, err := svc.DescribeSpotFleetInstances(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeSpotFleetRequestHistory() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeSpotFleetRequestHistoryInput{ - SpotFleetRequestId: aws.String("String"), // Required - StartTime: aws.Time(time.Now()), // Required - DryRun: aws.Bool(true), - EventType: aws.String("EventType"), - MaxResults: aws.Int64(1), - NextToken: aws.String("String"), - } - resp, err := svc.DescribeSpotFleetRequestHistory(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeSpotFleetRequests() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeSpotFleetRequestsInput{ - DryRun: aws.Bool(true), - MaxResults: aws.Int64(1), - NextToken: aws.String("String"), - SpotFleetRequestIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeSpotFleetRequests(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeSpotInstanceRequests() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeSpotInstanceRequestsInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - SpotInstanceRequestIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeSpotInstanceRequests(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeSpotPriceHistory() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeSpotPriceHistoryInput{ - AvailabilityZone: aws.String("String"), - DryRun: aws.Bool(true), - EndTime: aws.Time(time.Now()), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - InstanceTypes: []*string{ - aws.String("InstanceType"), // Required - // More values... - }, - MaxResults: aws.Int64(1), - NextToken: aws.String("String"), - ProductDescriptions: []*string{ - aws.String("String"), // Required - // More values... - }, - StartTime: aws.Time(time.Now()), - } - resp, err := svc.DescribeSpotPriceHistory(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeSubnets() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeSubnetsInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - SubnetIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeSubnets(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeTags() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeTagsInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - MaxResults: aws.Int64(1), - NextToken: aws.String("String"), - } - resp, err := svc.DescribeTags(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeVolumeAttribute() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeVolumeAttributeInput{ - VolumeId: aws.String("String"), // Required - Attribute: aws.String("VolumeAttributeName"), - DryRun: aws.Bool(true), - } - resp, err := svc.DescribeVolumeAttribute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeVolumeStatus() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeVolumeStatusInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - MaxResults: aws.Int64(1), - NextToken: aws.String("String"), - VolumeIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeVolumeStatus(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeVolumes() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeVolumesInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - MaxResults: aws.Int64(1), - NextToken: aws.String("String"), - VolumeIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeVolumes(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeVpcAttribute() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeVpcAttributeInput{ - VpcId: aws.String("String"), // Required - Attribute: aws.String("VpcAttributeName"), - DryRun: aws.Bool(true), - } - resp, err := svc.DescribeVpcAttribute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeVpcClassicLink() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeVpcClassicLinkInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - VpcIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeVpcClassicLink(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeVpcEndpointServices() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeVpcEndpointServicesInput{ - DryRun: aws.Bool(true), - MaxResults: aws.Int64(1), - NextToken: aws.String("String"), - } - resp, err := svc.DescribeVpcEndpointServices(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeVpcEndpoints() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeVpcEndpointsInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - MaxResults: aws.Int64(1), - NextToken: aws.String("String"), - VpcEndpointIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeVpcEndpoints(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeVpcPeeringConnections() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeVpcPeeringConnectionsInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - VpcPeeringConnectionIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeVpcPeeringConnections(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeVpcs() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeVpcsInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - VpcIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeVpcs(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeVpnConnections() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeVpnConnectionsInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - VpnConnectionIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeVpnConnections(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DescribeVpnGateways() { - svc := ec2.New(session.New()) - - params := &ec2.DescribeVpnGatewaysInput{ - DryRun: aws.Bool(true), - Filters: []*ec2.Filter{ - { // Required - Name: aws.String("String"), - Values: []*string{ - aws.String("String"), // Required - // More values... - }, - }, - // More values... - }, - VpnGatewayIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.DescribeVpnGateways(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DetachClassicLinkVpc() { - svc := ec2.New(session.New()) - - params := &ec2.DetachClassicLinkVpcInput{ - InstanceId: aws.String("String"), // Required - VpcId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DetachClassicLinkVpc(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DetachInternetGateway() { - svc := ec2.New(session.New()) - - params := &ec2.DetachInternetGatewayInput{ - InternetGatewayId: aws.String("String"), // Required - VpcId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DetachInternetGateway(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DetachNetworkInterface() { - svc := ec2.New(session.New()) - - params := &ec2.DetachNetworkInterfaceInput{ - AttachmentId: aws.String("String"), // Required - DryRun: aws.Bool(true), - Force: aws.Bool(true), - } - resp, err := svc.DetachNetworkInterface(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DetachVolume() { - svc := ec2.New(session.New()) - - params := &ec2.DetachVolumeInput{ - VolumeId: aws.String("String"), // Required - Device: aws.String("String"), - DryRun: aws.Bool(true), - Force: aws.Bool(true), - InstanceId: aws.String("String"), - } - resp, err := svc.DetachVolume(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DetachVpnGateway() { - svc := ec2.New(session.New()) - - params := &ec2.DetachVpnGatewayInput{ - VpcId: aws.String("String"), // Required - VpnGatewayId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DetachVpnGateway(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DisableVgwRoutePropagation() { - svc := ec2.New(session.New()) - - params := &ec2.DisableVgwRoutePropagationInput{ - GatewayId: aws.String("String"), // Required - RouteTableId: aws.String("String"), // Required - } - resp, err := svc.DisableVgwRoutePropagation(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DisableVpcClassicLink() { - svc := ec2.New(session.New()) - - params := &ec2.DisableVpcClassicLinkInput{ - VpcId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DisableVpcClassicLink(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DisassociateAddress() { - svc := ec2.New(session.New()) - - params := &ec2.DisassociateAddressInput{ - AssociationId: aws.String("String"), - DryRun: aws.Bool(true), - PublicIp: aws.String("String"), - } - resp, err := svc.DisassociateAddress(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_DisassociateRouteTable() { - svc := ec2.New(session.New()) - - params := &ec2.DisassociateRouteTableInput{ - AssociationId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.DisassociateRouteTable(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_EnableVgwRoutePropagation() { - svc := ec2.New(session.New()) - - params := &ec2.EnableVgwRoutePropagationInput{ - GatewayId: aws.String("String"), // Required - RouteTableId: aws.String("String"), // Required - } - resp, err := svc.EnableVgwRoutePropagation(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_EnableVolumeIO() { - svc := ec2.New(session.New()) - - params := &ec2.EnableVolumeIOInput{ - VolumeId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.EnableVolumeIO(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_EnableVpcClassicLink() { - svc := ec2.New(session.New()) - - params := &ec2.EnableVpcClassicLinkInput{ - VpcId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.EnableVpcClassicLink(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_GetConsoleOutput() { - svc := ec2.New(session.New()) - - params := &ec2.GetConsoleOutputInput{ - InstanceId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.GetConsoleOutput(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_GetPasswordData() { - svc := ec2.New(session.New()) - - params := &ec2.GetPasswordDataInput{ - InstanceId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.GetPasswordData(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ImportImage() { - svc := ec2.New(session.New()) - - params := &ec2.ImportImageInput{ - Architecture: aws.String("String"), - ClientData: &ec2.ClientData{ - Comment: aws.String("String"), - UploadEnd: aws.Time(time.Now()), - UploadSize: aws.Float64(1.0), - UploadStart: aws.Time(time.Now()), - }, - ClientToken: aws.String("String"), - Description: aws.String("String"), - DiskContainers: []*ec2.ImageDiskContainer{ - { // Required - Description: aws.String("String"), - DeviceName: aws.String("String"), - Format: aws.String("String"), - SnapshotId: aws.String("String"), - Url: aws.String("String"), - UserBucket: &ec2.UserBucket{ - S3Bucket: aws.String("String"), - S3Key: aws.String("String"), - }, - }, - // More values... - }, - DryRun: aws.Bool(true), - Hypervisor: aws.String("String"), - LicenseType: aws.String("String"), - Platform: aws.String("String"), - RoleName: aws.String("String"), - } - resp, err := svc.ImportImage(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ImportInstance() { - svc := ec2.New(session.New()) - - params := &ec2.ImportInstanceInput{ - Platform: aws.String("PlatformValues"), // Required - Description: aws.String("String"), - DiskImages: []*ec2.DiskImage{ - { // Required - Description: aws.String("String"), - Image: &ec2.DiskImageDetail{ - Bytes: aws.Int64(1), // Required - Format: aws.String("DiskImageFormat"), // Required - ImportManifestUrl: aws.String("String"), // Required - }, - Volume: &ec2.VolumeDetail{ - Size: aws.Int64(1), // Required - }, - }, - // More values... - }, - DryRun: aws.Bool(true), - LaunchSpecification: &ec2.ImportInstanceLaunchSpecification{ - AdditionalInfo: aws.String("String"), - Architecture: aws.String("ArchitectureValues"), - GroupIds: []*string{ - aws.String("String"), // Required - // More values... - }, - GroupNames: []*string{ - aws.String("String"), // Required - // More values... - }, - InstanceInitiatedShutdownBehavior: aws.String("ShutdownBehavior"), - InstanceType: aws.String("InstanceType"), - Monitoring: aws.Bool(true), - Placement: &ec2.Placement{ - AvailabilityZone: aws.String("String"), - GroupName: aws.String("String"), - Tenancy: aws.String("Tenancy"), - }, - PrivateIpAddress: aws.String("String"), - SubnetId: aws.String("String"), - UserData: &ec2.UserData{ - Data: aws.String("String"), - }, - }, - } - resp, err := svc.ImportInstance(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ImportKeyPair() { - svc := ec2.New(session.New()) - - params := &ec2.ImportKeyPairInput{ - KeyName: aws.String("String"), // Required - PublicKeyMaterial: []byte("PAYLOAD"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.ImportKeyPair(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ImportSnapshot() { - svc := ec2.New(session.New()) - - params := &ec2.ImportSnapshotInput{ - ClientData: &ec2.ClientData{ - Comment: aws.String("String"), - UploadEnd: aws.Time(time.Now()), - UploadSize: aws.Float64(1.0), - UploadStart: aws.Time(time.Now()), - }, - ClientToken: aws.String("String"), - Description: aws.String("String"), - DiskContainer: &ec2.SnapshotDiskContainer{ - Description: aws.String("String"), - Format: aws.String("String"), - Url: aws.String("String"), - UserBucket: &ec2.UserBucket{ - S3Bucket: aws.String("String"), - S3Key: aws.String("String"), - }, - }, - DryRun: aws.Bool(true), - RoleName: aws.String("String"), - } - resp, err := svc.ImportSnapshot(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ImportVolume() { - svc := ec2.New(session.New()) - - params := &ec2.ImportVolumeInput{ - AvailabilityZone: aws.String("String"), // Required - Image: &ec2.DiskImageDetail{ // Required - Bytes: aws.Int64(1), // Required - Format: aws.String("DiskImageFormat"), // Required - ImportManifestUrl: aws.String("String"), // Required - }, - Volume: &ec2.VolumeDetail{ // Required - Size: aws.Int64(1), // Required - }, - Description: aws.String("String"), - DryRun: aws.Bool(true), - } - resp, err := svc.ImportVolume(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ModifyImageAttribute() { - svc := ec2.New(session.New()) - - params := &ec2.ModifyImageAttributeInput{ - ImageId: aws.String("String"), // Required - Attribute: aws.String("String"), - Description: &ec2.AttributeValue{ - Value: aws.String("String"), - }, - DryRun: aws.Bool(true), - LaunchPermission: &ec2.LaunchPermissionModifications{ - Add: []*ec2.LaunchPermission{ - { // Required - Group: aws.String("PermissionGroup"), - UserId: aws.String("String"), - }, - // More values... - }, - Remove: []*ec2.LaunchPermission{ - { // Required - Group: aws.String("PermissionGroup"), - UserId: aws.String("String"), - }, - // More values... - }, - }, - OperationType: aws.String("OperationType"), - ProductCodes: []*string{ - aws.String("String"), // Required - // More values... - }, - UserGroups: []*string{ - aws.String("String"), // Required - // More values... - }, - UserIds: []*string{ - aws.String("String"), // Required - // More values... - }, - Value: aws.String("String"), - } - resp, err := svc.ModifyImageAttribute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ModifyInstanceAttribute() { - svc := ec2.New(session.New()) - - params := &ec2.ModifyInstanceAttributeInput{ - InstanceId: aws.String("String"), // Required - Attribute: aws.String("InstanceAttributeName"), - BlockDeviceMappings: []*ec2.InstanceBlockDeviceMappingSpecification{ - { // Required - DeviceName: aws.String("String"), - Ebs: &ec2.EbsInstanceBlockDeviceSpecification{ - DeleteOnTermination: aws.Bool(true), - VolumeId: aws.String("String"), - }, - NoDevice: aws.String("String"), - VirtualName: aws.String("String"), - }, - // More values... - }, - DisableApiTermination: &ec2.AttributeBooleanValue{ - Value: aws.Bool(true), - }, - DryRun: aws.Bool(true), - EbsOptimized: &ec2.AttributeBooleanValue{ - Value: aws.Bool(true), - }, - Groups: []*string{ - aws.String("String"), // Required - // More values... - }, - InstanceInitiatedShutdownBehavior: &ec2.AttributeValue{ - Value: aws.String("String"), - }, - InstanceType: &ec2.AttributeValue{ - Value: aws.String("String"), - }, - Kernel: &ec2.AttributeValue{ - Value: aws.String("String"), - }, - Ramdisk: &ec2.AttributeValue{ - Value: aws.String("String"), - }, - SourceDestCheck: &ec2.AttributeBooleanValue{ - Value: aws.Bool(true), - }, - SriovNetSupport: &ec2.AttributeValue{ - Value: aws.String("String"), - }, - UserData: &ec2.BlobAttributeValue{ - Value: []byte("PAYLOAD"), - }, - Value: aws.String("String"), - } - resp, err := svc.ModifyInstanceAttribute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ModifyNetworkInterfaceAttribute() { - svc := ec2.New(session.New()) - - params := &ec2.ModifyNetworkInterfaceAttributeInput{ - NetworkInterfaceId: aws.String("String"), // Required - Attachment: &ec2.NetworkInterfaceAttachmentChanges{ - AttachmentId: aws.String("String"), - DeleteOnTermination: aws.Bool(true), - }, - Description: &ec2.AttributeValue{ - Value: aws.String("String"), - }, - DryRun: aws.Bool(true), - Groups: []*string{ - aws.String("String"), // Required - // More values... - }, - SourceDestCheck: &ec2.AttributeBooleanValue{ - Value: aws.Bool(true), - }, - } - resp, err := svc.ModifyNetworkInterfaceAttribute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ModifyReservedInstances() { - svc := ec2.New(session.New()) - - params := &ec2.ModifyReservedInstancesInput{ - ReservedInstancesIds: []*string{ // Required - aws.String("String"), // Required - // More values... - }, - TargetConfigurations: []*ec2.ReservedInstancesConfiguration{ // Required - { // Required - AvailabilityZone: aws.String("String"), - InstanceCount: aws.Int64(1), - InstanceType: aws.String("InstanceType"), - Platform: aws.String("String"), - }, - // More values... - }, - ClientToken: aws.String("String"), - } - resp, err := svc.ModifyReservedInstances(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ModifySnapshotAttribute() { - svc := ec2.New(session.New()) - - params := &ec2.ModifySnapshotAttributeInput{ - SnapshotId: aws.String("String"), // Required - Attribute: aws.String("SnapshotAttributeName"), - CreateVolumePermission: &ec2.CreateVolumePermissionModifications{ - Add: []*ec2.CreateVolumePermission{ - { // Required - Group: aws.String("PermissionGroup"), - UserId: aws.String("String"), - }, - // More values... - }, - Remove: []*ec2.CreateVolumePermission{ - { // Required - Group: aws.String("PermissionGroup"), - UserId: aws.String("String"), - }, - // More values... - }, - }, - DryRun: aws.Bool(true), - GroupNames: []*string{ - aws.String("String"), // Required - // More values... - }, - OperationType: aws.String("OperationType"), - UserIds: []*string{ - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.ModifySnapshotAttribute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ModifySpotFleetRequest() { - svc := ec2.New(session.New()) - - params := &ec2.ModifySpotFleetRequestInput{ - SpotFleetRequestId: aws.String("String"), // Required - ExcessCapacityTerminationPolicy: aws.String("ExcessCapacityTerminationPolicy"), - TargetCapacity: aws.Int64(1), - } - resp, err := svc.ModifySpotFleetRequest(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ModifySubnetAttribute() { - svc := ec2.New(session.New()) - - params := &ec2.ModifySubnetAttributeInput{ - SubnetId: aws.String("String"), // Required - MapPublicIpOnLaunch: &ec2.AttributeBooleanValue{ - Value: aws.Bool(true), - }, - } - resp, err := svc.ModifySubnetAttribute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ModifyVolumeAttribute() { - svc := ec2.New(session.New()) - - params := &ec2.ModifyVolumeAttributeInput{ - VolumeId: aws.String("String"), // Required - AutoEnableIO: &ec2.AttributeBooleanValue{ - Value: aws.Bool(true), - }, - DryRun: aws.Bool(true), - } - resp, err := svc.ModifyVolumeAttribute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ModifyVpcAttribute() { - svc := ec2.New(session.New()) - - params := &ec2.ModifyVpcAttributeInput{ - VpcId: aws.String("String"), // Required - EnableDnsHostnames: &ec2.AttributeBooleanValue{ - Value: aws.Bool(true), - }, - EnableDnsSupport: &ec2.AttributeBooleanValue{ - Value: aws.Bool(true), - }, - } - resp, err := svc.ModifyVpcAttribute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ModifyVpcEndpoint() { - svc := ec2.New(session.New()) - - params := &ec2.ModifyVpcEndpointInput{ - VpcEndpointId: aws.String("String"), // Required - AddRouteTableIds: []*string{ - aws.String("String"), // Required - // More values... - }, - DryRun: aws.Bool(true), - PolicyDocument: aws.String("String"), - RemoveRouteTableIds: []*string{ - aws.String("String"), // Required - // More values... - }, - ResetPolicy: aws.Bool(true), - } - resp, err := svc.ModifyVpcEndpoint(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_MonitorInstances() { - svc := ec2.New(session.New()) - - params := &ec2.MonitorInstancesInput{ - InstanceIds: []*string{ // Required - aws.String("String"), // Required - // More values... - }, - DryRun: aws.Bool(true), - } - resp, err := svc.MonitorInstances(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_MoveAddressToVpc() { - svc := ec2.New(session.New()) - - params := &ec2.MoveAddressToVpcInput{ - PublicIp: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.MoveAddressToVpc(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_PurchaseReservedInstancesOffering() { - svc := ec2.New(session.New()) - - params := &ec2.PurchaseReservedInstancesOfferingInput{ - InstanceCount: aws.Int64(1), // Required - ReservedInstancesOfferingId: aws.String("String"), // Required - DryRun: aws.Bool(true), - LimitPrice: &ec2.ReservedInstanceLimitPrice{ - Amount: aws.Float64(1.0), - CurrencyCode: aws.String("CurrencyCodeValues"), - }, - } - resp, err := svc.PurchaseReservedInstancesOffering(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_RebootInstances() { - svc := ec2.New(session.New()) - - params := &ec2.RebootInstancesInput{ - InstanceIds: []*string{ // Required - aws.String("String"), // Required - // More values... - }, - DryRun: aws.Bool(true), - } - resp, err := svc.RebootInstances(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_RegisterImage() { - svc := ec2.New(session.New()) - - params := &ec2.RegisterImageInput{ - Name: aws.String("String"), // Required - Architecture: aws.String("ArchitectureValues"), - BlockDeviceMappings: []*ec2.BlockDeviceMapping{ - { // Required - DeviceName: aws.String("String"), - Ebs: &ec2.EbsBlockDevice{ - DeleteOnTermination: aws.Bool(true), - Encrypted: aws.Bool(true), - Iops: aws.Int64(1), - SnapshotId: aws.String("String"), - VolumeSize: aws.Int64(1), - VolumeType: aws.String("VolumeType"), - }, - NoDevice: aws.String("String"), - VirtualName: aws.String("String"), - }, - // More values... - }, - Description: aws.String("String"), - DryRun: aws.Bool(true), - ImageLocation: aws.String("String"), - KernelId: aws.String("String"), - RamdiskId: aws.String("String"), - RootDeviceName: aws.String("String"), - SriovNetSupport: aws.String("String"), - VirtualizationType: aws.String("String"), - } - resp, err := svc.RegisterImage(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_RejectVpcPeeringConnection() { - svc := ec2.New(session.New()) - - params := &ec2.RejectVpcPeeringConnectionInput{ - VpcPeeringConnectionId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.RejectVpcPeeringConnection(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ReleaseAddress() { - svc := ec2.New(session.New()) - - params := &ec2.ReleaseAddressInput{ - AllocationId: aws.String("String"), - DryRun: aws.Bool(true), - PublicIp: aws.String("String"), - } - resp, err := svc.ReleaseAddress(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ReplaceNetworkAclAssociation() { - svc := ec2.New(session.New()) - - params := &ec2.ReplaceNetworkAclAssociationInput{ - AssociationId: aws.String("String"), // Required - NetworkAclId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.ReplaceNetworkAclAssociation(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ReplaceNetworkAclEntry() { - svc := ec2.New(session.New()) - - params := &ec2.ReplaceNetworkAclEntryInput{ - CidrBlock: aws.String("String"), // Required - Egress: aws.Bool(true), // Required - NetworkAclId: aws.String("String"), // Required - Protocol: aws.String("String"), // Required - RuleAction: aws.String("RuleAction"), // Required - RuleNumber: aws.Int64(1), // Required - DryRun: aws.Bool(true), - IcmpTypeCode: &ec2.IcmpTypeCode{ - Code: aws.Int64(1), - Type: aws.Int64(1), - }, - PortRange: &ec2.PortRange{ - From: aws.Int64(1), - To: aws.Int64(1), - }, - } - resp, err := svc.ReplaceNetworkAclEntry(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ReplaceRoute() { - svc := ec2.New(session.New()) - - params := &ec2.ReplaceRouteInput{ - DestinationCidrBlock: aws.String("String"), // Required - RouteTableId: aws.String("String"), // Required - DryRun: aws.Bool(true), - GatewayId: aws.String("String"), - InstanceId: aws.String("String"), - NetworkInterfaceId: aws.String("String"), - VpcPeeringConnectionId: aws.String("String"), - } - resp, err := svc.ReplaceRoute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ReplaceRouteTableAssociation() { - svc := ec2.New(session.New()) - - params := &ec2.ReplaceRouteTableAssociationInput{ - AssociationId: aws.String("String"), // Required - RouteTableId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.ReplaceRouteTableAssociation(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ReportInstanceStatus() { - svc := ec2.New(session.New()) - - params := &ec2.ReportInstanceStatusInput{ - Instances: []*string{ // Required - aws.String("String"), // Required - // More values... - }, - ReasonCodes: []*string{ // Required - aws.String("ReportInstanceReasonCodes"), // Required - // More values... - }, - Status: aws.String("ReportStatusType"), // Required - Description: aws.String("String"), - DryRun: aws.Bool(true), - EndTime: aws.Time(time.Now()), - StartTime: aws.Time(time.Now()), - } - resp, err := svc.ReportInstanceStatus(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_RequestSpotFleet() { - svc := ec2.New(session.New()) - - params := &ec2.RequestSpotFleetInput{ - SpotFleetRequestConfig: &ec2.SpotFleetRequestConfigData{ // Required - IamFleetRole: aws.String("String"), // Required - LaunchSpecifications: []*ec2.SpotFleetLaunchSpecification{ // Required - { // Required - AddressingType: aws.String("String"), - BlockDeviceMappings: []*ec2.BlockDeviceMapping{ - { // Required - DeviceName: aws.String("String"), - Ebs: &ec2.EbsBlockDevice{ - DeleteOnTermination: aws.Bool(true), - Encrypted: aws.Bool(true), - Iops: aws.Int64(1), - SnapshotId: aws.String("String"), - VolumeSize: aws.Int64(1), - VolumeType: aws.String("VolumeType"), - }, - NoDevice: aws.String("String"), - VirtualName: aws.String("String"), - }, - // More values... - }, - EbsOptimized: aws.Bool(true), - IamInstanceProfile: &ec2.IamInstanceProfileSpecification{ - Arn: aws.String("String"), - Name: aws.String("String"), - }, - ImageId: aws.String("String"), - InstanceType: aws.String("InstanceType"), - KernelId: aws.String("String"), - KeyName: aws.String("String"), - Monitoring: &ec2.SpotFleetMonitoring{ - Enabled: aws.Bool(true), - }, - NetworkInterfaces: []*ec2.InstanceNetworkInterfaceSpecification{ - { // Required - AssociatePublicIpAddress: aws.Bool(true), - DeleteOnTermination: aws.Bool(true), - Description: aws.String("String"), - DeviceIndex: aws.Int64(1), - Groups: []*string{ - aws.String("String"), // Required - // More values... - }, - NetworkInterfaceId: aws.String("String"), - PrivateIpAddress: aws.String("String"), - PrivateIpAddresses: []*ec2.PrivateIpAddressSpecification{ - { // Required - PrivateIpAddress: aws.String("String"), // Required - Primary: aws.Bool(true), - }, - // More values... - }, - SecondaryPrivateIpAddressCount: aws.Int64(1), - SubnetId: aws.String("String"), - }, - // More values... - }, - Placement: &ec2.SpotPlacement{ - AvailabilityZone: aws.String("String"), - GroupName: aws.String("String"), - }, - RamdiskId: aws.String("String"), - SecurityGroups: []*ec2.GroupIdentifier{ - { // Required - GroupId: aws.String("String"), - GroupName: aws.String("String"), - }, - // More values... - }, - SpotPrice: aws.String("String"), - SubnetId: aws.String("String"), - UserData: aws.String("String"), - WeightedCapacity: aws.Float64(1.0), - }, - // More values... - }, - SpotPrice: aws.String("String"), // Required - TargetCapacity: aws.Int64(1), // Required - AllocationStrategy: aws.String("AllocationStrategy"), - ClientToken: aws.String("String"), - ExcessCapacityTerminationPolicy: aws.String("ExcessCapacityTerminationPolicy"), - TerminateInstancesWithExpiration: aws.Bool(true), - ValidFrom: aws.Time(time.Now()), - ValidUntil: aws.Time(time.Now()), - }, - DryRun: aws.Bool(true), - } - resp, err := svc.RequestSpotFleet(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_RequestSpotInstances() { - svc := ec2.New(session.New()) - - params := &ec2.RequestSpotInstancesInput{ - SpotPrice: aws.String("String"), // Required - AvailabilityZoneGroup: aws.String("String"), - BlockDurationMinutes: aws.Int64(1), - ClientToken: aws.String("String"), - DryRun: aws.Bool(true), - InstanceCount: aws.Int64(1), - LaunchGroup: aws.String("String"), - LaunchSpecification: &ec2.RequestSpotLaunchSpecification{ - AddressingType: aws.String("String"), - BlockDeviceMappings: []*ec2.BlockDeviceMapping{ - { // Required - DeviceName: aws.String("String"), - Ebs: &ec2.EbsBlockDevice{ - DeleteOnTermination: aws.Bool(true), - Encrypted: aws.Bool(true), - Iops: aws.Int64(1), - SnapshotId: aws.String("String"), - VolumeSize: aws.Int64(1), - VolumeType: aws.String("VolumeType"), - }, - NoDevice: aws.String("String"), - VirtualName: aws.String("String"), - }, - // More values... - }, - EbsOptimized: aws.Bool(true), - IamInstanceProfile: &ec2.IamInstanceProfileSpecification{ - Arn: aws.String("String"), - Name: aws.String("String"), - }, - ImageId: aws.String("String"), - InstanceType: aws.String("InstanceType"), - KernelId: aws.String("String"), - KeyName: aws.String("String"), - Monitoring: &ec2.RunInstancesMonitoringEnabled{ - Enabled: aws.Bool(true), // Required - }, - NetworkInterfaces: []*ec2.InstanceNetworkInterfaceSpecification{ - { // Required - AssociatePublicIpAddress: aws.Bool(true), - DeleteOnTermination: aws.Bool(true), - Description: aws.String("String"), - DeviceIndex: aws.Int64(1), - Groups: []*string{ - aws.String("String"), // Required - // More values... - }, - NetworkInterfaceId: aws.String("String"), - PrivateIpAddress: aws.String("String"), - PrivateIpAddresses: []*ec2.PrivateIpAddressSpecification{ - { // Required - PrivateIpAddress: aws.String("String"), // Required - Primary: aws.Bool(true), - }, - // More values... - }, - SecondaryPrivateIpAddressCount: aws.Int64(1), - SubnetId: aws.String("String"), - }, - // More values... - }, - Placement: &ec2.SpotPlacement{ - AvailabilityZone: aws.String("String"), - GroupName: aws.String("String"), - }, - RamdiskId: aws.String("String"), - SecurityGroupIds: []*string{ - aws.String("String"), // Required - // More values... - }, - SecurityGroups: []*string{ - aws.String("String"), // Required - // More values... - }, - SubnetId: aws.String("String"), - UserData: aws.String("String"), - }, - Type: aws.String("SpotInstanceType"), - ValidFrom: aws.Time(time.Now()), - ValidUntil: aws.Time(time.Now()), - } - resp, err := svc.RequestSpotInstances(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ResetImageAttribute() { - svc := ec2.New(session.New()) - - params := &ec2.ResetImageAttributeInput{ - Attribute: aws.String("ResetImageAttributeName"), // Required - ImageId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.ResetImageAttribute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ResetInstanceAttribute() { - svc := ec2.New(session.New()) - - params := &ec2.ResetInstanceAttributeInput{ - Attribute: aws.String("InstanceAttributeName"), // Required - InstanceId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.ResetInstanceAttribute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ResetNetworkInterfaceAttribute() { - svc := ec2.New(session.New()) - - params := &ec2.ResetNetworkInterfaceAttributeInput{ - NetworkInterfaceId: aws.String("String"), // Required - DryRun: aws.Bool(true), - SourceDestCheck: aws.String("String"), - } - resp, err := svc.ResetNetworkInterfaceAttribute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_ResetSnapshotAttribute() { - svc := ec2.New(session.New()) - - params := &ec2.ResetSnapshotAttributeInput{ - Attribute: aws.String("SnapshotAttributeName"), // Required - SnapshotId: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.ResetSnapshotAttribute(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_RestoreAddressToClassic() { - svc := ec2.New(session.New()) - - params := &ec2.RestoreAddressToClassicInput{ - PublicIp: aws.String("String"), // Required - DryRun: aws.Bool(true), - } - resp, err := svc.RestoreAddressToClassic(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_RevokeSecurityGroupEgress() { - svc := ec2.New(session.New()) - - params := &ec2.RevokeSecurityGroupEgressInput{ - GroupId: aws.String("String"), // Required - CidrIp: aws.String("String"), - DryRun: aws.Bool(true), - FromPort: aws.Int64(1), - IpPermissions: []*ec2.IpPermission{ - { // Required - FromPort: aws.Int64(1), - IpProtocol: aws.String("String"), - IpRanges: []*ec2.IpRange{ - { // Required - CidrIp: aws.String("String"), - }, - // More values... - }, - PrefixListIds: []*ec2.PrefixListId{ - { // Required - PrefixListId: aws.String("String"), - }, - // More values... - }, - ToPort: aws.Int64(1), - UserIdGroupPairs: []*ec2.UserIdGroupPair{ - { // Required - GroupId: aws.String("String"), - GroupName: aws.String("String"), - UserId: aws.String("String"), - }, - // More values... - }, - }, - // More values... - }, - IpProtocol: aws.String("String"), - SourceSecurityGroupName: aws.String("String"), - SourceSecurityGroupOwnerId: aws.String("String"), - ToPort: aws.Int64(1), - } - resp, err := svc.RevokeSecurityGroupEgress(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_RevokeSecurityGroupIngress() { - svc := ec2.New(session.New()) - - params := &ec2.RevokeSecurityGroupIngressInput{ - CidrIp: aws.String("String"), - DryRun: aws.Bool(true), - FromPort: aws.Int64(1), - GroupId: aws.String("String"), - GroupName: aws.String("String"), - IpPermissions: []*ec2.IpPermission{ - { // Required - FromPort: aws.Int64(1), - IpProtocol: aws.String("String"), - IpRanges: []*ec2.IpRange{ - { // Required - CidrIp: aws.String("String"), - }, - // More values... - }, - PrefixListIds: []*ec2.PrefixListId{ - { // Required - PrefixListId: aws.String("String"), - }, - // More values... - }, - ToPort: aws.Int64(1), - UserIdGroupPairs: []*ec2.UserIdGroupPair{ - { // Required - GroupId: aws.String("String"), - GroupName: aws.String("String"), - UserId: aws.String("String"), - }, - // More values... - }, - }, - // More values... - }, - IpProtocol: aws.String("String"), - SourceSecurityGroupName: aws.String("String"), - SourceSecurityGroupOwnerId: aws.String("String"), - ToPort: aws.Int64(1), - } - resp, err := svc.RevokeSecurityGroupIngress(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_RunInstances() { - svc := ec2.New(session.New()) - - params := &ec2.RunInstancesInput{ - ImageId: aws.String("String"), // Required - MaxCount: aws.Int64(1), // Required - MinCount: aws.Int64(1), // Required - AdditionalInfo: aws.String("String"), - BlockDeviceMappings: []*ec2.BlockDeviceMapping{ - { // Required - DeviceName: aws.String("String"), - Ebs: &ec2.EbsBlockDevice{ - DeleteOnTermination: aws.Bool(true), - Encrypted: aws.Bool(true), - Iops: aws.Int64(1), - SnapshotId: aws.String("String"), - VolumeSize: aws.Int64(1), - VolumeType: aws.String("VolumeType"), - }, - NoDevice: aws.String("String"), - VirtualName: aws.String("String"), - }, - // More values... - }, - ClientToken: aws.String("String"), - DisableApiTermination: aws.Bool(true), - DryRun: aws.Bool(true), - EbsOptimized: aws.Bool(true), - IamInstanceProfile: &ec2.IamInstanceProfileSpecification{ - Arn: aws.String("String"), - Name: aws.String("String"), - }, - InstanceInitiatedShutdownBehavior: aws.String("ShutdownBehavior"), - InstanceType: aws.String("InstanceType"), - KernelId: aws.String("String"), - KeyName: aws.String("String"), - Monitoring: &ec2.RunInstancesMonitoringEnabled{ - Enabled: aws.Bool(true), // Required - }, - NetworkInterfaces: []*ec2.InstanceNetworkInterfaceSpecification{ - { // Required - AssociatePublicIpAddress: aws.Bool(true), - DeleteOnTermination: aws.Bool(true), - Description: aws.String("String"), - DeviceIndex: aws.Int64(1), - Groups: []*string{ - aws.String("String"), // Required - // More values... - }, - NetworkInterfaceId: aws.String("String"), - PrivateIpAddress: aws.String("String"), - PrivateIpAddresses: []*ec2.PrivateIpAddressSpecification{ - { // Required - PrivateIpAddress: aws.String("String"), // Required - Primary: aws.Bool(true), - }, - // More values... - }, - SecondaryPrivateIpAddressCount: aws.Int64(1), - SubnetId: aws.String("String"), - }, - // More values... - }, - Placement: &ec2.Placement{ - AvailabilityZone: aws.String("String"), - GroupName: aws.String("String"), - Tenancy: aws.String("Tenancy"), - }, - PrivateIpAddress: aws.String("String"), - RamdiskId: aws.String("String"), - SecurityGroupIds: []*string{ - aws.String("String"), // Required - // More values... - }, - SecurityGroups: []*string{ - aws.String("String"), // Required - // More values... - }, - SubnetId: aws.String("String"), - UserData: aws.String("String"), - } - resp, err := svc.RunInstances(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_StartInstances() { - svc := ec2.New(session.New()) - - params := &ec2.StartInstancesInput{ - InstanceIds: []*string{ // Required - aws.String("String"), // Required - // More values... - }, - AdditionalInfo: aws.String("String"), - DryRun: aws.Bool(true), - } - resp, err := svc.StartInstances(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_StopInstances() { - svc := ec2.New(session.New()) - - params := &ec2.StopInstancesInput{ - InstanceIds: []*string{ // Required - aws.String("String"), // Required - // More values... - }, - DryRun: aws.Bool(true), - Force: aws.Bool(true), - } - resp, err := svc.StopInstances(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_TerminateInstances() { - svc := ec2.New(session.New()) - - params := &ec2.TerminateInstancesInput{ - InstanceIds: []*string{ // Required - aws.String("String"), // Required - // More values... - }, - DryRun: aws.Bool(true), - } - resp, err := svc.TerminateInstances(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_UnassignPrivateIpAddresses() { - svc := ec2.New(session.New()) - - params := &ec2.UnassignPrivateIpAddressesInput{ - NetworkInterfaceId: aws.String("String"), // Required - PrivateIpAddresses: []*string{ // Required - aws.String("String"), // Required - // More values... - }, - } - resp, err := svc.UnassignPrivateIpAddresses(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} - -func ExampleEC2_UnmonitorInstances() { - svc := ec2.New(session.New()) - - params := &ec2.UnmonitorInstancesInput{ - InstanceIds: []*string{ // Required - aws.String("String"), // Required - // More values... - }, - DryRun: aws.Bool(true), - } - resp, err := svc.UnmonitorInstances(params) - - if err != nil { - // Print the error, cast err to awserr.Error to get the Code and - // Message from an error. - fmt.Println(err.Error()) - return - } - - // Pretty-print the response data. - fmt.Println(resp) -} diff --git a/Godeps/_workspace/src/github.com/franela/goreq/.gitignore b/Godeps/_workspace/src/github.com/franela/goreq/.gitignore deleted file mode 100644 index 131fc16fbbc..00000000000 --- a/Godeps/_workspace/src/github.com/franela/goreq/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe - -src diff --git a/Godeps/_workspace/src/github.com/franela/goreq/.travis.yml b/Godeps/_workspace/src/github.com/franela/goreq/.travis.yml deleted file mode 100644 index d5041b4961f..00000000000 --- a/Godeps/_workspace/src/github.com/franela/goreq/.travis.yml +++ /dev/null @@ -1,8 +0,0 @@ -language: go -go: - - 1.5.3 - - tip -notifications: - email: - - ionathan@gmail.com - - marcosnils@gmail.com diff --git a/Godeps/_workspace/src/github.com/franela/goreq/Makefile b/Godeps/_workspace/src/github.com/franela/goreq/Makefile deleted file mode 100644 index 0f04d6572df..00000000000 --- a/Godeps/_workspace/src/github.com/franela/goreq/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -test: - go get -v -d -t ./... - go test -v diff --git a/Godeps/_workspace/src/github.com/franela/goreq/README.md b/Godeps/_workspace/src/github.com/franela/goreq/README.md deleted file mode 100644 index b6a0bfd2e1f..00000000000 --- a/Godeps/_workspace/src/github.com/franela/goreq/README.md +++ /dev/null @@ -1,444 +0,0 @@ -[![Build Status](https://img.shields.io/travis/franela/goreq/master.svg)](https://travis-ci.org/franela/goreq) -[![GoDoc](https://godoc.org/github.com/franela/goreq?status.svg)](https://godoc.org/github.com/franela/goreq) - -GoReq -======= - -Simple and sane HTTP request library for Go language. - - - -**Table of Contents** - -- [Why GoReq?](#user-content-why-goreq) -- [How do I install it?](#user-content-how-do-i-install-it) -- [What can I do with it?](#user-content-what-can-i-do-with-it) - - [Making requests with different methods](#user-content-making-requests-with-different-methods) - - [GET](#user-content-get) - - [Tags](#user-content-tags) - - [POST](#user-content-post) - - [Sending payloads in the Body](#user-content-sending-payloads-in-the-body) - - [Specifiying request headers](#user-content-specifiying-request-headers) - - [Sending Cookies](#cookie-support) - - [Setting timeouts](#user-content-setting-timeouts) - - [Using the Response and Error](#user-content-using-the-response-and-error) - - [Receiving JSON](#user-content-receiving-json) - - [Sending/Receiving Compressed Payloads](#user-content-sendingreceiving-compressed-payloads) - - [Using gzip compression:](#user-content-using-gzip-compression) - - [Using deflate compression:](#user-content-using-deflate-compression) - - [Using compressed responses:](#user-content-using-compressed-responses) - - [Proxy](#proxy) - - [Debugging requests](#debug) - - [Getting raw Request & Response](#getting-raw-request--response) - - [TODO:](#user-content-todo) - - - -Why GoReq? -========== - -Go has very nice native libraries that allows you to do lots of cool things. But sometimes those libraries are too low level, which means that to do a simple thing, like an HTTP Request, it takes some time. And if you want to do something as simple as adding a timeout to a request, you will end up writing several lines of code. - -This is why we think GoReq is useful. Because you can do all your HTTP requests in a very simple and comprehensive way, while enabling you to do more advanced stuff by giving you access to the native API. - -How do I install it? -==================== - -```bash -go get github.com/franela/goreq -``` - -What can I do with it? -====================== - -## Making requests with different methods - -#### GET -```go -res, err := goreq.Request{ Uri: "http://www.google.com" }.Do() -``` - -GoReq default method is GET. - -You can also set value to GET method easily - -```go -type Item struct { - Limit int - Skip int - Fields string -} - -item := Item { - Limit: 3, - Skip: 5, - Fields: "Value", -} - -res, err := goreq.Request{ - Uri: "http://localhost:3000/", - QueryString: item, -}.Do() -``` -The sample above will send `http://localhost:3000/?limit=3&skip=5&fields=Value` - -Alternatively the `url` tag can be used in struct fields to customize encoding properties - -```go -type Item struct { - TheLimit int `url:"the_limit"` - TheSkip string `url:"the_skip,omitempty"` - TheFields string `url:"-"` -} - -item := Item { - TheLimit: 3, - TheSkip: "", - TheFields: "Value", -} - -res, err := goreq.Request{ - Uri: "http://localhost:3000/", - QueryString: item, -}.Do() -``` -The sample above will send `http://localhost:3000/?the_limit=3` - - -QueryString also support url.Values - -```go -item := url.Values{} -item.Set("Limit", 3) -item.Add("Field", "somefield") -item.Add("Field", "someotherfield") - -res, err := goreq.Request{ - Uri: "http://localhost:3000/", - QueryString: item, -}.Do() -``` - -The sample above will send `http://localhost:3000/?limit=3&field=somefield&field=someotherfield` - -### Tags - -Struct field `url` tag is mainly used as the request parameter name. -Tags can be comma separated multiple values, 1st value is for naming and rest has special meanings. - -- special tag for 1st value - - `-`: value is ignored if set this - -- special tag for rest 2nd value - - `omitempty`: zero-value is ignored if set this - - `squash`: the fields of embedded struct is used for parameter - -#### Tag Examples - -```go -type Place struct { - Country string `url:"country"` - City string `url:"city"` - ZipCode string `url:"zipcode,omitempty"` -} - -type Person struct { - Place `url:",squash"` - - FirstName string `url:"first_name"` - LastName string `url:"last_name"` - Age string `url:"age,omitempty"` - Password string `url:"-"` -} - -johnbull := Person{ - Place: Place{ // squash the embedded struct value - Country: "UK", - City: "London", - ZipCode: "SW1", - }, - FirstName: "John", - LastName: "Doe", - Age: "35", - Password: "my-secret", // ignored for parameter -} - -goreq.Request{ - Uri: "http://localhost/", - QueryString: johnbull, -}.Do() -// => `http://localhost/?first_name=John&last_name=Doe&age=35&country=UK&city=London&zip_code=SW1` - - -// age and zipcode will be ignored because of `omitempty` -// but firstname isn't. -samurai := Person{ - Place: Place{ // squash the embedded struct value - Country: "Japan", - City: "Tokyo", - }, - LastName: "Yagyu", -} - -goreq.Request{ - Uri: "http://localhost/", - QueryString: samurai, -}.Do() -// => `http://localhost/?first_name=&last_name=yagyu&country=Japan&city=Tokyo` -``` - - -#### POST - -```go -res, err := goreq.Request{ Method: "POST", Uri: "http://www.google.com" }.Do() -``` - -## Sending payloads in the Body - -You can send ```string```, ```Reader``` or ```interface{}``` in the body. The first two will be sent as text. The last one will be marshalled to JSON, if possible. - -```go -type Item struct { - Id int - Name string -} - -item := Item{ Id: 1111, Name: "foobar" } - -res, err := goreq.Request{ - Method: "POST", - Uri: "http://www.google.com", - Body: item, -}.Do() -``` - -## Specifiying request headers - -We think that most of the times the request headers that you use are: ```Host```, ```Content-Type```, ```Accept``` and ```User-Agent```. This is why we decided to make it very easy to set these headers. - -```go -res, err := goreq.Request{ - Uri: "http://www.google.com", - Host: "foobar.com", - Accept: "application/json", - ContentType: "application/json", - UserAgent: "goreq", -}.Do() -``` - -But sometimes you need to set other headers. You can still do it. - -```go -req := goreq.Request{ Uri: "http://www.google.com" } - -req.AddHeader("X-Custom", "somevalue") - -req.Do() -``` - -Alternatively you can use the `WithHeader` function to keep the syntax short - -```go -res, err = goreq.Request{ Uri: "http://www.google.com" }.WithHeader("X-Custom", "somevalue").Do() -``` - -## Cookie support - -Cookies can be either set at the request level by sending a [CookieJar](http://golang.org/pkg/net/http/cookiejar/) in the `CookieJar` request field -or you can use goreq's one-liner WithCookie method as shown below - -```go -res, err := goreq.Request{ - Uri: "http://www.google.com", -}. -WithCookie(&http.Cookie{Name: "c1", Value: "v1"}). -Do() -``` - -## Setting timeouts - -GoReq supports 2 kind of timeouts. A general connection timeout and a request specific one. By default the connection timeout is of 1 second. There is no default for request timeout, which means it will wait forever. - -You can change the connection timeout doing: - -```go -goreq.SetConnectTimeout(100 * time.Millisecond) -``` - -And specify the request timeout doing: - -```go -res, err := goreq.Request{ - Uri: "http://www.google.com", - Timeout: 500 * time.Millisecond, -}.Do() -``` - -## Using the Response and Error - -GoReq will always return 2 values: a ```Response``` and an ```Error```. -If ```Error``` is not ```nil``` it means that an error happened while doing the request and you shouldn't use the ```Response``` in any way. -You can check what happened by getting the error message: - -```go -fmt.Println(err.Error()) -``` -And to make it easy to know if it was a timeout error, you can ask the error or return it: - -```go -if serr, ok := err.(*goreq.Error); ok { - if serr.Timeout() { - ... - } -} -return err -``` - -If you don't get an error, you can safely use the ```Response```. - -```go -res.Uri // return final URL location of the response (fulfilled after redirect was made) -res.StatusCode // return the status code of the response -res.Body // gives you access to the body -res.Body.ToString() // will return the body as a string -res.Header.Get("Content-Type") // gives you access to all the response headers -``` -Remember that you should **always** close `res.Body` if it's not `nil` - -## Receiving JSON - -GoReq will help you to receive and unmarshal JSON. - -```go -type Item struct { - Id int - Name string -} - -var item Item - -res.Body.FromJsonTo(&item) -``` - -## Sending/Receiving Compressed Payloads -GoReq supports gzip, deflate and zlib compression of requests' body and transparent decompression of responses provided they have a correct `Content-Encoding` header. - -#####Using gzip compression: -```go -res, err := goreq.Request{ - Method: "POST", - Uri: "http://www.google.com", - Body: item, - Compression: goreq.Gzip(), -}.Do() -``` -#####Using deflate/zlib compression: -```go -res, err := goreq.Request{ - Method: "POST", - Uri: "http://www.google.com", - Body: item, - Compression: goreq.Deflate(), -}.Do() -``` -#####Using compressed responses: -If servers replies a correct and matching `Content-Encoding` header (gzip requires `Content-Encoding: gzip` and deflate `Content-Encoding: deflate`) goreq transparently decompresses the response so the previous example should always work: -```go -type Item struct { - Id int - Name string -} -res, err := goreq.Request{ - Method: "POST", - Uri: "http://www.google.com", - Body: item, - Compression: goreq.Gzip(), -}.Do() -var item Item -res.Body.FromJsonTo(&item) -``` -If no `Content-Encoding` header is replied by the server GoReq will return the crude response. - -## Proxy -If you need to use a proxy for your requests GoReq supports the standard `http_proxy` env variable as well as manually setting the proxy for each request - -```go -res, err := goreq.Request{ - Method: "GET", - Proxy: "http://myproxy:myproxyport", - Uri: "http://www.google.com", -}.Do() -``` - -### Proxy basic auth is also supported - -```go -res, err := goreq.Request{ - Method: "GET", - Proxy: "http://user:pass@myproxy:myproxyport", - Uri: "http://www.google.com", -}.Do() -``` - -## Debug -If you need to debug your http requests, it can print the http request detail. - -```go -res, err := goreq.Request{ - Method: "GET", - Uri: "http://www.google.com", - Compression: goreq.Gzip(), - ShowDebug: true, -}.Do() -fmt.Println(res, err) -``` - -and it will print the log: -``` -GET / HTTP/1.1 -Host: www.google.com -Accept: -Accept-Encoding: gzip -Content-Encoding: gzip -Content-Type: -``` - - -### Getting raw Request & Response - -To get the Request: - -```go -req := goreq.Request{ - Host: "foobar.com", -} - -//req.Request will return a new instance of an http.Request so you can safely use it for something else -request, _ := req.NewRequest() - -``` - - -To get the Response: - -```go -res, err := goreq.Request{ - Method: "GET", - Uri: "http://www.google.com", - Compression: goreq.Gzip(), - ShowDebug: true, -}.Do() - -// res.Response will contain the original http.Response structure -fmt.Println(res.Response, err) -``` - - - - -TODO: ------ - -We do have a couple of [issues](https://github.com/franela/goreq/issues) pending we'll be addressing soon. But feel free to -contribute and send us PRs (with tests please :smile:). diff --git a/Godeps/_workspace/src/github.com/franela/goreq/goreq.go b/Godeps/_workspace/src/github.com/franela/goreq/goreq.go deleted file mode 100644 index ffa5ea82200..00000000000 --- a/Godeps/_workspace/src/github.com/franela/goreq/goreq.go +++ /dev/null @@ -1,491 +0,0 @@ -package goreq - -import ( - "bufio" - "bytes" - "compress/gzip" - "compress/zlib" - "crypto/tls" - "encoding/json" - "errors" - "fmt" - "io" - "io/ioutil" - "log" - "net" - "net/http" - "net/http/httputil" - "net/url" - "reflect" - "strings" - "time" -) - -type itimeout interface { - Timeout() bool -} -type Request struct { - headers []headerTuple - cookies []*http.Cookie - Method string - Uri string - Body interface{} - QueryString interface{} - Timeout time.Duration - ContentType string - Accept string - Host string - UserAgent string - Insecure bool - MaxRedirects int - RedirectHeaders bool - Proxy string - Compression *compression - BasicAuthUsername string - BasicAuthPassword string - CookieJar http.CookieJar - ShowDebug bool - OnBeforeRequest func(goreq *Request, httpreq *http.Request) -} - -type compression struct { - writer func(buffer io.Writer) (io.WriteCloser, error) - reader func(buffer io.Reader) (io.ReadCloser, error) - ContentEncoding string -} - -type Response struct { - *http.Response - Uri string - Body *Body - req *http.Request -} - -func (r Response) CancelRequest() { - cancelRequest(DefaultTransport, r.req) - -} - -func cancelRequest(transport interface{}, r *http.Request) { - if tp, ok := transport.(transportRequestCanceler); ok { - tp.CancelRequest(r) - } -} - -type headerTuple struct { - name string - value string -} - -type Body struct { - reader io.ReadCloser - compressedReader io.ReadCloser -} - -type Error struct { - timeout bool - Err error -} - -type transportRequestCanceler interface { - CancelRequest(*http.Request) -} - -func (e *Error) Timeout() bool { - return e.timeout -} - -func (e *Error) Error() string { - return e.Err.Error() -} - -func (b *Body) Read(p []byte) (int, error) { - if b.compressedReader != nil { - return b.compressedReader.Read(p) - } - return b.reader.Read(p) -} - -func (b *Body) Close() error { - err := b.reader.Close() - if b.compressedReader != nil { - return b.compressedReader.Close() - } - return err -} - -func (b *Body) FromJsonTo(o interface{}) error { - return json.NewDecoder(b).Decode(o) -} - -func (b *Body) ToString() (string, error) { - body, err := ioutil.ReadAll(b) - if err != nil { - return "", err - } - return string(body), nil -} - -func Gzip() *compression { - reader := func(buffer io.Reader) (io.ReadCloser, error) { - return gzip.NewReader(buffer) - } - writer := func(buffer io.Writer) (io.WriteCloser, error) { - return gzip.NewWriter(buffer), nil - } - return &compression{writer: writer, reader: reader, ContentEncoding: "gzip"} -} - -func Deflate() *compression { - reader := func(buffer io.Reader) (io.ReadCloser, error) { - return zlib.NewReader(buffer) - } - writer := func(buffer io.Writer) (io.WriteCloser, error) { - return zlib.NewWriter(buffer), nil - } - return &compression{writer: writer, reader: reader, ContentEncoding: "deflate"} -} - -func Zlib() *compression { - return Deflate() -} - -func paramParse(query interface{}) (string, error) { - switch query.(type) { - case url.Values: - return query.(url.Values).Encode(), nil - case *url.Values: - return query.(*url.Values).Encode(), nil - default: - var v = &url.Values{} - err := paramParseStruct(v, query) - return v.Encode(), err - } -} - -func paramParseStruct(v *url.Values, query interface{}) error { - var ( - s = reflect.ValueOf(query) - t = reflect.TypeOf(query) - ) - for t.Kind() == reflect.Ptr || t.Kind() == reflect.Interface { - s = s.Elem() - t = s.Type() - } - - if t.Kind() != reflect.Struct { - return errors.New("Can not parse QueryString.") - } - - for i := 0; i < t.NumField(); i++ { - var name string - - field := s.Field(i) - typeField := t.Field(i) - - if !field.CanInterface() { - continue - } - - urlTag := typeField.Tag.Get("url") - if urlTag == "-" { - continue - } - - name, opts := parseTag(urlTag) - - var omitEmpty, squash bool - omitEmpty = opts.Contains("omitempty") - squash = opts.Contains("squash") - - if squash { - err := paramParseStruct(v, field.Interface()) - if err != nil { - return err - } - continue - } - - if urlTag == "" { - name = strings.ToLower(typeField.Name) - } - - if val := fmt.Sprintf("%v", field.Interface()); !(omitEmpty && len(val) == 0) { - v.Add(name, val) - } - } - return nil -} - -func prepareRequestBody(b interface{}) (io.Reader, error) { - switch b.(type) { - case string: - // treat is as text - return strings.NewReader(b.(string)), nil - case io.Reader: - // treat is as text - return b.(io.Reader), nil - case []byte: - //treat as byte array - return bytes.NewReader(b.([]byte)), nil - case nil: - return nil, nil - default: - // try to jsonify it - j, err := json.Marshal(b) - if err == nil { - return bytes.NewReader(j), nil - } - return nil, err - } -} - -var DefaultDialer = &net.Dialer{Timeout: 1000 * time.Millisecond} -var DefaultTransport http.RoundTripper = &http.Transport{Dial: DefaultDialer.Dial, Proxy: http.ProxyFromEnvironment} -var DefaultClient = &http.Client{Transport: DefaultTransport} - -var proxyTransport http.RoundTripper -var proxyClient *http.Client - -func SetConnectTimeout(duration time.Duration) { - DefaultDialer.Timeout = duration -} - -func (r *Request) AddHeader(name string, value string) { - if r.headers == nil { - r.headers = []headerTuple{} - } - r.headers = append(r.headers, headerTuple{name: name, value: value}) -} - -func (r Request) WithHeader(name string, value string) Request { - r.AddHeader(name, value) - return r -} - -func (r *Request) AddCookie(c *http.Cookie) { - r.cookies = append(r.cookies, c) -} - -func (r Request) WithCookie(c *http.Cookie) Request { - r.AddCookie(c) - return r - -} - -func (r Request) Do() (*Response, error) { - var client = DefaultClient - var transport = DefaultTransport - var resUri string - var redirectFailed bool - - r.Method = valueOrDefault(r.Method, "GET") - - // use a client with a cookie jar if necessary. We create a new client not - // to modify the default one. - if r.CookieJar != nil { - client = &http.Client{ - Transport: transport, - Jar: r.CookieJar, - } - } - - if r.Proxy != "" { - proxyUrl, err := url.Parse(r.Proxy) - if err != nil { - // proxy address is in a wrong format - return nil, &Error{Err: err} - } - - //If jar is specified new client needs to be built - if proxyTransport == nil || client.Jar != nil { - proxyTransport = &http.Transport{Dial: DefaultDialer.Dial, Proxy: http.ProxyURL(proxyUrl)} - proxyClient = &http.Client{Transport: proxyTransport, Jar: client.Jar} - } else if proxyTransport, ok := proxyTransport.(*http.Transport); ok { - proxyTransport.Proxy = http.ProxyURL(proxyUrl) - } - transport = proxyTransport - client = proxyClient - } - - client.CheckRedirect = func(req *http.Request, via []*http.Request) error { - - if len(via) > r.MaxRedirects { - redirectFailed = true - return errors.New("Error redirecting. MaxRedirects reached") - } - - resUri = req.URL.String() - - //By default Golang will not redirect request headers - // https://code.google.com/p/go/issues/detail?id=4800&q=request%20header - if r.RedirectHeaders { - for key, val := range via[0].Header { - req.Header[key] = val - } - } - return nil - } - - if transport, ok := transport.(*http.Transport); ok { - if r.Insecure { - if transport.TLSClientConfig != nil { - transport.TLSClientConfig.InsecureSkipVerify = true - } else { - transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} - } - } else if transport.TLSClientConfig != nil { - // the default TLS client (when transport.TLSClientConfig==nil) is - // already set to verify, so do nothing in that case - transport.TLSClientConfig.InsecureSkipVerify = false - } - } - - req, err := r.NewRequest() - - if err != nil { - // we couldn't parse the URL. - return nil, &Error{Err: err} - } - - timeout := false - if r.Timeout > 0 { - client.Timeout = r.Timeout - } - - if r.ShowDebug { - dump, err := httputil.DumpRequest(req, true) - if err != nil { - log.Println(err) - } - log.Println(string(dump)) - } - - if r.OnBeforeRequest != nil { - r.OnBeforeRequest(&r, req) - } - res, err := client.Do(req) - - if err != nil { - if !timeout { - if t, ok := err.(itimeout); ok { - timeout = t.Timeout() - } - if ue, ok := err.(*url.Error); ok { - if t, ok := ue.Err.(itimeout); ok { - timeout = t.Timeout() - } - } - } - - var response *Response - //If redirect fails we still want to return response data - if redirectFailed { - if res != nil { - response = &Response{res, resUri, &Body{reader: res.Body}, req} - } else { - response = &Response{res, resUri, nil, req} - } - } - - //If redirect fails and we haven't set a redirect count we shouldn't return an error - if redirectFailed && r.MaxRedirects == 0 { - return response, nil - } - - return response, &Error{timeout: timeout, Err: err} - } - - if r.Compression != nil && strings.Contains(res.Header.Get("Content-Encoding"), r.Compression.ContentEncoding) { - compressedReader, err := r.Compression.reader(res.Body) - if err != nil { - return nil, &Error{Err: err} - } - return &Response{res, resUri, &Body{reader: res.Body, compressedReader: compressedReader}, req}, nil - } - - return &Response{res, resUri, &Body{reader: res.Body}, req}, nil -} - -func (r Request) addHeaders(headersMap http.Header) { - if len(r.UserAgent) > 0 { - headersMap.Add("User-Agent", r.UserAgent) - } - if r.Accept != "" { - headersMap.Add("Accept", r.Accept) - } - if r.ContentType != "" { - headersMap.Add("Content-Type", r.ContentType) - } -} - -func (r Request) NewRequest() (*http.Request, error) { - - b, e := prepareRequestBody(r.Body) - if e != nil { - // there was a problem marshaling the body - return nil, &Error{Err: e} - } - - if r.QueryString != nil { - param, e := paramParse(r.QueryString) - if e != nil { - return nil, &Error{Err: e} - } - r.Uri = r.Uri + "?" + param - } - - var bodyReader io.Reader - if b != nil && r.Compression != nil { - buffer := bytes.NewBuffer([]byte{}) - readBuffer := bufio.NewReader(b) - writer, err := r.Compression.writer(buffer) - if err != nil { - return nil, &Error{Err: err} - } - _, e = readBuffer.WriteTo(writer) - writer.Close() - if e != nil { - return nil, &Error{Err: e} - } - bodyReader = buffer - } else { - bodyReader = b - } - - req, err := http.NewRequest(r.Method, r.Uri, bodyReader) - if err != nil { - return nil, err - } - // add headers to the request - req.Host = r.Host - - r.addHeaders(req.Header) - if r.Compression != nil { - req.Header.Add("Content-Encoding", r.Compression.ContentEncoding) - req.Header.Add("Accept-Encoding", r.Compression.ContentEncoding) - } - if r.headers != nil { - for _, header := range r.headers { - req.Header.Add(header.name, header.value) - } - } - - //use basic auth if required - if r.BasicAuthUsername != "" { - req.SetBasicAuth(r.BasicAuthUsername, r.BasicAuthPassword) - } - - for _, c := range r.cookies { - req.AddCookie(c) - } - return req, nil -} - -// Return value if nonempty, def otherwise. -func valueOrDefault(value, def string) string { - if value != "" { - return value - } - return def -} diff --git a/Godeps/_workspace/src/github.com/franela/goreq/tags.go b/Godeps/_workspace/src/github.com/franela/goreq/tags.go deleted file mode 100644 index ffe8789d394..00000000000 --- a/Godeps/_workspace/src/github.com/franela/goreq/tags.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package goreq - -import ( - "strings" - "unicode" -) - -// tagOptions is the string following a comma in a struct field's "json" -// tag, or the empty string. It does not include the leading comma. -type tagOptions string - -// parseTag splits a struct field's json tag into its name and -// comma-separated options. -func parseTag(tag string) (string, tagOptions) { - if idx := strings.Index(tag, ","); idx != -1 { - return tag[:idx], tagOptions(tag[idx+1:]) - } - return tag, tagOptions("") -} - -// Contains reports whether a comma-separated list of options -// contains a particular substr flag. substr must be surrounded by a -// string boundary or commas. -func (o tagOptions) Contains(optionName string) bool { - if len(o) == 0 { - return false - } - s := string(o) - for s != "" { - var next string - i := strings.Index(s, ",") - if i >= 0 { - s, next = s[:i], s[i+1:] - } - if s == optionName { - return true - } - s = next - } - return false -} - -func isValidTag(s string) bool { - if s == "" { - return false - } - for _, c := range s { - switch { - case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c): - // Backslash and quote chars are reserved, but - // otherwise any punctuation chars are allowed - // in a tag name. - default: - if !unicode.IsLetter(c) && !unicode.IsDigit(c) { - return false - } - } - } - return true -} diff --git a/Godeps/_workspace/src/github.com/go-ini/ini/ini.go b/Godeps/_workspace/src/github.com/go-ini/ini/ini.go deleted file mode 100644 index 1fee789a1d6..00000000000 --- a/Godeps/_workspace/src/github.com/go-ini/ini/ini.go +++ /dev/null @@ -1,1226 +0,0 @@ -// Copyright 2014 Unknwon -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -// Package ini provides INI file read and write functionality in Go. -package ini - -import ( - "bufio" - "bytes" - "errors" - "fmt" - "io" - "os" - "regexp" - "runtime" - "strconv" - "strings" - "sync" - "time" -) - -const ( - DEFAULT_SECTION = "DEFAULT" - // Maximum allowed depth when recursively substituing variable names. - _DEPTH_VALUES = 99 - - _VERSION = "1.6.0" -) - -func Version() string { - return _VERSION -} - -var ( - LineBreak = "\n" - - // Variable regexp pattern: %(variable)s - varPattern = regexp.MustCompile(`%\(([^\)]+)\)s`) - - // Write spaces around "=" to look better. - PrettyFormat = true -) - -func init() { - if runtime.GOOS == "windows" { - LineBreak = "\r\n" - } -} - -func inSlice(str string, s []string) bool { - for _, v := range s { - if str == v { - return true - } - } - return false -} - -// dataSource is a interface that returns file content. -type dataSource interface { - ReadCloser() (io.ReadCloser, error) -} - -type sourceFile struct { - name string -} - -func (s sourceFile) ReadCloser() (_ io.ReadCloser, err error) { - return os.Open(s.name) -} - -type bytesReadCloser struct { - reader io.Reader -} - -func (rc *bytesReadCloser) Read(p []byte) (n int, err error) { - return rc.reader.Read(p) -} - -func (rc *bytesReadCloser) Close() error { - return nil -} - -type sourceData struct { - data []byte -} - -func (s *sourceData) ReadCloser() (io.ReadCloser, error) { - return &bytesReadCloser{bytes.NewReader(s.data)}, nil -} - -// ____ __. -// | |/ _|____ ___.__. -// | <_/ __ < | | -// | | \ ___/\___ | -// |____|__ \___ > ____| -// \/ \/\/ - -// Key represents a key under a section. -type Key struct { - s *Section - Comment string - name string - value string - isAutoIncr bool -} - -// Name returns name of key. -func (k *Key) Name() string { - return k.name -} - -// Value returns raw value of key for performance purpose. -func (k *Key) Value() string { - return k.value -} - -// String returns string representation of value. -func (k *Key) String() string { - val := k.value - if strings.Index(val, "%") == -1 { - return val - } - - for i := 0; i < _DEPTH_VALUES; i++ { - vr := varPattern.FindString(val) - if len(vr) == 0 { - break - } - - // Take off leading '%(' and trailing ')s'. - noption := strings.TrimLeft(vr, "%(") - noption = strings.TrimRight(noption, ")s") - - // Search in the same section. - nk, err := k.s.GetKey(noption) - if err != nil { - // Search again in default section. - nk, _ = k.s.f.Section("").GetKey(noption) - } - - // Substitute by new value and take off leading '%(' and trailing ')s'. - val = strings.Replace(val, vr, nk.value, -1) - } - return val -} - -// Validate accepts a validate function which can -// return modifed result as key value. -func (k *Key) Validate(fn func(string) string) string { - return fn(k.String()) -} - -// parseBool returns the boolean value represented by the string. -// -// It accepts 1, t, T, TRUE, true, True, YES, yes, Yes, ON, on, On, -// 0, f, F, FALSE, false, False, NO, no, No, OFF, off, Off. -// Any other value returns an error. -func parseBool(str string) (value bool, err error) { - switch str { - case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "ON", "on", "On": - return true, nil - case "0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "OFF", "off", "Off": - return false, nil - } - return false, fmt.Errorf("parsing \"%s\": invalid syntax", str) -} - -// Bool returns bool type value. -func (k *Key) Bool() (bool, error) { - return parseBool(k.String()) -} - -// Float64 returns float64 type value. -func (k *Key) Float64() (float64, error) { - return strconv.ParseFloat(k.String(), 64) -} - -// Int returns int type value. -func (k *Key) Int() (int, error) { - return strconv.Atoi(k.String()) -} - -// Int64 returns int64 type value. -func (k *Key) Int64() (int64, error) { - return strconv.ParseInt(k.String(), 10, 64) -} - -// Uint returns uint type valued. -func (k *Key) Uint() (uint, error) { - u, e := strconv.ParseUint(k.String(), 10, 64) - return uint(u), e -} - -// Uint64 returns uint64 type value. -func (k *Key) Uint64() (uint64, error) { - return strconv.ParseUint(k.String(), 10, 64) -} - -// Duration returns time.Duration type value. -func (k *Key) Duration() (time.Duration, error) { - return time.ParseDuration(k.String()) -} - -// TimeFormat parses with given format and returns time.Time type value. -func (k *Key) TimeFormat(format string) (time.Time, error) { - return time.Parse(format, k.String()) -} - -// Time parses with RFC3339 format and returns time.Time type value. -func (k *Key) Time() (time.Time, error) { - return k.TimeFormat(time.RFC3339) -} - -// MustString returns default value if key value is empty. -func (k *Key) MustString(defaultVal string) string { - val := k.String() - if len(val) == 0 { - return defaultVal - } - return val -} - -// MustBool always returns value without error, -// it returns false if error occurs. -func (k *Key) MustBool(defaultVal ...bool) bool { - val, err := k.Bool() - if len(defaultVal) > 0 && err != nil { - return defaultVal[0] - } - return val -} - -// MustFloat64 always returns value without error, -// it returns 0.0 if error occurs. -func (k *Key) MustFloat64(defaultVal ...float64) float64 { - val, err := k.Float64() - if len(defaultVal) > 0 && err != nil { - return defaultVal[0] - } - return val -} - -// MustInt always returns value without error, -// it returns 0 if error occurs. -func (k *Key) MustInt(defaultVal ...int) int { - val, err := k.Int() - if len(defaultVal) > 0 && err != nil { - return defaultVal[0] - } - return val -} - -// MustInt64 always returns value without error, -// it returns 0 if error occurs. -func (k *Key) MustInt64(defaultVal ...int64) int64 { - val, err := k.Int64() - if len(defaultVal) > 0 && err != nil { - return defaultVal[0] - } - return val -} - -// MustUint always returns value without error, -// it returns 0 if error occurs. -func (k *Key) MustUint(defaultVal ...uint) uint { - val, err := k.Uint() - if len(defaultVal) > 0 && err != nil { - return defaultVal[0] - } - return val -} - -// MustUint64 always returns value without error, -// it returns 0 if error occurs. -func (k *Key) MustUint64(defaultVal ...uint64) uint64 { - val, err := k.Uint64() - if len(defaultVal) > 0 && err != nil { - return defaultVal[0] - } - return val -} - -// MustDuration always returns value without error, -// it returns zero value if error occurs. -func (k *Key) MustDuration(defaultVal ...time.Duration) time.Duration { - val, err := k.Duration() - if len(defaultVal) > 0 && err != nil { - return defaultVal[0] - } - return val -} - -// MustTimeFormat always parses with given format and returns value without error, -// it returns zero value if error occurs. -func (k *Key) MustTimeFormat(format string, defaultVal ...time.Time) time.Time { - val, err := k.TimeFormat(format) - if len(defaultVal) > 0 && err != nil { - return defaultVal[0] - } - return val -} - -// MustTime always parses with RFC3339 format and returns value without error, -// it returns zero value if error occurs. -func (k *Key) MustTime(defaultVal ...time.Time) time.Time { - return k.MustTimeFormat(time.RFC3339, defaultVal...) -} - -// In always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) In(defaultVal string, candidates []string) string { - val := k.String() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InFloat64 always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InFloat64(defaultVal float64, candidates []float64) float64 { - val := k.MustFloat64() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InInt always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InInt(defaultVal int, candidates []int) int { - val := k.MustInt() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InInt64 always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InInt64(defaultVal int64, candidates []int64) int64 { - val := k.MustInt64() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InUint always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InUint(defaultVal uint, candidates []uint) uint { - val := k.MustUint() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InUint64 always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InUint64(defaultVal uint64, candidates []uint64) uint64 { - val := k.MustUint64() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InTimeFormat always parses with given format and returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InTimeFormat(format string, defaultVal time.Time, candidates []time.Time) time.Time { - val := k.MustTimeFormat(format) - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InTime always parses with RFC3339 format and returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InTime(defaultVal time.Time, candidates []time.Time) time.Time { - return k.InTimeFormat(time.RFC3339, defaultVal, candidates) -} - -// RangeFloat64 checks if value is in given range inclusively, -// and returns default value if it's not. -func (k *Key) RangeFloat64(defaultVal, min, max float64) float64 { - val := k.MustFloat64() - if val < min || val > max { - return defaultVal - } - return val -} - -// RangeInt checks if value is in given range inclusively, -// and returns default value if it's not. -func (k *Key) RangeInt(defaultVal, min, max int) int { - val := k.MustInt() - if val < min || val > max { - return defaultVal - } - return val -} - -// RangeInt64 checks if value is in given range inclusively, -// and returns default value if it's not. -func (k *Key) RangeInt64(defaultVal, min, max int64) int64 { - val := k.MustInt64() - if val < min || val > max { - return defaultVal - } - return val -} - -// RangeTimeFormat checks if value with given format is in given range inclusively, -// and returns default value if it's not. -func (k *Key) RangeTimeFormat(format string, defaultVal, min, max time.Time) time.Time { - val := k.MustTimeFormat(format) - if val.Unix() < min.Unix() || val.Unix() > max.Unix() { - return defaultVal - } - return val -} - -// RangeTime checks if value with RFC3339 format is in given range inclusively, -// and returns default value if it's not. -func (k *Key) RangeTime(defaultVal, min, max time.Time) time.Time { - return k.RangeTimeFormat(time.RFC3339, defaultVal, min, max) -} - -// Strings returns list of string devide by given delimiter. -func (k *Key) Strings(delim string) []string { - str := k.String() - if len(str) == 0 { - return []string{} - } - - vals := strings.Split(str, delim) - for i := range vals { - vals[i] = strings.TrimSpace(vals[i]) - } - return vals -} - -// Float64s returns list of float64 devide by given delimiter. -func (k *Key) Float64s(delim string) []float64 { - strs := k.Strings(delim) - vals := make([]float64, len(strs)) - for i := range strs { - vals[i], _ = strconv.ParseFloat(strs[i], 64) - } - return vals -} - -// Ints returns list of int devide by given delimiter. -func (k *Key) Ints(delim string) []int { - strs := k.Strings(delim) - vals := make([]int, len(strs)) - for i := range strs { - vals[i], _ = strconv.Atoi(strs[i]) - } - return vals -} - -// Int64s returns list of int64 devide by given delimiter. -func (k *Key) Int64s(delim string) []int64 { - strs := k.Strings(delim) - vals := make([]int64, len(strs)) - for i := range strs { - vals[i], _ = strconv.ParseInt(strs[i], 10, 64) - } - return vals -} - -// Uints returns list of uint devide by given delimiter. -func (k *Key) Uints(delim string) []uint { - strs := k.Strings(delim) - vals := make([]uint, len(strs)) - for i := range strs { - u, _ := strconv.ParseUint(strs[i], 10, 64) - vals[i] = uint(u) - } - return vals -} - -// Uint64s returns list of uint64 devide by given delimiter. -func (k *Key) Uint64s(delim string) []uint64 { - strs := k.Strings(delim) - vals := make([]uint64, len(strs)) - for i := range strs { - vals[i], _ = strconv.ParseUint(strs[i], 10, 64) - } - return vals -} - -// TimesFormat parses with given format and returns list of time.Time devide by given delimiter. -func (k *Key) TimesFormat(format, delim string) []time.Time { - strs := k.Strings(delim) - vals := make([]time.Time, len(strs)) - for i := range strs { - vals[i], _ = time.Parse(format, strs[i]) - } - return vals -} - -// Times parses with RFC3339 format and returns list of time.Time devide by given delimiter. -func (k *Key) Times(delim string) []time.Time { - return k.TimesFormat(time.RFC3339, delim) -} - -// SetValue changes key value. -func (k *Key) SetValue(v string) { - k.value = v -} - -// _________ __ .__ -// / _____/ ____ _____/ |_|__| ____ ____ -// \_____ \_/ __ \_/ ___\ __\ |/ _ \ / \ -// / \ ___/\ \___| | | ( <_> ) | \ -// /_______ /\___ >\___ >__| |__|\____/|___| / -// \/ \/ \/ \/ - -// Section represents a config section. -type Section struct { - f *File - Comment string - name string - keys map[string]*Key - keyList []string - keysHash map[string]string -} - -func newSection(f *File, name string) *Section { - return &Section{f, "", name, make(map[string]*Key), make([]string, 0, 10), make(map[string]string)} -} - -// Name returns name of Section. -func (s *Section) Name() string { - return s.name -} - -// NewKey creates a new key to given section. -func (s *Section) NewKey(name, val string) (*Key, error) { - if len(name) == 0 { - return nil, errors.New("error creating new key: empty key name") - } - - if s.f.BlockMode { - s.f.lock.Lock() - defer s.f.lock.Unlock() - } - - if inSlice(name, s.keyList) { - s.keys[name].value = val - return s.keys[name], nil - } - - s.keyList = append(s.keyList, name) - s.keys[name] = &Key{s, "", name, val, false} - s.keysHash[name] = val - return s.keys[name], nil -} - -// GetKey returns key in section by given name. -func (s *Section) GetKey(name string) (*Key, error) { - // FIXME: change to section level lock? - if s.f.BlockMode { - s.f.lock.RLock() - } - key := s.keys[name] - if s.f.BlockMode { - s.f.lock.RUnlock() - } - - if key == nil { - // Check if it is a child-section. - sname := s.name - for { - if i := strings.LastIndex(sname, "."); i > -1 { - sname = sname[:i] - sec, err := s.f.GetSection(sname) - if err != nil { - continue - } - return sec.GetKey(name) - } else { - break - } - } - return nil, fmt.Errorf("error when getting key of section '%s': key '%s' not exists", s.name, name) - } - return key, nil -} - -// Key assumes named Key exists in section and returns a zero-value when not. -func (s *Section) Key(name string) *Key { - key, err := s.GetKey(name) - if err != nil { - // It's OK here because the only possible error is empty key name, - // but if it's empty, this piece of code won't be executed. - key, _ = s.NewKey(name, "") - return key - } - return key -} - -// Keys returns list of keys of section. -func (s *Section) Keys() []*Key { - keys := make([]*Key, len(s.keyList)) - for i := range s.keyList { - keys[i] = s.Key(s.keyList[i]) - } - return keys -} - -// KeyStrings returns list of key names of section. -func (s *Section) KeyStrings() []string { - list := make([]string, len(s.keyList)) - copy(list, s.keyList) - return list -} - -// KeysHash returns keys hash consisting of names and values. -func (s *Section) KeysHash() map[string]string { - if s.f.BlockMode { - s.f.lock.RLock() - defer s.f.lock.RUnlock() - } - - hash := map[string]string{} - for key, value := range s.keysHash { - hash[key] = value - } - return hash -} - -// DeleteKey deletes a key from section. -func (s *Section) DeleteKey(name string) { - if s.f.BlockMode { - s.f.lock.Lock() - defer s.f.lock.Unlock() - } - - for i, k := range s.keyList { - if k == name { - s.keyList = append(s.keyList[:i], s.keyList[i+1:]...) - delete(s.keys, name) - return - } - } -} - -// ___________.__.__ -// \_ _____/|__| | ____ -// | __) | | | _/ __ \ -// | \ | | |_\ ___/ -// \___ / |__|____/\___ > -// \/ \/ - -// File represents a combination of a or more INI file(s) in memory. -type File struct { - // Should make things safe, but sometimes doesn't matter. - BlockMode bool - // Make sure data is safe in multiple goroutines. - lock sync.RWMutex - - // Allow combination of multiple data sources. - dataSources []dataSource - // Actual data is stored here. - sections map[string]*Section - - // To keep data in order. - sectionList []string - - NameMapper -} - -// newFile initializes File object with given data sources. -func newFile(dataSources []dataSource) *File { - return &File{ - BlockMode: true, - dataSources: dataSources, - sections: make(map[string]*Section), - sectionList: make([]string, 0, 10), - } -} - -func parseDataSource(source interface{}) (dataSource, error) { - switch s := source.(type) { - case string: - return sourceFile{s}, nil - case []byte: - return &sourceData{s}, nil - default: - return nil, fmt.Errorf("error parsing data source: unknown type '%s'", s) - } -} - -// Load loads and parses from INI data sources. -// Arguments can be mixed of file name with string type, or raw data in []byte. -func Load(source interface{}, others ...interface{}) (_ *File, err error) { - sources := make([]dataSource, len(others)+1) - sources[0], err = parseDataSource(source) - if err != nil { - return nil, err - } - for i := range others { - sources[i+1], err = parseDataSource(others[i]) - if err != nil { - return nil, err - } - } - f := newFile(sources) - return f, f.Reload() -} - -// Empty returns an empty file object. -func Empty() *File { - // Ignore error here, we sure our data is good. - f, _ := Load([]byte("")) - return f -} - -// NewSection creates a new section. -func (f *File) NewSection(name string) (*Section, error) { - if len(name) == 0 { - return nil, errors.New("error creating new section: empty section name") - } - - if f.BlockMode { - f.lock.Lock() - defer f.lock.Unlock() - } - - if inSlice(name, f.sectionList) { - return f.sections[name], nil - } - - f.sectionList = append(f.sectionList, name) - f.sections[name] = newSection(f, name) - return f.sections[name], nil -} - -// NewSections creates a list of sections. -func (f *File) NewSections(names ...string) (err error) { - for _, name := range names { - if _, err = f.NewSection(name); err != nil { - return err - } - } - return nil -} - -// GetSection returns section by given name. -func (f *File) GetSection(name string) (*Section, error) { - if len(name) == 0 { - name = DEFAULT_SECTION - } - - if f.BlockMode { - f.lock.RLock() - defer f.lock.RUnlock() - } - - sec := f.sections[name] - if sec == nil { - return nil, fmt.Errorf("error when getting section: section '%s' not exists", name) - } - return sec, nil -} - -// Section assumes named section exists and returns a zero-value when not. -func (f *File) Section(name string) *Section { - sec, err := f.GetSection(name) - if err != nil { - // Note: It's OK here because the only possible error is empty section name, - // but if it's empty, this piece of code won't be executed. - sec, _ = f.NewSection(name) - return sec - } - return sec -} - -// Section returns list of Section. -func (f *File) Sections() []*Section { - sections := make([]*Section, len(f.sectionList)) - for i := range f.sectionList { - sections[i] = f.Section(f.sectionList[i]) - } - return sections -} - -// SectionStrings returns list of section names. -func (f *File) SectionStrings() []string { - list := make([]string, len(f.sectionList)) - copy(list, f.sectionList) - return list -} - -// DeleteSection deletes a section. -func (f *File) DeleteSection(name string) { - if f.BlockMode { - f.lock.Lock() - defer f.lock.Unlock() - } - - if len(name) == 0 { - name = DEFAULT_SECTION - } - - for i, s := range f.sectionList { - if s == name { - f.sectionList = append(f.sectionList[:i], f.sectionList[i+1:]...) - delete(f.sections, name) - return - } - } -} - -func cutComment(str string) string { - i := strings.Index(str, "#") - if i == -1 { - return str - } - return str[:i] -} - -func checkMultipleLines(buf *bufio.Reader, line, val, valQuote string) (string, error) { - isEnd := false - for { - next, err := buf.ReadString('\n') - if err != nil { - if err != io.EOF { - return "", err - } - isEnd = true - } - pos := strings.LastIndex(next, valQuote) - if pos > -1 { - val += next[:pos] - break - } - val += next - if isEnd { - return "", fmt.Errorf("error parsing line: missing closing key quote from '%s' to '%s'", line, next) - } - } - return val, nil -} - -func checkContinuationLines(buf *bufio.Reader, val string) (string, bool, error) { - isEnd := false - for { - valLen := len(val) - if valLen == 0 || val[valLen-1] != '\\' { - break - } - val = val[:valLen-1] - - next, err := buf.ReadString('\n') - if err != nil { - if err != io.EOF { - return "", isEnd, err - } - isEnd = true - } - - next = strings.TrimSpace(next) - if len(next) == 0 { - break - } - val += next - } - return val, isEnd, nil -} - -// parse parses data through an io.Reader. -func (f *File) parse(reader io.Reader) error { - buf := bufio.NewReader(reader) - - // Handle BOM-UTF8. - // http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding - mask, err := buf.Peek(3) - if err == nil && len(mask) >= 3 && mask[0] == 239 && mask[1] == 187 && mask[2] == 191 { - buf.Read(mask) - } - - count := 1 - comments := "" - isEnd := false - - section, err := f.NewSection(DEFAULT_SECTION) - if err != nil { - return err - } - - for { - line, err := buf.ReadString('\n') - line = strings.TrimSpace(line) - length := len(line) - - // Check error and ignore io.EOF just for a moment. - if err != nil { - if err != io.EOF { - return fmt.Errorf("error reading next line: %v", err) - } - // The last line of file could be an empty line. - if length == 0 { - break - } - isEnd = true - } - - // Skip empty lines. - if length == 0 { - continue - } - - switch { - case line[0] == '#' || line[0] == ';': // Comments. - if len(comments) == 0 { - comments = line - } else { - comments += LineBreak + line - } - continue - case line[0] == '[' && line[length-1] == ']': // New sction. - section, err = f.NewSection(strings.TrimSpace(line[1 : length-1])) - if err != nil { - return err - } - - if len(comments) > 0 { - section.Comment = comments - comments = "" - } - // Reset counter. - count = 1 - continue - } - - // Other possibilities. - var ( - i int - keyQuote string - kname string - valQuote string - val string - ) - - // Key name surrounded by quotes. - if line[0] == '"' { - if length > 6 && line[0:3] == `"""` { - keyQuote = `"""` - } else { - keyQuote = `"` - } - } else if line[0] == '`' { - keyQuote = "`" - } - if len(keyQuote) > 0 { - qLen := len(keyQuote) - pos := strings.Index(line[qLen:], keyQuote) - if pos == -1 { - return fmt.Errorf("error parsing line: missing closing key quote: %s", line) - } - pos = pos + qLen - i = strings.IndexAny(line[pos:], "=:") - if i < 0 { - return fmt.Errorf("error parsing line: key-value delimiter not found: %s", line) - } else if i == pos { - return fmt.Errorf("error parsing line: key is empty: %s", line) - } - i = i + pos - kname = line[qLen:pos] // Just keep spaces inside quotes. - } else { - i = strings.IndexAny(line, "=:") - if i < 0 { - return fmt.Errorf("error parsing line: key-value delimiter not found: %s", line) - } else if i == 0 { - return fmt.Errorf("error parsing line: key is empty: %s", line) - } - kname = strings.TrimSpace(line[0:i]) - } - - isAutoIncr := false - // Auto increment. - if kname == "-" { - isAutoIncr = true - kname = "#" + fmt.Sprint(count) - count++ - } - - lineRight := strings.TrimSpace(line[i+1:]) - lineRightLength := len(lineRight) - firstChar := "" - if lineRightLength >= 2 { - firstChar = lineRight[0:1] - } - if firstChar == "`" { - valQuote = "`" - } else if firstChar == `"` { - if lineRightLength >= 3 && lineRight[0:3] == `"""` { - valQuote = `"""` - } else { - valQuote = `"` - } - } else if firstChar == `'` { - valQuote = `'` - } - - if len(valQuote) > 0 { - qLen := len(valQuote) - pos := strings.LastIndex(lineRight[qLen:], valQuote) - // For multiple-line value check. - if pos == -1 { - if valQuote == `"` || valQuote == `'` { - return fmt.Errorf("error parsing line: single quote does not allow multiple-line value: %s", line) - } - - val = lineRight[qLen:] + "\n" - val, err = checkMultipleLines(buf, line, val, valQuote) - if err != nil { - return err - } - } else { - val = lineRight[qLen : pos+qLen] - } - } else { - val = strings.TrimSpace(cutComment(lineRight)) - val, isEnd, err = checkContinuationLines(buf, val) - if err != nil { - return err - } - } - - k, err := section.NewKey(kname, val) - if err != nil { - return err - } - k.isAutoIncr = isAutoIncr - if len(comments) > 0 { - k.Comment = comments - comments = "" - } - - if isEnd { - break - } - } - return nil -} - -func (f *File) reload(s dataSource) error { - r, err := s.ReadCloser() - if err != nil { - return err - } - defer r.Close() - - return f.parse(r) -} - -// Reload reloads and parses all data sources. -func (f *File) Reload() (err error) { - for _, s := range f.dataSources { - if err = f.reload(s); err != nil { - return err - } - } - return nil -} - -// Append appends one or more data sources and reloads automatically. -func (f *File) Append(source interface{}, others ...interface{}) error { - ds, err := parseDataSource(source) - if err != nil { - return err - } - f.dataSources = append(f.dataSources, ds) - for _, s := range others { - ds, err = parseDataSource(s) - if err != nil { - return err - } - f.dataSources = append(f.dataSources, ds) - } - return f.Reload() -} - -// WriteToIndent writes file content into io.Writer with given value indention. -func (f *File) WriteToIndent(w io.Writer, indent string) (n int64, err error) { - equalSign := "=" - if PrettyFormat { - equalSign = " = " - } - - // Use buffer to make sure target is safe until finish encoding. - buf := bytes.NewBuffer(nil) - for i, sname := range f.sectionList { - sec := f.Section(sname) - if len(sec.Comment) > 0 { - if sec.Comment[0] != '#' && sec.Comment[0] != ';' { - sec.Comment = "; " + sec.Comment - } - if _, err = buf.WriteString(sec.Comment + LineBreak); err != nil { - return 0, err - } - } - - if i > 0 { - if _, err = buf.WriteString("[" + sname + "]" + LineBreak); err != nil { - return 0, err - } - } else { - // Write nothing if default section is empty. - if len(sec.keyList) == 0 { - continue - } - } - - for _, kname := range sec.keyList { - key := sec.Key(kname) - if len(key.Comment) > 0 { - if len(indent) > 0 && sname != DEFAULT_SECTION { - buf.WriteString(indent) - } - if key.Comment[0] != '#' && key.Comment[0] != ';' { - key.Comment = "; " + key.Comment - } - if _, err = buf.WriteString(key.Comment + LineBreak); err != nil { - return 0, err - } - } - - if len(indent) > 0 && sname != DEFAULT_SECTION { - buf.WriteString(indent) - } - - switch { - case key.isAutoIncr: - kname = "-" - case strings.Contains(kname, "`") || strings.Contains(kname, `"`): - kname = `"""` + kname + `"""` - case strings.Contains(kname, `=`) || strings.Contains(kname, `:`): - kname = "`" + kname + "`" - } - - val := key.value - // In case key value contains "\n", "`" or "\"". - if strings.Contains(val, "\n") || strings.Contains(val, "`") || strings.Contains(val, `"`) || - strings.Contains(val, "#") { - val = `"""` + val + `"""` - } - if _, err = buf.WriteString(kname + equalSign + val + LineBreak); err != nil { - return 0, err - } - } - - // Put a line between sections. - if _, err = buf.WriteString(LineBreak); err != nil { - return 0, err - } - } - - return buf.WriteTo(w) -} - -// WriteTo writes file content into io.Writer. -func (f *File) WriteTo(w io.Writer) (int64, error) { - return f.WriteToIndent(w, "") -} - -// SaveToIndent writes content to file system with given value indention. -func (f *File) SaveToIndent(filename, indent string) error { - // Note: Because we are truncating with os.Create, - // so it's safer to save to a temporary file location and rename afte done. - tmpPath := filename + "." + strconv.Itoa(time.Now().Nanosecond()) + ".tmp" - defer os.Remove(tmpPath) - - fw, err := os.Create(tmpPath) - if err != nil { - return err - } - - if _, err = f.WriteToIndent(fw, indent); err != nil { - fw.Close() - return err - } - fw.Close() - - // Remove old file and rename the new one. - os.Remove(filename) - return os.Rename(tmpPath, filename) -} - -// SaveTo writes content to file system. -func (f *File) SaveTo(filename string) error { - return f.SaveToIndent(filename, "") -} diff --git a/Godeps/_workspace/src/github.com/go-ini/ini/ini_test.go b/Godeps/_workspace/src/github.com/go-ini/ini/ini_test.go deleted file mode 100644 index 82ff36dd236..00000000000 --- a/Godeps/_workspace/src/github.com/go-ini/ini/ini_test.go +++ /dev/null @@ -1,512 +0,0 @@ -// Copyright 2014 Unknwon -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package ini - -import ( - "fmt" - "strings" - "testing" - "time" - - . "github.com/smartystreets/goconvey/convey" -) - -func Test_Version(t *testing.T) { - Convey("Get version", t, func() { - So(Version(), ShouldEqual, _VERSION) - }) -} - -const _CONF_DATA = ` -; Package name -NAME = ini -; Package version -VERSION = v1 -; Package import path -IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s - -# Information about package author -# Bio can be written in multiple lines. -[author] -NAME = Unknwon # Succeeding comment -E-MAIL = fake@localhost -GITHUB = https://github.com/%(NAME)s -BIO = """Gopher. -Coding addict. -Good man. -""" # Succeeding comment - -[package] -CLONE_URL = https://%(IMPORT_PATH)s - -[package.sub] -UNUSED_KEY = should be deleted - -[features] --: Support read/write comments of keys and sections --: Support auto-increment of key names --: Support load multiple files to overwrite key values - -[types] -STRING = str -BOOL = true -BOOL_FALSE = false -FLOAT64 = 1.25 -INT = 10 -TIME = 2015-01-01T20:17:05Z -DURATION = 2h45m -UINT = 3 - -[array] -STRINGS = en, zh, de -FLOAT64S = 1.1, 2.2, 3.3 -INTS = 1, 2, 3 -UINTS = 1, 2, 3 -TIMES = 2015-01-01T20:17:05Z,2015-01-01T20:17:05Z,2015-01-01T20:17:05Z - -[note] -empty_lines = next line is empty\ - -[advance] -value with quotes = "some value" -value quote2 again = 'some value' -true = """"2+3=5"""" -"1+1=2" = true -"""6+1=7""" = true -"""` + "`" + `5+5` + "`" + `""" = 10 -""""6+6"""" = 12 -` + "`" + `7-2=4` + "`" + ` = false -ADDRESS = ` + "`" + `404 road, -NotFound, State, 50000` + "`" + ` - -two_lines = how about \ - continuation lines? -lots_of_lines = 1 \ - 2 \ - 3 \ - 4 \ -` - -func Test_Load(t *testing.T) { - Convey("Load from data sources", t, func() { - - Convey("Load with empty data", func() { - So(Empty(), ShouldNotBeNil) - }) - - Convey("Load with multiple data sources", func() { - cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini") - So(err, ShouldBeNil) - So(cfg, ShouldNotBeNil) - }) - }) - - Convey("Bad load process", t, func() { - - Convey("Load from invalid data sources", func() { - _, err := Load(_CONF_DATA) - So(err, ShouldNotBeNil) - - _, err = Load("testdata/404.ini") - So(err, ShouldNotBeNil) - - _, err = Load(1) - So(err, ShouldNotBeNil) - - _, err = Load([]byte(""), 1) - So(err, ShouldNotBeNil) - }) - - Convey("Load with empty section name", func() { - _, err := Load([]byte("[]")) - So(err, ShouldNotBeNil) - }) - - Convey("Load with bad keys", func() { - _, err := Load([]byte(`"""name`)) - So(err, ShouldNotBeNil) - - _, err = Load([]byte(`"""name"""`)) - So(err, ShouldNotBeNil) - - _, err = Load([]byte(`""=1`)) - So(err, ShouldNotBeNil) - - _, err = Load([]byte(`=`)) - So(err, ShouldNotBeNil) - - _, err = Load([]byte(`name`)) - So(err, ShouldNotBeNil) - }) - - Convey("Load with bad values", func() { - _, err := Load([]byte(`name="""Unknwon`)) - So(err, ShouldNotBeNil) - - _, err = Load([]byte(`key = "value`)) - So(err, ShouldNotBeNil) - }) - }) -} - -func Test_Values(t *testing.T) { - Convey("Test getting and setting values", t, func() { - cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini") - So(err, ShouldBeNil) - So(cfg, ShouldNotBeNil) - - Convey("Get values in default section", func() { - sec := cfg.Section("") - So(sec, ShouldNotBeNil) - So(sec.Key("NAME").Value(), ShouldEqual, "ini") - So(sec.Key("NAME").String(), ShouldEqual, "ini") - So(sec.Key("NAME").Validate(func(in string) string { - return in - }), ShouldEqual, "ini") - So(sec.Key("NAME").Comment, ShouldEqual, "; Package name") - So(sec.Key("IMPORT_PATH").String(), ShouldEqual, "gopkg.in/ini.v1") - }) - - Convey("Get values in non-default section", func() { - sec := cfg.Section("author") - So(sec, ShouldNotBeNil) - So(sec.Key("NAME").String(), ShouldEqual, "Unknwon") - So(sec.Key("GITHUB").String(), ShouldEqual, "https://github.com/Unknwon") - - sec = cfg.Section("package") - So(sec, ShouldNotBeNil) - So(sec.Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1") - }) - - Convey("Get auto-increment key names", func() { - keys := cfg.Section("features").Keys() - for i, k := range keys { - So(k.Name(), ShouldEqual, fmt.Sprintf("#%d", i+1)) - } - }) - - Convey("Get overwrite value", func() { - So(cfg.Section("author").Key("E-MAIL").String(), ShouldEqual, "u@gogs.io") - }) - - Convey("Get sections", func() { - sections := cfg.Sections() - for i, name := range []string{DEFAULT_SECTION, "author", "package", "package.sub", "features", "types", "array", "note", "advance"} { - So(sections[i].Name(), ShouldEqual, name) - } - }) - - Convey("Get parent section value", func() { - So(cfg.Section("package.sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1") - }) - - Convey("Get multiple line value", func() { - So(cfg.Section("author").Key("BIO").String(), ShouldEqual, "Gopher.\nCoding addict.\nGood man.\n") - }) - - Convey("Get values with type", func() { - sec := cfg.Section("types") - v1, err := sec.Key("BOOL").Bool() - So(err, ShouldBeNil) - So(v1, ShouldBeTrue) - - v1, err = sec.Key("BOOL_FALSE").Bool() - So(err, ShouldBeNil) - So(v1, ShouldBeFalse) - - v2, err := sec.Key("FLOAT64").Float64() - So(err, ShouldBeNil) - So(v2, ShouldEqual, 1.25) - - v3, err := sec.Key("INT").Int() - So(err, ShouldBeNil) - So(v3, ShouldEqual, 10) - - v4, err := sec.Key("INT").Int64() - So(err, ShouldBeNil) - So(v4, ShouldEqual, 10) - - v5, err := sec.Key("UINT").Uint() - So(err, ShouldBeNil) - So(v5, ShouldEqual, 3) - - v6, err := sec.Key("UINT").Uint64() - So(err, ShouldBeNil) - So(v6, ShouldEqual, 3) - - t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z") - So(err, ShouldBeNil) - v7, err := sec.Key("TIME").Time() - So(err, ShouldBeNil) - So(v7.String(), ShouldEqual, t.String()) - - Convey("Must get values with type", func() { - So(sec.Key("STRING").MustString("404"), ShouldEqual, "str") - So(sec.Key("BOOL").MustBool(), ShouldBeTrue) - So(sec.Key("FLOAT64").MustFloat64(), ShouldEqual, 1.25) - So(sec.Key("INT").MustInt(), ShouldEqual, 10) - So(sec.Key("INT").MustInt64(), ShouldEqual, 10) - So(sec.Key("UINT").MustUint(), ShouldEqual, 3) - So(sec.Key("UINT").MustUint64(), ShouldEqual, 3) - So(sec.Key("TIME").MustTime().String(), ShouldEqual, t.String()) - - dur, err := time.ParseDuration("2h45m") - So(err, ShouldBeNil) - So(sec.Key("DURATION").MustDuration().Seconds(), ShouldEqual, dur.Seconds()) - - Convey("Must get values with default value", func() { - So(sec.Key("STRING_404").MustString("404"), ShouldEqual, "404") - So(sec.Key("BOOL_404").MustBool(true), ShouldBeTrue) - So(sec.Key("FLOAT64_404").MustFloat64(2.5), ShouldEqual, 2.5) - So(sec.Key("INT_404").MustInt(15), ShouldEqual, 15) - So(sec.Key("INT_404").MustInt64(15), ShouldEqual, 15) - So(sec.Key("UINT_404").MustUint(6), ShouldEqual, 6) - So(sec.Key("UINT_404").MustUint64(6), ShouldEqual, 6) - - t, err := time.Parse(time.RFC3339, "2014-01-01T20:17:05Z") - So(err, ShouldBeNil) - So(sec.Key("TIME_404").MustTime(t).String(), ShouldEqual, t.String()) - - So(sec.Key("DURATION_404").MustDuration(dur).Seconds(), ShouldEqual, dur.Seconds()) - }) - }) - }) - - Convey("Get value with candidates", func() { - sec := cfg.Section("types") - So(sec.Key("STRING").In("", []string{"str", "arr", "types"}), ShouldEqual, "str") - So(sec.Key("FLOAT64").InFloat64(0, []float64{1.25, 2.5, 3.75}), ShouldEqual, 1.25) - So(sec.Key("INT").InInt(0, []int{10, 20, 30}), ShouldEqual, 10) - So(sec.Key("INT").InInt64(0, []int64{10, 20, 30}), ShouldEqual, 10) - So(sec.Key("UINT").InUint(0, []uint{3, 6, 9}), ShouldEqual, 3) - So(sec.Key("UINT").InUint64(0, []uint64{3, 6, 9}), ShouldEqual, 3) - - zt, err := time.Parse(time.RFC3339, "0001-01-01T01:00:00Z") - So(err, ShouldBeNil) - t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z") - So(err, ShouldBeNil) - So(sec.Key("TIME").InTime(zt, []time.Time{t, time.Now(), time.Now().Add(1 * time.Second)}).String(), ShouldEqual, t.String()) - - Convey("Get value with candidates and default value", func() { - So(sec.Key("STRING_404").In("str", []string{"str", "arr", "types"}), ShouldEqual, "str") - So(sec.Key("FLOAT64_404").InFloat64(1.25, []float64{1.25, 2.5, 3.75}), ShouldEqual, 1.25) - So(sec.Key("INT_404").InInt(10, []int{10, 20, 30}), ShouldEqual, 10) - So(sec.Key("INT64_404").InInt64(10, []int64{10, 20, 30}), ShouldEqual, 10) - So(sec.Key("UINT_404").InUint(3, []uint{3, 6, 9}), ShouldEqual, 3) - So(sec.Key("UINT_404").InUint64(3, []uint64{3, 6, 9}), ShouldEqual, 3) - So(sec.Key("TIME_404").InTime(t, []time.Time{time.Now(), time.Now(), time.Now().Add(1 * time.Second)}).String(), ShouldEqual, t.String()) - }) - }) - - Convey("Get values in range", func() { - sec := cfg.Section("types") - So(sec.Key("FLOAT64").RangeFloat64(0, 1, 2), ShouldEqual, 1.25) - So(sec.Key("INT").RangeInt(0, 10, 20), ShouldEqual, 10) - So(sec.Key("INT").RangeInt64(0, 10, 20), ShouldEqual, 10) - - minT, err := time.Parse(time.RFC3339, "0001-01-01T01:00:00Z") - So(err, ShouldBeNil) - midT, err := time.Parse(time.RFC3339, "2013-01-01T01:00:00Z") - So(err, ShouldBeNil) - maxT, err := time.Parse(time.RFC3339, "9999-01-01T01:00:00Z") - So(err, ShouldBeNil) - t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z") - So(err, ShouldBeNil) - So(sec.Key("TIME").RangeTime(t, minT, maxT).String(), ShouldEqual, t.String()) - - Convey("Get value in range with default value", func() { - So(sec.Key("FLOAT64").RangeFloat64(5, 0, 1), ShouldEqual, 5) - So(sec.Key("INT").RangeInt(7, 0, 5), ShouldEqual, 7) - So(sec.Key("INT").RangeInt64(7, 0, 5), ShouldEqual, 7) - So(sec.Key("TIME").RangeTime(t, minT, midT).String(), ShouldEqual, t.String()) - }) - }) - - Convey("Get values into slice", func() { - sec := cfg.Section("array") - So(strings.Join(sec.Key("STRINGS").Strings(","), ","), ShouldEqual, "en,zh,de") - So(len(sec.Key("STRINGS_404").Strings(",")), ShouldEqual, 0) - - vals1 := sec.Key("FLOAT64S").Float64s(",") - for i, v := range []float64{1.1, 2.2, 3.3} { - So(vals1[i], ShouldEqual, v) - } - - vals2 := sec.Key("INTS").Ints(",") - for i, v := range []int{1, 2, 3} { - So(vals2[i], ShouldEqual, v) - } - - vals3 := sec.Key("INTS").Int64s(",") - for i, v := range []int64{1, 2, 3} { - So(vals3[i], ShouldEqual, v) - } - - vals4 := sec.Key("UINTS").Uints(",") - for i, v := range []uint{1, 2, 3} { - So(vals4[i], ShouldEqual, v) - } - - vals5 := sec.Key("UINTS").Uint64s(",") - for i, v := range []uint64{1, 2, 3} { - So(vals5[i], ShouldEqual, v) - } - - t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z") - So(err, ShouldBeNil) - vals6 := sec.Key("TIMES").Times(",") - for i, v := range []time.Time{t, t, t} { - So(vals6[i].String(), ShouldEqual, v.String()) - } - }) - - Convey("Get key hash", func() { - cfg.Section("").KeysHash() - }) - - Convey("Set key value", func() { - k := cfg.Section("author").Key("NAME") - k.SetValue("无闻") - So(k.String(), ShouldEqual, "无闻") - }) - - Convey("Get key strings", func() { - So(strings.Join(cfg.Section("types").KeyStrings(), ","), ShouldEqual, "STRING,BOOL,BOOL_FALSE,FLOAT64,INT,TIME,DURATION,UINT") - }) - - Convey("Delete a key", func() { - cfg.Section("package.sub").DeleteKey("UNUSED_KEY") - _, err := cfg.Section("package.sub").GetKey("UNUSED_KEY") - So(err, ShouldNotBeNil) - }) - - Convey("Get section strings", func() { - So(strings.Join(cfg.SectionStrings(), ","), ShouldEqual, "DEFAULT,author,package,package.sub,features,types,array,note,advance") - }) - - Convey("Delete a section", func() { - cfg.DeleteSection("") - So(cfg.SectionStrings()[0], ShouldNotEqual, DEFAULT_SECTION) - }) - - Convey("Create new sections", func() { - cfg.NewSections("test", "test2") - _, err := cfg.GetSection("test") - So(err, ShouldBeNil) - _, err = cfg.GetSection("test2") - So(err, ShouldBeNil) - }) - }) - - Convey("Test getting and setting bad values", t, func() { - cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini") - So(err, ShouldBeNil) - So(cfg, ShouldNotBeNil) - - Convey("Create new key with empty name", func() { - k, err := cfg.Section("").NewKey("", "") - So(err, ShouldNotBeNil) - So(k, ShouldBeNil) - }) - - Convey("Create new section with empty name", func() { - s, err := cfg.NewSection("") - So(err, ShouldNotBeNil) - So(s, ShouldBeNil) - }) - - Convey("Create new sections with empty name", func() { - So(cfg.NewSections(""), ShouldNotBeNil) - }) - - Convey("Get section that not exists", func() { - s, err := cfg.GetSection("404") - So(err, ShouldNotBeNil) - So(s, ShouldBeNil) - - s = cfg.Section("404") - So(s, ShouldNotBeNil) - }) - }) -} - -func Test_File_Append(t *testing.T) { - Convey("Append data sources", t, func() { - cfg, err := Load([]byte("")) - So(err, ShouldBeNil) - So(cfg, ShouldNotBeNil) - - So(cfg.Append([]byte(""), []byte("")), ShouldBeNil) - - Convey("Append bad data sources", func() { - So(cfg.Append(1), ShouldNotBeNil) - So(cfg.Append([]byte(""), 1), ShouldNotBeNil) - }) - }) -} - -func Test_File_SaveTo(t *testing.T) { - Convey("Save file", t, func() { - cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini") - So(err, ShouldBeNil) - So(cfg, ShouldNotBeNil) - - cfg.Section("").Key("NAME").Comment = "Package name" - cfg.Section("author").Comment = `Information about package author -# Bio can be written in multiple lines.` - cfg.Section("advanced").Key("val w/ pound").SetValue("my#password") - So(cfg.SaveTo("testdata/conf_out.ini"), ShouldBeNil) - - cfg.Section("author").Key("NAME").Comment = "This is author name" - So(cfg.SaveToIndent("testdata/conf_out.ini", "\t"), ShouldBeNil) - }) -} - -func Benchmark_Key_Value(b *testing.B) { - c, _ := Load([]byte(_CONF_DATA)) - for i := 0; i < b.N; i++ { - c.Section("").Key("NAME").Value() - } -} - -func Benchmark_Key_String(b *testing.B) { - c, _ := Load([]byte(_CONF_DATA)) - for i := 0; i < b.N; i++ { - c.Section("").Key("NAME").String() - } -} - -func Benchmark_Key_Value_NonBlock(b *testing.B) { - c, _ := Load([]byte(_CONF_DATA)) - c.BlockMode = false - for i := 0; i < b.N; i++ { - c.Section("").Key("NAME").Value() - } -} - -func Benchmark_Key_String_NonBlock(b *testing.B) { - c, _ := Load([]byte(_CONF_DATA)) - c.BlockMode = false - for i := 0; i < b.N; i++ { - c.Section("").Key("NAME").String() - } -} - -func Benchmark_Key_SetValue(b *testing.B) { - c, _ := Load([]byte(_CONF_DATA)) - for i := 0; i < b.N; i++ { - c.Section("").Key("NAME").SetValue("10") - } -} diff --git a/Godeps/_workspace/src/github.com/go-ini/ini/struct_test.go b/Godeps/_workspace/src/github.com/go-ini/ini/struct_test.go deleted file mode 100644 index d865ad78eb7..00000000000 --- a/Godeps/_workspace/src/github.com/go-ini/ini/struct_test.go +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright 2014 Unknwon -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package ini - -import ( - "strings" - "testing" - "time" - - . "github.com/smartystreets/goconvey/convey" -) - -type testNested struct { - Cities []string `delim:"|"` - Visits []time.Time - Note string - Unused int `ini:"-"` -} - -type testEmbeded struct { - GPA float64 -} - -type testStruct struct { - Name string `ini:"NAME"` - Age int - Male bool - Money float64 - Born time.Time - Time time.Duration `ini:"Duration"` - Others testNested - *testEmbeded `ini:"grade"` - Unused int `ini:"-"` - Unsigned uint -} - -const _CONF_DATA_STRUCT = ` -NAME = Unknwon -Age = 21 -Male = true -Money = 1.25 -Born = 1993-10-07T20:17:05Z -Duration = 2h45m -Unsigned = 3 - -[Others] -Cities = HangZhou|Boston -Visits = 1993-10-07T20:17:05Z, 1993-10-07T20:17:05Z -Note = Hello world! - -[grade] -GPA = 2.8 - -[foo.bar] -Here = there -When = then -` - -type unsupport struct { - Byte byte -} - -type unsupport2 struct { - Others struct { - Cities byte - } -} - -type unsupport3 struct { - Cities byte -} - -type unsupport4 struct { - *unsupport3 `ini:"Others"` -} - -type defaultValue struct { - Name string - Age int - Male bool - Money float64 - Born time.Time - Cities []string -} - -type fooBar struct { - Here, When string -} - -const _INVALID_DATA_CONF_STRUCT = ` -Name = -Age = age -Male = 123 -Money = money -Born = nil -Cities = -` - -func Test_Struct(t *testing.T) { - Convey("Map to struct", t, func() { - Convey("Map file to struct", func() { - ts := new(testStruct) - So(MapTo(ts, []byte(_CONF_DATA_STRUCT)), ShouldBeNil) - - So(ts.Name, ShouldEqual, "Unknwon") - So(ts.Age, ShouldEqual, 21) - So(ts.Male, ShouldBeTrue) - So(ts.Money, ShouldEqual, 1.25) - So(ts.Unsigned, ShouldEqual, 3) - - t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z") - So(err, ShouldBeNil) - So(ts.Born.String(), ShouldEqual, t.String()) - - dur, err := time.ParseDuration("2h45m") - So(err, ShouldBeNil) - So(ts.Time.Seconds(), ShouldEqual, dur.Seconds()) - - So(strings.Join(ts.Others.Cities, ","), ShouldEqual, "HangZhou,Boston") - So(ts.Others.Visits[0].String(), ShouldEqual, t.String()) - So(ts.Others.Note, ShouldEqual, "Hello world!") - So(ts.testEmbeded.GPA, ShouldEqual, 2.8) - }) - - Convey("Map section to struct", func() { - foobar := new(fooBar) - f, err := Load([]byte(_CONF_DATA_STRUCT)) - So(err, ShouldBeNil) - - So(f.Section("foo.bar").MapTo(foobar), ShouldBeNil) - So(foobar.Here, ShouldEqual, "there") - So(foobar.When, ShouldEqual, "then") - }) - - Convey("Map to non-pointer struct", func() { - cfg, err := Load([]byte(_CONF_DATA_STRUCT)) - So(err, ShouldBeNil) - So(cfg, ShouldNotBeNil) - - So(cfg.MapTo(testStruct{}), ShouldNotBeNil) - }) - - Convey("Map to unsupported type", func() { - cfg, err := Load([]byte(_CONF_DATA_STRUCT)) - So(err, ShouldBeNil) - So(cfg, ShouldNotBeNil) - - cfg.NameMapper = func(raw string) string { - if raw == "Byte" { - return "NAME" - } - return raw - } - So(cfg.MapTo(&unsupport{}), ShouldNotBeNil) - So(cfg.MapTo(&unsupport2{}), ShouldNotBeNil) - So(cfg.MapTo(&unsupport4{}), ShouldNotBeNil) - }) - - Convey("Map from invalid data source", func() { - So(MapTo(&testStruct{}, "hi"), ShouldNotBeNil) - }) - - Convey("Map to wrong types and gain default values", func() { - cfg, err := Load([]byte(_INVALID_DATA_CONF_STRUCT)) - So(err, ShouldBeNil) - - t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z") - So(err, ShouldBeNil) - dv := &defaultValue{"Joe", 10, true, 1.25, t, []string{"HangZhou", "Boston"}} - So(cfg.MapTo(dv), ShouldBeNil) - So(dv.Name, ShouldEqual, "Joe") - So(dv.Age, ShouldEqual, 10) - So(dv.Male, ShouldBeTrue) - So(dv.Money, ShouldEqual, 1.25) - So(dv.Born.String(), ShouldEqual, t.String()) - So(strings.Join(dv.Cities, ","), ShouldEqual, "HangZhou,Boston") - }) - }) - - Convey("Reflect from struct", t, func() { - type Embeded struct { - Dates []time.Time `delim:"|"` - Places []string - None []int - } - type Author struct { - Name string `ini:"NAME"` - Male bool - Age int - GPA float64 - NeverMind string `ini:"-"` - *Embeded `ini:"infos"` - } - a := &Author{"Unknwon", true, 21, 2.8, "", - &Embeded{ - []time.Time{time.Now(), time.Now()}, - []string{"HangZhou", "Boston"}, - []int{}, - }} - cfg := Empty() - So(ReflectFrom(cfg, a), ShouldBeNil) - cfg.SaveTo("testdata/conf_reflect.ini") - - Convey("Reflect from non-point struct", func() { - So(ReflectFrom(cfg, Author{}), ShouldNotBeNil) - }) - }) -} - -type testMapper struct { - PackageName string -} - -func Test_NameGetter(t *testing.T) { - Convey("Test name mappers", t, func() { - So(MapToWithMapper(&testMapper{}, TitleUnderscore, []byte("packag_name=ini")), ShouldBeNil) - - cfg, err := Load([]byte("PACKAGE_NAME=ini")) - So(err, ShouldBeNil) - So(cfg, ShouldNotBeNil) - - cfg.NameMapper = AllCapsUnderscore - tg := new(testMapper) - So(cfg.MapTo(tg), ShouldBeNil) - So(tg.PackageName, ShouldEqual, "ini") - }) -} diff --git a/Godeps/_workspace/src/github.com/go-ini/ini/testdata/conf.ini b/Godeps/_workspace/src/github.com/go-ini/ini/testdata/conf.ini deleted file mode 100644 index 2ed0ac1d3ac..00000000000 --- a/Godeps/_workspace/src/github.com/go-ini/ini/testdata/conf.ini +++ /dev/null @@ -1,2 +0,0 @@ -[author] -E-MAIL = u@gogs.io \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/go-xorm/xorm/docs/images/cache_design.png b/Godeps/_workspace/src/github.com/go-xorm/xorm/docs/images/cache_design.png deleted file mode 100644 index 11ce817663c..00000000000 Binary files a/Godeps/_workspace/src/github.com/go-xorm/xorm/docs/images/cache_design.png and /dev/null differ diff --git a/Godeps/_workspace/src/github.com/grafana/grafana-cli/LICENSE b/Godeps/_workspace/src/github.com/grafana/grafana-cli/LICENSE deleted file mode 100644 index 8dada3edaf5..00000000000 --- a/Godeps/_workspace/src/github.com/grafana/grafana-cli/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/command_line.go b/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/command_line.go deleted file mode 100644 index edbdc03d7c2..00000000000 --- a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/command_line.go +++ /dev/null @@ -1,35 +0,0 @@ -package commands - -import ( - "github.com/codegangsta/cli" -) - -type CommandLine interface { - ShowHelp() - ShowVersion() - Application() *cli.App - Args() cli.Args - Bool(name string) bool - Int(name string) int - String(name string) string - StringSlice(name string) []string - GlobalString(name string) string - FlagNames() (names []string) - Generic(name string) interface{} -} - -type contextCommandLine struct { - *cli.Context -} - -func (c *contextCommandLine) ShowHelp() { - cli.ShowCommandHelp(c.Context, c.Command.Name) -} - -func (c *contextCommandLine) ShowVersion() { - cli.ShowVersion(c.Context) -} - -func (c *contextCommandLine) Application() *cli.App { - return c.App -} diff --git a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/commands.go b/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/commands.go deleted file mode 100644 index e72a1e45ff6..00000000000 --- a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/commands.go +++ /dev/null @@ -1,48 +0,0 @@ -package commands - -import ( - "github.com/codegangsta/cli" - "github.com/grafana/grafana-cli/pkg/log" -) - -func runCommand(command func(commandLine CommandLine) error) func(context *cli.Context) { - return func(context *cli.Context) { - - cmd := &contextCommandLine{context} - if err := command(cmd); err != nil { - log.Errorf("%v\n\n", err) - - cmd.ShowHelp() - } else { - log.Info("Restart grafana after installing plugins . \n") - } - } -} - -var Commands = []cli.Command{ - { - Name: "install", - Usage: "installs stuff", - Action: runCommand(installCommand), - }, { - Name: "list-remote", - Usage: "list remote available plugins", - Action: runCommand(listremoteCommand), - }, { - Name: "upgrade", - Usage: "upgrades one plugin", - Action: runCommand(upgradeCommand), - }, { - Name: "upgrade-all", - Usage: "upgrades all your installed plugins", - Action: runCommand(upgradeAllCommand), - }, { - Name: "ls", - Usage: "list all installed plugins", - Action: runCommand(lsCommand), - }, { - Name: "remove", - Usage: "removes stuff", - Action: runCommand(removeCommand), - }, -} diff --git a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/commandstest/fake_commandLine.go b/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/commandstest/fake_commandLine.go deleted file mode 100644 index 4a070b5a192..00000000000 --- a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/commandstest/fake_commandLine.go +++ /dev/null @@ -1,95 +0,0 @@ -package commandstest - -import ( - "github.com/codegangsta/cli" -) - -type FakeFlagger struct { - Data map[string]interface{} -} - -type FakeCommandLine struct { - LocalFlags, GlobalFlags *FakeFlagger - HelpShown, VersionShown bool - CliArgs []string -} - -func (ff FakeFlagger) String(key string) string { - if value, ok := ff.Data[key]; ok { - return value.(string) - } - return "" -} - -func (ff FakeFlagger) StringSlice(key string) []string { - if value, ok := ff.Data[key]; ok { - return value.([]string) - } - return []string{} -} - -func (ff FakeFlagger) Int(key string) int { - if value, ok := ff.Data[key]; ok { - return value.(int) - } - return 0 -} - -func (ff FakeFlagger) Bool(key string) bool { - if value, ok := ff.Data[key]; ok { - return value.(bool) - } - return false -} - -func (fcli *FakeCommandLine) String(key string) string { - return fcli.LocalFlags.String(key) -} - -func (fcli *FakeCommandLine) StringSlice(key string) []string { - return fcli.LocalFlags.StringSlice(key) -} - -func (fcli *FakeCommandLine) Int(key string) int { - return fcli.LocalFlags.Int(key) -} - -func (fcli *FakeCommandLine) Bool(key string) bool { - if fcli.LocalFlags == nil { - return false - } - return fcli.LocalFlags.Bool(key) -} - -func (fcli *FakeCommandLine) GlobalString(key string) string { - return fcli.GlobalFlags.String(key) -} - -func (fcli *FakeCommandLine) Generic(name string) interface{} { - return fcli.LocalFlags.Data[name] -} - -func (fcli *FakeCommandLine) FlagNames() []string { - flagNames := []string{} - for key := range fcli.LocalFlags.Data { - flagNames = append(flagNames, key) - } - - return flagNames -} - -func (fcli *FakeCommandLine) ShowHelp() { - fcli.HelpShown = true -} - -func (fcli *FakeCommandLine) Application() *cli.App { - return cli.NewApp() -} - -func (fcli *FakeCommandLine) Args() cli.Args { - return fcli.CliArgs -} - -func (fcli *FakeCommandLine) ShowVersion() { - fcli.VersionShown = true -} diff --git a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/commandstest/fake_ioutil.go b/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/commandstest/fake_ioutil.go deleted file mode 100644 index e6715a5ea77..00000000000 --- a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/commandstest/fake_ioutil.go +++ /dev/null @@ -1,55 +0,0 @@ -package commandstest - -import ( - "os" - "time" -) - -type FakeIoUtil struct { - FakeReadDir []os.FileInfo - FakeIsDirectory bool -} - -func (util *FakeIoUtil) Stat(path string) (os.FileInfo, error) { - return FakeFileInfo{IsDirectory: util.FakeIsDirectory}, nil -} - -func (util *FakeIoUtil) RemoveAll(path string) error { - return nil -} - -func (util *FakeIoUtil) ReadDir(path string) ([]os.FileInfo, error) { - return util.FakeReadDir, nil -} - -func (i *FakeIoUtil) ReadFile(filename string) ([]byte, error) { - return make([]byte, 0), nil -} - -type FakeFileInfo struct { - IsDirectory bool -} - -func (ffi FakeFileInfo) IsDir() bool { - return ffi.IsDirectory -} - -func (ffi FakeFileInfo) Size() int64 { - return 1 -} - -func (ffi FakeFileInfo) Mode() os.FileMode { - return 0777 -} - -func (ffi FakeFileInfo) Name() string { - return "" -} - -func (ffi FakeFileInfo) ModTime() time.Time { - return time.Time{} -} - -func (ffi FakeFileInfo) Sys() interface{} { - return nil -} diff --git a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/install_command.go b/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/install_command.go deleted file mode 100644 index f8807d66108..00000000000 --- a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/install_command.go +++ /dev/null @@ -1,146 +0,0 @@ -package commands - -import ( - "archive/zip" - "bytes" - "errors" - "github.com/grafana/grafana-cli/pkg/log" - m "github.com/grafana/grafana-cli/pkg/models" - services "github.com/grafana/grafana-cli/pkg/services" - "io" - "io/ioutil" - "net/http" - "os" - "path" - "regexp" -) - -func validateInput(c CommandLine, pluginFolder string) error { - arg := c.Args().First() - if arg == "" { - return errors.New("please specify plugin to install") - } - - pluginDir := c.GlobalString("path") - if pluginDir == "" { - return errors.New("missing path flag") - } - - fileinfo, err := os.Stat(pluginDir) - if err != nil && !fileinfo.IsDir() { - return errors.New("path is not a directory") - } - - return nil -} - -func installCommand(c CommandLine) error { - pluginFolder := c.GlobalString("path") - if err := validateInput(c, pluginFolder); err != nil { - return err - } - - pluginToInstall := c.Args().First() - version := c.Args().Get(1) - - log.Infof("version: %v\n", version) - - return InstallPlugin(pluginToInstall, pluginFolder, version) -} - -func InstallPlugin(pluginName, pluginFolder, version string) error { - plugin, err := services.GetPlugin(pluginName) - if err != nil { - return err - } - - v, err := SelectVersion(plugin, version) - if err != nil { - return err - } - - url := v.Url - commit := v.Commit - - downloadURL := url + "/archive/" + commit + ".zip" - - log.Infof("installing %v @ %v\n", plugin.Id, version) - log.Infof("from url: %v\n", downloadURL) - log.Infof("on commit: %v\n", commit) - log.Infof("into: %v\n", pluginFolder) - - err = downloadFile(plugin.Id, pluginFolder, downloadURL) - if err == nil { - log.Info("Installed %s successfully ✔\n", plugin.Id) - } - - res := services.ReadPlugin(pluginFolder, pluginName) - - for _, v := range res.Dependency.Plugins { - log.Infof("Depends on %s install!\n", v.Id) - - //Todo: uncomment this code once the repo is more correct. - //InstallPlugin(v.Id, pluginFolder, "") - } - - return err -} - -func SelectVersion(plugin m.Plugin, version string) (m.Version, error) { - if version == "" { - return plugin.Versions[0], nil - } - - for _, v := range plugin.Versions { - if v.Version == version { - return v, nil - } - } - - return m.Version{}, errors.New("Could not find the version your looking for") -} - -func RemoveGitBuildFromname(pluginname, filename string) string { - r := regexp.MustCompile("^[a-zA-Z0-9_.-]*/") - return r.ReplaceAllString(filename, pluginname+"/") -} - -func downloadFile(pluginName, filepath, url string) (err error) { - resp, err := http.Get(url) - if err != nil { - return err - } - defer resp.Body.Close() - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return err - } - - r, err := zip.NewReader(bytes.NewReader(body), resp.ContentLength) - if err != nil { - return err - } - for _, zf := range r.File { - newfile := path.Join(filepath, RemoveGitBuildFromname(pluginName, zf.Name)) - - if zf.FileInfo().IsDir() { - os.Mkdir(newfile, 0777) - } else { - dst, err := os.Create(newfile) - if err != nil { - log.Errorf("%v", err) - } - defer dst.Close() - src, err := zf.Open() - if err != nil { - log.Errorf("%v", err) - } - defer src.Close() - - io.Copy(dst, src) - } - } - - return nil -} diff --git a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/listremote_command.go b/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/listremote_command.go deleted file mode 100644 index 9dc1af204c9..00000000000 --- a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/listremote_command.go +++ /dev/null @@ -1,20 +0,0 @@ -package commands - -import ( - "github.com/grafana/grafana-cli/pkg/log" - "github.com/grafana/grafana-cli/pkg/services" -) - -func listremoteCommand(c CommandLine) error { - plugin, err := services.ListAllPlugins() - - if err != nil { - return err - } - - for _, i := range plugin.Plugins { - log.Infof("id: %v version:\n", i.Id) - } - - return nil -} diff --git a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/ls_command.go b/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/ls_command.go deleted file mode 100644 index 7965f74de27..00000000000 --- a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/ls_command.go +++ /dev/null @@ -1,49 +0,0 @@ -package commands - -import ( - "errors" - "github.com/grafana/grafana-cli/pkg/log" - m "github.com/grafana/grafana-cli/pkg/models" - s "github.com/grafana/grafana-cli/pkg/services" -) - -var getPlugins func(path string) []m.InstalledPlugin - -var GetStat m.IoUtil - -func init() { - getPlugins = s.GetLocalPlugins - GetStat = s.IoUtil -} - -func validateCommand(pluginDir string) error { - if pluginDir == "" { - return errors.New("missing path flag") - } - - log.Info("plugindir: " + pluginDir + "\n") - pluginDirInfo, err := GetStat.Stat(pluginDir) - - if err != nil { - return errors.New("missing path flag") - } - - if pluginDirInfo.IsDir() == false { - return errors.New("plugin path is not a directory") - } - - return nil -} - -func lsCommand(c CommandLine) error { - pluginDir := c.GlobalString("path") - if err := validateCommand(pluginDir); err != nil { - return err - } - - for _, plugin := range getPlugins(pluginDir) { - log.Infof("plugin: %s @ %s \n", plugin.Name, plugin.Info.Version) - } - - return nil -} diff --git a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/remove_command.go b/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/remove_command.go deleted file mode 100644 index 4a25d04404e..00000000000 --- a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/remove_command.go +++ /dev/null @@ -1,35 +0,0 @@ -package commands - -import ( - "errors" - "github.com/grafana/grafana-cli/pkg/log" - m "github.com/grafana/grafana-cli/pkg/models" - services "github.com/grafana/grafana-cli/pkg/services" -) - -var getPluginss func(path string) []m.InstalledPlugin = services.GetLocalPlugins -var removePlugin func(pluginPath, id string) error = services.RemoveInstalledPlugin - -func removeCommand(c CommandLine) error { - pluginPath := c.GlobalString("path") - localPlugins := getPluginss(pluginPath) - - log.Info("remove!\n") - - plugin := c.Args().First() - log.Info("plugin: " + plugin + "\n") - if plugin == "" { - return errors.New("Missing which plugin parameter") - } - - log.Infof("plugins : \n%v\n", localPlugins) - - for _, p := range localPlugins { - log.Infof("is %s == %s ? %v", p.Id, c.Args().First(), p.Id == c.Args().First()) - if p.Id == c.Args().First() { - removePlugin(pluginPath, p.Id) - } - } - - return nil -} diff --git a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/upgrade_all_command.go b/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/upgrade_all_command.go deleted file mode 100644 index 97454769e62..00000000000 --- a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/upgrade_all_command.go +++ /dev/null @@ -1,61 +0,0 @@ -package commands - -import ( - "github.com/grafana/grafana-cli/pkg/log" - m "github.com/grafana/grafana-cli/pkg/models" - services "github.com/grafana/grafana-cli/pkg/services" - "github.com/hashicorp/go-version" -) - -func ShouldUpgrade(installed string, remote m.Plugin) bool { - installedVersion, err1 := version.NewVersion(installed) - - if err1 != nil { - return false - } - - for _, v := range remote.Versions { - remoteVersion, err2 := version.NewVersion(v.Version) - - if err2 == nil { - if installedVersion.LessThan(remoteVersion) { - return true - } - } - } - - return false -} - -func upgradeAllCommand(c CommandLine) error { - pluginDir := c.GlobalString("path") - - localPlugins := services.GetLocalPlugins(pluginDir) - - remotePlugins, err := services.ListAllPlugins() - - if err != nil { - return err - } - - pluginsToUpgrade := make([]m.InstalledPlugin, 0) - - for _, localPlugin := range localPlugins { - for _, remotePlugin := range remotePlugins.Plugins { - if localPlugin.Id == remotePlugin.Id { - if ShouldUpgrade(localPlugin.Info.Version, remotePlugin) { - pluginsToUpgrade = append(pluginsToUpgrade, localPlugin) - } - } - } - } - - for _, p := range pluginsToUpgrade { - log.Infof("lets upgrade %v \n", p) - - services.RemoveInstalledPlugin(pluginDir, p.Id) - InstallPlugin(p.Id, pluginDir, "") - } - - return nil -} diff --git a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/upgrade_command.go b/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/upgrade_command.go deleted file mode 100644 index df9581b3dc3..00000000000 --- a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/commands/upgrade_command.go +++ /dev/null @@ -1,9 +0,0 @@ -package commands - -import ( - "errors" -) - -func upgradeCommand(c CommandLine) error { - return errors.New("Not yet Implemented") -} diff --git a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/log/log.go b/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/log/log.go deleted file mode 100644 index c8222d60c81..00000000000 --- a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/log/log.go +++ /dev/null @@ -1,49 +0,0 @@ -package log - -import ( - "fmt" -) - -var ( - debugmode = false -) - -func Debug(args ...interface{}) { - if debugmode { - fmt.Print(args...) - } -} - -func Debugf(fmtString string, args ...interface{}) { - if debugmode { - fmt.Printf(fmtString, args...) - } -} - -func Error(args ...interface{}) { - fmt.Print(args...) -} - -func Errorf(fmtString string, args ...interface{}) { - fmt.Printf(fmtString, args...) -} - -func Info(args ...interface{}) { - fmt.Print(args...) -} - -func Infof(fmtString string, args ...interface{}) { - fmt.Printf(fmtString, args...) -} - -func Warn(args ...interface{}) { - fmt.Print(args...) -} - -func Warnf(fmtString string, args ...interface{}) { - fmt.Printf(fmtString, args...) -} - -func SetDebug(value bool) { - debugmode = value -} diff --git a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/models/model.go b/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/models/model.go deleted file mode 100644 index 3a39c5fbe65..00000000000 --- a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/models/model.go +++ /dev/null @@ -1,48 +0,0 @@ -package models - -import ( - "os" -) - -type InstalledPlugin struct { - Id string `json:"id"` - Name string `json:"name"` - Type string `json:"type"` - - Info PluginInfo `json:"info"` - Dependency Dependency `json:"dependencies"` -} - -type Dependency struct { - GrafanaVersion string `json:"grafanaVersion"` - Plugins []Plugin `json:"plugins"` -} - -type PluginInfo struct { - Version string `json:"version"` - Updated string `json:"updated"` -} - -type Plugin struct { - Id string `json:"id"` - Category string `json:"category"` - Versions []Version `json:"versions"` -} - -type Version struct { - Commit string `json:"commit"` - Url string `json:"url"` - Version string `json:"version"` -} - -type PluginRepo struct { - Plugins []Plugin `json:"plugins"` - Version string `json:"version"` -} - -type IoUtil interface { - Stat(path string) (os.FileInfo, error) - RemoveAll(path string) error - ReadDir(path string) ([]os.FileInfo, error) - ReadFile(filename string) ([]byte, error) -} diff --git a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/services/io_util.go b/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/services/io_util.go deleted file mode 100644 index 5a7cd187575..00000000000 --- a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/services/io_util.go +++ /dev/null @@ -1,28 +0,0 @@ -package services - -import ( - m "github.com/grafana/grafana-cli/pkg/models" - "io/ioutil" - "os" -) - -var IoUtil m.IoUtil = IoUtilImp{} - -type IoUtilImp struct { -} - -func (i IoUtilImp) Stat(path string) (os.FileInfo, error) { - return os.Stat(path) -} - -func (i IoUtilImp) RemoveAll(path string) error { - return os.RemoveAll(path) -} - -func (i IoUtilImp) ReadDir(path string) ([]os.FileInfo, error) { - return ioutil.ReadDir(path) -} - -func (i IoUtilImp) ReadFile(filename string) ([]byte, error) { - return ioutil.ReadFile(filename) -} diff --git a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/services/services.go b/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/services/services.go deleted file mode 100644 index 9e5b65f5e84..00000000000 --- a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/services/services.go +++ /dev/null @@ -1,70 +0,0 @@ -package services - -import ( - "encoding/json" - "errors" - "github.com/franela/goreq" - m "github.com/grafana/grafana-cli/pkg/models" - "path" -) - -var IoHelper m.IoUtil = IoUtilImp{} - -func ListAllPlugins() (m.PluginRepo, error) { - res, _ := goreq.Request{Uri: "https://raw.githubusercontent.com/grafana/grafana-plugin-repository/master/repo.json"}.Do() - - var resp m.PluginRepo - err := res.Body.FromJsonTo(&resp) - if err != nil { - return m.PluginRepo{}, errors.New("Could not load plugin data") - } - - return resp, nil -} - -func ReadPlugin(pluginDir, pluginName string) m.InstalledPlugin { - pluginDataPath := path.Join(pluginDir, pluginName, "plugin.json") - pluginData, _ := IoHelper.ReadFile(pluginDataPath) - - res := m.InstalledPlugin{} - json.Unmarshal(pluginData, &res) - - if res.Info.Version == "" { - res.Info.Version = "0.0.0" - } - - if res.Id == "" { - res.Id = res.Name - } - - return res -} - -func GetLocalPlugins(pluginDir string) []m.InstalledPlugin { - result := make([]m.InstalledPlugin, 0) - files, _ := IoHelper.ReadDir(pluginDir) - for _, f := range files { - res := ReadPlugin(pluginDir, f.Name()) - result = append(result, res) - } - - return result -} - -func RemoveInstalledPlugin(pluginPath, id string) error { - return IoHelper.RemoveAll(path.Join(pluginPath, id)) -} - -func GetPlugin(id string) (m.Plugin, error) { - resp, err := ListAllPlugins() - if err != nil { - } - - for _, i := range resp.Plugins { - if i.Id == id { - return i, nil - } - } - - return m.Plugin{}, errors.New("could not find plugin named \"" + id + "\"") -} diff --git a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/version/version.go b/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/version/version.go deleted file mode 100644 index 2a0eddf9859..00000000000 --- a/Godeps/_workspace/src/github.com/grafana/grafana-cli/pkg/version/version.go +++ /dev/null @@ -1,5 +0,0 @@ -package version - -var ( - Version = "0.0.2" -) diff --git a/Godeps/_workspace/src/github.com/mattn/go-sqlite3/error_test.go b/Godeps/_workspace/src/github.com/mattn/go-sqlite3/error_test.go deleted file mode 100644 index 1ccbe5bf858..00000000000 --- a/Godeps/_workspace/src/github.com/mattn/go-sqlite3/error_test.go +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright (C) 2014 Yasuhiro Matsumoto . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package sqlite3 - -import ( - "database/sql" - "io/ioutil" - "os" - "path" - "testing" -) - -func TestSimpleError(t *testing.T) { - e := ErrError.Error() - if e != "SQL logic error or missing database" { - t.Error("wrong error code:" + e) - } -} - -func TestCorruptDbErrors(t *testing.T) { - dirName, err := ioutil.TempDir("", "sqlite3") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dirName) - - dbFileName := path.Join(dirName, "test.db") - f, err := os.Create(dbFileName) - if err != nil { - t.Error(err) - } - f.Write([]byte{1, 2, 3, 4, 5}) - f.Close() - - db, err := sql.Open("sqlite3", dbFileName) - if err == nil { - _, err = db.Exec("drop table foo") - } - - sqliteErr := err.(Error) - if sqliteErr.Code != ErrNotADB { - t.Error("wrong error code for corrupted DB") - } - if err.Error() == "" { - t.Error("wrong error string for corrupted DB") - } - db.Close() -} - -func TestSqlLogicErrors(t *testing.T) { - dirName, err := ioutil.TempDir("", "sqlite3") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dirName) - - dbFileName := path.Join(dirName, "test.db") - db, err := sql.Open("sqlite3", dbFileName) - if err != nil { - t.Error(err) - } - defer db.Close() - - _, err = db.Exec("CREATE TABLE Foo (id INTEGER PRIMARY KEY)") - if err != nil { - t.Error(err) - } - - const expectedErr = "table Foo already exists" - _, err = db.Exec("CREATE TABLE Foo (id INTEGER PRIMARY KEY)") - if err.Error() != expectedErr { - t.Errorf("Unexpected error: %s, expected %s", err.Error(), expectedErr) - } - -} - -func TestExtendedErrorCodes_ForeignKey(t *testing.T) { - dirName, err := ioutil.TempDir("", "sqlite3-err") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dirName) - - dbFileName := path.Join(dirName, "test.db") - db, err := sql.Open("sqlite3", dbFileName) - if err != nil { - t.Error(err) - } - defer db.Close() - - _, err = db.Exec("PRAGMA foreign_keys=ON;") - if err != nil { - t.Errorf("PRAGMA foreign_keys=ON: %v", err) - } - - _, err = db.Exec(`CREATE TABLE Foo ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - value INTEGER NOT NULL, - ref INTEGER NULL REFERENCES Foo (id), - UNIQUE(value) - );`) - if err != nil { - t.Error(err) - } - - _, err = db.Exec("INSERT INTO Foo (ref, value) VALUES (100, 100);") - if err == nil { - t.Error("No error!") - } else { - sqliteErr := err.(Error) - if sqliteErr.Code != ErrConstraint { - t.Errorf("Wrong basic error code: %d != %d", - sqliteErr.Code, ErrConstraint) - } - if sqliteErr.ExtendedCode != ErrConstraintForeignKey { - t.Errorf("Wrong extended error code: %d != %d", - sqliteErr.ExtendedCode, ErrConstraintForeignKey) - } - } - -} - -func TestExtendedErrorCodes_NotNull(t *testing.T) { - dirName, err := ioutil.TempDir("", "sqlite3-err") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dirName) - - dbFileName := path.Join(dirName, "test.db") - db, err := sql.Open("sqlite3", dbFileName) - if err != nil { - t.Error(err) - } - defer db.Close() - - _, err = db.Exec("PRAGMA foreign_keys=ON;") - if err != nil { - t.Errorf("PRAGMA foreign_keys=ON: %v", err) - } - - _, err = db.Exec(`CREATE TABLE Foo ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - value INTEGER NOT NULL, - ref INTEGER NULL REFERENCES Foo (id), - UNIQUE(value) - );`) - if err != nil { - t.Error(err) - } - - res, err := db.Exec("INSERT INTO Foo (value) VALUES (100);") - if err != nil { - t.Fatalf("Creating first row: %v", err) - } - - id, err := res.LastInsertId() - if err != nil { - t.Fatalf("Retrieving last insert id: %v", err) - } - - _, err = db.Exec("INSERT INTO Foo (ref) VALUES (?);", id) - if err == nil { - t.Error("No error!") - } else { - sqliteErr := err.(Error) - if sqliteErr.Code != ErrConstraint { - t.Errorf("Wrong basic error code: %d != %d", - sqliteErr.Code, ErrConstraint) - } - if sqliteErr.ExtendedCode != ErrConstraintNotNull { - t.Errorf("Wrong extended error code: %d != %d", - sqliteErr.ExtendedCode, ErrConstraintNotNull) - } - } - -} - -func TestExtendedErrorCodes_Unique(t *testing.T) { - dirName, err := ioutil.TempDir("", "sqlite3-err") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dirName) - - dbFileName := path.Join(dirName, "test.db") - db, err := sql.Open("sqlite3", dbFileName) - if err != nil { - t.Error(err) - } - defer db.Close() - - _, err = db.Exec("PRAGMA foreign_keys=ON;") - if err != nil { - t.Errorf("PRAGMA foreign_keys=ON: %v", err) - } - - _, err = db.Exec(`CREATE TABLE Foo ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - value INTEGER NOT NULL, - ref INTEGER NULL REFERENCES Foo (id), - UNIQUE(value) - );`) - if err != nil { - t.Error(err) - } - - res, err := db.Exec("INSERT INTO Foo (value) VALUES (100);") - if err != nil { - t.Fatalf("Creating first row: %v", err) - } - - id, err := res.LastInsertId() - if err != nil { - t.Fatalf("Retrieving last insert id: %v", err) - } - - _, err = db.Exec("INSERT INTO Foo (ref, value) VALUES (?, 100);", id) - if err == nil { - t.Error("No error!") - } else { - sqliteErr := err.(Error) - if sqliteErr.Code != ErrConstraint { - t.Errorf("Wrong basic error code: %d != %d", - sqliteErr.Code, ErrConstraint) - } - if sqliteErr.ExtendedCode != ErrConstraintUnique { - t.Errorf("Wrong extended error code: %d != %d", - sqliteErr.ExtendedCode, ErrConstraintUnique) - } - extended := sqliteErr.Code.Extend(3).Error() - expected := "constraint failed" - if extended != expected { - t.Errorf("Wrong basic error code: %q != %q", - extended, expected) - } - } - -} diff --git a/Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3_fts3_test.go b/Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3_fts3_test.go deleted file mode 100644 index a1cd2172d79..00000000000 --- a/Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3_fts3_test.go +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (C) 2015 Yasuhiro Matsumoto . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package sqlite3 - -import ( - "database/sql" - "os" - "testing" -) - -func TestFTS3(t *testing.T) { - tempFilename := TempFilename() - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer os.Remove(tempFilename) - defer db.Close() - - _, err = db.Exec("DROP TABLE foo") - _, err = db.Exec("CREATE VIRTUAL TABLE foo USING fts3(id INTEGER PRIMARY KEY, value TEXT)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - _, err = db.Exec("INSERT INTO foo(id, value) VALUES(?, ?)", 1, `今日の 晩御飯は 天麩羅よ`) - if err != nil { - t.Fatal("Failed to insert value:", err) - } - - _, err = db.Exec("INSERT INTO foo(id, value) VALUES(?, ?)", 2, `今日は いい 天気だ`) - if err != nil { - t.Fatal("Failed to insert value:", err) - } - - rows, err := db.Query("SELECT id, value FROM foo WHERE value MATCH '今日* 天*'") - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - defer rows.Close() - - for rows.Next() { - var id int - var value string - - if err := rows.Scan(&id, &value); err != nil { - t.Error("Unable to scan results:", err) - continue - } - - if id == 1 && value != `今日の 晩御飯は 天麩羅よ` { - t.Error("Value for id 1 should be `今日の 晩御飯は 天麩羅よ`, but:", value) - } else if id == 2 && value != `今日は いい 天気だ` { - t.Error("Value for id 2 should be `今日は いい 天気だ`, but:", value) - } - } - - rows, err = db.Query("SELECT value FROM foo WHERE value MATCH '今日* 天麩羅*'") - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - defer rows.Close() - - var value string - if !rows.Next() { - t.Fatal("Result should be only one") - } - - if err := rows.Scan(&value); err != nil { - t.Fatal("Unable to scan results:", err) - } - - if value != `今日の 晩御飯は 天麩羅よ` { - t.Fatal("Value should be `今日の 晩御飯は 天麩羅よ`, but:", value) - } - - if rows.Next() { - t.Fatal("Result should be only one") - } -} diff --git a/Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3_test.go b/Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3_test.go deleted file mode 100644 index aa8601181b5..00000000000 --- a/Godeps/_workspace/src/github.com/mattn/go-sqlite3/sqlite3_test.go +++ /dev/null @@ -1,947 +0,0 @@ -// Copyright (C) 2014 Yasuhiro Matsumoto . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package sqlite3 - -import ( - "crypto/rand" - "database/sql" - "encoding/hex" - "net/url" - "os" - "path/filepath" - "strings" - "testing" - "time" - - "github.com/mattn/go-sqlite3/sqlite3_test" -) - -func TempFilename() string { - randBytes := make([]byte, 16) - rand.Read(randBytes) - return filepath.Join(os.TempDir(), "foo"+hex.EncodeToString(randBytes)+".db") -} - -func TestOpen(t *testing.T) { - tempFilename := TempFilename() - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer os.Remove(tempFilename) - defer db.Close() - - _, err = db.Exec("drop table foo") - _, err = db.Exec("create table foo (id integer)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - if stat, err := os.Stat(tempFilename); err != nil || stat.IsDir() { - t.Error("Failed to create ./foo.db") - } -} - -func TestClose(t *testing.T) { - tempFilename := TempFilename() - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer os.Remove(tempFilename) - - _, err = db.Exec("drop table foo") - _, err = db.Exec("create table foo (id integer)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - stmt, err := db.Prepare("select id from foo where id = ?") - if err != nil { - t.Fatal("Failed to select records:", err) - } - - db.Close() - _, err = stmt.Exec(1) - if err == nil { - t.Fatal("Failed to operate closed statement") - } -} - -func TestInsert(t *testing.T) { - tempFilename := TempFilename() - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer os.Remove(tempFilename) - defer db.Close() - - _, err = db.Exec("drop table foo") - _, err = db.Exec("create table foo (id integer)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - res, err := db.Exec("insert into foo(id) values(123)") - if err != nil { - t.Fatal("Failed to insert record:", err) - } - affected, _ := res.RowsAffected() - if affected != 1 { - t.Fatalf("Expected %d for affected rows, but %d:", 1, affected) - } - - rows, err := db.Query("select id from foo") - if err != nil { - t.Fatal("Failed to select records:", err) - } - defer rows.Close() - - rows.Next() - - var result int - rows.Scan(&result) - if result != 123 { - t.Errorf("Fetched %q; expected %q", 123, result) - } -} - -func TestUpdate(t *testing.T) { - tempFilename := TempFilename() - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer os.Remove(tempFilename) - defer db.Close() - - _, err = db.Exec("drop table foo") - _, err = db.Exec("create table foo (id integer)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - res, err := db.Exec("insert into foo(id) values(123)") - if err != nil { - t.Fatal("Failed to insert record:", err) - } - expected, err := res.LastInsertId() - if err != nil { - t.Fatal("Failed to get LastInsertId:", err) - } - affected, _ := res.RowsAffected() - if err != nil { - t.Fatal("Failed to get RowsAffected:", err) - } - if affected != 1 { - t.Fatalf("Expected %d for affected rows, but %d:", 1, affected) - } - - res, err = db.Exec("update foo set id = 234") - if err != nil { - t.Fatal("Failed to update record:", err) - } - lastId, err := res.LastInsertId() - if err != nil { - t.Fatal("Failed to get LastInsertId:", err) - } - if expected != lastId { - t.Errorf("Expected %q for last Id, but %q:", expected, lastId) - } - affected, _ = res.RowsAffected() - if err != nil { - t.Fatal("Failed to get RowsAffected:", err) - } - if affected != 1 { - t.Fatalf("Expected %d for affected rows, but %d:", 1, affected) - } - - rows, err := db.Query("select id from foo") - if err != nil { - t.Fatal("Failed to select records:", err) - } - defer rows.Close() - - rows.Next() - - var result int - rows.Scan(&result) - if result != 234 { - t.Errorf("Fetched %q; expected %q", 234, result) - } -} - -func TestDelete(t *testing.T) { - tempFilename := TempFilename() - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer os.Remove(tempFilename) - defer db.Close() - - _, err = db.Exec("drop table foo") - _, err = db.Exec("create table foo (id integer)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - res, err := db.Exec("insert into foo(id) values(123)") - if err != nil { - t.Fatal("Failed to insert record:", err) - } - expected, err := res.LastInsertId() - if err != nil { - t.Fatal("Failed to get LastInsertId:", err) - } - affected, err := res.RowsAffected() - if err != nil { - t.Fatal("Failed to get RowsAffected:", err) - } - if affected != 1 { - t.Errorf("Expected %d for cout of affected rows, but %q:", 1, affected) - } - - res, err = db.Exec("delete from foo where id = 123") - if err != nil { - t.Fatal("Failed to delete record:", err) - } - lastId, err := res.LastInsertId() - if err != nil { - t.Fatal("Failed to get LastInsertId:", err) - } - if expected != lastId { - t.Errorf("Expected %q for last Id, but %q:", expected, lastId) - } - affected, err = res.RowsAffected() - if err != nil { - t.Fatal("Failed to get RowsAffected:", err) - } - if affected != 1 { - t.Errorf("Expected %d for cout of affected rows, but %q:", 1, affected) - } - - rows, err := db.Query("select id from foo") - if err != nil { - t.Fatal("Failed to select records:", err) - } - defer rows.Close() - - if rows.Next() { - t.Error("Fetched row but expected not rows") - } -} - -func TestBooleanRoundtrip(t *testing.T) { - tempFilename := TempFilename() - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer os.Remove(tempFilename) - defer db.Close() - - _, err = db.Exec("DROP TABLE foo") - _, err = db.Exec("CREATE TABLE foo(id INTEGER, value BOOL)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - _, err = db.Exec("INSERT INTO foo(id, value) VALUES(1, ?)", true) - if err != nil { - t.Fatal("Failed to insert true value:", err) - } - - _, err = db.Exec("INSERT INTO foo(id, value) VALUES(2, ?)", false) - if err != nil { - t.Fatal("Failed to insert false value:", err) - } - - rows, err := db.Query("SELECT id, value FROM foo") - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - defer rows.Close() - - for rows.Next() { - var id int - var value bool - - if err := rows.Scan(&id, &value); err != nil { - t.Error("Unable to scan results:", err) - continue - } - - if id == 1 && !value { - t.Error("Value for id 1 should be true, not false") - - } else if id == 2 && value { - t.Error("Value for id 2 should be false, not true") - } - } -} - -func TestTimestamp(t *testing.T) { - tempFilename := TempFilename() - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer os.Remove(tempFilename) - defer db.Close() - - _, err = db.Exec("DROP TABLE foo") - _, err = db.Exec("CREATE TABLE foo(id INTEGER, ts timeSTAMP, dt DATETIME)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - timestamp1 := time.Date(2012, time.April, 6, 22, 50, 0, 0, time.UTC) - timestamp2 := time.Date(2006, time.January, 2, 15, 4, 5, 123456789, time.UTC) - timestamp3 := time.Date(2012, time.November, 4, 0, 0, 0, 0, time.UTC) - tests := []struct { - value interface{} - expected time.Time - }{ - {"nonsense", time.Time{}}, - {"0000-00-00 00:00:00", time.Time{}}, - {timestamp1, timestamp1}, - {timestamp1.Unix(), timestamp1}, - {timestamp1.UnixNano() / int64(time.Millisecond), timestamp1}, - {timestamp1.In(time.FixedZone("TEST", -7*3600)), timestamp1}, - {timestamp1.Format("2006-01-02 15:04:05.000"), timestamp1}, - {timestamp1.Format("2006-01-02T15:04:05.000"), timestamp1}, - {timestamp1.Format("2006-01-02 15:04:05"), timestamp1}, - {timestamp1.Format("2006-01-02T15:04:05"), timestamp1}, - {timestamp2, timestamp2}, - {"2006-01-02 15:04:05.123456789", timestamp2}, - {"2006-01-02T15:04:05.123456789", timestamp2}, - {"2012-11-04", timestamp3}, - {"2012-11-04 00:00", timestamp3}, - {"2012-11-04 00:00:00", timestamp3}, - {"2012-11-04 00:00:00.000", timestamp3}, - {"2012-11-04T00:00", timestamp3}, - {"2012-11-04T00:00:00", timestamp3}, - {"2012-11-04T00:00:00.000", timestamp3}, - } - for i := range tests { - _, err = db.Exec("INSERT INTO foo(id, ts, dt) VALUES(?, ?, ?)", i, tests[i].value, tests[i].value) - if err != nil { - t.Fatal("Failed to insert timestamp:", err) - } - } - - rows, err := db.Query("SELECT id, ts, dt FROM foo ORDER BY id ASC") - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - defer rows.Close() - - seen := 0 - for rows.Next() { - var id int - var ts, dt time.Time - - if err := rows.Scan(&id, &ts, &dt); err != nil { - t.Error("Unable to scan results:", err) - continue - } - if id < 0 || id >= len(tests) { - t.Error("Bad row id: ", id) - continue - } - seen++ - if !tests[id].expected.Equal(ts) { - t.Errorf("Timestamp value for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected, dt) - } - if !tests[id].expected.Equal(dt) { - t.Errorf("Datetime value for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected, dt) - } - } - - if seen != len(tests) { - t.Errorf("Expected to see %d rows", len(tests)) - } -} - -func TestBoolean(t *testing.T) { - tempFilename := TempFilename() - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - - defer os.Remove(tempFilename) - defer db.Close() - - _, err = db.Exec("CREATE TABLE foo(id INTEGER, fbool BOOLEAN)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - bool1 := true - _, err = db.Exec("INSERT INTO foo(id, fbool) VALUES(1, ?)", bool1) - if err != nil { - t.Fatal("Failed to insert boolean:", err) - } - - bool2 := false - _, err = db.Exec("INSERT INTO foo(id, fbool) VALUES(2, ?)", bool2) - if err != nil { - t.Fatal("Failed to insert boolean:", err) - } - - bool3 := "nonsense" - _, err = db.Exec("INSERT INTO foo(id, fbool) VALUES(3, ?)", bool3) - if err != nil { - t.Fatal("Failed to insert nonsense:", err) - } - - rows, err := db.Query("SELECT id, fbool FROM foo where fbool = ?", bool1) - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - counter := 0 - - var id int - var fbool bool - - for rows.Next() { - if err := rows.Scan(&id, &fbool); err != nil { - t.Fatal("Unable to scan results:", err) - } - counter++ - } - - if counter != 1 { - t.Fatalf("Expected 1 row but %v", counter) - } - - if id != 1 && fbool != true { - t.Fatalf("Value for id 1 should be %v, not %v", bool1, fbool) - } - - rows, err = db.Query("SELECT id, fbool FROM foo where fbool = ?", bool2) - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - - counter = 0 - - for rows.Next() { - if err := rows.Scan(&id, &fbool); err != nil { - t.Fatal("Unable to scan results:", err) - } - counter++ - } - - if counter != 1 { - t.Fatalf("Expected 1 row but %v", counter) - } - - if id != 2 && fbool != false { - t.Fatalf("Value for id 2 should be %v, not %v", bool2, fbool) - } - - // make sure "nonsense" triggered an error - rows, err = db.Query("SELECT id, fbool FROM foo where id=?;", 3) - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - - rows.Next() - err = rows.Scan(&id, &fbool) - if err == nil { - t.Error("Expected error from \"nonsense\" bool") - } -} - -func TestFloat32(t *testing.T) { - tempFilename := TempFilename() - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - - defer os.Remove(tempFilename) - defer db.Close() - - _, err = db.Exec("CREATE TABLE foo(id INTEGER)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - _, err = db.Exec("INSERT INTO foo(id) VALUES(null)") - if err != nil { - t.Fatal("Failed to insert null:", err) - } - - rows, err := db.Query("SELECT id FROM foo") - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - - if !rows.Next() { - t.Fatal("Unable to query results:", err) - } - - var id interface{} - if err := rows.Scan(&id); err != nil { - t.Fatal("Unable to scan results:", err) - } - if id != nil { - t.Error("Expected nil but not") - } -} - -func TestNull(t *testing.T) { - tempFilename := TempFilename() - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - - defer os.Remove(tempFilename) - defer db.Close() - - rows, err := db.Query("SELECT 3.141592") - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - - if !rows.Next() { - t.Fatal("Unable to query results:", err) - } - - var v interface{} - if err := rows.Scan(&v); err != nil { - t.Fatal("Unable to scan results:", err) - } - f, ok := v.(float64) - if !ok { - t.Error("Expected float but not") - } - if f != 3.141592 { - t.Error("Expected 3.141592 but not") - } -} - -func TestTransaction(t *testing.T) { - tempFilename := TempFilename() - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - - defer os.Remove(tempFilename) - defer db.Close() - - _, err = db.Exec("CREATE TABLE foo(id INTEGER)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - tx, err := db.Begin() - if err != nil { - t.Fatal("Failed to begin transaction:", err) - } - - _, err = tx.Exec("INSERT INTO foo(id) VALUES(1)") - if err != nil { - t.Fatal("Failed to insert null:", err) - } - - rows, err := tx.Query("SELECT id from foo") - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - - err = tx.Rollback() - if err != nil { - t.Fatal("Failed to rollback transaction:", err) - } - - if rows.Next() { - t.Fatal("Unable to query results:", err) - } - - tx, err = db.Begin() - if err != nil { - t.Fatal("Failed to begin transaction:", err) - } - - _, err = tx.Exec("INSERT INTO foo(id) VALUES(1)") - if err != nil { - t.Fatal("Failed to insert null:", err) - } - - err = tx.Commit() - if err != nil { - t.Fatal("Failed to commit transaction:", err) - } - - rows, err = tx.Query("SELECT id from foo") - if err == nil { - t.Fatal("Expected failure to query") - } -} - -func TestWAL(t *testing.T) { - tempFilename := TempFilename() - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - - defer os.Remove(tempFilename) - defer db.Close() - if _, err = db.Exec("PRAGMA journal_mode=WAL;"); err != nil { - t.Fatal("Failed to Exec PRAGMA journal_mode:", err) - } - if _, err = db.Exec("PRAGMA locking_mode=EXCLUSIVE;"); err != nil { - t.Fatal("Failed to Exec PRAGMA locking_mode:", err) - } - if _, err = db.Exec("CREATE TABLE test (id SERIAL, user TEXT NOT NULL, name TEXT NOT NULL);"); err != nil { - t.Fatal("Failed to Exec CREATE TABLE:", err) - } - if _, err = db.Exec("INSERT INTO test (user, name) VALUES ('user','name');"); err != nil { - t.Fatal("Failed to Exec INSERT:", err) - } - - trans, err := db.Begin() - if err != nil { - t.Fatal("Failed to Begin:", err) - } - s, err := trans.Prepare("INSERT INTO test (user, name) VALUES (?, ?);") - if err != nil { - t.Fatal("Failed to Prepare:", err) - } - - var count int - if err = trans.QueryRow("SELECT count(user) FROM test;").Scan(&count); err != nil { - t.Fatal("Failed to QueryRow:", err) - } - if _, err = s.Exec("bbbb", "aaaa"); err != nil { - t.Fatal("Failed to Exec prepared statement:", err) - } - if err = s.Close(); err != nil { - t.Fatal("Failed to Close prepared statement:", err) - } - if err = trans.Commit(); err != nil { - t.Fatal("Failed to Commit:", err) - } -} - -func TestTimezoneConversion(t *testing.T) { - zones := []string{"UTC", "US/Central", "US/Pacific", "Local"} - for _, tz := range zones { - tempFilename := TempFilename() - db, err := sql.Open("sqlite3", tempFilename+"?_loc="+url.QueryEscape(tz)) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer os.Remove(tempFilename) - defer db.Close() - - _, err = db.Exec("DROP TABLE foo") - _, err = db.Exec("CREATE TABLE foo(id INTEGER, ts TIMESTAMP, dt DATETIME)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - loc, err := time.LoadLocation(tz) - if err != nil { - t.Fatal("Failed to load location:", err) - } - - timestamp1 := time.Date(2012, time.April, 6, 22, 50, 0, 0, time.UTC) - timestamp2 := time.Date(2006, time.January, 2, 15, 4, 5, 123456789, time.UTC) - timestamp3 := time.Date(2012, time.November, 4, 0, 0, 0, 0, time.UTC) - tests := []struct { - value interface{} - expected time.Time - }{ - {"nonsense", time.Time{}.In(loc)}, - {"0000-00-00 00:00:00", time.Time{}.In(loc)}, - {timestamp1, timestamp1.In(loc)}, - {timestamp1.Unix(), timestamp1.In(loc)}, - {timestamp1.In(time.FixedZone("TEST", -7*3600)), timestamp1.In(loc)}, - {timestamp1.Format("2006-01-02 15:04:05.000"), timestamp1.In(loc)}, - {timestamp1.Format("2006-01-02T15:04:05.000"), timestamp1.In(loc)}, - {timestamp1.Format("2006-01-02 15:04:05"), timestamp1.In(loc)}, - {timestamp1.Format("2006-01-02T15:04:05"), timestamp1.In(loc)}, - {timestamp2, timestamp2.In(loc)}, - {"2006-01-02 15:04:05.123456789", timestamp2.In(loc)}, - {"2006-01-02T15:04:05.123456789", timestamp2.In(loc)}, - {"2012-11-04", timestamp3.In(loc)}, - {"2012-11-04 00:00", timestamp3.In(loc)}, - {"2012-11-04 00:00:00", timestamp3.In(loc)}, - {"2012-11-04 00:00:00.000", timestamp3.In(loc)}, - {"2012-11-04T00:00", timestamp3.In(loc)}, - {"2012-11-04T00:00:00", timestamp3.In(loc)}, - {"2012-11-04T00:00:00.000", timestamp3.In(loc)}, - } - for i := range tests { - _, err = db.Exec("INSERT INTO foo(id, ts, dt) VALUES(?, ?, ?)", i, tests[i].value, tests[i].value) - if err != nil { - t.Fatal("Failed to insert timestamp:", err) - } - } - - rows, err := db.Query("SELECT id, ts, dt FROM foo ORDER BY id ASC") - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - defer rows.Close() - - seen := 0 - for rows.Next() { - var id int - var ts, dt time.Time - - if err := rows.Scan(&id, &ts, &dt); err != nil { - t.Error("Unable to scan results:", err) - continue - } - if id < 0 || id >= len(tests) { - t.Error("Bad row id: ", id) - continue - } - seen++ - if !tests[id].expected.Equal(ts) { - t.Errorf("Timestamp value for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected, ts) - } - if !tests[id].expected.Equal(dt) { - t.Errorf("Datetime value for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected, dt) - } - if tests[id].expected.Location().String() != ts.Location().String() { - t.Errorf("Location for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected.Location().String(), ts.Location().String()) - } - if tests[id].expected.Location().String() != dt.Location().String() { - t.Errorf("Location for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected.Location().String(), dt.Location().String()) - } - } - - if seen != len(tests) { - t.Errorf("Expected to see %d rows", len(tests)) - } - } -} - -func TestSuite(t *testing.T) { - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - t.Fatal(err) - } - defer db.Close() - - sqlite3_test.RunTests(t, db, sqlite3_test.SQLITE) -} - -// TODO: Execer & Queryer currently disabled -// https://github.com/mattn/go-sqlite3/issues/82 -func TestExecer(t *testing.T) { - tempFilename := TempFilename() - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer os.Remove(tempFilename) - defer db.Close() - - _, err = db.Exec(` - create table foo (id integer); -- one comment - insert into foo(id) values(?); - insert into foo(id) values(?); - insert into foo(id) values(?); -- another comment - `, 1, 2, 3) - if err != nil { - t.Error("Failed to call db.Exec:", err) - } -} - -func TestQueryer(t *testing.T) { - tempFilename := TempFilename() - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer os.Remove(tempFilename) - defer db.Close() - - _, err = db.Exec(` - create table foo (id integer); - `) - if err != nil { - t.Error("Failed to call db.Query:", err) - } - - rows, err := db.Query(` - insert into foo(id) values(?); - insert into foo(id) values(?); - insert into foo(id) values(?); - select id from foo order by id; - `, 3, 2, 1) - if err != nil { - t.Error("Failed to call db.Query:", err) - } - defer rows.Close() - n := 1 - if rows != nil { - for rows.Next() { - var id int - err = rows.Scan(&id) - if err != nil { - t.Error("Failed to db.Query:", err) - } - if id != n { - t.Error("Failed to db.Query: not matched results") - } - } - } -} - -func TestStress(t *testing.T) { - tempFilename := TempFilename() - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - db.Exec("CREATE TABLE foo (id int);") - db.Exec("INSERT INTO foo VALUES(1);") - db.Exec("INSERT INTO foo VALUES(2);") - db.Close() - - for i := 0; i < 10000; i++ { - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - - for j := 0; j < 3; j++ { - rows, err := db.Query("select * from foo where id=1;") - if err != nil { - t.Error("Failed to call db.Query:", err) - } - for rows.Next() { - var i int - if err := rows.Scan(&i); err != nil { - t.Errorf("Scan failed: %v\n", err) - } - } - if err := rows.Err(); err != nil { - t.Errorf("Post-scan failed: %v\n", err) - } - rows.Close() - } - db.Close() - } -} - -func TestDateTimeLocal(t *testing.T) { - zone := "Asia/Tokyo" - tempFilename := TempFilename() - db, err := sql.Open("sqlite3", tempFilename+"?_loc="+zone) - if err != nil { - t.Fatal("Failed to open database:", err) - } - db.Exec("CREATE TABLE foo (dt datetime);") - db.Exec("INSERT INTO foo VALUES('2015-03-05 15:16:17');") - - row := db.QueryRow("select * from foo") - var d time.Time - err = row.Scan(&d) - if err != nil { - t.Fatal("Failed to scan datetime:", err) - } - if d.Hour() == 15 || !strings.Contains(d.String(), "JST") { - t.Fatal("Result should have timezone", d) - } - db.Close() - - db, err = sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - - row = db.QueryRow("select * from foo") - err = row.Scan(&d) - if err != nil { - t.Fatal("Failed to scan datetime:", err) - } - if d.UTC().Hour() != 15 || !strings.Contains(d.String(), "UTC") { - t.Fatalf("Result should not have timezone %v %v", zone, d.String()) - } - - _, err = db.Exec("DELETE FROM foo") - if err != nil { - t.Fatal("Failed to delete table:", err) - } - dt, err := time.Parse("2006/1/2 15/4/5 -0700 MST", "2015/3/5 15/16/17 +0900 JST") - if err != nil { - t.Fatal("Failed to parse datetime:", err) - } - db.Exec("INSERT INTO foo VALUES(?);", dt) - - db.Close() - db, err = sql.Open("sqlite3", tempFilename+"?_loc="+zone) - if err != nil { - t.Fatal("Failed to open database:", err) - } - - row = db.QueryRow("select * from foo") - err = row.Scan(&d) - if err != nil { - t.Fatal("Failed to scan datetime:", err) - } - if d.Hour() != 15 || !strings.Contains(d.String(), "JST") { - t.Fatalf("Result should have timezone %v %v", zone, d.String()) - } -} - -func TestVersion(t *testing.T) { - s, n, id := Version() - if s == "" || n == 0 || id == "" { - t.Errorf("Version failed %q, %d, %q\n", s, n, id) - } -} - -func TestNumberNamedParams(t *testing.T) { - tempFilename := TempFilename() - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer os.Remove(tempFilename) - defer db.Close() - - _, err = db.Exec(` - create table foo (id integer, name text, extra text); - `) - if err != nil { - t.Error("Failed to call db.Query:", err) - } - - _, err = db.Exec(`insert into foo(id, name, extra) values($1, $2, $2)`, 1, "foo") - if err != nil { - t.Error("Failed to call db.Exec:", err) - } - - row := db.QueryRow(`select id, extra from foo where id = $1 and extra = $2`, 1, "foo") - if row == nil { - t.Error("Failed to call db.QueryRow") - } - var id int - var extra string - err = row.Scan(&id, &extra) - if err != nil { - t.Error("Failed to db.Scan:", err) - } - if id != 1 || extra != "foo" { - t.Error("Failed to db.QueryRow: not matched results") - } -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/assertions.goconvey b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/assertions.goconvey deleted file mode 100644 index 8a7f1b6671a..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/assertions.goconvey +++ /dev/null @@ -1,3 +0,0 @@ -#ignore --timeout=1s --coverpkg=github.com/smartystreets/goconvey/convey/assertions,github.com/smartystreets/goconvey/convey/assertions/oglematchers \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/collections_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/collections_test.go deleted file mode 100644 index 25612bd7670..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/collections_test.go +++ /dev/null @@ -1,103 +0,0 @@ -package assertions - -import ( - "fmt" - "testing" - "time" -) - -func TestShouldContain(t *testing.T) { - fail(t, so([]int{}, ShouldContain), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so([]int{}, ShouldContain, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") - - fail(t, so(Thing1{}, ShouldContain, 1), "You must provide a valid container (was assertions.Thing1)!") - fail(t, so(nil, ShouldContain, 1), "You must provide a valid container (was )!") - fail(t, so([]int{1}, ShouldContain, 2), "Expected the container ([]int) to contain: '2' (but it didn't)!") - - pass(t, so([]int{1}, ShouldContain, 1)) - pass(t, so([]int{1, 2, 3}, ShouldContain, 2)) -} - -func TestShouldNotContain(t *testing.T) { - fail(t, so([]int{}, ShouldNotContain), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so([]int{}, ShouldNotContain, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") - - fail(t, so(Thing1{}, ShouldNotContain, 1), "You must provide a valid container (was assertions.Thing1)!") - fail(t, so(nil, ShouldNotContain, 1), "You must provide a valid container (was )!") - - fail(t, so([]int{1}, ShouldNotContain, 1), "Expected the container ([]int) NOT to contain: '1' (but it did)!") - fail(t, so([]int{1, 2, 3}, ShouldNotContain, 2), "Expected the container ([]int) NOT to contain: '2' (but it did)!") - - pass(t, so([]int{1}, ShouldNotContain, 2)) -} - -func TestShouldBeIn(t *testing.T) { - fail(t, so(4, ShouldBeIn), shouldHaveProvidedCollectionMembers) - - container := []int{1, 2, 3, 4} - pass(t, so(4, ShouldBeIn, container)) - pass(t, so(4, ShouldBeIn, 1, 2, 3, 4)) - - fail(t, so(4, ShouldBeIn, 1, 2, 3), "Expected '4' to be in the container ([]interface {}, but it wasn't)!") - fail(t, so(4, ShouldBeIn, []int{1, 2, 3}), "Expected '4' to be in the container ([]int, but it wasn't)!") -} - -func TestShouldNotBeIn(t *testing.T) { - fail(t, so(4, ShouldNotBeIn), shouldHaveProvidedCollectionMembers) - - container := []int{1, 2, 3, 4} - pass(t, so(42, ShouldNotBeIn, container)) - pass(t, so(42, ShouldNotBeIn, 1, 2, 3, 4)) - - fail(t, so(2, ShouldNotBeIn, 1, 2, 3), "Expected '2' NOT to be in the container ([]interface {}, but it was)!") - fail(t, so(2, ShouldNotBeIn, []int{1, 2, 3}), "Expected '2' NOT to be in the container ([]int, but it was)!") -} - -func TestShouldBeEmpty(t *testing.T) { - fail(t, so(1, ShouldBeEmpty, 2, 3), "This assertion requires exactly 0 comparison values (you provided 2).") - - pass(t, so([]int{}, ShouldBeEmpty)) // empty slice - pass(t, so([]interface{}{}, ShouldBeEmpty)) // empty slice - pass(t, so(map[string]int{}, ShouldBeEmpty)) // empty map - pass(t, so("", ShouldBeEmpty)) // empty string - pass(t, so(&[]int{}, ShouldBeEmpty)) // pointer to empty slice - pass(t, so(&[0]int{}, ShouldBeEmpty)) // pointer to empty array - pass(t, so(nil, ShouldBeEmpty)) // nil - pass(t, so(make(chan string), ShouldBeEmpty)) // empty channel - - fail(t, so([]int{1}, ShouldBeEmpty), "Expected [1] to be empty (but it wasn't)!") // non-empty slice - fail(t, so([]interface{}{1}, ShouldBeEmpty), "Expected [1] to be empty (but it wasn't)!") // non-empty slice - fail(t, so(map[string]int{"hi": 0}, ShouldBeEmpty), "Expected map[hi:0] to be empty (but it wasn't)!") // non-empty map - fail(t, so("hi", ShouldBeEmpty), "Expected hi to be empty (but it wasn't)!") // non-empty string - fail(t, so(&[]int{1}, ShouldBeEmpty), "Expected &[1] to be empty (but it wasn't)!") // pointer to non-empty slice - fail(t, so(&[1]int{1}, ShouldBeEmpty), "Expected &[1] to be empty (but it wasn't)!") // pointer to non-empty array - c := make(chan int, 1) // non-empty channel - go func() { c <- 1 }() - time.Sleep(time.Millisecond) - fail(t, so(c, ShouldBeEmpty), fmt.Sprintf("Expected %+v to be empty (but it wasn't)!", c)) -} - -func TestShouldNotBeEmpty(t *testing.T) { - fail(t, so(1, ShouldNotBeEmpty, 2, 3), "This assertion requires exactly 0 comparison values (you provided 2).") - - fail(t, so([]int{}, ShouldNotBeEmpty), "Expected [] to NOT be empty (but it was)!") // empty slice - fail(t, so([]interface{}{}, ShouldNotBeEmpty), "Expected [] to NOT be empty (but it was)!") // empty slice - fail(t, so(map[string]int{}, ShouldNotBeEmpty), "Expected map[] to NOT be empty (but it was)!") // empty map - fail(t, so("", ShouldNotBeEmpty), "Expected to NOT be empty (but it was)!") // empty string - fail(t, so(&[]int{}, ShouldNotBeEmpty), "Expected &[] to NOT be empty (but it was)!") // pointer to empty slice - fail(t, so(&[0]int{}, ShouldNotBeEmpty), "Expected &[] to NOT be empty (but it was)!") // pointer to empty array - fail(t, so(nil, ShouldNotBeEmpty), "Expected to NOT be empty (but it was)!") // nil - c := make(chan int, 0) // non-empty channel - fail(t, so(c, ShouldNotBeEmpty), fmt.Sprintf("Expected %+v to NOT be empty (but it was)!", c)) // empty channel - - pass(t, so([]int{1}, ShouldNotBeEmpty)) // non-empty slice - pass(t, so([]interface{}{1}, ShouldNotBeEmpty)) // non-empty slice - pass(t, so(map[string]int{"hi": 0}, ShouldNotBeEmpty)) // non-empty map - pass(t, so("hi", ShouldNotBeEmpty)) // non-empty string - pass(t, so(&[]int{1}, ShouldNotBeEmpty)) // pointer to non-empty slice - pass(t, so(&[1]int{1}, ShouldNotBeEmpty)) // pointer to non-empty array - c = make(chan int, 1) - go func() { c <- 1 }() - time.Sleep(time.Millisecond) - pass(t, so(c, ShouldNotBeEmpty)) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/doc.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/doc.go deleted file mode 100644 index 7bbd628eef2..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/doc.go +++ /dev/null @@ -1,43 +0,0 @@ -// Package assertions contains the implementations for all assertions which -// are referenced in the convey package for use with the So(...) method. -package assertions - -// This function is not used by the goconvey library. It's actually a convenience method -// for running assertions on arbitrary arguments outside of any testing context, like for -// application logging. It allows you to perform assertion-like behavior (and get nicely -// formatted messages detailing discrepancies) but without the probram blowing up or panicking. -// All that is required is to import this package and call `So` with one of the assertions -// exported by this package as the second parameter. -// The first return parameter is a boolean indicating if the assertion was true. The second -// return parameter is the well-formatted message showing why an assertion was incorrect, or -// blank if the assertion was correct. -// -// Example: -// -// if ok, message := So(x, ShouldBeGreaterThan, y); !ok { -// log.Println(message) -// } -// -func So(actual interface{}, assert assertion, expected ...interface{}) (bool, string) { - serializer = noop - - if result := so(actual, assert, expected...); len(result) == 0 { - return true, result - } else { - return false, result - } -} - -// so is like So, except that it only returns the string message, which is blank if the -// assertion passed. Used to facilitate testing. -func so(actual interface{}, assert func(interface{}, ...interface{}) string, expected ...interface{}) string { - return assert(actual, expected...) -} - -// assertion is an alias for a function with a signature that the So() -// function can handle. Any future or custom assertions should conform to this -// method signature. The return value should be an empty string if the assertion -// passes and a well-formed failure message if not. -type assertion func(actual interface{}, expected ...interface{}) string - -//////////////////////////////////////////////////////////////////////////// diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/equality_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/equality_test.go deleted file mode 100644 index ee3939712fc..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/equality_test.go +++ /dev/null @@ -1,267 +0,0 @@ -package assertions - -import ( - "fmt" - "reflect" - "testing" -) - -func TestShouldEqual(t *testing.T) { - serializer = newFakeSerializer() - - fail(t, so(1, ShouldEqual), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so(1, ShouldEqual, 1, 2), "This assertion requires exactly 1 comparison values (you provided 2).") - fail(t, so(1, ShouldEqual, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") - - pass(t, so(1, ShouldEqual, 1)) - fail(t, so(1, ShouldEqual, 2), "2|1|Expected: '2' Actual: '1' (Should be equal)") - - pass(t, so(true, ShouldEqual, true)) - fail(t, so(true, ShouldEqual, false), "false|true|Expected: 'false' Actual: 'true' (Should be equal)") - - pass(t, so("hi", ShouldEqual, "hi")) - fail(t, so("hi", ShouldEqual, "bye"), "bye|hi|Expected: 'bye' Actual: 'hi' (Should be equal)") - - pass(t, so(42, ShouldEqual, uint(42))) - - fail(t, so(Thing1{"hi"}, ShouldEqual, Thing1{}), "{}|{hi}|Expected: '{}' Actual: '{hi}' (Should be equal)") - fail(t, so(Thing1{"hi"}, ShouldEqual, Thing1{"hi"}), "{hi}|{hi}|Expected: '{hi}' Actual: '{hi}' (Should be equal)") - fail(t, so(&Thing1{"hi"}, ShouldEqual, &Thing1{"hi"}), "&{hi}|&{hi}|Expected: '&{hi}' Actual: '&{hi}' (Should be equal)") - - fail(t, so(Thing1{}, ShouldEqual, Thing2{}), "{}|{}|Expected: '{}' Actual: '{}' (Should be equal)") -} - -func TestShouldNotEqual(t *testing.T) { - fail(t, so(1, ShouldNotEqual), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so(1, ShouldNotEqual, 1, 2), "This assertion requires exactly 1 comparison values (you provided 2).") - fail(t, so(1, ShouldNotEqual, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") - - pass(t, so(1, ShouldNotEqual, 2)) - fail(t, so(1, ShouldNotEqual, 1), "Expected '1' to NOT equal '1' (but it did)!") - - pass(t, so(true, ShouldNotEqual, false)) - fail(t, so(true, ShouldNotEqual, true), "Expected 'true' to NOT equal 'true' (but it did)!") - - pass(t, so("hi", ShouldNotEqual, "bye")) - fail(t, so("hi", ShouldNotEqual, "hi"), "Expected 'hi' to NOT equal 'hi' (but it did)!") - - pass(t, so(&Thing1{"hi"}, ShouldNotEqual, &Thing1{"hi"})) - pass(t, so(Thing1{"hi"}, ShouldNotEqual, Thing1{"hi"})) - pass(t, so(Thing1{}, ShouldNotEqual, Thing1{})) - pass(t, so(Thing1{}, ShouldNotEqual, Thing2{})) -} - -func TestShouldAlmostEqual(t *testing.T) { - fail(t, so(1, ShouldAlmostEqual), "This assertion requires exactly one comparison value and an optional delta (you provided neither)") - fail(t, so(1, ShouldAlmostEqual, 1, 2, 3), "This assertion requires exactly one comparison value and an optional delta (you provided more values)") - - // with the default delta - pass(t, so(1, ShouldAlmostEqual, .99999999999999)) - pass(t, so(1.3612499999999996, ShouldAlmostEqual, 1.36125)) - pass(t, so(0.7285312499999999, ShouldAlmostEqual, 0.72853125)) - fail(t, so(1, ShouldAlmostEqual, .99), "Expected '1' to almost equal '0.99' (but it didn't)!") - - // with a different delta - pass(t, so(100.0, ShouldAlmostEqual, 110.0, 10.0)) - fail(t, so(100.0, ShouldAlmostEqual, 111.0, 10.5), "Expected '100' to almost equal '111' (but it didn't)!") - - // ints should work - pass(t, so(100, ShouldAlmostEqual, 100.0)) - fail(t, so(100, ShouldAlmostEqual, 99.0), "Expected '100' to almost equal '99' (but it didn't)!") - - // float32 should work - pass(t, so(float64(100.0), ShouldAlmostEqual, float32(100.0))) - fail(t, so(float32(100.0), ShouldAlmostEqual, 99.0, float32(0.1)), "Expected '100' to almost equal '99' (but it didn't)!") -} - -func TestShouldNotAlmostEqual(t *testing.T) { - fail(t, so(1, ShouldNotAlmostEqual), "This assertion requires exactly one comparison value and an optional delta (you provided neither)") - fail(t, so(1, ShouldNotAlmostEqual, 1, 2, 3), "This assertion requires exactly one comparison value and an optional delta (you provided more values)") - - // with the default delta - fail(t, so(1, ShouldNotAlmostEqual, .99999999999999), "Expected '1' to NOT almost equal '0.99999999999999' (but it did)!") - fail(t, so(1.3612499999999996, ShouldNotAlmostEqual, 1.36125), "Expected '1.3612499999999996' to NOT almost equal '1.36125' (but it did)!") - pass(t, so(1, ShouldNotAlmostEqual, .99)) - - // with a different delta - fail(t, so(100.0, ShouldNotAlmostEqual, 110.0, 10.0), "Expected '100' to NOT almost equal '110' (but it did)!") - pass(t, so(100.0, ShouldNotAlmostEqual, 111.0, 10.5)) - - // ints should work - fail(t, so(100, ShouldNotAlmostEqual, 100.0), "Expected '100' to NOT almost equal '100' (but it did)!") - pass(t, so(100, ShouldNotAlmostEqual, 99.0)) - - // float32 should work - fail(t, so(float64(100.0), ShouldNotAlmostEqual, float32(100.0)), "Expected '100' to NOT almost equal '100' (but it did)!") - pass(t, so(float32(100.0), ShouldNotAlmostEqual, 99.0, float32(0.1))) -} - -func TestShouldResemble(t *testing.T) { - serializer = newFakeSerializer() - - fail(t, so(Thing1{"hi"}, ShouldResemble), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so(Thing1{"hi"}, ShouldResemble, Thing1{"hi"}, Thing1{"hi"}), "This assertion requires exactly 1 comparison values (you provided 2).") - - pass(t, so(Thing1{"hi"}, ShouldResemble, Thing1{"hi"})) - fail(t, so(Thing1{"hi"}, ShouldResemble, Thing1{"bye"}), "{bye}|{hi}|Expected: 'assertions.Thing1{a:\"bye\"}' Actual: 'assertions.Thing1{a:\"hi\"}' (Should resemble)!") - - var ( - a []int - b []int = []int{} - ) - - fail(t, so(a, ShouldResemble, b), "[]|[]|Expected: '[]int{}' Actual: '[]int(nil)' (Should resemble)!") - fail(t, so(2, ShouldResemble, 1), "1|2|Expected: '1' Actual: '2' (Should resemble)!") - - fail(t, so(StringStringMapAlias{"hi": "bye"}, ShouldResemble, map[string]string{"hi": "bye"}), - "map[hi:bye]|map[hi:bye]|Expected: 'map[string]string{\"hi\":\"bye\"}' Actual: 'assertions.StringStringMapAlias{\"hi\":\"bye\"}' (Should resemble)!") - fail(t, so(StringSliceAlias{"hi", "bye"}, ShouldResemble, []string{"hi", "bye"}), - "[hi bye]|[hi bye]|Expected: '[]string{\"hi\", \"bye\"}' Actual: 'assertions.StringSliceAlias{\"hi\", \"bye\"}' (Should resemble)!") - - // some types come out looking the same when represented with "%#v" so we show type mismatch info: - fail(t, so(StringAlias("hi"), ShouldResemble, "hi"), "hi|hi|Expected: '\"hi\"' Actual: '\"hi\"' (Type mismatch: 'string' vs 'assertions.StringAlias')!") - fail(t, so(IntAlias(42), ShouldResemble, 42), "42|42|Expected: '42' Actual: '42' (Type mismatch: 'int' vs 'assertions.IntAlias')!") -} - -func TestShouldNotResemble(t *testing.T) { - fail(t, so(Thing1{"hi"}, ShouldNotResemble), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so(Thing1{"hi"}, ShouldNotResemble, Thing1{"hi"}, Thing1{"hi"}), "This assertion requires exactly 1 comparison values (you provided 2).") - - pass(t, so(Thing1{"hi"}, ShouldNotResemble, Thing1{"bye"})) - fail(t, so(Thing1{"hi"}, ShouldNotResemble, Thing1{"hi"}), - "Expected 'assertions.Thing1{a:\"hi\"}' to NOT resemble 'assertions.Thing1{a:\"hi\"}' (but it did)!") - - pass(t, so(map[string]string{"hi": "bye"}, ShouldResemble, map[string]string{"hi": "bye"})) - pass(t, so(IntAlias(42), ShouldNotResemble, 42)) - - pass(t, so(StringSliceAlias{"hi", "bye"}, ShouldNotResemble, []string{"hi", "bye"})) -} - -func TestShouldPointTo(t *testing.T) { - serializer = newFakeSerializer() - - t1 := &Thing1{} - t2 := t1 - t3 := &Thing1{} - - pointer1 := reflect.ValueOf(t1).Pointer() - pointer3 := reflect.ValueOf(t3).Pointer() - - fail(t, so(t1, ShouldPointTo), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so(t1, ShouldPointTo, t2, t3), "This assertion requires exactly 1 comparison values (you provided 2).") - - pass(t, so(t1, ShouldPointTo, t2)) - fail(t, so(t1, ShouldPointTo, t3), fmt.Sprintf( - "%v|%v|Expected '&{a:}' (address: '%v') and '&{a:}' (address: '%v') to be the same address (but their weren't)!", - pointer3, pointer1, pointer1, pointer3)) - - t4 := Thing1{} - t5 := t4 - - fail(t, so(t4, ShouldPointTo, t5), "Both arguments should be pointers (the first was not)!") - fail(t, so(&t4, ShouldPointTo, t5), "Both arguments should be pointers (the second was not)!") - fail(t, so(nil, ShouldPointTo, nil), "Both arguments should be pointers (the first was nil)!") - fail(t, so(&t4, ShouldPointTo, nil), "Both arguments should be pointers (the second was nil)!") -} - -func TestShouldNotPointTo(t *testing.T) { - t1 := &Thing1{} - t2 := t1 - t3 := &Thing1{} - - pointer1 := reflect.ValueOf(t1).Pointer() - - fail(t, so(t1, ShouldNotPointTo), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so(t1, ShouldNotPointTo, t2, t3), "This assertion requires exactly 1 comparison values (you provided 2).") - - pass(t, so(t1, ShouldNotPointTo, t3)) - fail(t, so(t1, ShouldNotPointTo, t2), fmt.Sprintf("Expected '&{a:}' and '&{a:}' to be different references (but they matched: '%v')!", pointer1)) - - t4 := Thing1{} - t5 := t4 - - fail(t, so(t4, ShouldNotPointTo, t5), "Both arguments should be pointers (the first was not)!") - fail(t, so(&t4, ShouldNotPointTo, t5), "Both arguments should be pointers (the second was not)!") - fail(t, so(nil, ShouldNotPointTo, nil), "Both arguments should be pointers (the first was nil)!") - fail(t, so(&t4, ShouldNotPointTo, nil), "Both arguments should be pointers (the second was nil)!") -} - -func TestShouldBeNil(t *testing.T) { - fail(t, so(nil, ShouldBeNil, nil, nil, nil), "This assertion requires exactly 0 comparison values (you provided 3).") - fail(t, so(nil, ShouldBeNil, nil), "This assertion requires exactly 0 comparison values (you provided 1).") - - pass(t, so(nil, ShouldBeNil)) - fail(t, so(1, ShouldBeNil), "Expected: nil Actual: '1'") - - var thing Thinger - pass(t, so(thing, ShouldBeNil)) - thing = &Thing{} - fail(t, so(thing, ShouldBeNil), "Expected: nil Actual: '&{}'") - - var thingOne *Thing1 - pass(t, so(thingOne, ShouldBeNil)) - - var nilSlice []int = nil - pass(t, so(nilSlice, ShouldBeNil)) - - var nilMap map[string]string = nil - pass(t, so(nilMap, ShouldBeNil)) - - var nilChannel chan int = nil - pass(t, so(nilChannel, ShouldBeNil)) - - var nilFunc func() = nil - pass(t, so(nilFunc, ShouldBeNil)) - - var nilInterface interface{} = nil - pass(t, so(nilInterface, ShouldBeNil)) -} - -func TestShouldNotBeNil(t *testing.T) { - fail(t, so(nil, ShouldNotBeNil, nil, nil, nil), "This assertion requires exactly 0 comparison values (you provided 3).") - fail(t, so(nil, ShouldNotBeNil, nil), "This assertion requires exactly 0 comparison values (you provided 1).") - - fail(t, so(nil, ShouldNotBeNil), "Expected '' to NOT be nil (but it was)!") - pass(t, so(1, ShouldNotBeNil)) - - var thing Thinger - fail(t, so(thing, ShouldNotBeNil), "Expected '' to NOT be nil (but it was)!") - thing = &Thing{} - pass(t, so(thing, ShouldNotBeNil)) -} - -func TestShouldBeTrue(t *testing.T) { - fail(t, so(true, ShouldBeTrue, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).") - fail(t, so(true, ShouldBeTrue, 1), "This assertion requires exactly 0 comparison values (you provided 1).") - - fail(t, so(false, ShouldBeTrue), "Expected: true Actual: false") - fail(t, so(1, ShouldBeTrue), "Expected: true Actual: 1") - pass(t, so(true, ShouldBeTrue)) -} - -func TestShouldBeFalse(t *testing.T) { - fail(t, so(false, ShouldBeFalse, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).") - fail(t, so(false, ShouldBeFalse, 1), "This assertion requires exactly 0 comparison values (you provided 1).") - - fail(t, so(true, ShouldBeFalse), "Expected: false Actual: true") - fail(t, so(1, ShouldBeFalse), "Expected: false Actual: 1") - pass(t, so(false, ShouldBeFalse)) -} - -func TestShouldBeZeroValue(t *testing.T) { - serializer = newFakeSerializer() - - fail(t, so(0, ShouldBeZeroValue, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).") - fail(t, so(false, ShouldBeZeroValue, true), "This assertion requires exactly 0 comparison values (you provided 1).") - - fail(t, so(1, ShouldBeZeroValue), "0|1|'1' should have been the zero value") //"Expected: (zero value) Actual: 1") - fail(t, so(true, ShouldBeZeroValue), "false|true|'true' should have been the zero value") //"Expected: (zero value) Actual: true") - fail(t, so("123", ShouldBeZeroValue), "|123|'123' should have been the zero value") //"Expected: (zero value) Actual: 123") - fail(t, so(" ", ShouldBeZeroValue), "| |' ' should have been the zero value") //"Expected: (zero value) Actual: ") - fail(t, so([]string{"Nonempty"}, ShouldBeZeroValue), "[]|[Nonempty]|'[Nonempty]' should have been the zero value") //"Expected: (zero value) Actual: [Nonempty]") - fail(t, so(struct{ a string }{a: "asdf"}, ShouldBeZeroValue), "{}|{asdf}|'{a:asdf}' should have been the zero value") - pass(t, so(0, ShouldBeZeroValue)) - pass(t, so(false, ShouldBeZeroValue)) - pass(t, so("", ShouldBeZeroValue)) - pass(t, so(struct{}{}, ShouldBeZeroValue)) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/init.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/init.go deleted file mode 100644 index 753bcc7daa7..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/init.go +++ /dev/null @@ -1,6 +0,0 @@ -package assertions - -var ( - serializer Serializer = newSerializer() - noop Serializer = new(noopSerializer) -) diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/.gitignore b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/.gitignore deleted file mode 100644 index dd8fc7468f4..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -*.6 -6.out -_obj/ -_test/ -_testmain.go diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/all_of_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/all_of_test.go deleted file mode 100644 index 4655f2e7389..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/all_of_test.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - "errors" - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type allOfFakeMatcher struct { - desc string - err error -} - -func (m *allOfFakeMatcher) Matches(c interface{}) error { - return m.err -} - -func (m *allOfFakeMatcher) Description() string { - return m.desc -} - -type AllOfTest struct { -} - -func init() { RegisterTestSuite(&AllOfTest{}) } - -//////////////////////////////////////////////////////////////////////// -// Tests -//////////////////////////////////////////////////////////////////////// - -func (t *AllOfTest) DescriptionWithEmptySet() { - m := AllOf() - ExpectEq("is anything", m.Description()) -} - -func (t *AllOfTest) DescriptionWithOneMatcher() { - m := AllOf(&allOfFakeMatcher{"taco", errors.New("")}) - ExpectEq("taco", m.Description()) -} - -func (t *AllOfTest) DescriptionWithMultipleMatchers() { - m := AllOf( - &allOfFakeMatcher{"taco", errors.New("")}, - &allOfFakeMatcher{"burrito", errors.New("")}, - &allOfFakeMatcher{"enchilada", errors.New("")}) - - ExpectEq("taco, and burrito, and enchilada", m.Description()) -} - -func (t *AllOfTest) EmptySet() { - m := AllOf() - err := m.Matches(17) - - ExpectEq(nil, err) -} - -func (t *AllOfTest) OneMatcherReturnsFatalErrorAndSomeOthersFail() { - m := AllOf( - &allOfFakeMatcher{"", errors.New("")}, - &allOfFakeMatcher{"", NewFatalError("taco")}, - &allOfFakeMatcher{"", errors.New("")}, - &allOfFakeMatcher{"", nil}) - - err := m.Matches(17) - - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("taco"))) -} - -func (t *AllOfTest) OneMatcherReturnsNonFatalAndOthersSayTrue() { - m := AllOf( - &allOfFakeMatcher{"", nil}, - &allOfFakeMatcher{"", errors.New("taco")}, - &allOfFakeMatcher{"", nil}) - - err := m.Matches(17) - - ExpectFalse(isFatal(err)) - ExpectThat(err, Error(Equals("taco"))) -} - -func (t *AllOfTest) AllMatchersSayTrue() { - m := AllOf( - &allOfFakeMatcher{"", nil}, - &allOfFakeMatcher{"", nil}, - &allOfFakeMatcher{"", nil}) - - err := m.Matches(17) - - ExpectEq(nil, err) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/any_of_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/any_of_test.go deleted file mode 100644 index b73e101285a..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/any_of_test.go +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - "errors" - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type fakeAnyOfMatcher struct { - desc string - err error -} - -func (m *fakeAnyOfMatcher) Matches(c interface{}) error { - return m.err -} - -func (m *fakeAnyOfMatcher) Description() string { - return m.desc -} - -type AnyOfTest struct { -} - -func init() { RegisterTestSuite(&AnyOfTest{}) } - -//////////////////////////////////////////////////////////////////////// -// Tests -//////////////////////////////////////////////////////////////////////// - -func (t *AnyOfTest) EmptySet() { - matcher := AnyOf() - - err := matcher.Matches(0) - ExpectThat(err, Error(Equals(""))) -} - -func (t *AnyOfTest) OneTrue() { - matcher := AnyOf( - &fakeAnyOfMatcher{"", NewFatalError("foo")}, - 17, - &fakeAnyOfMatcher{"", errors.New("foo")}, - &fakeAnyOfMatcher{"", nil}, - &fakeAnyOfMatcher{"", errors.New("foo")}, - ) - - err := matcher.Matches(0) - ExpectEq(nil, err) -} - -func (t *AnyOfTest) OneEqual() { - matcher := AnyOf( - &fakeAnyOfMatcher{"", NewFatalError("foo")}, - &fakeAnyOfMatcher{"", errors.New("foo")}, - 13, - "taco", - 19, - &fakeAnyOfMatcher{"", errors.New("foo")}, - ) - - err := matcher.Matches("taco") - ExpectEq(nil, err) -} - -func (t *AnyOfTest) OneFatal() { - matcher := AnyOf( - &fakeAnyOfMatcher{"", errors.New("foo")}, - 17, - &fakeAnyOfMatcher{"", NewFatalError("taco")}, - &fakeAnyOfMatcher{"", errors.New("foo")}, - ) - - err := matcher.Matches(0) - ExpectThat(err, Error(Equals("taco"))) -} - -func (t *AnyOfTest) AllFalseAndNotEqual() { - matcher := AnyOf( - &fakeAnyOfMatcher{"", errors.New("foo")}, - 17, - &fakeAnyOfMatcher{"", errors.New("foo")}, - 19, - ) - - err := matcher.Matches(0) - ExpectThat(err, Error(Equals(""))) -} - -func (t *AnyOfTest) DescriptionForEmptySet() { - matcher := AnyOf() - ExpectEq("or()", matcher.Description()) -} - -func (t *AnyOfTest) DescriptionForNonEmptySet() { - matcher := AnyOf( - &fakeAnyOfMatcher{"taco", nil}, - "burrito", - &fakeAnyOfMatcher{"enchilada", nil}, - ) - - ExpectEq("or(taco, burrito, enchilada)", matcher.Description()) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/any_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/any_test.go deleted file mode 100644 index e0492b82773..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/any_test.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type AnyTest struct { -} - -func init() { RegisterTestSuite(&AnyTest{}) } - -//////////////////////////////////////////////////////////////////////// -// Tests -//////////////////////////////////////////////////////////////////////// - -func (t *AnyTest) Description() { - m := Any() - ExpectEq("is anything", m.Description()) -} - -func (t *AnyTest) Matches() { - var err error - m := Any() - - err = m.Matches(nil) - ExpectEq(nil, err) - - err = m.Matches(17) - ExpectEq(nil, err) - - err = m.Matches("taco") - ExpectEq(nil, err) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/contains_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/contains_test.go deleted file mode 100644 index c61cd886c6c..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/contains_test.go +++ /dev/null @@ -1,234 +0,0 @@ -// Copyright 2012 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type ContainsTest struct{} - -func init() { RegisterTestSuite(&ContainsTest{}) } - -//////////////////////////////////////////////////////////////////////// -// Tests -//////////////////////////////////////////////////////////////////////// - -func (t *ContainsTest) WrongTypeCandidates() { - m := Contains("") - ExpectEq("contains: ", m.Description()) - - var err error - - // Nil candidate - err = m.Matches(nil) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("array"))) - ExpectThat(err, Error(HasSubstr("slice"))) - - // String candidate - err = m.Matches("") - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("array"))) - ExpectThat(err, Error(HasSubstr("slice"))) - - // Map candidate - err = m.Matches(make(map[string]string)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("array"))) - ExpectThat(err, Error(HasSubstr("slice"))) -} - -func (t *ContainsTest) NilArgument() { - m := Contains(nil) - ExpectEq("contains: is nil", m.Description()) - - var c interface{} - var err error - - // Empty array of pointers - c = [...]*int{} - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) - - // Empty slice of pointers - c = []*int{} - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) - - // Non-empty array of integers - c = [...]int{17, 0, 19} - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) - - // Non-empty slice of integers - c = []int{17, 0, 19} - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) - - // Non-matching array of pointers - c = [...]*int{new(int), new(int)} - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) - - // Non-matching slice of pointers - c = []*int{new(int), new(int)} - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) - - // Matching array of pointers - c = [...]*int{new(int), nil, new(int)} - err = m.Matches(c) - ExpectEq(nil, err) - - // Matching slice of pointers - c = []*int{new(int), nil, new(int)} - err = m.Matches(c) - ExpectEq(nil, err) - - // Non-matching slice of pointers from matching array - someArray := [...]*int{new(int), nil, new(int)} - c = someArray[0:1] - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) -} - -func (t *ContainsTest) StringArgument() { - m := Contains("taco") - ExpectEq("contains: taco", m.Description()) - - var c interface{} - var err error - - // Non-matching array of strings - c = [...]string{"burrito", "enchilada"} - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) - - // Non-matching slice of strings - c = []string{"burrito", "enchilada"} - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) - - // Matching array of strings - c = [...]string{"burrito", "taco", "enchilada"} - err = m.Matches(c) - ExpectEq(nil, err) - - // Matching slice of strings - c = []string{"burrito", "taco", "enchilada"} - err = m.Matches(c) - ExpectEq(nil, err) - - // Non-matching slice of strings from matching array - someArray := [...]string{"burrito", "taco", "enchilada"} - c = someArray[0:1] - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) -} - -func (t *ContainsTest) IntegerArgument() { - m := Contains(int(17)) - ExpectEq("contains: 17", m.Description()) - - var c interface{} - var err error - - // Non-matching array of integers - c = [...]int{13, 19} - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) - - // Non-matching slice of integers - c = []int{13, 19} - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) - - // Matching array of integers - c = [...]int{13, 17, 19} - err = m.Matches(c) - ExpectEq(nil, err) - - // Matching slice of integers - c = []int{13, 17, 19} - err = m.Matches(c) - ExpectEq(nil, err) - - // Non-matching slice of integers from matching array - someArray := [...]int{13, 17, 19} - c = someArray[0:1] - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) - - // Non-matching array of floats - c = [...]float32{13, 17.5, 19} - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) - - // Non-matching slice of floats - c = []float32{13, 17.5, 19} - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) - - // Matching array of floats - c = [...]float32{13, 17, 19} - err = m.Matches(c) - ExpectEq(nil, err) - - // Matching slice of floats - c = []float32{13, 17, 19} - err = m.Matches(c) - ExpectEq(nil, err) -} - -func (t *ContainsTest) MatcherArgument() { - m := Contains(HasSubstr("ac")) - ExpectEq("contains: has substring \"ac\"", m.Description()) - - var c interface{} - var err error - - // Non-matching array of strings - c = [...]string{"burrito", "enchilada"} - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) - - // Non-matching slice of strings - c = []string{"burrito", "enchilada"} - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) - - // Matching array of strings - c = [...]string{"burrito", "taco", "enchilada"} - err = m.Matches(c) - ExpectEq(nil, err) - - // Matching slice of strings - c = []string{"burrito", "taco", "enchilada"} - err = m.Matches(c) - ExpectEq(nil, err) - - // Non-matching slice of strings from matching array - someArray := [...]string{"burrito", "taco", "enchilada"} - c = someArray[0:1] - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/deep_equals_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/deep_equals_test.go deleted file mode 100644 index 640bb0e19d1..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/deep_equals_test.go +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright 2012 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - "bytes" - "testing" - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type DeepEqualsTest struct{} - -func init() { RegisterTestSuite(&DeepEqualsTest{}) } - -//////////////////////////////////////////////////////////////////////// -// Tests -//////////////////////////////////////////////////////////////////////// - -func (t *DeepEqualsTest) WrongTypeCandidateWithScalarValue() { - var x int = 17 - m := DeepEquals(x) - - var err error - - // Nil candidate. - err = m.Matches(nil) - AssertNe(nil, err) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("type"))) - ExpectThat(err, Error(HasSubstr(""))) - - // Int alias candidate. - type intAlias int - err = m.Matches(intAlias(x)) - AssertNe(nil, err) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("type"))) - ExpectThat(err, Error(HasSubstr("intAlias"))) - - // String candidate. - err = m.Matches("taco") - AssertNe(nil, err) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("type"))) - ExpectThat(err, Error(HasSubstr("string"))) - - // Byte slice candidate. - err = m.Matches([]byte{}) - AssertNe(nil, err) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("type"))) - ExpectThat(err, Error(HasSubstr("[]uint8"))) - - // Other slice candidate. - err = m.Matches([]uint16{}) - AssertNe(nil, err) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("type"))) - ExpectThat(err, Error(HasSubstr("[]uint16"))) - - // Unsigned int candidate. - err = m.Matches(uint(17)) - AssertNe(nil, err) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("type"))) - ExpectThat(err, Error(HasSubstr("uint"))) -} - -func (t *DeepEqualsTest) WrongTypeCandidateWithByteSliceValue() { - x := []byte{} - m := DeepEquals(x) - - var err error - - // Nil candidate. - err = m.Matches(nil) - AssertNe(nil, err) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("type"))) - ExpectThat(err, Error(HasSubstr(""))) - - // String candidate. - err = m.Matches("taco") - AssertNe(nil, err) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("type"))) - ExpectThat(err, Error(HasSubstr("string"))) - - // Slice candidate with wrong value type. - err = m.Matches([]uint16{}) - AssertNe(nil, err) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("type"))) - ExpectThat(err, Error(HasSubstr("[]uint16"))) -} - -func (t *DeepEqualsTest) WrongTypeCandidateWithOtherSliceValue() { - x := []uint16{} - m := DeepEquals(x) - - var err error - - // Nil candidate. - err = m.Matches(nil) - AssertNe(nil, err) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("type"))) - ExpectThat(err, Error(HasSubstr(""))) - - // String candidate. - err = m.Matches("taco") - AssertNe(nil, err) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("type"))) - ExpectThat(err, Error(HasSubstr("string"))) - - // Byte slice candidate with wrong value type. - err = m.Matches([]byte{}) - AssertNe(nil, err) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("type"))) - ExpectThat(err, Error(HasSubstr("[]uint8"))) - - // Other slice candidate with wrong value type. - err = m.Matches([]uint32{}) - AssertNe(nil, err) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("type"))) - ExpectThat(err, Error(HasSubstr("[]uint32"))) -} - -func (t *DeepEqualsTest) WrongTypeCandidateWithNilLiteralValue() { - m := DeepEquals(nil) - - var err error - - // String candidate. - err = m.Matches("taco") - AssertNe(nil, err) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("type"))) - ExpectThat(err, Error(HasSubstr("string"))) - - // Nil byte slice candidate. - err = m.Matches([]byte(nil)) - AssertNe(nil, err) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("type"))) - ExpectThat(err, Error(HasSubstr("[]uint8"))) - - // Nil other slice candidate. - err = m.Matches([]uint16(nil)) - AssertNe(nil, err) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("type"))) - ExpectThat(err, Error(HasSubstr("[]uint16"))) -} - -func (t *DeepEqualsTest) NilLiteralValue() { - m := DeepEquals(nil) - ExpectEq("deep equals: ", m.Description()) - - var c interface{} - var err error - - // Nil literal candidate. - c = nil - err = m.Matches(c) - ExpectEq(nil, err) -} - -func (t *DeepEqualsTest) IntValue() { - m := DeepEquals(int(17)) - ExpectEq("deep equals: 17", m.Description()) - - var c interface{} - var err error - - // Matching int. - c = int(17) - err = m.Matches(c) - ExpectEq(nil, err) - - // Non-matching int. - c = int(18) - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) -} - -func (t *DeepEqualsTest) ByteSliceValue() { - x := []byte{17, 19} - m := DeepEquals(x) - ExpectEq("deep equals: [17 19]", m.Description()) - - var c []byte - var err error - - // Matching. - c = make([]byte, len(x)) - AssertEq(len(x), copy(c, x)) - - err = m.Matches(c) - ExpectEq(nil, err) - - // Nil slice. - c = []byte(nil) - err = m.Matches(c) - ExpectThat(err, Error(Equals("which is nil"))) - - // Prefix. - AssertGt(len(x), 1) - c = make([]byte, len(x)-1) - AssertEq(len(x)-1, copy(c, x)) - - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) - - // Suffix. - c = make([]byte, len(x)+1) - AssertEq(len(x), copy(c, x)) - - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) -} - -func (t *DeepEqualsTest) OtherSliceValue() { - x := []uint16{17, 19} - m := DeepEquals(x) - ExpectEq("deep equals: [17 19]", m.Description()) - - var c []uint16 - var err error - - // Matching. - c = make([]uint16, len(x)) - AssertEq(len(x), copy(c, x)) - - err = m.Matches(c) - ExpectEq(nil, err) - - // Nil slice. - c = []uint16(nil) - err = m.Matches(c) - ExpectThat(err, Error(Equals("which is nil"))) - - // Prefix. - AssertGt(len(x), 1) - c = make([]uint16, len(x)-1) - AssertEq(len(x)-1, copy(c, x)) - - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) - - // Suffix. - c = make([]uint16, len(x)+1) - AssertEq(len(x), copy(c, x)) - - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) -} - -func (t *DeepEqualsTest) NilByteSliceValue() { - x := []byte(nil) - m := DeepEquals(x) - ExpectEq("deep equals: ", m.Description()) - - var c []byte - var err error - - // Nil slice. - c = []byte(nil) - err = m.Matches(c) - ExpectEq(nil, err) - - // Non-nil slice. - c = []byte{} - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) -} - -func (t *DeepEqualsTest) NilOtherSliceValue() { - x := []uint16(nil) - m := DeepEquals(x) - ExpectEq("deep equals: ", m.Description()) - - var c []uint16 - var err error - - // Nil slice. - c = []uint16(nil) - err = m.Matches(c) - ExpectEq(nil, err) - - // Non-nil slice. - c = []uint16{} - err = m.Matches(c) - ExpectThat(err, Error(Equals(""))) -} - -//////////////////////////////////////////////////////////////////////// -// Benchmarks -//////////////////////////////////////////////////////////////////////// - -func benchmarkWithSize(b *testing.B, size int) { - b.StopTimer() - buf := bytes.Repeat([]byte{0x01}, size) - bufCopy := make([]byte, size) - copy(bufCopy, buf) - - matcher := DeepEquals(buf) - b.StartTimer() - - for i := 0; i < b.N; i++ { - matcher.Matches(bufCopy) - } - - b.SetBytes(int64(size)) -} - -func BenchmarkShortByteSlice(b *testing.B) { - benchmarkWithSize(b, 256) -} - -func BenchmarkLongByteSlice(b *testing.B) { - benchmarkWithSize(b, 1<<24) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/elements_are_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/elements_are_test.go deleted file mode 100644 index cfc645489cd..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/elements_are_test.go +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright 2012 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type ElementsAreTest struct { -} - -func init() { RegisterTestSuite(&ElementsAreTest{}) } - -//////////////////////////////////////////////////////////////////////// -// Tests -//////////////////////////////////////////////////////////////////////// - -func (t *ElementsAreTest) EmptySet() { - m := ElementsAre() - ExpectEq("elements are: []", m.Description()) - - var c []interface{} - var err error - - // No candidates. - c = []interface{}{} - err = m.Matches(c) - ExpectEq(nil, err) - - // One candidate. - c = []interface{}{17} - err = m.Matches(c) - ExpectThat(err, Error(HasSubstr("length 1"))) -} - -func (t *ElementsAreTest) OneMatcher() { - m := ElementsAre(LessThan(17)) - ExpectEq("elements are: [less than 17]", m.Description()) - - var c []interface{} - var err error - - // No candidates. - c = []interface{}{} - err = m.Matches(c) - ExpectThat(err, Error(HasSubstr("length 0"))) - - // Matching candidate. - c = []interface{}{16} - err = m.Matches(c) - ExpectEq(nil, err) - - // Non-matching candidate. - c = []interface{}{19} - err = m.Matches(c) - ExpectNe(nil, err) - - // Two candidates. - c = []interface{}{17, 19} - err = m.Matches(c) - ExpectThat(err, Error(HasSubstr("length 2"))) -} - -func (t *ElementsAreTest) OneValue() { - m := ElementsAre(17) - ExpectEq("elements are: [17]", m.Description()) - - var c []interface{} - var err error - - // No candidates. - c = []interface{}{} - err = m.Matches(c) - ExpectThat(err, Error(HasSubstr("length 0"))) - - // Matching int. - c = []interface{}{int(17)} - err = m.Matches(c) - ExpectEq(nil, err) - - // Matching float. - c = []interface{}{float32(17)} - err = m.Matches(c) - ExpectEq(nil, err) - - // Non-matching candidate. - c = []interface{}{19} - err = m.Matches(c) - ExpectNe(nil, err) - - // Two candidates. - c = []interface{}{17, 19} - err = m.Matches(c) - ExpectThat(err, Error(HasSubstr("length 2"))) -} - -func (t *ElementsAreTest) MultipleElements() { - m := ElementsAre("taco", LessThan(17)) - ExpectEq("elements are: [taco, less than 17]", m.Description()) - - var c []interface{} - var err error - - // One candidate. - c = []interface{}{17} - err = m.Matches(c) - ExpectThat(err, Error(HasSubstr("length 1"))) - - // Both matching. - c = []interface{}{"taco", 16} - err = m.Matches(c) - ExpectEq(nil, err) - - // First non-matching. - c = []interface{}{"burrito", 16} - err = m.Matches(c) - ExpectThat(err, Error(Equals("whose element 0 doesn't match"))) - - // Second non-matching. - c = []interface{}{"taco", 17} - err = m.Matches(c) - ExpectThat(err, Error(Equals("whose element 1 doesn't match"))) - - // Three candidates. - c = []interface{}{"taco", 17, 19} - err = m.Matches(c) - ExpectThat(err, Error(HasSubstr("length 3"))) -} - -func (t *ElementsAreTest) ArrayCandidates() { - m := ElementsAre("taco", LessThan(17)) - - var err error - - // One candidate. - err = m.Matches([1]interface{}{"taco"}) - ExpectThat(err, Error(HasSubstr("length 1"))) - - // Both matching. - err = m.Matches([2]interface{}{"taco", 16}) - ExpectEq(nil, err) - - // First non-matching. - err = m.Matches([2]interface{}{"burrito", 16}) - ExpectThat(err, Error(Equals("whose element 0 doesn't match"))) -} - -func (t *ElementsAreTest) WrongTypeCandidate() { - m := ElementsAre("taco") - - var err error - - // String candidate. - err = m.Matches("taco") - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("array"))) - ExpectThat(err, Error(HasSubstr("slice"))) - - // Map candidate. - err = m.Matches(map[string]string{}) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("array"))) - ExpectThat(err, Error(HasSubstr("slice"))) - - // Nil candidate. - err = m.Matches(nil) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("array"))) - ExpectThat(err, Error(HasSubstr("slice"))) -} - -func (t *ElementsAreTest) PropagatesFatality() { - m := ElementsAre(LessThan(17)) - ExpectEq("elements are: [less than 17]", m.Description()) - - var c []interface{} - var err error - - // Non-fatal error. - c = []interface{}{19} - err = m.Matches(c) - AssertNe(nil, err) - ExpectFalse(isFatal(err)) - - // Fatal error. - c = []interface{}{"taco"} - err = m.Matches(c) - AssertNe(nil, err) - ExpectTrue(isFatal(err)) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/equals_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/equals_test.go deleted file mode 100644 index 1b2b66ec57d..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/equals_test.go +++ /dev/null @@ -1,3785 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - "fmt" - "math" - "unsafe" - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -var someInt int = -17 - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type EqualsTest struct { -} - -func init() { RegisterTestSuite(&EqualsTest{}) } - -type equalsTestCase struct { - candidate interface{} - expectedResult bool - shouldBeFatal bool - expectedError string -} - -func (t *EqualsTest) checkTestCases(matcher Matcher, cases []equalsTestCase) { - for i, c := range cases { - err := matcher.Matches(c.candidate) - ExpectEq(c.expectedResult, (err == nil), "Result for case %d: %v", i, c) - - if err == nil { - continue - } - - _, isFatal := err.(*FatalError) - ExpectEq(c.shouldBeFatal, isFatal, "Fatality for case %d: %v", i, c) - - ExpectThat(err, Error(Equals(c.expectedError)), "Case %d: %v", i, c) - } -} - -//////////////////////////////////////////////////////////////////////// -// nil -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) EqualsNil() { - matcher := Equals(nil) - ExpectEq("is nil", matcher.Description()) - - cases := []equalsTestCase{ - // Legal types - equalsTestCase{nil, true, false, ""}, - equalsTestCase{chan int(nil), true, false, ""}, - equalsTestCase{(func())(nil), true, false, ""}, - equalsTestCase{interface{}(nil), true, false, ""}, - equalsTestCase{map[int]int(nil), true, false, ""}, - equalsTestCase{(*int)(nil), true, false, ""}, - equalsTestCase{[]int(nil), true, false, ""}, - - equalsTestCase{make(chan int), false, false, ""}, - equalsTestCase{func() {}, false, false, ""}, - equalsTestCase{map[int]int{}, false, false, ""}, - equalsTestCase{&someInt, false, false, ""}, - equalsTestCase{[]int{}, false, false, ""}, - - // Illegal types - equalsTestCase{17, false, true, "which cannot be compared to nil"}, - equalsTestCase{int8(17), false, true, "which cannot be compared to nil"}, - equalsTestCase{uintptr(17), false, true, "which cannot be compared to nil"}, - equalsTestCase{[...]int{}, false, true, "which cannot be compared to nil"}, - equalsTestCase{"taco", false, true, "which cannot be compared to nil"}, - equalsTestCase{equalsTestCase{}, false, true, "which cannot be compared to nil"}, - equalsTestCase{unsafe.Pointer(&someInt), false, true, "which cannot be compared to nil"}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// Integer literals -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) NegativeIntegerLiteral() { - // -2^30 - matcher := Equals(-1073741824) - ExpectEq("-1073741824", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of -1073741824. - equalsTestCase{-1073741824, true, false, ""}, - equalsTestCase{-1073741824.0, true, false, ""}, - equalsTestCase{-1073741824 + 0i, true, false, ""}, - equalsTestCase{int(-1073741824), true, false, ""}, - equalsTestCase{int32(-1073741824), true, false, ""}, - equalsTestCase{int64(-1073741824), true, false, ""}, - equalsTestCase{float32(-1073741824), true, false, ""}, - equalsTestCase{float64(-1073741824), true, false, ""}, - equalsTestCase{complex64(-1073741824), true, false, ""}, - equalsTestCase{complex128(-1073741824), true, false, ""}, - equalsTestCase{interface{}(int(-1073741824)), true, false, ""}, - - // Values that would be -1073741824 in two's complement. - equalsTestCase{uint((1 << 32) - 1073741824), false, false, ""}, - equalsTestCase{uint32((1 << 32) - 1073741824), false, false, ""}, - equalsTestCase{uint64((1 << 64) - 1073741824), false, false, ""}, - - // Non-equal values of signed integer type. - equalsTestCase{int(-1073741823), false, false, ""}, - equalsTestCase{int32(-1073741823), false, false, ""}, - equalsTestCase{int64(-1073741823), false, false, ""}, - - // Non-equal values of other numeric types. - equalsTestCase{float64(-1073741824.1), false, false, ""}, - equalsTestCase{float64(-1073741823.9), false, false, ""}, - equalsTestCase{complex128(-1073741823), false, false, ""}, - equalsTestCase{complex128(-1073741824 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) PositiveIntegerLiteral() { - // 2^30 - matcher := Equals(1073741824) - ExpectEq("1073741824", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of 1073741824. - equalsTestCase{1073741824, true, false, ""}, - equalsTestCase{1073741824.0, true, false, ""}, - equalsTestCase{1073741824 + 0i, true, false, ""}, - equalsTestCase{int(1073741824), true, false, ""}, - equalsTestCase{uint(1073741824), true, false, ""}, - equalsTestCase{int32(1073741824), true, false, ""}, - equalsTestCase{int64(1073741824), true, false, ""}, - equalsTestCase{uint32(1073741824), true, false, ""}, - equalsTestCase{uint64(1073741824), true, false, ""}, - equalsTestCase{float32(1073741824), true, false, ""}, - equalsTestCase{float64(1073741824), true, false, ""}, - equalsTestCase{complex64(1073741824), true, false, ""}, - equalsTestCase{complex128(1073741824), true, false, ""}, - equalsTestCase{interface{}(int(1073741824)), true, false, ""}, - equalsTestCase{interface{}(uint(1073741824)), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int(1073741823), false, false, ""}, - equalsTestCase{int32(1073741823), false, false, ""}, - equalsTestCase{int64(1073741823), false, false, ""}, - equalsTestCase{float64(1073741824.1), false, false, ""}, - equalsTestCase{float64(1073741823.9), false, false, ""}, - equalsTestCase{complex128(1073741823), false, false, ""}, - equalsTestCase{complex128(1073741824 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// Floating point literals -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) NegativeIntegralFloatingPointLiteral() { - // -2^30 - matcher := Equals(-1073741824.0) - ExpectEq("-1.073741824e+09", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of -1073741824. - equalsTestCase{-1073741824, true, false, ""}, - equalsTestCase{-1073741824.0, true, false, ""}, - equalsTestCase{-1073741824 + 0i, true, false, ""}, - equalsTestCase{int(-1073741824), true, false, ""}, - equalsTestCase{int32(-1073741824), true, false, ""}, - equalsTestCase{int64(-1073741824), true, false, ""}, - equalsTestCase{float32(-1073741824), true, false, ""}, - equalsTestCase{float64(-1073741824), true, false, ""}, - equalsTestCase{complex64(-1073741824), true, false, ""}, - equalsTestCase{complex128(-1073741824), true, false, ""}, - equalsTestCase{interface{}(int(-1073741824)), true, false, ""}, - equalsTestCase{interface{}(float64(-1073741824)), true, false, ""}, - - // Values that would be -1073741824 in two's complement. - equalsTestCase{uint((1 << 32) - 1073741824), false, false, ""}, - equalsTestCase{uint32((1 << 32) - 1073741824), false, false, ""}, - equalsTestCase{uint64((1 << 64) - 1073741824), false, false, ""}, - - // Non-equal values of signed integer type. - equalsTestCase{int(-1073741823), false, false, ""}, - equalsTestCase{int32(-1073741823), false, false, ""}, - equalsTestCase{int64(-1073741823), false, false, ""}, - - // Non-equal values of other numeric types. - equalsTestCase{float64(-1073741824.1), false, false, ""}, - equalsTestCase{float64(-1073741823.9), false, false, ""}, - equalsTestCase{complex128(-1073741823), false, false, ""}, - equalsTestCase{complex128(-1073741824 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) PositiveIntegralFloatingPointLiteral() { - // 2^30 - matcher := Equals(1073741824.0) - ExpectEq("1.073741824e+09", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of 1073741824. - equalsTestCase{1073741824, true, false, ""}, - equalsTestCase{1073741824.0, true, false, ""}, - equalsTestCase{1073741824 + 0i, true, false, ""}, - equalsTestCase{int(1073741824), true, false, ""}, - equalsTestCase{int32(1073741824), true, false, ""}, - equalsTestCase{int64(1073741824), true, false, ""}, - equalsTestCase{uint(1073741824), true, false, ""}, - equalsTestCase{uint32(1073741824), true, false, ""}, - equalsTestCase{uint64(1073741824), true, false, ""}, - equalsTestCase{float32(1073741824), true, false, ""}, - equalsTestCase{float64(1073741824), true, false, ""}, - equalsTestCase{complex64(1073741824), true, false, ""}, - equalsTestCase{complex128(1073741824), true, false, ""}, - equalsTestCase{interface{}(int(1073741824)), true, false, ""}, - equalsTestCase{interface{}(float64(1073741824)), true, false, ""}, - - // Values that would be 1073741824 in two's complement. - equalsTestCase{uint((1 << 32) - 1073741824), false, false, ""}, - equalsTestCase{uint32((1 << 32) - 1073741824), false, false, ""}, - equalsTestCase{uint64((1 << 64) - 1073741824), false, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int(1073741823), false, false, ""}, - equalsTestCase{int32(1073741823), false, false, ""}, - equalsTestCase{int64(1073741823), false, false, ""}, - equalsTestCase{uint(1073741823), false, false, ""}, - equalsTestCase{uint32(1073741823), false, false, ""}, - equalsTestCase{uint64(1073741823), false, false, ""}, - equalsTestCase{float64(1073741824.1), false, false, ""}, - equalsTestCase{float64(1073741823.9), false, false, ""}, - equalsTestCase{complex128(1073741823), false, false, ""}, - equalsTestCase{complex128(1073741824 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) NonIntegralFloatingPointLiteral() { - matcher := Equals(17.1) - ExpectEq("17.1", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of 17.1. - equalsTestCase{17.1, true, false, ""}, - equalsTestCase{17.1, true, false, ""}, - equalsTestCase{17.1 + 0i, true, false, ""}, - equalsTestCase{float32(17.1), true, false, ""}, - equalsTestCase{float64(17.1), true, false, ""}, - equalsTestCase{complex64(17.1), true, false, ""}, - equalsTestCase{complex128(17.1), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{17, false, false, ""}, - equalsTestCase{17.2, false, false, ""}, - equalsTestCase{18, false, false, ""}, - equalsTestCase{int(17), false, false, ""}, - equalsTestCase{int(18), false, false, ""}, - equalsTestCase{int32(17), false, false, ""}, - equalsTestCase{int64(17), false, false, ""}, - equalsTestCase{uint(17), false, false, ""}, - equalsTestCase{uint32(17), false, false, ""}, - equalsTestCase{uint64(17), false, false, ""}, - equalsTestCase{complex128(17.1 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// bool -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) False() { - matcher := Equals(false) - ExpectEq("false", matcher.Description()) - - cases := []equalsTestCase{ - // bools - equalsTestCase{false, true, false, ""}, - equalsTestCase{bool(false), true, false, ""}, - - equalsTestCase{true, false, false, ""}, - equalsTestCase{bool(true), false, false, ""}, - - // Other types. - equalsTestCase{int(0), false, true, "which is not a bool"}, - equalsTestCase{int8(0), false, true, "which is not a bool"}, - equalsTestCase{int16(0), false, true, "which is not a bool"}, - equalsTestCase{int32(0), false, true, "which is not a bool"}, - equalsTestCase{int64(0), false, true, "which is not a bool"}, - equalsTestCase{uint(0), false, true, "which is not a bool"}, - equalsTestCase{uint8(0), false, true, "which is not a bool"}, - equalsTestCase{uint16(0), false, true, "which is not a bool"}, - equalsTestCase{uint32(0), false, true, "which is not a bool"}, - equalsTestCase{uint64(0), false, true, "which is not a bool"}, - equalsTestCase{uintptr(0), false, true, "which is not a bool"}, - equalsTestCase{[...]int{}, false, true, "which is not a bool"}, - equalsTestCase{make(chan int), false, true, "which is not a bool"}, - equalsTestCase{func() {}, false, true, "which is not a bool"}, - equalsTestCase{map[int]int{}, false, true, "which is not a bool"}, - equalsTestCase{&someInt, false, true, "which is not a bool"}, - equalsTestCase{[]int{}, false, true, "which is not a bool"}, - equalsTestCase{"taco", false, true, "which is not a bool"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not a bool"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) True() { - matcher := Equals(true) - ExpectEq("true", matcher.Description()) - - cases := []equalsTestCase{ - // bools - equalsTestCase{true, true, false, ""}, - equalsTestCase{bool(true), true, false, ""}, - - equalsTestCase{false, false, false, ""}, - equalsTestCase{bool(false), false, false, ""}, - - // Other types. - equalsTestCase{int(1), false, true, "which is not a bool"}, - equalsTestCase{int8(1), false, true, "which is not a bool"}, - equalsTestCase{int16(1), false, true, "which is not a bool"}, - equalsTestCase{int32(1), false, true, "which is not a bool"}, - equalsTestCase{int64(1), false, true, "which is not a bool"}, - equalsTestCase{uint(1), false, true, "which is not a bool"}, - equalsTestCase{uint8(1), false, true, "which is not a bool"}, - equalsTestCase{uint16(1), false, true, "which is not a bool"}, - equalsTestCase{uint32(1), false, true, "which is not a bool"}, - equalsTestCase{uint64(1), false, true, "which is not a bool"}, - equalsTestCase{uintptr(1), false, true, "which is not a bool"}, - equalsTestCase{[...]int{}, false, true, "which is not a bool"}, - equalsTestCase{make(chan int), false, true, "which is not a bool"}, - equalsTestCase{func() {}, false, true, "which is not a bool"}, - equalsTestCase{map[int]int{}, false, true, "which is not a bool"}, - equalsTestCase{&someInt, false, true, "which is not a bool"}, - equalsTestCase{[]int{}, false, true, "which is not a bool"}, - equalsTestCase{"taco", false, true, "which is not a bool"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not a bool"}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// int -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) NegativeInt() { - // -2^30 - matcher := Equals(int(-1073741824)) - ExpectEq("-1073741824", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of -1073741824. - equalsTestCase{-1073741824, true, false, ""}, - equalsTestCase{-1073741824.0, true, false, ""}, - equalsTestCase{-1073741824 + 0i, true, false, ""}, - equalsTestCase{int(-1073741824), true, false, ""}, - equalsTestCase{int32(-1073741824), true, false, ""}, - equalsTestCase{int64(-1073741824), true, false, ""}, - equalsTestCase{float32(-1073741824), true, false, ""}, - equalsTestCase{float64(-1073741824), true, false, ""}, - equalsTestCase{complex64(-1073741824), true, false, ""}, - equalsTestCase{complex128(-1073741824), true, false, ""}, - equalsTestCase{interface{}(int(-1073741824)), true, false, ""}, - - // Values that would be -1073741824 in two's complement. - equalsTestCase{uint((1 << 32) - 1073741824), false, false, ""}, - equalsTestCase{uint32((1 << 32) - 1073741824), false, false, ""}, - equalsTestCase{uint64((1 << 64) - 1073741824), false, false, ""}, - - // Non-equal values of signed integer type. - equalsTestCase{int(-1073741823), false, false, ""}, - equalsTestCase{int32(-1073741823), false, false, ""}, - equalsTestCase{int64(-1073741823), false, false, ""}, - - // Non-equal values of other numeric types. - equalsTestCase{float64(-1073741824.1), false, false, ""}, - equalsTestCase{float64(-1073741823.9), false, false, ""}, - equalsTestCase{complex128(-1073741823), false, false, ""}, - equalsTestCase{complex128(-1073741824 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) PositiveInt() { - // 2^30 - matcher := Equals(int(1073741824)) - ExpectEq("1073741824", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of 1073741824. - equalsTestCase{1073741824, true, false, ""}, - equalsTestCase{1073741824.0, true, false, ""}, - equalsTestCase{1073741824 + 0i, true, false, ""}, - equalsTestCase{int(1073741824), true, false, ""}, - equalsTestCase{uint(1073741824), true, false, ""}, - equalsTestCase{int32(1073741824), true, false, ""}, - equalsTestCase{int64(1073741824), true, false, ""}, - equalsTestCase{uint32(1073741824), true, false, ""}, - equalsTestCase{uint64(1073741824), true, false, ""}, - equalsTestCase{float32(1073741824), true, false, ""}, - equalsTestCase{float64(1073741824), true, false, ""}, - equalsTestCase{complex64(1073741824), true, false, ""}, - equalsTestCase{complex128(1073741824), true, false, ""}, - equalsTestCase{interface{}(int(1073741824)), true, false, ""}, - equalsTestCase{interface{}(uint(1073741824)), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int(1073741823), false, false, ""}, - equalsTestCase{int32(1073741823), false, false, ""}, - equalsTestCase{int64(1073741823), false, false, ""}, - equalsTestCase{float64(1073741824.1), false, false, ""}, - equalsTestCase{float64(1073741823.9), false, false, ""}, - equalsTestCase{complex128(1073741823), false, false, ""}, - equalsTestCase{complex128(1073741824 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// int8 -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) NegativeInt8() { - matcher := Equals(int8(-17)) - ExpectEq("-17", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of -17. - equalsTestCase{-17, true, false, ""}, - equalsTestCase{-17.0, true, false, ""}, - equalsTestCase{-17 + 0i, true, false, ""}, - equalsTestCase{int(-17), true, false, ""}, - equalsTestCase{int8(-17), true, false, ""}, - equalsTestCase{int16(-17), true, false, ""}, - equalsTestCase{int32(-17), true, false, ""}, - equalsTestCase{int64(-17), true, false, ""}, - equalsTestCase{float32(-17), true, false, ""}, - equalsTestCase{float64(-17), true, false, ""}, - equalsTestCase{complex64(-17), true, false, ""}, - equalsTestCase{complex128(-17), true, false, ""}, - equalsTestCase{interface{}(int(-17)), true, false, ""}, - - // Values that would be -17 in two's complement. - equalsTestCase{uint((1 << 32) - 17), false, false, ""}, - equalsTestCase{uint8((1 << 8) - 17), false, false, ""}, - equalsTestCase{uint16((1 << 16) - 17), false, false, ""}, - equalsTestCase{uint32((1 << 32) - 17), false, false, ""}, - equalsTestCase{uint64((1 << 64) - 17), false, false, ""}, - - // Non-equal values of signed integer type. - equalsTestCase{int(-16), false, false, ""}, - equalsTestCase{int8(-16), false, false, ""}, - equalsTestCase{int16(-16), false, false, ""}, - equalsTestCase{int32(-16), false, false, ""}, - equalsTestCase{int64(-16), false, false, ""}, - - // Non-equal values of other numeric types. - equalsTestCase{float32(-17.1), false, false, ""}, - equalsTestCase{float32(-16.9), false, false, ""}, - equalsTestCase{complex64(-16), false, false, ""}, - equalsTestCase{complex64(-17 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr((1 << 32) - 17), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{-17}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{-17}, false, true, "which is not numeric"}, - equalsTestCase{"-17", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) ZeroInt8() { - matcher := Equals(int8(0)) - ExpectEq("0", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of 0. - equalsTestCase{0, true, false, ""}, - equalsTestCase{0.0, true, false, ""}, - equalsTestCase{0 + 0i, true, false, ""}, - equalsTestCase{int(0), true, false, ""}, - equalsTestCase{int8(0), true, false, ""}, - equalsTestCase{int16(0), true, false, ""}, - equalsTestCase{int32(0), true, false, ""}, - equalsTestCase{int64(0), true, false, ""}, - equalsTestCase{float32(0), true, false, ""}, - equalsTestCase{float64(0), true, false, ""}, - equalsTestCase{complex64(0), true, false, ""}, - equalsTestCase{complex128(0), true, false, ""}, - equalsTestCase{interface{}(int(0)), true, false, ""}, - equalsTestCase{uint(0), true, false, ""}, - equalsTestCase{uint8(0), true, false, ""}, - equalsTestCase{uint16(0), true, false, ""}, - equalsTestCase{uint32(0), true, false, ""}, - equalsTestCase{uint64(0), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int(1), false, false, ""}, - equalsTestCase{int8(1), false, false, ""}, - equalsTestCase{int16(1), false, false, ""}, - equalsTestCase{int32(1), false, false, ""}, - equalsTestCase{int64(1), false, false, ""}, - equalsTestCase{float32(-0.1), false, false, ""}, - equalsTestCase{float32(0.1), false, false, ""}, - equalsTestCase{complex64(1), false, false, ""}, - equalsTestCase{complex64(0 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{0}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{0}, false, true, "which is not numeric"}, - equalsTestCase{"0", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) PositiveInt8() { - matcher := Equals(int8(17)) - ExpectEq("17", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of 17. - equalsTestCase{17, true, false, ""}, - equalsTestCase{17.0, true, false, ""}, - equalsTestCase{17 + 0i, true, false, ""}, - equalsTestCase{int(17), true, false, ""}, - equalsTestCase{int8(17), true, false, ""}, - equalsTestCase{int16(17), true, false, ""}, - equalsTestCase{int32(17), true, false, ""}, - equalsTestCase{int64(17), true, false, ""}, - equalsTestCase{float32(17), true, false, ""}, - equalsTestCase{float64(17), true, false, ""}, - equalsTestCase{complex64(17), true, false, ""}, - equalsTestCase{complex128(17), true, false, ""}, - equalsTestCase{interface{}(int(17)), true, false, ""}, - equalsTestCase{uint(17), true, false, ""}, - equalsTestCase{uint8(17), true, false, ""}, - equalsTestCase{uint16(17), true, false, ""}, - equalsTestCase{uint32(17), true, false, ""}, - equalsTestCase{uint64(17), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int(16), false, false, ""}, - equalsTestCase{int8(16), false, false, ""}, - equalsTestCase{int16(16), false, false, ""}, - equalsTestCase{int32(16), false, false, ""}, - equalsTestCase{int64(16), false, false, ""}, - equalsTestCase{float32(16.9), false, false, ""}, - equalsTestCase{float32(17.1), false, false, ""}, - equalsTestCase{complex64(16), false, false, ""}, - equalsTestCase{complex64(17 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(17), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{17}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{17}, false, true, "which is not numeric"}, - equalsTestCase{"17", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// int16 -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) NegativeInt16() { - matcher := Equals(int16(-32766)) - ExpectEq("-32766", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of -32766. - equalsTestCase{-32766, true, false, ""}, - equalsTestCase{-32766.0, true, false, ""}, - equalsTestCase{-32766 + 0i, true, false, ""}, - equalsTestCase{int(-32766), true, false, ""}, - equalsTestCase{int16(-32766), true, false, ""}, - equalsTestCase{int32(-32766), true, false, ""}, - equalsTestCase{int64(-32766), true, false, ""}, - equalsTestCase{float32(-32766), true, false, ""}, - equalsTestCase{float64(-32766), true, false, ""}, - equalsTestCase{complex64(-32766), true, false, ""}, - equalsTestCase{complex128(-32766), true, false, ""}, - equalsTestCase{interface{}(int(-32766)), true, false, ""}, - - // Values that would be -32766 in two's complement. - equalsTestCase{uint((1 << 32) - 32766), false, false, ""}, - equalsTestCase{uint16((1 << 16) - 32766), false, false, ""}, - equalsTestCase{uint32((1 << 32) - 32766), false, false, ""}, - equalsTestCase{uint64((1 << 64) - 32766), false, false, ""}, - - // Non-equal values of signed integer type. - equalsTestCase{int(-16), false, false, ""}, - equalsTestCase{int8(-16), false, false, ""}, - equalsTestCase{int16(-16), false, false, ""}, - equalsTestCase{int32(-16), false, false, ""}, - equalsTestCase{int64(-16), false, false, ""}, - - // Non-equal values of other numeric types. - equalsTestCase{float32(-32766.1), false, false, ""}, - equalsTestCase{float32(-32765.9), false, false, ""}, - equalsTestCase{complex64(-32766.1), false, false, ""}, - equalsTestCase{complex64(-32766 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr((1 << 32) - 32766), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{-32766}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{-32766}, false, true, "which is not numeric"}, - equalsTestCase{"-32766", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) ZeroInt16() { - matcher := Equals(int16(0)) - ExpectEq("0", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of 0. - equalsTestCase{0, true, false, ""}, - equalsTestCase{0.0, true, false, ""}, - equalsTestCase{0 + 0i, true, false, ""}, - equalsTestCase{int(0), true, false, ""}, - equalsTestCase{int8(0), true, false, ""}, - equalsTestCase{int16(0), true, false, ""}, - equalsTestCase{int32(0), true, false, ""}, - equalsTestCase{int64(0), true, false, ""}, - equalsTestCase{float32(0), true, false, ""}, - equalsTestCase{float64(0), true, false, ""}, - equalsTestCase{complex64(0), true, false, ""}, - equalsTestCase{complex128(0), true, false, ""}, - equalsTestCase{interface{}(int(0)), true, false, ""}, - equalsTestCase{uint(0), true, false, ""}, - equalsTestCase{uint8(0), true, false, ""}, - equalsTestCase{uint16(0), true, false, ""}, - equalsTestCase{uint32(0), true, false, ""}, - equalsTestCase{uint64(0), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int(1), false, false, ""}, - equalsTestCase{int8(1), false, false, ""}, - equalsTestCase{int16(1), false, false, ""}, - equalsTestCase{int32(1), false, false, ""}, - equalsTestCase{int64(1), false, false, ""}, - equalsTestCase{float32(-0.1), false, false, ""}, - equalsTestCase{float32(0.1), false, false, ""}, - equalsTestCase{complex64(1), false, false, ""}, - equalsTestCase{complex64(0 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{0}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{0}, false, true, "which is not numeric"}, - equalsTestCase{"0", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) PositiveInt16() { - matcher := Equals(int16(32765)) - ExpectEq("32765", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of 32765. - equalsTestCase{32765, true, false, ""}, - equalsTestCase{32765.0, true, false, ""}, - equalsTestCase{32765 + 0i, true, false, ""}, - equalsTestCase{int(32765), true, false, ""}, - equalsTestCase{int16(32765), true, false, ""}, - equalsTestCase{int32(32765), true, false, ""}, - equalsTestCase{int64(32765), true, false, ""}, - equalsTestCase{float32(32765), true, false, ""}, - equalsTestCase{float64(32765), true, false, ""}, - equalsTestCase{complex64(32765), true, false, ""}, - equalsTestCase{complex128(32765), true, false, ""}, - equalsTestCase{interface{}(int(32765)), true, false, ""}, - equalsTestCase{uint(32765), true, false, ""}, - equalsTestCase{uint16(32765), true, false, ""}, - equalsTestCase{uint32(32765), true, false, ""}, - equalsTestCase{uint64(32765), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int(32764), false, false, ""}, - equalsTestCase{int16(32764), false, false, ""}, - equalsTestCase{int32(32764), false, false, ""}, - equalsTestCase{int64(32764), false, false, ""}, - equalsTestCase{float32(32764.9), false, false, ""}, - equalsTestCase{float32(32765.1), false, false, ""}, - equalsTestCase{complex64(32765.9), false, false, ""}, - equalsTestCase{complex64(32765 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(32765), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{32765}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{32765}, false, true, "which is not numeric"}, - equalsTestCase{"32765", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// int32 -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) NegativeInt32() { - // -2^30 - matcher := Equals(int32(-1073741824)) - ExpectEq("-1073741824", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of -1073741824. - equalsTestCase{-1073741824, true, false, ""}, - equalsTestCase{-1073741824.0, true, false, ""}, - equalsTestCase{-1073741824 + 0i, true, false, ""}, - equalsTestCase{int(-1073741824), true, false, ""}, - equalsTestCase{int32(-1073741824), true, false, ""}, - equalsTestCase{int64(-1073741824), true, false, ""}, - equalsTestCase{float32(-1073741824), true, false, ""}, - equalsTestCase{float64(-1073741824), true, false, ""}, - equalsTestCase{complex64(-1073741824), true, false, ""}, - equalsTestCase{complex128(-1073741824), true, false, ""}, - equalsTestCase{interface{}(int(-1073741824)), true, false, ""}, - - // Values that would be -1073741824 in two's complement. - equalsTestCase{uint((1 << 32) - 1073741824), false, false, ""}, - equalsTestCase{uint32((1 << 32) - 1073741824), false, false, ""}, - equalsTestCase{uint64((1 << 64) - 1073741824), false, false, ""}, - - // Non-equal values of signed integer type. - equalsTestCase{int(-1073741823), false, false, ""}, - equalsTestCase{int32(-1073741823), false, false, ""}, - equalsTestCase{int64(-1073741823), false, false, ""}, - - // Non-equal values of other numeric types. - equalsTestCase{float64(-1073741824.1), false, false, ""}, - equalsTestCase{float64(-1073741823.9), false, false, ""}, - equalsTestCase{complex128(-1073741823), false, false, ""}, - equalsTestCase{complex128(-1073741824 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) PositiveInt32() { - // 2^30 - matcher := Equals(int32(1073741824)) - ExpectEq("1073741824", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of 1073741824. - equalsTestCase{1073741824, true, false, ""}, - equalsTestCase{1073741824.0, true, false, ""}, - equalsTestCase{1073741824 + 0i, true, false, ""}, - equalsTestCase{int(1073741824), true, false, ""}, - equalsTestCase{uint(1073741824), true, false, ""}, - equalsTestCase{int32(1073741824), true, false, ""}, - equalsTestCase{int64(1073741824), true, false, ""}, - equalsTestCase{uint32(1073741824), true, false, ""}, - equalsTestCase{uint64(1073741824), true, false, ""}, - equalsTestCase{float32(1073741824), true, false, ""}, - equalsTestCase{float64(1073741824), true, false, ""}, - equalsTestCase{complex64(1073741824), true, false, ""}, - equalsTestCase{complex128(1073741824), true, false, ""}, - equalsTestCase{interface{}(int(1073741824)), true, false, ""}, - equalsTestCase{interface{}(uint(1073741824)), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int(1073741823), false, false, ""}, - equalsTestCase{int32(1073741823), false, false, ""}, - equalsTestCase{int64(1073741823), false, false, ""}, - equalsTestCase{float64(1073741824.1), false, false, ""}, - equalsTestCase{float64(1073741823.9), false, false, ""}, - equalsTestCase{complex128(1073741823), false, false, ""}, - equalsTestCase{complex128(1073741824 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// int64 -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) NegativeInt64() { - // -2^40 - matcher := Equals(int64(-1099511627776)) - ExpectEq("-1099511627776", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of -1099511627776. - equalsTestCase{-1099511627776.0, true, false, ""}, - equalsTestCase{-1099511627776 + 0i, true, false, ""}, - equalsTestCase{int64(-1099511627776), true, false, ""}, - equalsTestCase{float32(-1099511627776), true, false, ""}, - equalsTestCase{float64(-1099511627776), true, false, ""}, - equalsTestCase{complex64(-1099511627776), true, false, ""}, - equalsTestCase{complex128(-1099511627776), true, false, ""}, - equalsTestCase{interface{}(int64(-1099511627776)), true, false, ""}, - - // Values that would be -1099511627776 in two's complement. - equalsTestCase{uint64((1 << 64) - 1099511627776), false, false, ""}, - - // Non-equal values of signed integer type. - equalsTestCase{int64(-1099511627775), false, false, ""}, - - // Non-equal values of other numeric types. - equalsTestCase{float64(-1099511627776.1), false, false, ""}, - equalsTestCase{float64(-1099511627775.9), false, false, ""}, - equalsTestCase{complex128(-1099511627775), false, false, ""}, - equalsTestCase{complex128(-1099511627776 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) PositiveInt64() { - // 2^40 - matcher := Equals(int64(1099511627776)) - ExpectEq("1099511627776", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of 1099511627776. - equalsTestCase{1099511627776.0, true, false, ""}, - equalsTestCase{1099511627776 + 0i, true, false, ""}, - equalsTestCase{int64(1099511627776), true, false, ""}, - equalsTestCase{uint64(1099511627776), true, false, ""}, - equalsTestCase{float32(1099511627776), true, false, ""}, - equalsTestCase{float64(1099511627776), true, false, ""}, - equalsTestCase{complex64(1099511627776), true, false, ""}, - equalsTestCase{complex128(1099511627776), true, false, ""}, - equalsTestCase{interface{}(int64(1099511627776)), true, false, ""}, - equalsTestCase{interface{}(uint64(1099511627776)), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int64(1099511627775), false, false, ""}, - equalsTestCase{uint64(1099511627775), false, false, ""}, - equalsTestCase{float64(1099511627776.1), false, false, ""}, - equalsTestCase{float64(1099511627775.9), false, false, ""}, - equalsTestCase{complex128(1099511627775), false, false, ""}, - equalsTestCase{complex128(1099511627776 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) Int64NotExactlyRepresentableBySinglePrecision() { - // Single-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo25 = 1 << 25 - matcher := Equals(int64(kTwoTo25 + 1)) - ExpectEq("33554433", matcher.Description()) - - cases := []equalsTestCase{ - // Integers. - equalsTestCase{int64(kTwoTo25 + 0), false, false, ""}, - equalsTestCase{int64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{int64(kTwoTo25 + 2), false, false, ""}, - - equalsTestCase{uint64(kTwoTo25 + 0), false, false, ""}, - equalsTestCase{uint64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{uint64(kTwoTo25 + 2), false, false, ""}, - - // Single-precision floating point. - equalsTestCase{float32(kTwoTo25 - 2), false, false, ""}, - equalsTestCase{float32(kTwoTo25 - 1), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 0), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 2), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 3), false, false, ""}, - - equalsTestCase{complex64(kTwoTo25 - 2), false, false, ""}, - equalsTestCase{complex64(kTwoTo25 - 1), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 0), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 2), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 3), false, false, ""}, - - // Double-precision floating point. - equalsTestCase{float64(kTwoTo25 + 0), false, false, ""}, - equalsTestCase{float64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{float64(kTwoTo25 + 2), false, false, ""}, - - equalsTestCase{complex128(kTwoTo25 + 0), false, false, ""}, - equalsTestCase{complex128(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{complex128(kTwoTo25 + 2), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) Int64NotExactlyRepresentableByDoublePrecision() { - // Double-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo54 = 1 << 54 - matcher := Equals(int64(kTwoTo54 + 1)) - ExpectEq("18014398509481985", matcher.Description()) - - cases := []equalsTestCase{ - // Integers. - equalsTestCase{int64(kTwoTo54 + 0), false, false, ""}, - equalsTestCase{int64(kTwoTo54 + 1), true, false, ""}, - equalsTestCase{int64(kTwoTo54 + 2), false, false, ""}, - - equalsTestCase{uint64(kTwoTo54 + 0), false, false, ""}, - equalsTestCase{uint64(kTwoTo54 + 1), true, false, ""}, - equalsTestCase{uint64(kTwoTo54 + 2), false, false, ""}, - - // Double-precision floating point. - equalsTestCase{float64(kTwoTo54 - 2), false, false, ""}, - equalsTestCase{float64(kTwoTo54 - 1), true, false, ""}, - equalsTestCase{float64(kTwoTo54 + 0), true, false, ""}, - equalsTestCase{float64(kTwoTo54 + 1), true, false, ""}, - equalsTestCase{float64(kTwoTo54 + 2), true, false, ""}, - equalsTestCase{float64(kTwoTo54 + 3), false, false, ""}, - - equalsTestCase{complex128(kTwoTo54 - 2), false, false, ""}, - equalsTestCase{complex128(kTwoTo54 - 1), true, false, ""}, - equalsTestCase{complex128(kTwoTo54 + 0), true, false, ""}, - equalsTestCase{complex128(kTwoTo54 + 1), true, false, ""}, - equalsTestCase{complex128(kTwoTo54 + 2), true, false, ""}, - equalsTestCase{complex128(kTwoTo54 + 3), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// uint -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) SmallUint() { - const kExpected = 17 - matcher := Equals(uint(kExpected)) - ExpectEq("17", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of the expected value. - equalsTestCase{17, true, false, ""}, - equalsTestCase{17.0, true, false, ""}, - equalsTestCase{17 + 0i, true, false, ""}, - equalsTestCase{int(kExpected), true, false, ""}, - equalsTestCase{int8(kExpected), true, false, ""}, - equalsTestCase{int16(kExpected), true, false, ""}, - equalsTestCase{int32(kExpected), true, false, ""}, - equalsTestCase{int64(kExpected), true, false, ""}, - equalsTestCase{uint(kExpected), true, false, ""}, - equalsTestCase{uint8(kExpected), true, false, ""}, - equalsTestCase{uint16(kExpected), true, false, ""}, - equalsTestCase{uint32(kExpected), true, false, ""}, - equalsTestCase{uint64(kExpected), true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric types. - equalsTestCase{kExpected + 1, false, false, ""}, - equalsTestCase{int(kExpected + 1), false, false, ""}, - equalsTestCase{int8(kExpected + 1), false, false, ""}, - equalsTestCase{int16(kExpected + 1), false, false, ""}, - equalsTestCase{int32(kExpected + 1), false, false, ""}, - equalsTestCase{int64(kExpected + 1), false, false, ""}, - equalsTestCase{uint(kExpected + 1), false, false, ""}, - equalsTestCase{uint8(kExpected + 1), false, false, ""}, - equalsTestCase{uint16(kExpected + 1), false, false, ""}, - equalsTestCase{uint32(kExpected + 1), false, false, ""}, - equalsTestCase{uint64(kExpected + 1), false, false, ""}, - equalsTestCase{float32(kExpected + 1), false, false, ""}, - equalsTestCase{float64(kExpected + 1), false, false, ""}, - equalsTestCase{complex64(kExpected + 2i), false, false, ""}, - equalsTestCase{complex64(kExpected + 1), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - equalsTestCase{complex128(kExpected + 1), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) LargeUint() { - const kExpected = (1 << 16) + 17 - matcher := Equals(uint(kExpected)) - ExpectEq("65553", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of the expected value. - equalsTestCase{65553, true, false, ""}, - equalsTestCase{65553.0, true, false, ""}, - equalsTestCase{65553 + 0i, true, false, ""}, - equalsTestCase{int32(kExpected), true, false, ""}, - equalsTestCase{int64(kExpected), true, false, ""}, - equalsTestCase{uint32(kExpected), true, false, ""}, - equalsTestCase{uint64(kExpected), true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric types. - equalsTestCase{int16(17), false, false, ""}, - equalsTestCase{int32(kExpected + 1), false, false, ""}, - equalsTestCase{int64(kExpected + 1), false, false, ""}, - equalsTestCase{uint16(17), false, false, ""}, - equalsTestCase{uint32(kExpected + 1), false, false, ""}, - equalsTestCase{uint64(kExpected + 1), false, false, ""}, - equalsTestCase{float64(kExpected + 1), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - equalsTestCase{complex128(kExpected + 1), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) UintNotExactlyRepresentableBySinglePrecision() { - // Single-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo25 = 1 << 25 - matcher := Equals(uint(kTwoTo25 + 1)) - ExpectEq("33554433", matcher.Description()) - - cases := []equalsTestCase{ - // Integers. - equalsTestCase{int64(kTwoTo25 + 0), false, false, ""}, - equalsTestCase{int64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{int64(kTwoTo25 + 2), false, false, ""}, - - equalsTestCase{uint64(kTwoTo25 + 0), false, false, ""}, - equalsTestCase{uint64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{uint64(kTwoTo25 + 2), false, false, ""}, - - // Single-precision floating point. - equalsTestCase{float32(kTwoTo25 - 2), false, false, ""}, - equalsTestCase{float32(kTwoTo25 - 1), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 0), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 2), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 3), false, false, ""}, - - equalsTestCase{complex64(kTwoTo25 - 2), false, false, ""}, - equalsTestCase{complex64(kTwoTo25 - 1), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 0), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 2), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 3), false, false, ""}, - - // Double-precision floating point. - equalsTestCase{float64(kTwoTo25 + 0), false, false, ""}, - equalsTestCase{float64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{float64(kTwoTo25 + 2), false, false, ""}, - - equalsTestCase{complex128(kTwoTo25 + 0), false, false, ""}, - equalsTestCase{complex128(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{complex128(kTwoTo25 + 2), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// uint8 -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) SmallUint8() { - const kExpected = 17 - matcher := Equals(uint8(kExpected)) - ExpectEq("17", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of the expected value. - equalsTestCase{17, true, false, ""}, - equalsTestCase{17.0, true, false, ""}, - equalsTestCase{17 + 0i, true, false, ""}, - equalsTestCase{int(kExpected), true, false, ""}, - equalsTestCase{int8(kExpected), true, false, ""}, - equalsTestCase{int16(kExpected), true, false, ""}, - equalsTestCase{int32(kExpected), true, false, ""}, - equalsTestCase{int64(kExpected), true, false, ""}, - equalsTestCase{uint(kExpected), true, false, ""}, - equalsTestCase{uint8(kExpected), true, false, ""}, - equalsTestCase{uint16(kExpected), true, false, ""}, - equalsTestCase{uint32(kExpected), true, false, ""}, - equalsTestCase{uint64(kExpected), true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric types. - equalsTestCase{kExpected + 1, false, false, ""}, - equalsTestCase{int(kExpected + 1), false, false, ""}, - equalsTestCase{int8(kExpected + 1), false, false, ""}, - equalsTestCase{int16(kExpected + 1), false, false, ""}, - equalsTestCase{int32(kExpected + 1), false, false, ""}, - equalsTestCase{int64(kExpected + 1), false, false, ""}, - equalsTestCase{uint(kExpected + 1), false, false, ""}, - equalsTestCase{uint8(kExpected + 1), false, false, ""}, - equalsTestCase{uint16(kExpected + 1), false, false, ""}, - equalsTestCase{uint32(kExpected + 1), false, false, ""}, - equalsTestCase{uint64(kExpected + 1), false, false, ""}, - equalsTestCase{float32(kExpected + 1), false, false, ""}, - equalsTestCase{float64(kExpected + 1), false, false, ""}, - equalsTestCase{complex64(kExpected + 2i), false, false, ""}, - equalsTestCase{complex64(kExpected + 1), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - equalsTestCase{complex128(kExpected + 1), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// uint16 -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) SmallUint16() { - const kExpected = 17 - matcher := Equals(uint16(kExpected)) - ExpectEq("17", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of the expected value. - equalsTestCase{17, true, false, ""}, - equalsTestCase{17.0, true, false, ""}, - equalsTestCase{17 + 0i, true, false, ""}, - equalsTestCase{int(kExpected), true, false, ""}, - equalsTestCase{int8(kExpected), true, false, ""}, - equalsTestCase{int16(kExpected), true, false, ""}, - equalsTestCase{int32(kExpected), true, false, ""}, - equalsTestCase{int64(kExpected), true, false, ""}, - equalsTestCase{uint(kExpected), true, false, ""}, - equalsTestCase{uint8(kExpected), true, false, ""}, - equalsTestCase{uint16(kExpected), true, false, ""}, - equalsTestCase{uint32(kExpected), true, false, ""}, - equalsTestCase{uint64(kExpected), true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric types. - equalsTestCase{kExpected + 1, false, false, ""}, - equalsTestCase{int(kExpected + 1), false, false, ""}, - equalsTestCase{int8(kExpected + 1), false, false, ""}, - equalsTestCase{int16(kExpected + 1), false, false, ""}, - equalsTestCase{int32(kExpected + 1), false, false, ""}, - equalsTestCase{int64(kExpected + 1), false, false, ""}, - equalsTestCase{uint(kExpected + 1), false, false, ""}, - equalsTestCase{uint8(kExpected + 1), false, false, ""}, - equalsTestCase{uint16(kExpected + 1), false, false, ""}, - equalsTestCase{uint32(kExpected + 1), false, false, ""}, - equalsTestCase{uint64(kExpected + 1), false, false, ""}, - equalsTestCase{float32(kExpected + 1), false, false, ""}, - equalsTestCase{float64(kExpected + 1), false, false, ""}, - equalsTestCase{complex64(kExpected + 2i), false, false, ""}, - equalsTestCase{complex64(kExpected + 1), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - equalsTestCase{complex128(kExpected + 1), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) LargeUint16() { - const kExpected = (1 << 8) + 17 - matcher := Equals(uint16(kExpected)) - ExpectEq("273", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of the expected value. - equalsTestCase{273, true, false, ""}, - equalsTestCase{273.0, true, false, ""}, - equalsTestCase{273 + 0i, true, false, ""}, - equalsTestCase{int16(kExpected), true, false, ""}, - equalsTestCase{int32(kExpected), true, false, ""}, - equalsTestCase{int64(kExpected), true, false, ""}, - equalsTestCase{uint16(kExpected), true, false, ""}, - equalsTestCase{uint32(kExpected), true, false, ""}, - equalsTestCase{uint64(kExpected), true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric types. - equalsTestCase{int8(17), false, false, ""}, - equalsTestCase{int16(kExpected + 1), false, false, ""}, - equalsTestCase{int32(kExpected + 1), false, false, ""}, - equalsTestCase{int64(kExpected + 1), false, false, ""}, - equalsTestCase{uint8(17), false, false, ""}, - equalsTestCase{uint16(kExpected + 1), false, false, ""}, - equalsTestCase{uint32(kExpected + 1), false, false, ""}, - equalsTestCase{uint64(kExpected + 1), false, false, ""}, - equalsTestCase{float64(kExpected + 1), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - equalsTestCase{complex128(kExpected + 1), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// uint32 -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) SmallUint32() { - const kExpected = 17 - matcher := Equals(uint32(kExpected)) - ExpectEq("17", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of the expected value. - equalsTestCase{17, true, false, ""}, - equalsTestCase{17.0, true, false, ""}, - equalsTestCase{17 + 0i, true, false, ""}, - equalsTestCase{int(kExpected), true, false, ""}, - equalsTestCase{int8(kExpected), true, false, ""}, - equalsTestCase{int16(kExpected), true, false, ""}, - equalsTestCase{int32(kExpected), true, false, ""}, - equalsTestCase{int64(kExpected), true, false, ""}, - equalsTestCase{uint(kExpected), true, false, ""}, - equalsTestCase{uint8(kExpected), true, false, ""}, - equalsTestCase{uint16(kExpected), true, false, ""}, - equalsTestCase{uint32(kExpected), true, false, ""}, - equalsTestCase{uint64(kExpected), true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric types. - equalsTestCase{kExpected + 1, false, false, ""}, - equalsTestCase{int(kExpected + 1), false, false, ""}, - equalsTestCase{int8(kExpected + 1), false, false, ""}, - equalsTestCase{int16(kExpected + 1), false, false, ""}, - equalsTestCase{int32(kExpected + 1), false, false, ""}, - equalsTestCase{int64(kExpected + 1), false, false, ""}, - equalsTestCase{uint(kExpected + 1), false, false, ""}, - equalsTestCase{uint8(kExpected + 1), false, false, ""}, - equalsTestCase{uint16(kExpected + 1), false, false, ""}, - equalsTestCase{uint32(kExpected + 1), false, false, ""}, - equalsTestCase{uint64(kExpected + 1), false, false, ""}, - equalsTestCase{float32(kExpected + 1), false, false, ""}, - equalsTestCase{float64(kExpected + 1), false, false, ""}, - equalsTestCase{complex64(kExpected + 2i), false, false, ""}, - equalsTestCase{complex64(kExpected + 1), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - equalsTestCase{complex128(kExpected + 1), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) LargeUint32() { - const kExpected = (1 << 16) + 17 - matcher := Equals(uint32(kExpected)) - ExpectEq("65553", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of the expected value. - equalsTestCase{65553, true, false, ""}, - equalsTestCase{65553.0, true, false, ""}, - equalsTestCase{65553 + 0i, true, false, ""}, - equalsTestCase{int32(kExpected), true, false, ""}, - equalsTestCase{int64(kExpected), true, false, ""}, - equalsTestCase{uint32(kExpected), true, false, ""}, - equalsTestCase{uint64(kExpected), true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric types. - equalsTestCase{int16(17), false, false, ""}, - equalsTestCase{int32(kExpected + 1), false, false, ""}, - equalsTestCase{int64(kExpected + 1), false, false, ""}, - equalsTestCase{uint16(17), false, false, ""}, - equalsTestCase{uint32(kExpected + 1), false, false, ""}, - equalsTestCase{uint64(kExpected + 1), false, false, ""}, - equalsTestCase{float64(kExpected + 1), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - equalsTestCase{complex128(kExpected + 1), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) Uint32NotExactlyRepresentableBySinglePrecision() { - // Single-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo25 = 1 << 25 - matcher := Equals(uint32(kTwoTo25 + 1)) - ExpectEq("33554433", matcher.Description()) - - cases := []equalsTestCase{ - // Integers. - equalsTestCase{int64(kTwoTo25 + 0), false, false, ""}, - equalsTestCase{int64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{int64(kTwoTo25 + 2), false, false, ""}, - - equalsTestCase{uint64(kTwoTo25 + 0), false, false, ""}, - equalsTestCase{uint64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{uint64(kTwoTo25 + 2), false, false, ""}, - - // Single-precision floating point. - equalsTestCase{float32(kTwoTo25 - 2), false, false, ""}, - equalsTestCase{float32(kTwoTo25 - 1), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 0), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 2), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 3), false, false, ""}, - - equalsTestCase{complex64(kTwoTo25 - 2), false, false, ""}, - equalsTestCase{complex64(kTwoTo25 - 1), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 0), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 2), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 3), false, false, ""}, - - // Double-precision floating point. - equalsTestCase{float64(kTwoTo25 + 0), false, false, ""}, - equalsTestCase{float64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{float64(kTwoTo25 + 2), false, false, ""}, - - equalsTestCase{complex128(kTwoTo25 + 0), false, false, ""}, - equalsTestCase{complex128(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{complex128(kTwoTo25 + 2), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// uint64 -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) SmallUint64() { - const kExpected = 17 - matcher := Equals(uint64(kExpected)) - ExpectEq("17", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of the expected value. - equalsTestCase{17, true, false, ""}, - equalsTestCase{17.0, true, false, ""}, - equalsTestCase{17 + 0i, true, false, ""}, - equalsTestCase{int(kExpected), true, false, ""}, - equalsTestCase{int8(kExpected), true, false, ""}, - equalsTestCase{int16(kExpected), true, false, ""}, - equalsTestCase{int32(kExpected), true, false, ""}, - equalsTestCase{int64(kExpected), true, false, ""}, - equalsTestCase{uint(kExpected), true, false, ""}, - equalsTestCase{uint8(kExpected), true, false, ""}, - equalsTestCase{uint16(kExpected), true, false, ""}, - equalsTestCase{uint32(kExpected), true, false, ""}, - equalsTestCase{uint64(kExpected), true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric types. - equalsTestCase{kExpected + 1, false, false, ""}, - equalsTestCase{int(kExpected + 1), false, false, ""}, - equalsTestCase{int8(kExpected + 1), false, false, ""}, - equalsTestCase{int16(kExpected + 1), false, false, ""}, - equalsTestCase{int32(kExpected + 1), false, false, ""}, - equalsTestCase{int64(kExpected + 1), false, false, ""}, - equalsTestCase{uint(kExpected + 1), false, false, ""}, - equalsTestCase{uint8(kExpected + 1), false, false, ""}, - equalsTestCase{uint16(kExpected + 1), false, false, ""}, - equalsTestCase{uint32(kExpected + 1), false, false, ""}, - equalsTestCase{uint64(kExpected + 1), false, false, ""}, - equalsTestCase{float32(kExpected + 1), false, false, ""}, - equalsTestCase{float64(kExpected + 1), false, false, ""}, - equalsTestCase{complex64(kExpected + 2i), false, false, ""}, - equalsTestCase{complex64(kExpected + 1), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - equalsTestCase{complex128(kExpected + 1), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) LargeUint64() { - const kExpected = (1 << 32) + 17 - matcher := Equals(uint64(kExpected)) - ExpectEq("4294967313", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of the expected value. - equalsTestCase{4294967313.0, true, false, ""}, - equalsTestCase{4294967313 + 0i, true, false, ""}, - equalsTestCase{int64(kExpected), true, false, ""}, - equalsTestCase{uint64(kExpected), true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric types. - equalsTestCase{int(17), false, false, ""}, - equalsTestCase{int32(17), false, false, ""}, - equalsTestCase{int64(kExpected + 1), false, false, ""}, - equalsTestCase{uint(17), false, false, ""}, - equalsTestCase{uint32(17), false, false, ""}, - equalsTestCase{uint64(kExpected + 1), false, false, ""}, - equalsTestCase{float64(kExpected + 1), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - equalsTestCase{complex128(kExpected + 1), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) Uint64NotExactlyRepresentableBySinglePrecision() { - // Single-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo25 = 1 << 25 - matcher := Equals(uint64(kTwoTo25 + 1)) - ExpectEq("33554433", matcher.Description()) - - cases := []equalsTestCase{ - // Integers. - equalsTestCase{int64(kTwoTo25 + 0), false, false, ""}, - equalsTestCase{int64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{int64(kTwoTo25 + 2), false, false, ""}, - - equalsTestCase{uint64(kTwoTo25 + 0), false, false, ""}, - equalsTestCase{uint64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{uint64(kTwoTo25 + 2), false, false, ""}, - - // Single-precision floating point. - equalsTestCase{float32(kTwoTo25 - 2), false, false, ""}, - equalsTestCase{float32(kTwoTo25 - 1), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 0), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 2), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 3), false, false, ""}, - - equalsTestCase{complex64(kTwoTo25 - 2), false, false, ""}, - equalsTestCase{complex64(kTwoTo25 - 1), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 0), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 2), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 3), false, false, ""}, - - // Double-precision floating point. - equalsTestCase{float64(kTwoTo25 + 0), false, false, ""}, - equalsTestCase{float64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{float64(kTwoTo25 + 2), false, false, ""}, - - equalsTestCase{complex128(kTwoTo25 + 0), false, false, ""}, - equalsTestCase{complex128(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{complex128(kTwoTo25 + 2), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) Uint64NotExactlyRepresentableByDoublePrecision() { - // Double-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo54 = 1 << 54 - matcher := Equals(uint64(kTwoTo54 + 1)) - ExpectEq("18014398509481985", matcher.Description()) - - cases := []equalsTestCase{ - // Integers. - equalsTestCase{int64(kTwoTo54 + 0), false, false, ""}, - equalsTestCase{int64(kTwoTo54 + 1), true, false, ""}, - equalsTestCase{int64(kTwoTo54 + 2), false, false, ""}, - - equalsTestCase{uint64(kTwoTo54 + 0), false, false, ""}, - equalsTestCase{uint64(kTwoTo54 + 1), true, false, ""}, - equalsTestCase{uint64(kTwoTo54 + 2), false, false, ""}, - - // Double-precision floating point. - equalsTestCase{float64(kTwoTo54 - 2), false, false, ""}, - equalsTestCase{float64(kTwoTo54 - 1), true, false, ""}, - equalsTestCase{float64(kTwoTo54 + 0), true, false, ""}, - equalsTestCase{float64(kTwoTo54 + 1), true, false, ""}, - equalsTestCase{float64(kTwoTo54 + 2), true, false, ""}, - equalsTestCase{float64(kTwoTo54 + 3), false, false, ""}, - - equalsTestCase{complex128(kTwoTo54 - 2), false, false, ""}, - equalsTestCase{complex128(kTwoTo54 - 1), true, false, ""}, - equalsTestCase{complex128(kTwoTo54 + 0), true, false, ""}, - equalsTestCase{complex128(kTwoTo54 + 1), true, false, ""}, - equalsTestCase{complex128(kTwoTo54 + 2), true, false, ""}, - equalsTestCase{complex128(kTwoTo54 + 3), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// uintptr -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) NilUintptr() { - var ptr1 uintptr - var ptr2 uintptr - - matcher := Equals(ptr1) - ExpectEq("0", matcher.Description()) - - cases := []equalsTestCase{ - // uintptrs - equalsTestCase{ptr1, true, false, ""}, - equalsTestCase{ptr2, true, false, ""}, - equalsTestCase{uintptr(0), true, false, ""}, - equalsTestCase{uintptr(17), false, false, ""}, - - // Other types. - equalsTestCase{0, false, true, "which is not a uintptr"}, - equalsTestCase{bool(false), false, true, "which is not a uintptr"}, - equalsTestCase{int(0), false, true, "which is not a uintptr"}, - equalsTestCase{int8(0), false, true, "which is not a uintptr"}, - equalsTestCase{int16(0), false, true, "which is not a uintptr"}, - equalsTestCase{int32(0), false, true, "which is not a uintptr"}, - equalsTestCase{int64(0), false, true, "which is not a uintptr"}, - equalsTestCase{uint(0), false, true, "which is not a uintptr"}, - equalsTestCase{uint8(0), false, true, "which is not a uintptr"}, - equalsTestCase{uint16(0), false, true, "which is not a uintptr"}, - equalsTestCase{uint32(0), false, true, "which is not a uintptr"}, - equalsTestCase{uint64(0), false, true, "which is not a uintptr"}, - equalsTestCase{true, false, true, "which is not a uintptr"}, - equalsTestCase{[...]int{}, false, true, "which is not a uintptr"}, - equalsTestCase{make(chan int), false, true, "which is not a uintptr"}, - equalsTestCase{func() {}, false, true, "which is not a uintptr"}, - equalsTestCase{map[int]int{}, false, true, "which is not a uintptr"}, - equalsTestCase{&someInt, false, true, "which is not a uintptr"}, - equalsTestCase{[]int{}, false, true, "which is not a uintptr"}, - equalsTestCase{"taco", false, true, "which is not a uintptr"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not a uintptr"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) NonNilUintptr() { - matcher := Equals(uintptr(17)) - ExpectEq("17", matcher.Description()) - - cases := []equalsTestCase{ - // uintptrs - equalsTestCase{uintptr(17), true, false, ""}, - equalsTestCase{uintptr(16), false, false, ""}, - equalsTestCase{uintptr(0), false, false, ""}, - - // Other types. - equalsTestCase{0, false, true, "which is not a uintptr"}, - equalsTestCase{bool(false), false, true, "which is not a uintptr"}, - equalsTestCase{int(0), false, true, "which is not a uintptr"}, - equalsTestCase{int8(0), false, true, "which is not a uintptr"}, - equalsTestCase{int16(0), false, true, "which is not a uintptr"}, - equalsTestCase{int32(0), false, true, "which is not a uintptr"}, - equalsTestCase{int64(0), false, true, "which is not a uintptr"}, - equalsTestCase{uint(0), false, true, "which is not a uintptr"}, - equalsTestCase{uint8(0), false, true, "which is not a uintptr"}, - equalsTestCase{uint16(0), false, true, "which is not a uintptr"}, - equalsTestCase{uint32(0), false, true, "which is not a uintptr"}, - equalsTestCase{uint64(0), false, true, "which is not a uintptr"}, - equalsTestCase{true, false, true, "which is not a uintptr"}, - equalsTestCase{[...]int{}, false, true, "which is not a uintptr"}, - equalsTestCase{make(chan int), false, true, "which is not a uintptr"}, - equalsTestCase{func() {}, false, true, "which is not a uintptr"}, - equalsTestCase{map[int]int{}, false, true, "which is not a uintptr"}, - equalsTestCase{&someInt, false, true, "which is not a uintptr"}, - equalsTestCase{[]int{}, false, true, "which is not a uintptr"}, - equalsTestCase{"taco", false, true, "which is not a uintptr"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not a uintptr"}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// float32 -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) NegativeIntegralFloat32() { - matcher := Equals(float32(-32769)) - ExpectEq("-32769", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of -32769. - equalsTestCase{-32769.0, true, false, ""}, - equalsTestCase{-32769 + 0i, true, false, ""}, - equalsTestCase{int32(-32769), true, false, ""}, - equalsTestCase{int64(-32769), true, false, ""}, - equalsTestCase{float32(-32769), true, false, ""}, - equalsTestCase{float64(-32769), true, false, ""}, - equalsTestCase{complex64(-32769), true, false, ""}, - equalsTestCase{complex128(-32769), true, false, ""}, - equalsTestCase{interface{}(float32(-32769)), true, false, ""}, - equalsTestCase{interface{}(int64(-32769)), true, false, ""}, - - // Values that would be -32769 in two's complement. - equalsTestCase{uint64((1 << 64) - 32769), false, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int64(-32770), false, false, ""}, - equalsTestCase{float32(-32769.1), false, false, ""}, - equalsTestCase{float32(-32768.9), false, false, ""}, - equalsTestCase{float64(-32769.1), false, false, ""}, - equalsTestCase{float64(-32768.9), false, false, ""}, - equalsTestCase{complex128(-32768), false, false, ""}, - equalsTestCase{complex128(-32769 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) NegativeNonIntegralFloat32() { - matcher := Equals(float32(-32769.1)) - ExpectEq("-32769.1", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of -32769.1. - equalsTestCase{-32769.1, true, false, ""}, - equalsTestCase{-32769.1 + 0i, true, false, ""}, - equalsTestCase{float32(-32769.1), true, false, ""}, - equalsTestCase{float64(-32769.1), true, false, ""}, - equalsTestCase{complex64(-32769.1), true, false, ""}, - equalsTestCase{complex128(-32769.1), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int32(-32769), false, false, ""}, - equalsTestCase{int32(-32770), false, false, ""}, - equalsTestCase{int64(-32769), false, false, ""}, - equalsTestCase{int64(-32770), false, false, ""}, - equalsTestCase{float32(-32769.2), false, false, ""}, - equalsTestCase{float32(-32769.0), false, false, ""}, - equalsTestCase{float64(-32769.2), false, false, ""}, - equalsTestCase{complex128(-32769.1 + 2i), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) LargeNegativeFloat32() { - const kExpected = -1 * (1 << 65) - matcher := Equals(float32(kExpected)) - ExpectEq("-3.689349e+19", matcher.Description()) - - floatExpected := float32(kExpected) - castedInt := int64(floatExpected) - - cases := []equalsTestCase{ - // Equal values of numeric type. - equalsTestCase{kExpected + 0i, true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{castedInt, false, false, ""}, - equalsTestCase{int64(0), false, false, ""}, - equalsTestCase{int64(math.MinInt64), false, false, ""}, - equalsTestCase{int64(math.MaxInt64), false, false, ""}, - equalsTestCase{float32(kExpected / 2), false, false, ""}, - equalsTestCase{float64(kExpected / 2), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) ZeroFloat32() { - matcher := Equals(float32(0)) - ExpectEq("0", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of zero. - equalsTestCase{0.0, true, false, ""}, - equalsTestCase{0 + 0i, true, false, ""}, - equalsTestCase{int(0), true, false, ""}, - equalsTestCase{int8(0), true, false, ""}, - equalsTestCase{int16(0), true, false, ""}, - equalsTestCase{int32(0), true, false, ""}, - equalsTestCase{int64(0), true, false, ""}, - equalsTestCase{uint(0), true, false, ""}, - equalsTestCase{uint8(0), true, false, ""}, - equalsTestCase{uint16(0), true, false, ""}, - equalsTestCase{uint32(0), true, false, ""}, - equalsTestCase{uint64(0), true, false, ""}, - equalsTestCase{float32(0), true, false, ""}, - equalsTestCase{float64(0), true, false, ""}, - equalsTestCase{complex64(0), true, false, ""}, - equalsTestCase{complex128(0), true, false, ""}, - equalsTestCase{interface{}(float32(0)), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int64(1), false, false, ""}, - equalsTestCase{int64(-1), false, false, ""}, - equalsTestCase{float32(1), false, false, ""}, - equalsTestCase{float32(-1), false, false, ""}, - equalsTestCase{complex128(0 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) PositiveIntegralFloat32() { - matcher := Equals(float32(32769)) - ExpectEq("32769", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of 32769. - equalsTestCase{32769.0, true, false, ""}, - equalsTestCase{32769 + 0i, true, false, ""}, - equalsTestCase{int(32769), true, false, ""}, - equalsTestCase{int32(32769), true, false, ""}, - equalsTestCase{int64(32769), true, false, ""}, - equalsTestCase{uint(32769), true, false, ""}, - equalsTestCase{uint32(32769), true, false, ""}, - equalsTestCase{uint64(32769), true, false, ""}, - equalsTestCase{float32(32769), true, false, ""}, - equalsTestCase{float64(32769), true, false, ""}, - equalsTestCase{complex64(32769), true, false, ""}, - equalsTestCase{complex128(32769), true, false, ""}, - equalsTestCase{interface{}(float32(32769)), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int64(32770), false, false, ""}, - equalsTestCase{uint64(32770), false, false, ""}, - equalsTestCase{float32(32769.1), false, false, ""}, - equalsTestCase{float32(32768.9), false, false, ""}, - equalsTestCase{float64(32769.1), false, false, ""}, - equalsTestCase{float64(32768.9), false, false, ""}, - equalsTestCase{complex128(32768), false, false, ""}, - equalsTestCase{complex128(32769 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) PositiveNonIntegralFloat32() { - matcher := Equals(float32(32769.1)) - ExpectEq("32769.1", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of 32769.1. - equalsTestCase{32769.1, true, false, ""}, - equalsTestCase{32769.1 + 0i, true, false, ""}, - equalsTestCase{float32(32769.1), true, false, ""}, - equalsTestCase{float64(32769.1), true, false, ""}, - equalsTestCase{complex64(32769.1), true, false, ""}, - equalsTestCase{complex128(32769.1), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int32(32769), false, false, ""}, - equalsTestCase{int32(32770), false, false, ""}, - equalsTestCase{uint64(32769), false, false, ""}, - equalsTestCase{uint64(32770), false, false, ""}, - equalsTestCase{float32(32769.2), false, false, ""}, - equalsTestCase{float32(32769.0), false, false, ""}, - equalsTestCase{float64(32769.2), false, false, ""}, - equalsTestCase{complex128(32769.1 + 2i), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) LargePositiveFloat32() { - const kExpected = 1 << 65 - matcher := Equals(float32(kExpected)) - ExpectEq("3.689349e+19", matcher.Description()) - - floatExpected := float32(kExpected) - castedInt := uint64(floatExpected) - - cases := []equalsTestCase{ - // Equal values of numeric type. - equalsTestCase{kExpected + 0i, true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{castedInt, false, false, ""}, - equalsTestCase{int64(0), false, false, ""}, - equalsTestCase{int64(math.MinInt64), false, false, ""}, - equalsTestCase{int64(math.MaxInt64), false, false, ""}, - equalsTestCase{uint64(0), false, false, ""}, - equalsTestCase{uint64(math.MaxUint64), false, false, ""}, - equalsTestCase{float32(kExpected / 2), false, false, ""}, - equalsTestCase{float64(kExpected / 2), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) Float32AboveExactIntegerRange() { - // Single-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo25 = 1 << 25 - matcher := Equals(float32(kTwoTo25 + 1)) - ExpectEq("3.3554432e+07", matcher.Description()) - - cases := []equalsTestCase{ - // Integers. - equalsTestCase{int64(kTwoTo25 - 2), false, false, ""}, - equalsTestCase{int64(kTwoTo25 - 1), true, false, ""}, - equalsTestCase{int64(kTwoTo25 + 0), true, false, ""}, - equalsTestCase{int64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{int64(kTwoTo25 + 2), true, false, ""}, - equalsTestCase{int64(kTwoTo25 + 3), false, false, ""}, - - equalsTestCase{uint64(kTwoTo25 - 2), false, false, ""}, - equalsTestCase{uint64(kTwoTo25 - 1), true, false, ""}, - equalsTestCase{uint64(kTwoTo25 + 0), true, false, ""}, - equalsTestCase{uint64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{uint64(kTwoTo25 + 2), true, false, ""}, - equalsTestCase{uint64(kTwoTo25 + 3), false, false, ""}, - - // Single-precision floating point. - equalsTestCase{float32(kTwoTo25 - 2), false, false, ""}, - equalsTestCase{float32(kTwoTo25 - 1), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 0), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 2), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 3), false, false, ""}, - - equalsTestCase{complex64(kTwoTo25 - 2), false, false, ""}, - equalsTestCase{complex64(kTwoTo25 - 1), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 0), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 2), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 3), false, false, ""}, - - // Double-precision floating point. - equalsTestCase{float64(kTwoTo25 - 2), false, false, ""}, - equalsTestCase{float64(kTwoTo25 - 1), true, false, ""}, - equalsTestCase{float64(kTwoTo25 + 0), true, false, ""}, - equalsTestCase{float64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{float64(kTwoTo25 + 2), true, false, ""}, - equalsTestCase{float64(kTwoTo25 + 3), false, false, ""}, - - equalsTestCase{complex128(kTwoTo25 - 2), false, false, ""}, - equalsTestCase{complex128(kTwoTo25 - 1), true, false, ""}, - equalsTestCase{complex128(kTwoTo25 + 0), true, false, ""}, - equalsTestCase{complex128(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{complex128(kTwoTo25 + 2), true, false, ""}, - equalsTestCase{complex128(kTwoTo25 + 3), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// float64 -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) NegativeIntegralFloat64() { - const kExpected = -(1 << 50) - matcher := Equals(float64(kExpected)) - ExpectEq("-1.125899906842624e+15", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of the expected value. - equalsTestCase{-1125899906842624.0, true, false, ""}, - equalsTestCase{-1125899906842624.0 + 0i, true, false, ""}, - equalsTestCase{int64(kExpected), true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - equalsTestCase{interface{}(float64(kExpected)), true, false, ""}, - - // Values that would be kExpected in two's complement. - equalsTestCase{uint64((1 << 64) + kExpected), false, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int64(kExpected + 1), false, false, ""}, - equalsTestCase{float32(kExpected - (1 << 30)), false, false, ""}, - equalsTestCase{float32(kExpected + (1 << 30)), false, false, ""}, - equalsTestCase{float64(kExpected - 0.5), false, false, ""}, - equalsTestCase{float64(kExpected + 0.5), false, false, ""}, - equalsTestCase{complex128(kExpected - 1), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) NegativeNonIntegralFloat64() { - const kTwoTo50 = 1 << 50 - const kExpected = -kTwoTo50 - 0.25 - - matcher := Equals(float64(kExpected)) - ExpectEq("-1.1258999068426242e+15", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of the expected value. - equalsTestCase{kExpected, true, false, ""}, - equalsTestCase{kExpected + 0i, true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int64(-kTwoTo50), false, false, ""}, - equalsTestCase{int64(-kTwoTo50 - 1), false, false, ""}, - equalsTestCase{float32(kExpected - (1 << 30)), false, false, ""}, - equalsTestCase{float64(kExpected - 0.25), false, false, ""}, - equalsTestCase{float64(kExpected + 0.25), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) LargeNegativeFloat64() { - const kExpected = -1 * (1 << 65) - matcher := Equals(float64(kExpected)) - ExpectEq("-3.6893488147419103e+19", matcher.Description()) - - floatExpected := float64(kExpected) - castedInt := int64(floatExpected) - - cases := []equalsTestCase{ - // Equal values of numeric type. - equalsTestCase{kExpected + 0i, true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{castedInt, false, false, ""}, - equalsTestCase{int64(0), false, false, ""}, - equalsTestCase{int64(math.MinInt64), false, false, ""}, - equalsTestCase{int64(math.MaxInt64), false, false, ""}, - equalsTestCase{float32(kExpected / 2), false, false, ""}, - equalsTestCase{float64(kExpected / 2), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) ZeroFloat64() { - matcher := Equals(float64(0)) - ExpectEq("0", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of zero. - equalsTestCase{0.0, true, false, ""}, - equalsTestCase{0 + 0i, true, false, ""}, - equalsTestCase{int(0), true, false, ""}, - equalsTestCase{int8(0), true, false, ""}, - equalsTestCase{int16(0), true, false, ""}, - equalsTestCase{int32(0), true, false, ""}, - equalsTestCase{int64(0), true, false, ""}, - equalsTestCase{uint(0), true, false, ""}, - equalsTestCase{uint8(0), true, false, ""}, - equalsTestCase{uint16(0), true, false, ""}, - equalsTestCase{uint32(0), true, false, ""}, - equalsTestCase{uint64(0), true, false, ""}, - equalsTestCase{float32(0), true, false, ""}, - equalsTestCase{float64(0), true, false, ""}, - equalsTestCase{complex64(0), true, false, ""}, - equalsTestCase{complex128(0), true, false, ""}, - equalsTestCase{interface{}(float32(0)), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int64(1), false, false, ""}, - equalsTestCase{int64(-1), false, false, ""}, - equalsTestCase{float32(1), false, false, ""}, - equalsTestCase{float32(-1), false, false, ""}, - equalsTestCase{complex128(0 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) PositiveIntegralFloat64() { - const kExpected = 1 << 50 - matcher := Equals(float64(kExpected)) - ExpectEq("1.125899906842624e+15", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of 32769. - equalsTestCase{1125899906842624.0, true, false, ""}, - equalsTestCase{1125899906842624.0 + 0i, true, false, ""}, - equalsTestCase{int64(kExpected), true, false, ""}, - equalsTestCase{uint64(kExpected), true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - equalsTestCase{interface{}(float64(kExpected)), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int64(kExpected + 1), false, false, ""}, - equalsTestCase{uint64(kExpected + 1), false, false, ""}, - equalsTestCase{float32(kExpected - (1 << 30)), false, false, ""}, - equalsTestCase{float32(kExpected + (1 << 30)), false, false, ""}, - equalsTestCase{float64(kExpected - 0.5), false, false, ""}, - equalsTestCase{float64(kExpected + 0.5), false, false, ""}, - equalsTestCase{complex128(kExpected - 1), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) PositiveNonIntegralFloat64() { - const kTwoTo50 = 1 << 50 - const kExpected = kTwoTo50 + 0.25 - matcher := Equals(float64(kExpected)) - ExpectEq("1.1258999068426242e+15", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of the expected value. - equalsTestCase{kExpected, true, false, ""}, - equalsTestCase{kExpected + 0i, true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int64(kTwoTo50), false, false, ""}, - equalsTestCase{int64(kTwoTo50 - 1), false, false, ""}, - equalsTestCase{float64(kExpected - 0.25), false, false, ""}, - equalsTestCase{float64(kExpected + 0.25), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) LargePositiveFloat64() { - const kExpected = 1 << 65 - matcher := Equals(float64(kExpected)) - ExpectEq("3.6893488147419103e+19", matcher.Description()) - - floatExpected := float64(kExpected) - castedInt := uint64(floatExpected) - - cases := []equalsTestCase{ - // Equal values of numeric type. - equalsTestCase{kExpected + 0i, true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{castedInt, false, false, ""}, - equalsTestCase{int64(0), false, false, ""}, - equalsTestCase{int64(math.MinInt64), false, false, ""}, - equalsTestCase{int64(math.MaxInt64), false, false, ""}, - equalsTestCase{uint64(0), false, false, ""}, - equalsTestCase{uint64(math.MaxUint64), false, false, ""}, - equalsTestCase{float32(kExpected / 2), false, false, ""}, - equalsTestCase{float64(kExpected / 2), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) Float64AboveExactIntegerRange() { - // Double-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo54 = 1 << 54 - matcher := Equals(float64(kTwoTo54 + 1)) - ExpectEq("1.8014398509481984e+16", matcher.Description()) - - cases := []equalsTestCase{ - // Integers. - equalsTestCase{int64(kTwoTo54 - 2), false, false, ""}, - equalsTestCase{int64(kTwoTo54 - 1), true, false, ""}, - equalsTestCase{int64(kTwoTo54 + 0), true, false, ""}, - equalsTestCase{int64(kTwoTo54 + 1), true, false, ""}, - equalsTestCase{int64(kTwoTo54 + 2), true, false, ""}, - equalsTestCase{int64(kTwoTo54 + 3), false, false, ""}, - - equalsTestCase{uint64(kTwoTo54 - 2), false, false, ""}, - equalsTestCase{uint64(kTwoTo54 - 1), true, false, ""}, - equalsTestCase{uint64(kTwoTo54 + 0), true, false, ""}, - equalsTestCase{uint64(kTwoTo54 + 1), true, false, ""}, - equalsTestCase{uint64(kTwoTo54 + 2), true, false, ""}, - equalsTestCase{uint64(kTwoTo54 + 3), false, false, ""}, - - // Double-precision floating point. - equalsTestCase{float64(kTwoTo54 - 2), false, false, ""}, - equalsTestCase{float64(kTwoTo54 - 1), true, false, ""}, - equalsTestCase{float64(kTwoTo54 + 0), true, false, ""}, - equalsTestCase{float64(kTwoTo54 + 1), true, false, ""}, - equalsTestCase{float64(kTwoTo54 + 2), true, false, ""}, - equalsTestCase{float64(kTwoTo54 + 3), false, false, ""}, - - equalsTestCase{complex128(kTwoTo54 - 2), false, false, ""}, - equalsTestCase{complex128(kTwoTo54 - 1), true, false, ""}, - equalsTestCase{complex128(kTwoTo54 + 0), true, false, ""}, - equalsTestCase{complex128(kTwoTo54 + 1), true, false, ""}, - equalsTestCase{complex128(kTwoTo54 + 2), true, false, ""}, - equalsTestCase{complex128(kTwoTo54 + 3), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// complex64 -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) NegativeIntegralComplex64() { - const kExpected = -32769 - matcher := Equals(complex64(kExpected)) - ExpectEq("(-32769+0i)", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of the expected value. - equalsTestCase{-32769.0, true, false, ""}, - equalsTestCase{-32769.0 + 0i, true, false, ""}, - equalsTestCase{int(kExpected), true, false, ""}, - equalsTestCase{int32(kExpected), true, false, ""}, - equalsTestCase{int64(kExpected), true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - equalsTestCase{interface{}(float64(kExpected)), true, false, ""}, - - // Values that would be kExpected in two's complement. - equalsTestCase{uint32((1 << 32) + kExpected), false, false, ""}, - equalsTestCase{uint64((1 << 64) + kExpected), false, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int64(kExpected + 1), false, false, ""}, - equalsTestCase{float32(kExpected - (1 << 30)), false, false, ""}, - equalsTestCase{float32(kExpected + (1 << 30)), false, false, ""}, - equalsTestCase{float64(kExpected - 0.5), false, false, ""}, - equalsTestCase{float64(kExpected + 0.5), false, false, ""}, - equalsTestCase{complex64(kExpected - 1), false, false, ""}, - equalsTestCase{complex64(kExpected + 2i), false, false, ""}, - equalsTestCase{complex128(kExpected - 1), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) NegativeNonIntegralComplex64() { - const kTwoTo20 = 1 << 20 - const kExpected = -kTwoTo20 - 0.25 - - matcher := Equals(complex64(kExpected)) - ExpectEq("(-1.0485762e+06+0i)", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of the expected value. - equalsTestCase{kExpected, true, false, ""}, - equalsTestCase{kExpected + 0i, true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int(-kTwoTo20), false, false, ""}, - equalsTestCase{int(-kTwoTo20 - 1), false, false, ""}, - equalsTestCase{int32(-kTwoTo20), false, false, ""}, - equalsTestCase{int32(-kTwoTo20 - 1), false, false, ""}, - equalsTestCase{int64(-kTwoTo20), false, false, ""}, - equalsTestCase{int64(-kTwoTo20 - 1), false, false, ""}, - equalsTestCase{float32(kExpected - (1 << 30)), false, false, ""}, - equalsTestCase{float64(kExpected - 0.25), false, false, ""}, - equalsTestCase{float64(kExpected + 0.25), false, false, ""}, - equalsTestCase{complex64(kExpected - 0.75), false, false, ""}, - equalsTestCase{complex64(kExpected + 2i), false, false, ""}, - equalsTestCase{complex128(kExpected - 0.75), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) LargeNegativeComplex64() { - const kExpected = -1 * (1 << 65) - matcher := Equals(complex64(kExpected)) - ExpectEq("(-3.689349e+19+0i)", matcher.Description()) - - floatExpected := float64(kExpected) - castedInt := int64(floatExpected) - - cases := []equalsTestCase{ - // Equal values of numeric type. - equalsTestCase{kExpected + 0i, true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{castedInt, false, false, ""}, - equalsTestCase{int64(0), false, false, ""}, - equalsTestCase{int64(math.MinInt64), false, false, ""}, - equalsTestCase{int64(math.MaxInt64), false, false, ""}, - equalsTestCase{float32(kExpected / 2), false, false, ""}, - equalsTestCase{float64(kExpected / 2), false, false, ""}, - equalsTestCase{complex64(kExpected + 2i), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) ZeroComplex64() { - matcher := Equals(complex64(0)) - ExpectEq("(0+0i)", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of zero. - equalsTestCase{0.0, true, false, ""}, - equalsTestCase{0 + 0i, true, false, ""}, - equalsTestCase{int(0), true, false, ""}, - equalsTestCase{int8(0), true, false, ""}, - equalsTestCase{int16(0), true, false, ""}, - equalsTestCase{int32(0), true, false, ""}, - equalsTestCase{int64(0), true, false, ""}, - equalsTestCase{uint(0), true, false, ""}, - equalsTestCase{uint8(0), true, false, ""}, - equalsTestCase{uint16(0), true, false, ""}, - equalsTestCase{uint32(0), true, false, ""}, - equalsTestCase{uint64(0), true, false, ""}, - equalsTestCase{float32(0), true, false, ""}, - equalsTestCase{float64(0), true, false, ""}, - equalsTestCase{complex64(0), true, false, ""}, - equalsTestCase{complex128(0), true, false, ""}, - equalsTestCase{interface{}(float32(0)), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int64(1), false, false, ""}, - equalsTestCase{int64(-1), false, false, ""}, - equalsTestCase{float32(1), false, false, ""}, - equalsTestCase{float32(-1), false, false, ""}, - equalsTestCase{float64(1), false, false, ""}, - equalsTestCase{float64(-1), false, false, ""}, - equalsTestCase{complex64(0 + 2i), false, false, ""}, - equalsTestCase{complex128(0 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) PositiveIntegralComplex64() { - const kExpected = 1 << 20 - matcher := Equals(complex64(kExpected)) - ExpectEq("(1.048576e+06+0i)", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of 32769. - equalsTestCase{1048576.0, true, false, ""}, - equalsTestCase{1048576.0 + 0i, true, false, ""}, - equalsTestCase{int(kExpected), true, false, ""}, - equalsTestCase{int32(kExpected), true, false, ""}, - equalsTestCase{int64(kExpected), true, false, ""}, - equalsTestCase{uint(kExpected), true, false, ""}, - equalsTestCase{uint32(kExpected), true, false, ""}, - equalsTestCase{uint64(kExpected), true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - equalsTestCase{interface{}(float64(kExpected)), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int(kExpected + 1), false, false, ""}, - equalsTestCase{int32(kExpected + 1), false, false, ""}, - equalsTestCase{int64(kExpected + 1), false, false, ""}, - equalsTestCase{uint(kExpected + 1), false, false, ""}, - equalsTestCase{uint32(kExpected + 1), false, false, ""}, - equalsTestCase{uint64(kExpected + 1), false, false, ""}, - equalsTestCase{float32(kExpected - (1 << 30)), false, false, ""}, - equalsTestCase{float32(kExpected + (1 << 30)), false, false, ""}, - equalsTestCase{float64(kExpected - 0.5), false, false, ""}, - equalsTestCase{float64(kExpected + 0.5), false, false, ""}, - equalsTestCase{complex128(kExpected - 1), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) PositiveNonIntegralComplex64() { - const kTwoTo20 = 1 << 20 - const kExpected = kTwoTo20 + 0.25 - matcher := Equals(complex64(kExpected)) - ExpectEq("(1.0485762e+06+0i)", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of the expected value. - equalsTestCase{kExpected, true, false, ""}, - equalsTestCase{kExpected + 0i, true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int64(kTwoTo20), false, false, ""}, - equalsTestCase{int64(kTwoTo20 - 1), false, false, ""}, - equalsTestCase{uint64(kTwoTo20), false, false, ""}, - equalsTestCase{uint64(kTwoTo20 - 1), false, false, ""}, - equalsTestCase{float32(kExpected - 1), false, false, ""}, - equalsTestCase{float32(kExpected + 1), false, false, ""}, - equalsTestCase{float64(kExpected - 0.25), false, false, ""}, - equalsTestCase{float64(kExpected + 0.25), false, false, ""}, - equalsTestCase{complex64(kExpected - 1), false, false, ""}, - equalsTestCase{complex64(kExpected - 1i), false, false, ""}, - equalsTestCase{complex128(kExpected - 1), false, false, ""}, - equalsTestCase{complex128(kExpected - 1i), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) LargePositiveComplex64() { - const kExpected = 1 << 65 - matcher := Equals(complex64(kExpected)) - ExpectEq("(3.689349e+19+0i)", matcher.Description()) - - floatExpected := float64(kExpected) - castedInt := uint64(floatExpected) - - cases := []equalsTestCase{ - // Equal values of numeric type. - equalsTestCase{kExpected + 0i, true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{castedInt, false, false, ""}, - equalsTestCase{int64(0), false, false, ""}, - equalsTestCase{int64(math.MinInt64), false, false, ""}, - equalsTestCase{int64(math.MaxInt64), false, false, ""}, - equalsTestCase{uint64(0), false, false, ""}, - equalsTestCase{uint64(math.MaxUint64), false, false, ""}, - equalsTestCase{float32(kExpected / 2), false, false, ""}, - equalsTestCase{float64(kExpected / 2), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) Complex64AboveExactIntegerRange() { - // Single-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo25 = 1 << 25 - matcher := Equals(complex64(kTwoTo25 + 1)) - ExpectEq("(3.3554432e+07+0i)", matcher.Description()) - - cases := []equalsTestCase{ - // Integers. - equalsTestCase{int64(kTwoTo25 - 2), false, false, ""}, - equalsTestCase{int64(kTwoTo25 - 1), true, false, ""}, - equalsTestCase{int64(kTwoTo25 + 0), true, false, ""}, - equalsTestCase{int64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{int64(kTwoTo25 + 2), true, false, ""}, - equalsTestCase{int64(kTwoTo25 + 3), false, false, ""}, - - equalsTestCase{uint64(kTwoTo25 - 2), false, false, ""}, - equalsTestCase{uint64(kTwoTo25 - 1), true, false, ""}, - equalsTestCase{uint64(kTwoTo25 + 0), true, false, ""}, - equalsTestCase{uint64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{uint64(kTwoTo25 + 2), true, false, ""}, - equalsTestCase{uint64(kTwoTo25 + 3), false, false, ""}, - - // Single-precision floating point. - equalsTestCase{float32(kTwoTo25 - 2), false, false, ""}, - equalsTestCase{float32(kTwoTo25 - 1), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 0), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 2), true, false, ""}, - equalsTestCase{float32(kTwoTo25 + 3), false, false, ""}, - - equalsTestCase{complex64(kTwoTo25 - 2), false, false, ""}, - equalsTestCase{complex64(kTwoTo25 - 1), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 0), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 2), true, false, ""}, - equalsTestCase{complex64(kTwoTo25 + 3), false, false, ""}, - - // Double-precision floating point. - equalsTestCase{float64(kTwoTo25 - 2), false, false, ""}, - equalsTestCase{float64(kTwoTo25 - 1), true, false, ""}, - equalsTestCase{float64(kTwoTo25 + 0), true, false, ""}, - equalsTestCase{float64(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{float64(kTwoTo25 + 2), true, false, ""}, - equalsTestCase{float64(kTwoTo25 + 3), false, false, ""}, - - equalsTestCase{complex128(kTwoTo25 - 2), false, false, ""}, - equalsTestCase{complex128(kTwoTo25 - 1), true, false, ""}, - equalsTestCase{complex128(kTwoTo25 + 0), true, false, ""}, - equalsTestCase{complex128(kTwoTo25 + 1), true, false, ""}, - equalsTestCase{complex128(kTwoTo25 + 2), true, false, ""}, - equalsTestCase{complex128(kTwoTo25 + 3), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) Complex64WithNonZeroImaginaryPart() { - const kRealPart = 17 - const kImagPart = 0.25i - const kExpected = kRealPart + kImagPart - matcher := Equals(complex64(kExpected)) - ExpectEq("(17+0.25i)", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of the expected value. - equalsTestCase{kExpected, true, false, ""}, - equalsTestCase{kRealPart + kImagPart, true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int(kRealPart), false, false, ""}, - equalsTestCase{int8(kRealPart), false, false, ""}, - equalsTestCase{int16(kRealPart), false, false, ""}, - equalsTestCase{int32(kRealPart), false, false, ""}, - equalsTestCase{int64(kRealPart), false, false, ""}, - equalsTestCase{uint(kRealPart), false, false, ""}, - equalsTestCase{uint8(kRealPart), false, false, ""}, - equalsTestCase{uint16(kRealPart), false, false, ""}, - equalsTestCase{uint32(kRealPart), false, false, ""}, - equalsTestCase{uint64(kRealPart), false, false, ""}, - equalsTestCase{float32(kRealPart), false, false, ""}, - equalsTestCase{float64(kRealPart), false, false, ""}, - equalsTestCase{complex64(kRealPart), false, false, ""}, - equalsTestCase{complex64(kRealPart + kImagPart + 0.5), false, false, ""}, - equalsTestCase{complex64(kRealPart + kImagPart + 0.5i), false, false, ""}, - equalsTestCase{complex128(kRealPart), false, false, ""}, - equalsTestCase{complex128(kRealPart + kImagPart + 0.5), false, false, ""}, - equalsTestCase{complex128(kRealPart + kImagPart + 0.5i), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// complex128 -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) NegativeIntegralComplex128() { - const kExpected = -32769 - matcher := Equals(complex128(kExpected)) - ExpectEq("(-32769+0i)", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of the expected value. - equalsTestCase{-32769.0, true, false, ""}, - equalsTestCase{-32769.0 + 0i, true, false, ""}, - equalsTestCase{int(kExpected), true, false, ""}, - equalsTestCase{int32(kExpected), true, false, ""}, - equalsTestCase{int64(kExpected), true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - equalsTestCase{interface{}(float64(kExpected)), true, false, ""}, - - // Values that would be kExpected in two's complement. - equalsTestCase{uint32((1 << 32) + kExpected), false, false, ""}, - equalsTestCase{uint64((1 << 64) + kExpected), false, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int64(kExpected + 1), false, false, ""}, - equalsTestCase{float32(kExpected - (1 << 30)), false, false, ""}, - equalsTestCase{float32(kExpected + (1 << 30)), false, false, ""}, - equalsTestCase{float64(kExpected - 0.5), false, false, ""}, - equalsTestCase{float64(kExpected + 0.5), false, false, ""}, - equalsTestCase{complex64(kExpected - 1), false, false, ""}, - equalsTestCase{complex64(kExpected + 2i), false, false, ""}, - equalsTestCase{complex128(kExpected - 1), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) NegativeNonIntegralComplex128() { - const kTwoTo20 = 1 << 20 - const kExpected = -kTwoTo20 - 0.25 - - matcher := Equals(complex128(kExpected)) - ExpectEq("(-1.04857625e+06+0i)", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of the expected value. - equalsTestCase{kExpected, true, false, ""}, - equalsTestCase{kExpected + 0i, true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int(-kTwoTo20), false, false, ""}, - equalsTestCase{int(-kTwoTo20 - 1), false, false, ""}, - equalsTestCase{int32(-kTwoTo20), false, false, ""}, - equalsTestCase{int32(-kTwoTo20 - 1), false, false, ""}, - equalsTestCase{int64(-kTwoTo20), false, false, ""}, - equalsTestCase{int64(-kTwoTo20 - 1), false, false, ""}, - equalsTestCase{float32(kExpected - (1 << 30)), false, false, ""}, - equalsTestCase{float64(kExpected - 0.25), false, false, ""}, - equalsTestCase{float64(kExpected + 0.25), false, false, ""}, - equalsTestCase{complex64(kExpected - 0.75), false, false, ""}, - equalsTestCase{complex64(kExpected + 2i), false, false, ""}, - equalsTestCase{complex128(kExpected - 0.75), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) LargeNegativeComplex128() { - const kExpected = -1 * (1 << 65) - matcher := Equals(complex128(kExpected)) - ExpectEq("(-3.6893488147419103e+19+0i)", matcher.Description()) - - floatExpected := float64(kExpected) - castedInt := int64(floatExpected) - - cases := []equalsTestCase{ - // Equal values of numeric type. - equalsTestCase{kExpected + 0i, true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{castedInt, false, false, ""}, - equalsTestCase{int64(0), false, false, ""}, - equalsTestCase{int64(math.MinInt64), false, false, ""}, - equalsTestCase{int64(math.MaxInt64), false, false, ""}, - equalsTestCase{float32(kExpected / 2), false, false, ""}, - equalsTestCase{float64(kExpected / 2), false, false, ""}, - equalsTestCase{complex64(kExpected + 2i), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) ZeroComplex128() { - matcher := Equals(complex128(0)) - ExpectEq("(0+0i)", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of zero. - equalsTestCase{0.0, true, false, ""}, - equalsTestCase{0 + 0i, true, false, ""}, - equalsTestCase{int(0), true, false, ""}, - equalsTestCase{int8(0), true, false, ""}, - equalsTestCase{int16(0), true, false, ""}, - equalsTestCase{int32(0), true, false, ""}, - equalsTestCase{int64(0), true, false, ""}, - equalsTestCase{uint(0), true, false, ""}, - equalsTestCase{uint8(0), true, false, ""}, - equalsTestCase{uint16(0), true, false, ""}, - equalsTestCase{uint32(0), true, false, ""}, - equalsTestCase{uint64(0), true, false, ""}, - equalsTestCase{float32(0), true, false, ""}, - equalsTestCase{float64(0), true, false, ""}, - equalsTestCase{complex64(0), true, false, ""}, - equalsTestCase{complex128(0), true, false, ""}, - equalsTestCase{interface{}(float32(0)), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int64(1), false, false, ""}, - equalsTestCase{int64(-1), false, false, ""}, - equalsTestCase{float32(1), false, false, ""}, - equalsTestCase{float32(-1), false, false, ""}, - equalsTestCase{float64(1), false, false, ""}, - equalsTestCase{float64(-1), false, false, ""}, - equalsTestCase{complex64(0 + 2i), false, false, ""}, - equalsTestCase{complex128(0 + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) PositiveIntegralComplex128() { - const kExpected = 1 << 20 - matcher := Equals(complex128(kExpected)) - ExpectEq("(1.048576e+06+0i)", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of 32769. - equalsTestCase{1048576.0, true, false, ""}, - equalsTestCase{1048576.0 + 0i, true, false, ""}, - equalsTestCase{int(kExpected), true, false, ""}, - equalsTestCase{int32(kExpected), true, false, ""}, - equalsTestCase{int64(kExpected), true, false, ""}, - equalsTestCase{uint(kExpected), true, false, ""}, - equalsTestCase{uint32(kExpected), true, false, ""}, - equalsTestCase{uint64(kExpected), true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - equalsTestCase{interface{}(float64(kExpected)), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int(kExpected + 1), false, false, ""}, - equalsTestCase{int32(kExpected + 1), false, false, ""}, - equalsTestCase{int64(kExpected + 1), false, false, ""}, - equalsTestCase{uint(kExpected + 1), false, false, ""}, - equalsTestCase{uint32(kExpected + 1), false, false, ""}, - equalsTestCase{uint64(kExpected + 1), false, false, ""}, - equalsTestCase{float32(kExpected - (1 << 30)), false, false, ""}, - equalsTestCase{float32(kExpected + (1 << 30)), false, false, ""}, - equalsTestCase{float64(kExpected - 0.5), false, false, ""}, - equalsTestCase{float64(kExpected + 0.5), false, false, ""}, - equalsTestCase{complex128(kExpected - 1), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - - // Non-numeric types. - equalsTestCase{uintptr(0), false, true, "which is not numeric"}, - equalsTestCase{true, false, true, "which is not numeric"}, - equalsTestCase{[...]int{}, false, true, "which is not numeric"}, - equalsTestCase{make(chan int), false, true, "which is not numeric"}, - equalsTestCase{func() {}, false, true, "which is not numeric"}, - equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, - equalsTestCase{&someInt, false, true, "which is not numeric"}, - equalsTestCase{[]int{}, false, true, "which is not numeric"}, - equalsTestCase{"taco", false, true, "which is not numeric"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) PositiveNonIntegralComplex128() { - const kTwoTo20 = 1 << 20 - const kExpected = kTwoTo20 + 0.25 - matcher := Equals(complex128(kExpected)) - ExpectEq("(1.04857625e+06+0i)", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of the expected value. - equalsTestCase{kExpected, true, false, ""}, - equalsTestCase{kExpected + 0i, true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int64(kTwoTo20), false, false, ""}, - equalsTestCase{int64(kTwoTo20 - 1), false, false, ""}, - equalsTestCase{uint64(kTwoTo20), false, false, ""}, - equalsTestCase{uint64(kTwoTo20 - 1), false, false, ""}, - equalsTestCase{float32(kExpected - 1), false, false, ""}, - equalsTestCase{float32(kExpected + 1), false, false, ""}, - equalsTestCase{float64(kExpected - 0.25), false, false, ""}, - equalsTestCase{float64(kExpected + 0.25), false, false, ""}, - equalsTestCase{complex64(kExpected - 1), false, false, ""}, - equalsTestCase{complex64(kExpected - 1i), false, false, ""}, - equalsTestCase{complex128(kExpected - 1), false, false, ""}, - equalsTestCase{complex128(kExpected - 1i), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) LargePositiveComplex128() { - const kExpected = 1 << 65 - matcher := Equals(complex128(kExpected)) - ExpectEq("(3.6893488147419103e+19+0i)", matcher.Description()) - - floatExpected := float64(kExpected) - castedInt := uint64(floatExpected) - - cases := []equalsTestCase{ - // Equal values of numeric type. - equalsTestCase{kExpected + 0i, true, false, ""}, - equalsTestCase{float32(kExpected), true, false, ""}, - equalsTestCase{float64(kExpected), true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{castedInt, false, false, ""}, - equalsTestCase{int64(0), false, false, ""}, - equalsTestCase{int64(math.MinInt64), false, false, ""}, - equalsTestCase{int64(math.MaxInt64), false, false, ""}, - equalsTestCase{uint64(0), false, false, ""}, - equalsTestCase{uint64(math.MaxUint64), false, false, ""}, - equalsTestCase{float32(kExpected / 2), false, false, ""}, - equalsTestCase{float64(kExpected / 2), false, false, ""}, - equalsTestCase{complex128(kExpected + 2i), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) Complex128AboveExactIntegerRange() { - // Double-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo54 = 1 << 54 - matcher := Equals(complex128(kTwoTo54 + 1)) - ExpectEq("(1.8014398509481984e+16+0i)", matcher.Description()) - - cases := []equalsTestCase{ - // Integers. - equalsTestCase{int64(kTwoTo54 - 2), false, false, ""}, - equalsTestCase{int64(kTwoTo54 - 1), true, false, ""}, - equalsTestCase{int64(kTwoTo54 + 0), true, false, ""}, - equalsTestCase{int64(kTwoTo54 + 1), true, false, ""}, - equalsTestCase{int64(kTwoTo54 + 2), true, false, ""}, - equalsTestCase{int64(kTwoTo54 + 3), false, false, ""}, - - equalsTestCase{uint64(kTwoTo54 - 2), false, false, ""}, - equalsTestCase{uint64(kTwoTo54 - 1), true, false, ""}, - equalsTestCase{uint64(kTwoTo54 + 0), true, false, ""}, - equalsTestCase{uint64(kTwoTo54 + 1), true, false, ""}, - equalsTestCase{uint64(kTwoTo54 + 2), true, false, ""}, - equalsTestCase{uint64(kTwoTo54 + 3), false, false, ""}, - - // Double-precision floating point. - equalsTestCase{float64(kTwoTo54 - 2), false, false, ""}, - equalsTestCase{float64(kTwoTo54 - 1), true, false, ""}, - equalsTestCase{float64(kTwoTo54 + 0), true, false, ""}, - equalsTestCase{float64(kTwoTo54 + 1), true, false, ""}, - equalsTestCase{float64(kTwoTo54 + 2), true, false, ""}, - equalsTestCase{float64(kTwoTo54 + 3), false, false, ""}, - - equalsTestCase{complex128(kTwoTo54 - 2), false, false, ""}, - equalsTestCase{complex128(kTwoTo54 - 1), true, false, ""}, - equalsTestCase{complex128(kTwoTo54 + 0), true, false, ""}, - equalsTestCase{complex128(kTwoTo54 + 1), true, false, ""}, - equalsTestCase{complex128(kTwoTo54 + 2), true, false, ""}, - equalsTestCase{complex128(kTwoTo54 + 3), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) Complex128WithNonZeroImaginaryPart() { - const kRealPart = 17 - const kImagPart = 0.25i - const kExpected = kRealPart + kImagPart - matcher := Equals(complex128(kExpected)) - ExpectEq("(17+0.25i)", matcher.Description()) - - cases := []equalsTestCase{ - // Various types of the expected value. - equalsTestCase{kExpected, true, false, ""}, - equalsTestCase{kRealPart + kImagPart, true, false, ""}, - equalsTestCase{complex64(kExpected), true, false, ""}, - equalsTestCase{complex128(kExpected), true, false, ""}, - - // Non-equal values of numeric type. - equalsTestCase{int(kRealPart), false, false, ""}, - equalsTestCase{int8(kRealPart), false, false, ""}, - equalsTestCase{int16(kRealPart), false, false, ""}, - equalsTestCase{int32(kRealPart), false, false, ""}, - equalsTestCase{int64(kRealPart), false, false, ""}, - equalsTestCase{uint(kRealPart), false, false, ""}, - equalsTestCase{uint8(kRealPart), false, false, ""}, - equalsTestCase{uint16(kRealPart), false, false, ""}, - equalsTestCase{uint32(kRealPart), false, false, ""}, - equalsTestCase{uint64(kRealPart), false, false, ""}, - equalsTestCase{float32(kRealPart), false, false, ""}, - equalsTestCase{float64(kRealPart), false, false, ""}, - equalsTestCase{complex64(kRealPart), false, false, ""}, - equalsTestCase{complex64(kRealPart + kImagPart + 0.5), false, false, ""}, - equalsTestCase{complex64(kRealPart + kImagPart + 0.5i), false, false, ""}, - equalsTestCase{complex128(kRealPart), false, false, ""}, - equalsTestCase{complex128(kRealPart + kImagPart + 0.5), false, false, ""}, - equalsTestCase{complex128(kRealPart + kImagPart + 0.5i), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// array -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) Array() { - var someArray [3]int - f := func() { Equals(someArray) } - ExpectThat(f, Panics(HasSubstr("unsupported kind array"))) -} - -//////////////////////////////////////////////////////////////////////// -// chan -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) NilChan() { - var nilChan1 chan int - var nilChan2 chan int - var nilChan3 chan uint - var nonNilChan1 chan int = make(chan int) - var nonNilChan2 chan uint = make(chan uint) - - matcher := Equals(nilChan1) - ExpectEq("", matcher.Description()) - - cases := []equalsTestCase{ - // int channels - equalsTestCase{nilChan1, true, false, ""}, - equalsTestCase{nilChan2, true, false, ""}, - equalsTestCase{nonNilChan1, false, false, ""}, - - // uint channels - equalsTestCase{nilChan3, false, true, "which is not a chan int"}, - equalsTestCase{nonNilChan2, false, true, "which is not a chan int"}, - - // Other types. - equalsTestCase{0, false, true, "which is not a chan int"}, - equalsTestCase{bool(false), false, true, "which is not a chan int"}, - equalsTestCase{int(0), false, true, "which is not a chan int"}, - equalsTestCase{int8(0), false, true, "which is not a chan int"}, - equalsTestCase{int16(0), false, true, "which is not a chan int"}, - equalsTestCase{int32(0), false, true, "which is not a chan int"}, - equalsTestCase{int64(0), false, true, "which is not a chan int"}, - equalsTestCase{uint(0), false, true, "which is not a chan int"}, - equalsTestCase{uint8(0), false, true, "which is not a chan int"}, - equalsTestCase{uint16(0), false, true, "which is not a chan int"}, - equalsTestCase{uint32(0), false, true, "which is not a chan int"}, - equalsTestCase{uint64(0), false, true, "which is not a chan int"}, - equalsTestCase{true, false, true, "which is not a chan int"}, - equalsTestCase{[...]int{}, false, true, "which is not a chan int"}, - equalsTestCase{func() {}, false, true, "which is not a chan int"}, - equalsTestCase{map[int]int{}, false, true, "which is not a chan int"}, - equalsTestCase{&someInt, false, true, "which is not a chan int"}, - equalsTestCase{[]int{}, false, true, "which is not a chan int"}, - equalsTestCase{"taco", false, true, "which is not a chan int"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not a chan int"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) NonNilChan() { - var nilChan1 chan int - var nilChan2 chan uint - var nonNilChan1 chan int = make(chan int) - var nonNilChan2 chan int = make(chan int) - var nonNilChan3 chan uint = make(chan uint) - - matcher := Equals(nonNilChan1) - ExpectEq(fmt.Sprintf("%v", nonNilChan1), matcher.Description()) - - cases := []equalsTestCase{ - // int channels - equalsTestCase{nonNilChan1, true, false, ""}, - equalsTestCase{nonNilChan2, false, false, ""}, - equalsTestCase{nilChan1, false, false, ""}, - - // uint channels - equalsTestCase{nilChan2, false, true, "which is not a chan int"}, - equalsTestCase{nonNilChan3, false, true, "which is not a chan int"}, - - // Other types. - equalsTestCase{0, false, true, "which is not a chan int"}, - equalsTestCase{bool(false), false, true, "which is not a chan int"}, - equalsTestCase{int(0), false, true, "which is not a chan int"}, - equalsTestCase{int8(0), false, true, "which is not a chan int"}, - equalsTestCase{int16(0), false, true, "which is not a chan int"}, - equalsTestCase{int32(0), false, true, "which is not a chan int"}, - equalsTestCase{int64(0), false, true, "which is not a chan int"}, - equalsTestCase{uint(0), false, true, "which is not a chan int"}, - equalsTestCase{uint8(0), false, true, "which is not a chan int"}, - equalsTestCase{uint16(0), false, true, "which is not a chan int"}, - equalsTestCase{uint32(0), false, true, "which is not a chan int"}, - equalsTestCase{uint64(0), false, true, "which is not a chan int"}, - equalsTestCase{true, false, true, "which is not a chan int"}, - equalsTestCase{[...]int{}, false, true, "which is not a chan int"}, - equalsTestCase{func() {}, false, true, "which is not a chan int"}, - equalsTestCase{map[int]int{}, false, true, "which is not a chan int"}, - equalsTestCase{&someInt, false, true, "which is not a chan int"}, - equalsTestCase{[]int{}, false, true, "which is not a chan int"}, - equalsTestCase{"taco", false, true, "which is not a chan int"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not a chan int"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) ChanDirection() { - var chan1 chan<- int - var chan2 <-chan int - var chan3 chan int - - matcher := Equals(chan1) - ExpectEq(fmt.Sprintf("%v", chan1), matcher.Description()) - - cases := []equalsTestCase{ - equalsTestCase{chan1, true, false, ""}, - equalsTestCase{chan2, false, true, "which is not a chan<- int"}, - equalsTestCase{chan3, false, true, "which is not a chan<- int"}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// func -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) Functions() { - func1 := func() {} - func2 := func() {} - func3 := func(x int) {} - - matcher := Equals(func1) - ExpectEq(fmt.Sprintf("%v", func1), matcher.Description()) - - cases := []equalsTestCase{ - // Functions. - equalsTestCase{func1, true, false, ""}, - equalsTestCase{func2, false, false, ""}, - equalsTestCase{func3, false, false, ""}, - - // Other types. - equalsTestCase{0, false, true, "which is not a function"}, - equalsTestCase{bool(false), false, true, "which is not a function"}, - equalsTestCase{int(0), false, true, "which is not a function"}, - equalsTestCase{int8(0), false, true, "which is not a function"}, - equalsTestCase{int16(0), false, true, "which is not a function"}, - equalsTestCase{int32(0), false, true, "which is not a function"}, - equalsTestCase{int64(0), false, true, "which is not a function"}, - equalsTestCase{uint(0), false, true, "which is not a function"}, - equalsTestCase{uint8(0), false, true, "which is not a function"}, - equalsTestCase{uint16(0), false, true, "which is not a function"}, - equalsTestCase{uint32(0), false, true, "which is not a function"}, - equalsTestCase{uint64(0), false, true, "which is not a function"}, - equalsTestCase{true, false, true, "which is not a function"}, - equalsTestCase{[...]int{}, false, true, "which is not a function"}, - equalsTestCase{map[int]int{}, false, true, "which is not a function"}, - equalsTestCase{&someInt, false, true, "which is not a function"}, - equalsTestCase{[]int{}, false, true, "which is not a function"}, - equalsTestCase{"taco", false, true, "which is not a function"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not a function"}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// map -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) NilMap() { - var nilMap1 map[int]int - var nilMap2 map[int]int - var nilMap3 map[int]uint - var nonNilMap1 map[int]int = make(map[int]int) - var nonNilMap2 map[int]uint = make(map[int]uint) - - matcher := Equals(nilMap1) - ExpectEq("map[]", matcher.Description()) - - cases := []equalsTestCase{ - // Correct type. - equalsTestCase{nilMap1, true, false, ""}, - equalsTestCase{nilMap2, true, false, ""}, - equalsTestCase{nilMap3, true, false, ""}, - equalsTestCase{nonNilMap1, false, false, ""}, - equalsTestCase{nonNilMap2, false, false, ""}, - - // Other types. - equalsTestCase{0, false, true, "which is not a map"}, - equalsTestCase{bool(false), false, true, "which is not a map"}, - equalsTestCase{int(0), false, true, "which is not a map"}, - equalsTestCase{int8(0), false, true, "which is not a map"}, - equalsTestCase{int16(0), false, true, "which is not a map"}, - equalsTestCase{int32(0), false, true, "which is not a map"}, - equalsTestCase{int64(0), false, true, "which is not a map"}, - equalsTestCase{uint(0), false, true, "which is not a map"}, - equalsTestCase{uint8(0), false, true, "which is not a map"}, - equalsTestCase{uint16(0), false, true, "which is not a map"}, - equalsTestCase{uint32(0), false, true, "which is not a map"}, - equalsTestCase{uint64(0), false, true, "which is not a map"}, - equalsTestCase{true, false, true, "which is not a map"}, - equalsTestCase{[...]int{}, false, true, "which is not a map"}, - equalsTestCase{func() {}, false, true, "which is not a map"}, - equalsTestCase{&someInt, false, true, "which is not a map"}, - equalsTestCase{[]int{}, false, true, "which is not a map"}, - equalsTestCase{"taco", false, true, "which is not a map"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not a map"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) NonNilMap() { - var nilMap1 map[int]int - var nilMap2 map[int]uint - var nonNilMap1 map[int]int = make(map[int]int) - var nonNilMap2 map[int]int = make(map[int]int) - var nonNilMap3 map[int]uint = make(map[int]uint) - - matcher := Equals(nonNilMap1) - ExpectEq("map[]", matcher.Description()) - - cases := []equalsTestCase{ - // Correct type. - equalsTestCase{nonNilMap1, true, false, ""}, - equalsTestCase{nonNilMap2, false, false, ""}, - equalsTestCase{nonNilMap3, false, false, ""}, - equalsTestCase{nilMap1, false, false, ""}, - equalsTestCase{nilMap2, false, false, ""}, - - // Other types. - equalsTestCase{0, false, true, "which is not a map"}, - equalsTestCase{bool(false), false, true, "which is not a map"}, - equalsTestCase{int(0), false, true, "which is not a map"}, - equalsTestCase{int8(0), false, true, "which is not a map"}, - equalsTestCase{int16(0), false, true, "which is not a map"}, - equalsTestCase{int32(0), false, true, "which is not a map"}, - equalsTestCase{int64(0), false, true, "which is not a map"}, - equalsTestCase{uint(0), false, true, "which is not a map"}, - equalsTestCase{uint8(0), false, true, "which is not a map"}, - equalsTestCase{uint16(0), false, true, "which is not a map"}, - equalsTestCase{uint32(0), false, true, "which is not a map"}, - equalsTestCase{uint64(0), false, true, "which is not a map"}, - equalsTestCase{true, false, true, "which is not a map"}, - equalsTestCase{[...]int{}, false, true, "which is not a map"}, - equalsTestCase{func() {}, false, true, "which is not a map"}, - equalsTestCase{&someInt, false, true, "which is not a map"}, - equalsTestCase{[]int{}, false, true, "which is not a map"}, - equalsTestCase{"taco", false, true, "which is not a map"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not a map"}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// Pointers -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) NilPointer() { - var someInt int = 17 - var someUint uint = 17 - - var nilInt1 *int - var nilInt2 *int - var nilUint *uint - var nonNilInt *int = &someInt - var nonNilUint *uint = &someUint - - matcher := Equals(nilInt1) - ExpectEq("", matcher.Description()) - - cases := []equalsTestCase{ - // Correct type. - equalsTestCase{nilInt1, true, false, ""}, - equalsTestCase{nilInt2, true, false, ""}, - equalsTestCase{nonNilInt, false, false, ""}, - - // Incorrect type. - equalsTestCase{nilUint, false, true, "which is not a *int"}, - equalsTestCase{nonNilUint, false, true, "which is not a *int"}, - - // Other types. - equalsTestCase{0, false, true, "which is not a *int"}, - equalsTestCase{bool(false), false, true, "which is not a *int"}, - equalsTestCase{int(0), false, true, "which is not a *int"}, - equalsTestCase{int8(0), false, true, "which is not a *int"}, - equalsTestCase{int16(0), false, true, "which is not a *int"}, - equalsTestCase{int32(0), false, true, "which is not a *int"}, - equalsTestCase{int64(0), false, true, "which is not a *int"}, - equalsTestCase{uint(0), false, true, "which is not a *int"}, - equalsTestCase{uint8(0), false, true, "which is not a *int"}, - equalsTestCase{uint16(0), false, true, "which is not a *int"}, - equalsTestCase{uint32(0), false, true, "which is not a *int"}, - equalsTestCase{uint64(0), false, true, "which is not a *int"}, - equalsTestCase{true, false, true, "which is not a *int"}, - equalsTestCase{[...]int{}, false, true, "which is not a *int"}, - equalsTestCase{func() {}, false, true, "which is not a *int"}, - equalsTestCase{map[int]int{}, false, true, "which is not a *int"}, - equalsTestCase{[]int{}, false, true, "which is not a *int"}, - equalsTestCase{"taco", false, true, "which is not a *int"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not a *int"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) NonNilPointer() { - var someInt int = 17 - var someOtherInt int = 17 - var someUint uint = 17 - - var nilInt *int - var nilUint *uint - var nonNilInt1 *int = &someInt - var nonNilInt2 *int = &someOtherInt - var nonNilUint *uint = &someUint - - matcher := Equals(nonNilInt1) - ExpectEq(fmt.Sprintf("%v", nonNilInt1), matcher.Description()) - - cases := []equalsTestCase{ - // Correct type. - equalsTestCase{nonNilInt1, true, false, ""}, - equalsTestCase{nonNilInt2, false, false, ""}, - equalsTestCase{nilInt, false, false, ""}, - - // Incorrect type. - equalsTestCase{nilUint, false, true, "which is not a *int"}, - equalsTestCase{nonNilUint, false, true, "which is not a *int"}, - - // Other types. - equalsTestCase{0, false, true, "which is not a *int"}, - equalsTestCase{bool(false), false, true, "which is not a *int"}, - equalsTestCase{int(0), false, true, "which is not a *int"}, - equalsTestCase{int8(0), false, true, "which is not a *int"}, - equalsTestCase{int16(0), false, true, "which is not a *int"}, - equalsTestCase{int32(0), false, true, "which is not a *int"}, - equalsTestCase{int64(0), false, true, "which is not a *int"}, - equalsTestCase{uint(0), false, true, "which is not a *int"}, - equalsTestCase{uint8(0), false, true, "which is not a *int"}, - equalsTestCase{uint16(0), false, true, "which is not a *int"}, - equalsTestCase{uint32(0), false, true, "which is not a *int"}, - equalsTestCase{uint64(0), false, true, "which is not a *int"}, - equalsTestCase{true, false, true, "which is not a *int"}, - equalsTestCase{[...]int{}, false, true, "which is not a *int"}, - equalsTestCase{func() {}, false, true, "which is not a *int"}, - equalsTestCase{map[int]int{}, false, true, "which is not a *int"}, - equalsTestCase{[]int{}, false, true, "which is not a *int"}, - equalsTestCase{"taco", false, true, "which is not a *int"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not a *int"}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// Slices -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) NilSlice() { - var nilInt1 []int - var nilInt2 []int - var nilUint []uint - - var nonNilInt []int = make([]int, 0) - var nonNilUint []uint = make([]uint, 0) - - matcher := Equals(nilInt1) - ExpectEq("[]", matcher.Description()) - - cases := []equalsTestCase{ - // Correct type. - equalsTestCase{nilInt1, true, false, ""}, - equalsTestCase{nilInt2, true, false, ""}, - equalsTestCase{nonNilInt, false, false, ""}, - - // Incorrect type. - equalsTestCase{nilUint, false, true, "which is not a []int"}, - equalsTestCase{nonNilUint, false, true, "which is not a []int"}, - - // Other types. - equalsTestCase{0, false, true, "which is not a []int"}, - equalsTestCase{bool(false), false, true, "which is not a []int"}, - equalsTestCase{int(0), false, true, "which is not a []int"}, - equalsTestCase{int8(0), false, true, "which is not a []int"}, - equalsTestCase{int16(0), false, true, "which is not a []int"}, - equalsTestCase{int32(0), false, true, "which is not a []int"}, - equalsTestCase{int64(0), false, true, "which is not a []int"}, - equalsTestCase{uint(0), false, true, "which is not a []int"}, - equalsTestCase{uint8(0), false, true, "which is not a []int"}, - equalsTestCase{uint16(0), false, true, "which is not a []int"}, - equalsTestCase{uint32(0), false, true, "which is not a []int"}, - equalsTestCase{uint64(0), false, true, "which is not a []int"}, - equalsTestCase{true, false, true, "which is not a []int"}, - equalsTestCase{[...]int{}, false, true, "which is not a []int"}, - equalsTestCase{func() {}, false, true, "which is not a []int"}, - equalsTestCase{map[int]int{}, false, true, "which is not a []int"}, - equalsTestCase{"taco", false, true, "which is not a []int"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not a []int"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) NonNilSlice() { - nonNil := make([]int, 0) - f := func() { Equals(nonNil) } - ExpectThat(f, Panics(HasSubstr("non-nil slice"))) -} - -//////////////////////////////////////////////////////////////////////// -// string -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) String() { - partial := "taco" - expected := fmt.Sprintf("%s%d", partial, 1) - - matcher := Equals(expected) - ExpectEq("taco1", matcher.Description()) - - type stringAlias string - - cases := []equalsTestCase{ - // Correct types. - equalsTestCase{"taco1", true, false, ""}, - equalsTestCase{"taco" + "1", true, false, ""}, - equalsTestCase{expected, true, false, ""}, - equalsTestCase{stringAlias("taco1"), true, false, ""}, - - equalsTestCase{"", false, false, ""}, - equalsTestCase{"taco", false, false, ""}, - equalsTestCase{"taco1\x00", false, false, ""}, - equalsTestCase{"taco2", false, false, ""}, - equalsTestCase{stringAlias("taco2"), false, false, ""}, - - // Other types. - equalsTestCase{0, false, true, "which is not a string"}, - equalsTestCase{bool(false), false, true, "which is not a string"}, - equalsTestCase{int(0), false, true, "which is not a string"}, - equalsTestCase{int8(0), false, true, "which is not a string"}, - equalsTestCase{int16(0), false, true, "which is not a string"}, - equalsTestCase{int32(0), false, true, "which is not a string"}, - equalsTestCase{int64(0), false, true, "which is not a string"}, - equalsTestCase{uint(0), false, true, "which is not a string"}, - equalsTestCase{uint8(0), false, true, "which is not a string"}, - equalsTestCase{uint16(0), false, true, "which is not a string"}, - equalsTestCase{uint32(0), false, true, "which is not a string"}, - equalsTestCase{uint64(0), false, true, "which is not a string"}, - equalsTestCase{true, false, true, "which is not a string"}, - equalsTestCase{[...]int{}, false, true, "which is not a string"}, - equalsTestCase{func() {}, false, true, "which is not a string"}, - equalsTestCase{map[int]int{}, false, true, "which is not a string"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not a string"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) StringAlias() { - type stringAlias string - - matcher := Equals(stringAlias("taco")) - ExpectEq("taco", matcher.Description()) - - cases := []equalsTestCase{ - // Correct types. - equalsTestCase{stringAlias("taco"), true, false, ""}, - equalsTestCase{"taco", true, false, ""}, - - equalsTestCase{"burrito", false, false, ""}, - equalsTestCase{stringAlias("burrito"), false, false, ""}, - - // Other types. - equalsTestCase{0, false, true, "which is not a string"}, - equalsTestCase{bool(false), false, true, "which is not a string"}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// struct -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) Struct() { - type someStruct struct{ foo uint } - f := func() { Equals(someStruct{17}) } - ExpectThat(f, Panics(HasSubstr("unsupported kind struct"))) -} - -//////////////////////////////////////////////////////////////////////// -// unsafe.Pointer -//////////////////////////////////////////////////////////////////////// - -func (t *EqualsTest) NilUnsafePointer() { - someInt := int(17) - - var nilPtr1 unsafe.Pointer - var nilPtr2 unsafe.Pointer - var nonNilPtr unsafe.Pointer = unsafe.Pointer(&someInt) - - matcher := Equals(nilPtr1) - ExpectEq("", matcher.Description()) - - cases := []equalsTestCase{ - // Correct type. - equalsTestCase{nilPtr1, true, false, ""}, - equalsTestCase{nilPtr2, true, false, ""}, - equalsTestCase{nonNilPtr, false, false, ""}, - - // Other types. - equalsTestCase{0, false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{bool(false), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{int(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{int8(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{int16(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{int32(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{int64(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{uint(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{uint8(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{uint16(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{uint32(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{uint64(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{uintptr(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{true, false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{[...]int{}, false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{make(chan int), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{func() {}, false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{map[int]int{}, false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{&someInt, false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{[]int{}, false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{"taco", false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not a unsafe.Pointer"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *EqualsTest) NonNilUnsafePointer() { - someInt := int(17) - someOtherInt := int(17) - - var nilPtr unsafe.Pointer - var nonNilPtr1 unsafe.Pointer = unsafe.Pointer(&someInt) - var nonNilPtr2 unsafe.Pointer = unsafe.Pointer(&someOtherInt) - - matcher := Equals(nonNilPtr1) - ExpectEq(fmt.Sprintf("%v", nonNilPtr1), matcher.Description()) - - cases := []equalsTestCase{ - // Correct type. - equalsTestCase{nonNilPtr1, true, false, ""}, - equalsTestCase{nonNilPtr2, false, false, ""}, - equalsTestCase{nilPtr, false, false, ""}, - - // Other types. - equalsTestCase{0, false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{bool(false), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{int(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{int8(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{int16(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{int32(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{int64(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{uint(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{uint8(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{uint16(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{uint32(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{uint64(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{uintptr(0), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{true, false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{[...]int{}, false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{make(chan int), false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{func() {}, false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{map[int]int{}, false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{&someInt, false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{[]int{}, false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{"taco", false, true, "which is not a unsafe.Pointer"}, - equalsTestCase{equalsTestCase{}, false, true, "which is not a unsafe.Pointer"}, - } - - t.checkTestCases(matcher, cases) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/error_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/error_test.go deleted file mode 100644 index 31eb685e8d6..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/error_test.go +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - "errors" - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type ErrorTest struct { - matcherCalled bool - suppliedCandidate interface{} - wrappedError error - - matcher Matcher -} - -func init() { RegisterTestSuite(&ErrorTest{}) } - -func (t *ErrorTest) SetUp(i *TestInfo) { - wrapped := &fakeMatcher{ - func(c interface{}) error { - t.matcherCalled = true - t.suppliedCandidate = c - return t.wrappedError - }, - "is foo", - } - - t.matcher = Error(wrapped) -} - -func isFatal(err error) bool { - _, isFatal := err.(*FatalError) - return isFatal -} - -//////////////////////////////////////////////////////////////////////// -// Tests -//////////////////////////////////////////////////////////////////////// - -func (t *ErrorTest) Description() { - ExpectThat(t.matcher.Description(), Equals("error is foo")) -} - -func (t *ErrorTest) CandidateIsNil() { - err := t.matcher.Matches(nil) - - ExpectThat(t.matcherCalled, Equals(false)) - ExpectThat(err.Error(), Equals("which is not an error")) - ExpectTrue(isFatal(err)) -} - -func (t *ErrorTest) CandidateIsString() { - err := t.matcher.Matches("taco") - - ExpectThat(t.matcherCalled, Equals(false)) - ExpectThat(err.Error(), Equals("which is not an error")) - ExpectTrue(isFatal(err)) -} - -func (t *ErrorTest) CallsWrappedMatcher() { - candidate := errors.New("taco") - t.matcher.Matches(candidate) - - ExpectThat(t.matcherCalled, Equals(true)) - ExpectThat(t.suppliedCandidate, Equals("taco")) -} - -func (t *ErrorTest) ReturnsWrappedMatcherResult() { - t.wrappedError = errors.New("burrito") - err := t.matcher.Matches(errors.New("")) - ExpectThat(err, Equals(t.wrappedError)) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/greater_or_equal_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/greater_or_equal_test.go deleted file mode 100644 index e2fe137f42e..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/greater_or_equal_test.go +++ /dev/null @@ -1,1059 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - "math" - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type GreaterOrEqualTest struct { -} - -func init() { RegisterTestSuite(&GreaterOrEqualTest{}) } - -type geTestCase struct { - candidate interface{} - expectedResult bool - shouldBeFatal bool - expectedError string -} - -func (t *GreaterOrEqualTest) checkTestCases(matcher Matcher, cases []geTestCase) { - for i, c := range cases { - err := matcher.Matches(c.candidate) - - ExpectThat( - (err == nil), - Equals(c.expectedResult), - "Case %d (candidate %v)", - i, - c.candidate) - - if err == nil { - continue - } - - _, isFatal := err.(*FatalError) - ExpectEq( - c.shouldBeFatal, - isFatal, - "Case %d (candidate %v)", - i, - c.candidate) - - ExpectThat( - err, - Error(Equals(c.expectedError)), - "Case %d (candidate %v)", - i, - c.candidate) - } -} - -//////////////////////////////////////////////////////////////////////// -// Integer literals -//////////////////////////////////////////////////////////////////////// - -func (t *GreaterOrEqualTest) IntegerCandidateBadTypes() { - matcher := GreaterOrEqual(int(-150)) - - cases := []geTestCase{ - geTestCase{true, false, true, "which is not comparable"}, - geTestCase{uintptr(17), false, true, "which is not comparable"}, - geTestCase{complex64(-151), false, true, "which is not comparable"}, - geTestCase{complex128(-151), false, true, "which is not comparable"}, - geTestCase{[...]int{-151}, false, true, "which is not comparable"}, - geTestCase{make(chan int), false, true, "which is not comparable"}, - geTestCase{func() {}, false, true, "which is not comparable"}, - geTestCase{map[int]int{}, false, true, "which is not comparable"}, - geTestCase{&geTestCase{}, false, true, "which is not comparable"}, - geTestCase{make([]int, 0), false, true, "which is not comparable"}, - geTestCase{"-151", false, true, "which is not comparable"}, - geTestCase{geTestCase{}, false, true, "which is not comparable"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterOrEqualTest) FloatCandidateBadTypes() { - matcher := GreaterOrEqual(float32(-150)) - - cases := []geTestCase{ - geTestCase{true, false, true, "which is not comparable"}, - geTestCase{uintptr(17), false, true, "which is not comparable"}, - geTestCase{complex64(-151), false, true, "which is not comparable"}, - geTestCase{complex128(-151), false, true, "which is not comparable"}, - geTestCase{[...]int{-151}, false, true, "which is not comparable"}, - geTestCase{make(chan int), false, true, "which is not comparable"}, - geTestCase{func() {}, false, true, "which is not comparable"}, - geTestCase{map[int]int{}, false, true, "which is not comparable"}, - geTestCase{&geTestCase{}, false, true, "which is not comparable"}, - geTestCase{make([]int, 0), false, true, "which is not comparable"}, - geTestCase{"-151", false, true, "which is not comparable"}, - geTestCase{geTestCase{}, false, true, "which is not comparable"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterOrEqualTest) StringCandidateBadTypes() { - matcher := GreaterOrEqual("17") - - cases := []geTestCase{ - geTestCase{true, false, true, "which is not comparable"}, - geTestCase{int(0), false, true, "which is not comparable"}, - geTestCase{int8(0), false, true, "which is not comparable"}, - geTestCase{int16(0), false, true, "which is not comparable"}, - geTestCase{int32(0), false, true, "which is not comparable"}, - geTestCase{int64(0), false, true, "which is not comparable"}, - geTestCase{uint(0), false, true, "which is not comparable"}, - geTestCase{uint8(0), false, true, "which is not comparable"}, - geTestCase{uint16(0), false, true, "which is not comparable"}, - geTestCase{uint32(0), false, true, "which is not comparable"}, - geTestCase{uint64(0), false, true, "which is not comparable"}, - geTestCase{uintptr(17), false, true, "which is not comparable"}, - geTestCase{float32(0), false, true, "which is not comparable"}, - geTestCase{float64(0), false, true, "which is not comparable"}, - geTestCase{complex64(-151), false, true, "which is not comparable"}, - geTestCase{complex128(-151), false, true, "which is not comparable"}, - geTestCase{[...]int{-151}, false, true, "which is not comparable"}, - geTestCase{make(chan int), false, true, "which is not comparable"}, - geTestCase{func() {}, false, true, "which is not comparable"}, - geTestCase{map[int]int{}, false, true, "which is not comparable"}, - geTestCase{&geTestCase{}, false, true, "which is not comparable"}, - geTestCase{make([]int, 0), false, true, "which is not comparable"}, - geTestCase{geTestCase{}, false, true, "which is not comparable"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterOrEqualTest) BadArgument() { - panicked := false - - defer func() { - ExpectThat(panicked, Equals(true)) - }() - - defer func() { - if r := recover(); r != nil { - panicked = true - } - }() - - GreaterOrEqual(complex128(0)) -} - -//////////////////////////////////////////////////////////////////////// -// Integer literals -//////////////////////////////////////////////////////////////////////// - -func (t *GreaterOrEqualTest) NegativeIntegerLiteral() { - matcher := GreaterOrEqual(-150) - desc := matcher.Description() - expectedDesc := "greater than or equal to -150" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []geTestCase{ - // Signed integers. - geTestCase{-(1 << 30), false, false, ""}, - geTestCase{-151, false, false, ""}, - geTestCase{-150, true, false, ""}, - geTestCase{0, true, false, ""}, - geTestCase{17, true, false, ""}, - - geTestCase{int(-(1 << 30)), false, false, ""}, - geTestCase{int(-151), false, false, ""}, - geTestCase{int(-150), true, false, ""}, - geTestCase{int(0), true, false, ""}, - geTestCase{int(17), true, false, ""}, - - geTestCase{int8(-127), true, false, ""}, - geTestCase{int8(0), true, false, ""}, - geTestCase{int8(17), true, false, ""}, - - geTestCase{int16(-(1 << 14)), false, false, ""}, - geTestCase{int16(-151), false, false, ""}, - geTestCase{int16(-150), true, false, ""}, - geTestCase{int16(0), true, false, ""}, - geTestCase{int16(17), true, false, ""}, - - geTestCase{int32(-(1 << 30)), false, false, ""}, - geTestCase{int32(-151), false, false, ""}, - geTestCase{int32(-150), true, false, ""}, - geTestCase{int32(0), true, false, ""}, - geTestCase{int32(17), true, false, ""}, - - geTestCase{int64(-(1 << 30)), false, false, ""}, - geTestCase{int64(-151), false, false, ""}, - geTestCase{int64(-150), true, false, ""}, - geTestCase{int64(0), true, false, ""}, - geTestCase{int64(17), true, false, ""}, - - // Unsigned integers. - geTestCase{uint((1 << 32) - 151), true, false, ""}, - geTestCase{uint(0), true, false, ""}, - geTestCase{uint(17), true, false, ""}, - - geTestCase{uint8(0), true, false, ""}, - geTestCase{uint8(17), true, false, ""}, - geTestCase{uint8(253), true, false, ""}, - - geTestCase{uint16((1 << 16) - 151), true, false, ""}, - geTestCase{uint16(0), true, false, ""}, - geTestCase{uint16(17), true, false, ""}, - - geTestCase{uint32((1 << 32) - 151), true, false, ""}, - geTestCase{uint32(0), true, false, ""}, - geTestCase{uint32(17), true, false, ""}, - - geTestCase{uint64((1 << 64) - 151), true, false, ""}, - geTestCase{uint64(0), true, false, ""}, - geTestCase{uint64(17), true, false, ""}, - - // Floating point. - geTestCase{float32(-(1 << 30)), false, false, ""}, - geTestCase{float32(-151), false, false, ""}, - geTestCase{float32(-150.1), false, false, ""}, - geTestCase{float32(-150), true, false, ""}, - geTestCase{float32(-149.9), true, false, ""}, - geTestCase{float32(0), true, false, ""}, - geTestCase{float32(17), true, false, ""}, - geTestCase{float32(160), true, false, ""}, - - geTestCase{float64(-(1 << 30)), false, false, ""}, - geTestCase{float64(-151), false, false, ""}, - geTestCase{float64(-150.1), false, false, ""}, - geTestCase{float64(-150), true, false, ""}, - geTestCase{float64(-149.9), true, false, ""}, - geTestCase{float64(0), true, false, ""}, - geTestCase{float64(17), true, false, ""}, - geTestCase{float64(160), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterOrEqualTest) ZeroIntegerLiteral() { - matcher := GreaterOrEqual(0) - desc := matcher.Description() - expectedDesc := "greater than or equal to 0" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []geTestCase{ - // Signed integers. - geTestCase{-(1 << 30), false, false, ""}, - geTestCase{-1, false, false, ""}, - geTestCase{0, true, false, ""}, - geTestCase{1, true, false, ""}, - geTestCase{17, true, false, ""}, - geTestCase{(1 << 30), true, false, ""}, - - geTestCase{int(-(1 << 30)), false, false, ""}, - geTestCase{int(-1), false, false, ""}, - geTestCase{int(0), true, false, ""}, - geTestCase{int(1), true, false, ""}, - geTestCase{int(17), true, false, ""}, - - geTestCase{int8(-1), false, false, ""}, - geTestCase{int8(0), true, false, ""}, - geTestCase{int8(1), true, false, ""}, - - geTestCase{int16(-(1 << 14)), false, false, ""}, - geTestCase{int16(-1), false, false, ""}, - geTestCase{int16(0), true, false, ""}, - geTestCase{int16(1), true, false, ""}, - geTestCase{int16(17), true, false, ""}, - - geTestCase{int32(-(1 << 30)), false, false, ""}, - geTestCase{int32(-1), false, false, ""}, - geTestCase{int32(0), true, false, ""}, - geTestCase{int32(1), true, false, ""}, - geTestCase{int32(17), true, false, ""}, - - geTestCase{int64(-(1 << 30)), false, false, ""}, - geTestCase{int64(-1), false, false, ""}, - geTestCase{int64(0), true, false, ""}, - geTestCase{int64(1), true, false, ""}, - geTestCase{int64(17), true, false, ""}, - - // Unsigned integers. - geTestCase{uint((1 << 32) - 1), true, false, ""}, - geTestCase{uint(0), true, false, ""}, - geTestCase{uint(17), true, false, ""}, - - geTestCase{uint8(0), true, false, ""}, - geTestCase{uint8(17), true, false, ""}, - geTestCase{uint8(253), true, false, ""}, - - geTestCase{uint16((1 << 16) - 1), true, false, ""}, - geTestCase{uint16(0), true, false, ""}, - geTestCase{uint16(17), true, false, ""}, - - geTestCase{uint32((1 << 32) - 1), true, false, ""}, - geTestCase{uint32(0), true, false, ""}, - geTestCase{uint32(17), true, false, ""}, - - geTestCase{uint64((1 << 64) - 1), true, false, ""}, - geTestCase{uint64(0), true, false, ""}, - geTestCase{uint64(17), true, false, ""}, - - // Floating point. - geTestCase{float32(-(1 << 30)), false, false, ""}, - geTestCase{float32(-1), false, false, ""}, - geTestCase{float32(-0.1), false, false, ""}, - geTestCase{float32(-0.0), true, false, ""}, - geTestCase{float32(0), true, false, ""}, - geTestCase{float32(0.1), true, false, ""}, - geTestCase{float32(17), true, false, ""}, - geTestCase{float32(160), true, false, ""}, - - geTestCase{float64(-(1 << 30)), false, false, ""}, - geTestCase{float64(-1), false, false, ""}, - geTestCase{float64(-0.1), false, false, ""}, - geTestCase{float64(-0), true, false, ""}, - geTestCase{float64(0), true, false, ""}, - geTestCase{float64(17), true, false, ""}, - geTestCase{float64(160), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterOrEqualTest) PositiveIntegerLiteral() { - matcher := GreaterOrEqual(150) - desc := matcher.Description() - expectedDesc := "greater than or equal to 150" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []geTestCase{ - // Signed integers. - geTestCase{-1, false, false, ""}, - geTestCase{149, false, false, ""}, - geTestCase{150, true, false, ""}, - geTestCase{151, true, false, ""}, - - geTestCase{int(-1), false, false, ""}, - geTestCase{int(149), false, false, ""}, - geTestCase{int(150), true, false, ""}, - geTestCase{int(151), true, false, ""}, - - geTestCase{int8(-1), false, false, ""}, - geTestCase{int8(0), false, false, ""}, - geTestCase{int8(17), false, false, ""}, - geTestCase{int8(127), false, false, ""}, - - geTestCase{int16(-1), false, false, ""}, - geTestCase{int16(149), false, false, ""}, - geTestCase{int16(150), true, false, ""}, - geTestCase{int16(151), true, false, ""}, - - geTestCase{int32(-1), false, false, ""}, - geTestCase{int32(149), false, false, ""}, - geTestCase{int32(150), true, false, ""}, - geTestCase{int32(151), true, false, ""}, - - geTestCase{int64(-1), false, false, ""}, - geTestCase{int64(149), false, false, ""}, - geTestCase{int64(150), true, false, ""}, - geTestCase{int64(151), true, false, ""}, - - // Unsigned integers. - geTestCase{uint(0), false, false, ""}, - geTestCase{uint(149), false, false, ""}, - geTestCase{uint(150), true, false, ""}, - geTestCase{uint(151), true, false, ""}, - - geTestCase{uint8(0), false, false, ""}, - geTestCase{uint8(127), false, false, ""}, - - geTestCase{uint16(0), false, false, ""}, - geTestCase{uint16(149), false, false, ""}, - geTestCase{uint16(150), true, false, ""}, - geTestCase{uint16(151), true, false, ""}, - - geTestCase{uint32(0), false, false, ""}, - geTestCase{uint32(149), false, false, ""}, - geTestCase{uint32(150), true, false, ""}, - geTestCase{uint32(151), true, false, ""}, - - geTestCase{uint64(0), false, false, ""}, - geTestCase{uint64(149), false, false, ""}, - geTestCase{uint64(150), true, false, ""}, - geTestCase{uint64(151), true, false, ""}, - - // Floating point. - geTestCase{float32(-1), false, false, ""}, - geTestCase{float32(149), false, false, ""}, - geTestCase{float32(149.9), false, false, ""}, - geTestCase{float32(150), true, false, ""}, - geTestCase{float32(150.1), true, false, ""}, - geTestCase{float32(151), true, false, ""}, - - geTestCase{float64(-1), false, false, ""}, - geTestCase{float64(149), false, false, ""}, - geTestCase{float64(149.9), false, false, ""}, - geTestCase{float64(150), true, false, ""}, - geTestCase{float64(150.1), true, false, ""}, - geTestCase{float64(151), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// Float literals -//////////////////////////////////////////////////////////////////////// - -func (t *GreaterOrEqualTest) NegativeFloatLiteral() { - matcher := GreaterOrEqual(-150.1) - desc := matcher.Description() - expectedDesc := "greater than or equal to -150.1" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []geTestCase{ - // Signed integers. - geTestCase{-(1 << 30), false, false, ""}, - geTestCase{-151, false, false, ""}, - geTestCase{-150, true, false, ""}, - geTestCase{0, true, false, ""}, - geTestCase{17, true, false, ""}, - - geTestCase{int(-(1 << 30)), false, false, ""}, - geTestCase{int(-151), false, false, ""}, - geTestCase{int(-150), true, false, ""}, - geTestCase{int(0), true, false, ""}, - geTestCase{int(17), true, false, ""}, - - geTestCase{int8(-127), true, false, ""}, - geTestCase{int8(0), true, false, ""}, - geTestCase{int8(17), true, false, ""}, - - geTestCase{int16(-(1 << 14)), false, false, ""}, - geTestCase{int16(-151), false, false, ""}, - geTestCase{int16(-150), true, false, ""}, - geTestCase{int16(0), true, false, ""}, - geTestCase{int16(17), true, false, ""}, - - geTestCase{int32(-(1 << 30)), false, false, ""}, - geTestCase{int32(-151), false, false, ""}, - geTestCase{int32(-150), true, false, ""}, - geTestCase{int32(0), true, false, ""}, - geTestCase{int32(17), true, false, ""}, - - geTestCase{int64(-(1 << 30)), false, false, ""}, - geTestCase{int64(-151), false, false, ""}, - geTestCase{int64(-150), true, false, ""}, - geTestCase{int64(0), true, false, ""}, - geTestCase{int64(17), true, false, ""}, - - // Unsigned integers. - geTestCase{uint((1 << 32) - 151), true, false, ""}, - geTestCase{uint(0), true, false, ""}, - geTestCase{uint(17), true, false, ""}, - - geTestCase{uint8(0), true, false, ""}, - geTestCase{uint8(17), true, false, ""}, - geTestCase{uint8(253), true, false, ""}, - - geTestCase{uint16((1 << 16) - 151), true, false, ""}, - geTestCase{uint16(0), true, false, ""}, - geTestCase{uint16(17), true, false, ""}, - - geTestCase{uint32((1 << 32) - 151), true, false, ""}, - geTestCase{uint32(0), true, false, ""}, - geTestCase{uint32(17), true, false, ""}, - - geTestCase{uint64((1 << 64) - 151), true, false, ""}, - geTestCase{uint64(0), true, false, ""}, - geTestCase{uint64(17), true, false, ""}, - - // Floating point. - geTestCase{float32(-(1 << 30)), false, false, ""}, - geTestCase{float32(-151), false, false, ""}, - geTestCase{float32(-150.2), false, false, ""}, - geTestCase{float32(-150.1), true, false, ""}, - geTestCase{float32(-150), true, false, ""}, - geTestCase{float32(0), true, false, ""}, - geTestCase{float32(17), true, false, ""}, - geTestCase{float32(160), true, false, ""}, - - geTestCase{float64(-(1 << 30)), false, false, ""}, - geTestCase{float64(-151), false, false, ""}, - geTestCase{float64(-150.2), false, false, ""}, - geTestCase{float64(-150.1), true, false, ""}, - geTestCase{float64(-150), true, false, ""}, - geTestCase{float64(0), true, false, ""}, - geTestCase{float64(17), true, false, ""}, - geTestCase{float64(160), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterOrEqualTest) PositiveFloatLiteral() { - matcher := GreaterOrEqual(149.9) - desc := matcher.Description() - expectedDesc := "greater than or equal to 149.9" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []geTestCase{ - // Signed integers. - geTestCase{-1, false, false, ""}, - geTestCase{149, false, false, ""}, - geTestCase{150, true, false, ""}, - geTestCase{151, true, false, ""}, - - geTestCase{int(-1), false, false, ""}, - geTestCase{int(149), false, false, ""}, - geTestCase{int(150), true, false, ""}, - geTestCase{int(151), true, false, ""}, - - geTestCase{int8(-1), false, false, ""}, - geTestCase{int8(0), false, false, ""}, - geTestCase{int8(17), false, false, ""}, - geTestCase{int8(127), false, false, ""}, - - geTestCase{int16(-1), false, false, ""}, - geTestCase{int16(149), false, false, ""}, - geTestCase{int16(150), true, false, ""}, - geTestCase{int16(151), true, false, ""}, - - geTestCase{int32(-1), false, false, ""}, - geTestCase{int32(149), false, false, ""}, - geTestCase{int32(150), true, false, ""}, - geTestCase{int32(151), true, false, ""}, - - geTestCase{int64(-1), false, false, ""}, - geTestCase{int64(149), false, false, ""}, - geTestCase{int64(150), true, false, ""}, - geTestCase{int64(151), true, false, ""}, - - // Unsigned integers. - geTestCase{uint(0), false, false, ""}, - geTestCase{uint(149), false, false, ""}, - geTestCase{uint(150), true, false, ""}, - geTestCase{uint(151), true, false, ""}, - - geTestCase{uint8(0), false, false, ""}, - geTestCase{uint8(127), false, false, ""}, - - geTestCase{uint16(0), false, false, ""}, - geTestCase{uint16(149), false, false, ""}, - geTestCase{uint16(150), true, false, ""}, - geTestCase{uint16(151), true, false, ""}, - - geTestCase{uint32(0), false, false, ""}, - geTestCase{uint32(149), false, false, ""}, - geTestCase{uint32(150), true, false, ""}, - geTestCase{uint32(151), true, false, ""}, - - geTestCase{uint64(0), false, false, ""}, - geTestCase{uint64(149), false, false, ""}, - geTestCase{uint64(150), true, false, ""}, - geTestCase{uint64(151), true, false, ""}, - - // Floating point. - geTestCase{float32(-1), false, false, ""}, - geTestCase{float32(149), false, false, ""}, - geTestCase{float32(149.8), false, false, ""}, - geTestCase{float32(149.9), true, false, ""}, - geTestCase{float32(150), true, false, ""}, - geTestCase{float32(151), true, false, ""}, - - geTestCase{float64(-1), false, false, ""}, - geTestCase{float64(149), false, false, ""}, - geTestCase{float64(149.8), false, false, ""}, - geTestCase{float64(149.9), true, false, ""}, - geTestCase{float64(150), true, false, ""}, - geTestCase{float64(151), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// Subtle cases -//////////////////////////////////////////////////////////////////////// - -func (t *GreaterOrEqualTest) Int64NotExactlyRepresentableBySinglePrecision() { - // Single-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo25 = 1 << 25 - matcher := GreaterOrEqual(int64(kTwoTo25 + 1)) - - desc := matcher.Description() - expectedDesc := "greater than or equal to 33554433" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []geTestCase{ - // Signed integers. - geTestCase{-1, false, false, ""}, - geTestCase{kTwoTo25 + 0, false, false, ""}, - geTestCase{kTwoTo25 + 1, true, false, ""}, - geTestCase{kTwoTo25 + 2, true, false, ""}, - - geTestCase{int(-1), false, false, ""}, - geTestCase{int(kTwoTo25 + 0), false, false, ""}, - geTestCase{int(kTwoTo25 + 1), true, false, ""}, - geTestCase{int(kTwoTo25 + 2), true, false, ""}, - - geTestCase{int8(-1), false, false, ""}, - geTestCase{int8(127), false, false, ""}, - - geTestCase{int16(-1), false, false, ""}, - geTestCase{int16(0), false, false, ""}, - geTestCase{int16(32767), false, false, ""}, - - geTestCase{int32(-1), false, false, ""}, - geTestCase{int32(kTwoTo25 + 0), false, false, ""}, - geTestCase{int32(kTwoTo25 + 1), true, false, ""}, - geTestCase{int32(kTwoTo25 + 2), true, false, ""}, - - geTestCase{int64(-1), false, false, ""}, - geTestCase{int64(kTwoTo25 + 0), false, false, ""}, - geTestCase{int64(kTwoTo25 + 1), true, false, ""}, - geTestCase{int64(kTwoTo25 + 2), true, false, ""}, - - // Unsigned integers. - geTestCase{uint(0), false, false, ""}, - geTestCase{uint(kTwoTo25 + 0), false, false, ""}, - geTestCase{uint(kTwoTo25 + 1), true, false, ""}, - geTestCase{uint(kTwoTo25 + 2), true, false, ""}, - - geTestCase{uint8(0), false, false, ""}, - geTestCase{uint8(255), false, false, ""}, - - geTestCase{uint16(0), false, false, ""}, - geTestCase{uint16(65535), false, false, ""}, - - geTestCase{uint32(0), false, false, ""}, - geTestCase{uint32(kTwoTo25 + 0), false, false, ""}, - geTestCase{uint32(kTwoTo25 + 1), true, false, ""}, - geTestCase{uint32(kTwoTo25 + 2), true, false, ""}, - - geTestCase{uint64(0), false, false, ""}, - geTestCase{uint64(kTwoTo25 + 0), false, false, ""}, - geTestCase{uint64(kTwoTo25 + 1), true, false, ""}, - geTestCase{uint64(kTwoTo25 + 2), true, false, ""}, - - // Floating point. - geTestCase{float32(-1), false, false, ""}, - geTestCase{float32(kTwoTo25 - 2), false, false, ""}, - geTestCase{float32(kTwoTo25 - 1), true, false, ""}, - geTestCase{float32(kTwoTo25 + 0), true, false, ""}, - geTestCase{float32(kTwoTo25 + 1), true, false, ""}, - geTestCase{float32(kTwoTo25 + 2), true, false, ""}, - geTestCase{float32(kTwoTo25 + 3), true, false, ""}, - - geTestCase{float64(-1), false, false, ""}, - geTestCase{float64(kTwoTo25 - 2), false, false, ""}, - geTestCase{float64(kTwoTo25 - 1), false, false, ""}, - geTestCase{float64(kTwoTo25 + 0), false, false, ""}, - geTestCase{float64(kTwoTo25 + 1), true, false, ""}, - geTestCase{float64(kTwoTo25 + 2), true, false, ""}, - geTestCase{float64(kTwoTo25 + 3), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterOrEqualTest) Int64NotExactlyRepresentableByDoublePrecision() { - // Double-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo54 = 1 << 54 - matcher := GreaterOrEqual(int64(kTwoTo54 + 1)) - - desc := matcher.Description() - expectedDesc := "greater than or equal to 18014398509481985" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []geTestCase{ - // Signed integers. - geTestCase{-1, false, false, ""}, - geTestCase{1 << 30, false, false, ""}, - - geTestCase{int(-1), false, false, ""}, - geTestCase{int(math.MaxInt32), false, false, ""}, - - geTestCase{int8(-1), false, false, ""}, - geTestCase{int8(127), false, false, ""}, - - geTestCase{int16(-1), false, false, ""}, - geTestCase{int16(0), false, false, ""}, - geTestCase{int16(32767), false, false, ""}, - - geTestCase{int32(-1), false, false, ""}, - geTestCase{int32(math.MaxInt32), false, false, ""}, - - geTestCase{int64(-1), false, false, ""}, - geTestCase{int64(kTwoTo54 - 1), false, false, ""}, - geTestCase{int64(kTwoTo54 + 0), false, false, ""}, - geTestCase{int64(kTwoTo54 + 1), true, false, ""}, - geTestCase{int64(kTwoTo54 + 2), true, false, ""}, - - // Unsigned integers. - geTestCase{uint(0), false, false, ""}, - geTestCase{uint(math.MaxUint32), false, false, ""}, - - geTestCase{uint8(0), false, false, ""}, - geTestCase{uint8(255), false, false, ""}, - - geTestCase{uint16(0), false, false, ""}, - geTestCase{uint16(65535), false, false, ""}, - - geTestCase{uint32(0), false, false, ""}, - geTestCase{uint32(math.MaxUint32), false, false, ""}, - - geTestCase{uint64(0), false, false, ""}, - geTestCase{uint64(kTwoTo54 - 1), false, false, ""}, - geTestCase{uint64(kTwoTo54 + 0), false, false, ""}, - geTestCase{uint64(kTwoTo54 + 1), true, false, ""}, - geTestCase{uint64(kTwoTo54 + 2), true, false, ""}, - - // Floating point. - geTestCase{float64(-1), false, false, ""}, - geTestCase{float64(kTwoTo54 - 2), false, false, ""}, - geTestCase{float64(kTwoTo54 - 1), true, false, ""}, - geTestCase{float64(kTwoTo54 + 0), true, false, ""}, - geTestCase{float64(kTwoTo54 + 1), true, false, ""}, - geTestCase{float64(kTwoTo54 + 2), true, false, ""}, - geTestCase{float64(kTwoTo54 + 3), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterOrEqualTest) Uint64NotExactlyRepresentableBySinglePrecision() { - // Single-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo25 = 1 << 25 - matcher := GreaterOrEqual(uint64(kTwoTo25 + 1)) - - desc := matcher.Description() - expectedDesc := "greater than or equal to 33554433" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []geTestCase{ - // Signed integers. - geTestCase{-1, false, false, ""}, - geTestCase{kTwoTo25 + 0, false, false, ""}, - geTestCase{kTwoTo25 + 1, true, false, ""}, - geTestCase{kTwoTo25 + 2, true, false, ""}, - - geTestCase{int(-1), false, false, ""}, - geTestCase{int(kTwoTo25 + 0), false, false, ""}, - geTestCase{int(kTwoTo25 + 1), true, false, ""}, - geTestCase{int(kTwoTo25 + 2), true, false, ""}, - - geTestCase{int8(-1), false, false, ""}, - geTestCase{int8(127), false, false, ""}, - - geTestCase{int16(-1), false, false, ""}, - geTestCase{int16(0), false, false, ""}, - geTestCase{int16(32767), false, false, ""}, - - geTestCase{int32(-1), false, false, ""}, - geTestCase{int32(kTwoTo25 + 0), false, false, ""}, - geTestCase{int32(kTwoTo25 + 1), true, false, ""}, - geTestCase{int32(kTwoTo25 + 2), true, false, ""}, - - geTestCase{int64(-1), false, false, ""}, - geTestCase{int64(kTwoTo25 + 0), false, false, ""}, - geTestCase{int64(kTwoTo25 + 1), true, false, ""}, - geTestCase{int64(kTwoTo25 + 2), true, false, ""}, - - // Unsigned integers. - geTestCase{uint(0), false, false, ""}, - geTestCase{uint(kTwoTo25 + 0), false, false, ""}, - geTestCase{uint(kTwoTo25 + 1), true, false, ""}, - geTestCase{uint(kTwoTo25 + 2), true, false, ""}, - - geTestCase{uint8(0), false, false, ""}, - geTestCase{uint8(255), false, false, ""}, - - geTestCase{uint16(0), false, false, ""}, - geTestCase{uint16(65535), false, false, ""}, - - geTestCase{uint32(0), false, false, ""}, - geTestCase{uint32(kTwoTo25 + 0), false, false, ""}, - geTestCase{uint32(kTwoTo25 + 1), true, false, ""}, - geTestCase{uint32(kTwoTo25 + 2), true, false, ""}, - - geTestCase{uint64(0), false, false, ""}, - geTestCase{uint64(kTwoTo25 + 0), false, false, ""}, - geTestCase{uint64(kTwoTo25 + 1), true, false, ""}, - geTestCase{uint64(kTwoTo25 + 2), true, false, ""}, - - // Floating point. - geTestCase{float32(-1), false, false, ""}, - geTestCase{float32(kTwoTo25 - 2), false, false, ""}, - geTestCase{float32(kTwoTo25 - 1), true, false, ""}, - geTestCase{float32(kTwoTo25 + 0), true, false, ""}, - geTestCase{float32(kTwoTo25 + 1), true, false, ""}, - geTestCase{float32(kTwoTo25 + 2), true, false, ""}, - geTestCase{float32(kTwoTo25 + 3), true, false, ""}, - - geTestCase{float64(-1), false, false, ""}, - geTestCase{float64(kTwoTo25 - 2), false, false, ""}, - geTestCase{float64(kTwoTo25 - 1), false, false, ""}, - geTestCase{float64(kTwoTo25 + 0), false, false, ""}, - geTestCase{float64(kTwoTo25 + 1), true, false, ""}, - geTestCase{float64(kTwoTo25 + 2), true, false, ""}, - geTestCase{float64(kTwoTo25 + 3), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterOrEqualTest) Uint64NotExactlyRepresentableByDoublePrecision() { - // Double-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo54 = 1 << 54 - matcher := GreaterOrEqual(uint64(kTwoTo54 + 1)) - - desc := matcher.Description() - expectedDesc := "greater than or equal to 18014398509481985" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []geTestCase{ - // Signed integers. - geTestCase{-1, false, false, ""}, - geTestCase{1 << 30, false, false, ""}, - - geTestCase{int(-1), false, false, ""}, - geTestCase{int(math.MaxInt32), false, false, ""}, - - geTestCase{int8(-1), false, false, ""}, - geTestCase{int8(127), false, false, ""}, - - geTestCase{int16(-1), false, false, ""}, - geTestCase{int16(0), false, false, ""}, - geTestCase{int16(32767), false, false, ""}, - - geTestCase{int32(-1), false, false, ""}, - geTestCase{int32(math.MaxInt32), false, false, ""}, - - geTestCase{int64(-1), false, false, ""}, - geTestCase{int64(kTwoTo54 - 1), false, false, ""}, - geTestCase{int64(kTwoTo54 + 0), false, false, ""}, - geTestCase{int64(kTwoTo54 + 1), true, false, ""}, - geTestCase{int64(kTwoTo54 + 2), true, false, ""}, - - // Unsigned integers. - geTestCase{uint(0), false, false, ""}, - geTestCase{uint(math.MaxUint32), false, false, ""}, - - geTestCase{uint8(0), false, false, ""}, - geTestCase{uint8(255), false, false, ""}, - - geTestCase{uint16(0), false, false, ""}, - geTestCase{uint16(65535), false, false, ""}, - - geTestCase{uint32(0), false, false, ""}, - geTestCase{uint32(math.MaxUint32), false, false, ""}, - - geTestCase{uint64(0), false, false, ""}, - geTestCase{uint64(kTwoTo54 - 1), false, false, ""}, - geTestCase{uint64(kTwoTo54 + 0), false, false, ""}, - geTestCase{uint64(kTwoTo54 + 1), true, false, ""}, - geTestCase{uint64(kTwoTo54 + 2), true, false, ""}, - - // Floating point. - geTestCase{float64(-1), false, false, ""}, - geTestCase{float64(kTwoTo54 - 2), false, false, ""}, - geTestCase{float64(kTwoTo54 - 1), true, false, ""}, - geTestCase{float64(kTwoTo54 + 0), true, false, ""}, - geTestCase{float64(kTwoTo54 + 1), true, false, ""}, - geTestCase{float64(kTwoTo54 + 2), true, false, ""}, - geTestCase{float64(kTwoTo54 + 3), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterOrEqualTest) Float32AboveExactIntegerRange() { - // Single-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo25 = 1 << 25 - matcher := GreaterOrEqual(float32(kTwoTo25 + 1)) - - desc := matcher.Description() - expectedDesc := "greater than or equal to 3.3554432e+07" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []geTestCase{ - // Signed integers. - geTestCase{int64(-1), false, false, ""}, - geTestCase{int64(kTwoTo25 - 2), false, false, ""}, - geTestCase{int64(kTwoTo25 - 1), true, false, ""}, - geTestCase{int64(kTwoTo25 + 0), true, false, ""}, - geTestCase{int64(kTwoTo25 + 1), true, false, ""}, - geTestCase{int64(kTwoTo25 + 2), true, false, ""}, - geTestCase{int64(kTwoTo25 + 3), true, false, ""}, - - // Unsigned integers. - geTestCase{uint64(0), false, false, ""}, - geTestCase{uint64(kTwoTo25 - 2), false, false, ""}, - geTestCase{uint64(kTwoTo25 - 1), true, false, ""}, - geTestCase{uint64(kTwoTo25 + 0), true, false, ""}, - geTestCase{uint64(kTwoTo25 + 1), true, false, ""}, - geTestCase{uint64(kTwoTo25 + 2), true, false, ""}, - geTestCase{uint64(kTwoTo25 + 3), true, false, ""}, - - // Floating point. - geTestCase{float32(-1), false, false, ""}, - geTestCase{float32(kTwoTo25 - 2), false, false, ""}, - geTestCase{float32(kTwoTo25 - 1), true, false, ""}, - geTestCase{float32(kTwoTo25 + 0), true, false, ""}, - geTestCase{float32(kTwoTo25 + 1), true, false, ""}, - geTestCase{float32(kTwoTo25 + 2), true, false, ""}, - geTestCase{float32(kTwoTo25 + 3), true, false, ""}, - - geTestCase{float64(-1), false, false, ""}, - geTestCase{float64(kTwoTo25 - 2), false, false, ""}, - geTestCase{float64(kTwoTo25 - 1), true, false, ""}, - geTestCase{float64(kTwoTo25 + 0), true, false, ""}, - geTestCase{float64(kTwoTo25 + 1), true, false, ""}, - geTestCase{float64(kTwoTo25 + 2), true, false, ""}, - geTestCase{float64(kTwoTo25 + 3), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterOrEqualTest) Float64AboveExactIntegerRange() { - // Double-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo54 = 1 << 54 - matcher := GreaterOrEqual(float64(kTwoTo54 + 1)) - - desc := matcher.Description() - expectedDesc := "greater than or equal to 1.8014398509481984e+16" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []geTestCase{ - // Signed integers. - geTestCase{int64(-1), false, false, ""}, - geTestCase{int64(kTwoTo54 - 2), false, false, ""}, - geTestCase{int64(kTwoTo54 - 1), true, false, ""}, - geTestCase{int64(kTwoTo54 + 0), true, false, ""}, - geTestCase{int64(kTwoTo54 + 1), true, false, ""}, - geTestCase{int64(kTwoTo54 + 2), true, false, ""}, - geTestCase{int64(kTwoTo54 + 3), true, false, ""}, - - // Unsigned integers. - geTestCase{uint64(0), false, false, ""}, - geTestCase{uint64(kTwoTo54 - 2), false, false, ""}, - geTestCase{uint64(kTwoTo54 - 1), true, false, ""}, - geTestCase{uint64(kTwoTo54 + 0), true, false, ""}, - geTestCase{uint64(kTwoTo54 + 1), true, false, ""}, - geTestCase{uint64(kTwoTo54 + 2), true, false, ""}, - geTestCase{uint64(kTwoTo54 + 3), true, false, ""}, - - // Floating point. - geTestCase{float64(-1), false, false, ""}, - geTestCase{float64(kTwoTo54 - 2), false, false, ""}, - geTestCase{float64(kTwoTo54 - 1), true, false, ""}, - geTestCase{float64(kTwoTo54 + 0), true, false, ""}, - geTestCase{float64(kTwoTo54 + 1), true, false, ""}, - geTestCase{float64(kTwoTo54 + 2), true, false, ""}, - geTestCase{float64(kTwoTo54 + 3), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// String literals -//////////////////////////////////////////////////////////////////////// - -func (t *GreaterOrEqualTest) EmptyString() { - matcher := GreaterOrEqual("") - desc := matcher.Description() - expectedDesc := "greater than or equal to \"\"" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []geTestCase{ - geTestCase{"", true, false, ""}, - geTestCase{"\x00", true, false, ""}, - geTestCase{"a", true, false, ""}, - geTestCase{"foo", true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterOrEqualTest) SingleNullByte() { - matcher := GreaterOrEqual("\x00") - desc := matcher.Description() - expectedDesc := "greater than or equal to \"\x00\"" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []geTestCase{ - geTestCase{"", false, false, ""}, - geTestCase{"\x00", true, false, ""}, - geTestCase{"a", true, false, ""}, - geTestCase{"foo", true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterOrEqualTest) LongerString() { - matcher := GreaterOrEqual("foo\x00") - desc := matcher.Description() - expectedDesc := "greater than or equal to \"foo\x00\"" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []geTestCase{ - geTestCase{"", false, false, ""}, - geTestCase{"\x00", false, false, ""}, - geTestCase{"bar", false, false, ""}, - geTestCase{"foo", false, false, ""}, - geTestCase{"foo\x00", true, false, ""}, - geTestCase{"fooa", true, false, ""}, - geTestCase{"qux", true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/greater_than_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/greater_than_test.go deleted file mode 100644 index 19c7567fd98..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/greater_than_test.go +++ /dev/null @@ -1,1079 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - "math" - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type GreaterThanTest struct { -} - -func init() { RegisterTestSuite(&GreaterThanTest{}) } - -type gtTestCase struct { - candidate interface{} - expectedResult bool - shouldBeFatal bool - expectedError string -} - -func (t *GreaterThanTest) checkTestCases(matcher Matcher, cases []gtTestCase) { - for i, c := range cases { - err := matcher.Matches(c.candidate) - - ExpectThat( - (err == nil), - Equals(c.expectedResult), - "Case %d (candidate %v)", - i, - c.candidate) - - if err == nil { - continue - } - - _, isFatal := err.(*FatalError) - ExpectEq( - c.shouldBeFatal, - isFatal, - "Case %d (candidate %v)", - i, - c.candidate) - - ExpectThat( - err, - Error(Equals(c.expectedError)), - "Case %d (candidate %v)", - i, - c.candidate) - } -} - -//////////////////////////////////////////////////////////////////////// -// Integer literals -//////////////////////////////////////////////////////////////////////// - -func (t *GreaterThanTest) IntegerCandidateBadTypes() { - matcher := GreaterThan(int(-150)) - - cases := []gtTestCase{ - gtTestCase{true, false, true, "which is not comparable"}, - gtTestCase{uintptr(17), false, true, "which is not comparable"}, - gtTestCase{complex64(-151), false, true, "which is not comparable"}, - gtTestCase{complex128(-151), false, true, "which is not comparable"}, - gtTestCase{[...]int{-151}, false, true, "which is not comparable"}, - gtTestCase{make(chan int), false, true, "which is not comparable"}, - gtTestCase{func() {}, false, true, "which is not comparable"}, - gtTestCase{map[int]int{}, false, true, "which is not comparable"}, - gtTestCase{>TestCase{}, false, true, "which is not comparable"}, - gtTestCase{make([]int, 0), false, true, "which is not comparable"}, - gtTestCase{"-151", false, true, "which is not comparable"}, - gtTestCase{gtTestCase{}, false, true, "which is not comparable"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterThanTest) FloatCandidateBadTypes() { - matcher := GreaterThan(float32(-150)) - - cases := []gtTestCase{ - gtTestCase{true, false, true, "which is not comparable"}, - gtTestCase{uintptr(17), false, true, "which is not comparable"}, - gtTestCase{complex64(-151), false, true, "which is not comparable"}, - gtTestCase{complex128(-151), false, true, "which is not comparable"}, - gtTestCase{[...]int{-151}, false, true, "which is not comparable"}, - gtTestCase{make(chan int), false, true, "which is not comparable"}, - gtTestCase{func() {}, false, true, "which is not comparable"}, - gtTestCase{map[int]int{}, false, true, "which is not comparable"}, - gtTestCase{>TestCase{}, false, true, "which is not comparable"}, - gtTestCase{make([]int, 0), false, true, "which is not comparable"}, - gtTestCase{"-151", false, true, "which is not comparable"}, - gtTestCase{gtTestCase{}, false, true, "which is not comparable"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterThanTest) StringCandidateBadTypes() { - matcher := GreaterThan("17") - - cases := []gtTestCase{ - gtTestCase{true, false, true, "which is not comparable"}, - gtTestCase{int(0), false, true, "which is not comparable"}, - gtTestCase{int8(0), false, true, "which is not comparable"}, - gtTestCase{int16(0), false, true, "which is not comparable"}, - gtTestCase{int32(0), false, true, "which is not comparable"}, - gtTestCase{int64(0), false, true, "which is not comparable"}, - gtTestCase{uint(0), false, true, "which is not comparable"}, - gtTestCase{uint8(0), false, true, "which is not comparable"}, - gtTestCase{uint16(0), false, true, "which is not comparable"}, - gtTestCase{uint32(0), false, true, "which is not comparable"}, - gtTestCase{uint64(0), false, true, "which is not comparable"}, - gtTestCase{uintptr(17), false, true, "which is not comparable"}, - gtTestCase{float32(0), false, true, "which is not comparable"}, - gtTestCase{float64(0), false, true, "which is not comparable"}, - gtTestCase{complex64(-151), false, true, "which is not comparable"}, - gtTestCase{complex128(-151), false, true, "which is not comparable"}, - gtTestCase{[...]int{-151}, false, true, "which is not comparable"}, - gtTestCase{make(chan int), false, true, "which is not comparable"}, - gtTestCase{func() {}, false, true, "which is not comparable"}, - gtTestCase{map[int]int{}, false, true, "which is not comparable"}, - gtTestCase{>TestCase{}, false, true, "which is not comparable"}, - gtTestCase{make([]int, 0), false, true, "which is not comparable"}, - gtTestCase{gtTestCase{}, false, true, "which is not comparable"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterThanTest) BadArgument() { - panicked := false - - defer func() { - ExpectThat(panicked, Equals(true)) - }() - - defer func() { - if r := recover(); r != nil { - panicked = true - } - }() - - GreaterThan(complex128(0)) -} - -//////////////////////////////////////////////////////////////////////// -// Integer literals -//////////////////////////////////////////////////////////////////////// - -func (t *GreaterThanTest) NegativeIntegerLiteral() { - matcher := GreaterThan(-150) - desc := matcher.Description() - expectedDesc := "greater than -150" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []gtTestCase{ - // Signed integers. - gtTestCase{-(1 << 30), false, false, ""}, - gtTestCase{-151, false, false, ""}, - gtTestCase{-150, false, false, ""}, - gtTestCase{-149, true, false, ""}, - gtTestCase{0, true, false, ""}, - gtTestCase{17, true, false, ""}, - - gtTestCase{int(-(1 << 30)), false, false, ""}, - gtTestCase{int(-151), false, false, ""}, - gtTestCase{int(-150), false, false, ""}, - gtTestCase{int(-149), true, false, ""}, - gtTestCase{int(0), true, false, ""}, - gtTestCase{int(17), true, false, ""}, - - gtTestCase{int8(-127), true, false, ""}, - gtTestCase{int8(0), true, false, ""}, - gtTestCase{int8(17), true, false, ""}, - - gtTestCase{int16(-(1 << 14)), false, false, ""}, - gtTestCase{int16(-151), false, false, ""}, - gtTestCase{int16(-150), false, false, ""}, - gtTestCase{int16(-149), true, false, ""}, - gtTestCase{int16(0), true, false, ""}, - gtTestCase{int16(17), true, false, ""}, - - gtTestCase{int32(-(1 << 30)), false, false, ""}, - gtTestCase{int32(-151), false, false, ""}, - gtTestCase{int32(-150), false, false, ""}, - gtTestCase{int32(-149), true, false, ""}, - gtTestCase{int32(0), true, false, ""}, - gtTestCase{int32(17), true, false, ""}, - - gtTestCase{int64(-(1 << 30)), false, false, ""}, - gtTestCase{int64(-151), false, false, ""}, - gtTestCase{int64(-150), false, false, ""}, - gtTestCase{int64(-149), true, false, ""}, - gtTestCase{int64(0), true, false, ""}, - gtTestCase{int64(17), true, false, ""}, - - // Unsigned integers. - gtTestCase{uint((1 << 32) - 151), true, false, ""}, - gtTestCase{uint(0), true, false, ""}, - gtTestCase{uint(17), true, false, ""}, - - gtTestCase{uint8(0), true, false, ""}, - gtTestCase{uint8(17), true, false, ""}, - gtTestCase{uint8(253), true, false, ""}, - - gtTestCase{uint16((1 << 16) - 151), true, false, ""}, - gtTestCase{uint16(0), true, false, ""}, - gtTestCase{uint16(17), true, false, ""}, - - gtTestCase{uint32((1 << 32) - 151), true, false, ""}, - gtTestCase{uint32(0), true, false, ""}, - gtTestCase{uint32(17), true, false, ""}, - - gtTestCase{uint64((1 << 64) - 151), true, false, ""}, - gtTestCase{uint64(0), true, false, ""}, - gtTestCase{uint64(17), true, false, ""}, - - // Floating point. - gtTestCase{float32(-(1 << 30)), false, false, ""}, - gtTestCase{float32(-151), false, false, ""}, - gtTestCase{float32(-150.1), false, false, ""}, - gtTestCase{float32(-150), false, false, ""}, - gtTestCase{float32(-149.9), true, false, ""}, - gtTestCase{float32(0), true, false, ""}, - gtTestCase{float32(17), true, false, ""}, - gtTestCase{float32(160), true, false, ""}, - - gtTestCase{float64(-(1 << 30)), false, false, ""}, - gtTestCase{float64(-151), false, false, ""}, - gtTestCase{float64(-150.1), false, false, ""}, - gtTestCase{float64(-150), false, false, ""}, - gtTestCase{float64(-149.9), true, false, ""}, - gtTestCase{float64(0), true, false, ""}, - gtTestCase{float64(17), true, false, ""}, - gtTestCase{float64(160), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterThanTest) ZeroIntegerLiteral() { - matcher := GreaterThan(0) - desc := matcher.Description() - expectedDesc := "greater than 0" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []gtTestCase{ - // Signed integers. - gtTestCase{-(1 << 30), false, false, ""}, - gtTestCase{-1, false, false, ""}, - gtTestCase{0, false, false, ""}, - gtTestCase{1, true, false, ""}, - gtTestCase{17, true, false, ""}, - gtTestCase{(1 << 30), true, false, ""}, - - gtTestCase{int(-(1 << 30)), false, false, ""}, - gtTestCase{int(-1), false, false, ""}, - gtTestCase{int(0), false, false, ""}, - gtTestCase{int(1), true, false, ""}, - gtTestCase{int(17), true, false, ""}, - - gtTestCase{int8(-1), false, false, ""}, - gtTestCase{int8(0), false, false, ""}, - gtTestCase{int8(1), true, false, ""}, - - gtTestCase{int16(-(1 << 14)), false, false, ""}, - gtTestCase{int16(-1), false, false, ""}, - gtTestCase{int16(0), false, false, ""}, - gtTestCase{int16(1), true, false, ""}, - gtTestCase{int16(17), true, false, ""}, - - gtTestCase{int32(-(1 << 30)), false, false, ""}, - gtTestCase{int32(-1), false, false, ""}, - gtTestCase{int32(0), false, false, ""}, - gtTestCase{int32(1), true, false, ""}, - gtTestCase{int32(17), true, false, ""}, - - gtTestCase{int64(-(1 << 30)), false, false, ""}, - gtTestCase{int64(-1), false, false, ""}, - gtTestCase{int64(0), false, false, ""}, - gtTestCase{int64(1), true, false, ""}, - gtTestCase{int64(17), true, false, ""}, - - // Unsigned integers. - gtTestCase{uint((1 << 32) - 1), true, false, ""}, - gtTestCase{uint(0), false, false, ""}, - gtTestCase{uint(1), true, false, ""}, - gtTestCase{uint(17), true, false, ""}, - - gtTestCase{uint8(0), false, false, ""}, - gtTestCase{uint8(1), true, false, ""}, - gtTestCase{uint8(17), true, false, ""}, - gtTestCase{uint8(253), true, false, ""}, - - gtTestCase{uint16((1 << 16) - 1), true, false, ""}, - gtTestCase{uint16(0), false, false, ""}, - gtTestCase{uint16(1), true, false, ""}, - gtTestCase{uint16(17), true, false, ""}, - - gtTestCase{uint32((1 << 32) - 1), true, false, ""}, - gtTestCase{uint32(0), false, false, ""}, - gtTestCase{uint32(1), true, false, ""}, - gtTestCase{uint32(17), true, false, ""}, - - gtTestCase{uint64((1 << 64) - 1), true, false, ""}, - gtTestCase{uint64(0), false, false, ""}, - gtTestCase{uint64(1), true, false, ""}, - gtTestCase{uint64(17), true, false, ""}, - - // Floating point. - gtTestCase{float32(-(1 << 30)), false, false, ""}, - gtTestCase{float32(-1), false, false, ""}, - gtTestCase{float32(-0.1), false, false, ""}, - gtTestCase{float32(-0.0), false, false, ""}, - gtTestCase{float32(0), false, false, ""}, - gtTestCase{float32(0.1), true, false, ""}, - gtTestCase{float32(17), true, false, ""}, - gtTestCase{float32(160), true, false, ""}, - - gtTestCase{float64(-(1 << 30)), false, false, ""}, - gtTestCase{float64(-1), false, false, ""}, - gtTestCase{float64(-0.1), false, false, ""}, - gtTestCase{float64(-0), false, false, ""}, - gtTestCase{float64(0), false, false, ""}, - gtTestCase{float64(0.1), true, false, ""}, - gtTestCase{float64(17), true, false, ""}, - gtTestCase{float64(160), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterThanTest) PositiveIntegerLiteral() { - matcher := GreaterThan(150) - desc := matcher.Description() - expectedDesc := "greater than 150" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []gtTestCase{ - // Signed integers. - gtTestCase{-1, false, false, ""}, - gtTestCase{149, false, false, ""}, - gtTestCase{150, false, false, ""}, - gtTestCase{151, true, false, ""}, - - gtTestCase{int(-1), false, false, ""}, - gtTestCase{int(149), false, false, ""}, - gtTestCase{int(150), false, false, ""}, - gtTestCase{int(151), true, false, ""}, - - gtTestCase{int8(-1), false, false, ""}, - gtTestCase{int8(0), false, false, ""}, - gtTestCase{int8(17), false, false, ""}, - gtTestCase{int8(127), false, false, ""}, - - gtTestCase{int16(-1), false, false, ""}, - gtTestCase{int16(149), false, false, ""}, - gtTestCase{int16(150), false, false, ""}, - gtTestCase{int16(151), true, false, ""}, - - gtTestCase{int32(-1), false, false, ""}, - gtTestCase{int32(149), false, false, ""}, - gtTestCase{int32(150), false, false, ""}, - gtTestCase{int32(151), true, false, ""}, - - gtTestCase{int64(-1), false, false, ""}, - gtTestCase{int64(149), false, false, ""}, - gtTestCase{int64(150), false, false, ""}, - gtTestCase{int64(151), true, false, ""}, - - // Unsigned integers. - gtTestCase{uint(0), false, false, ""}, - gtTestCase{uint(149), false, false, ""}, - gtTestCase{uint(150), false, false, ""}, - gtTestCase{uint(151), true, false, ""}, - - gtTestCase{uint8(0), false, false, ""}, - gtTestCase{uint8(127), false, false, ""}, - - gtTestCase{uint16(0), false, false, ""}, - gtTestCase{uint16(149), false, false, ""}, - gtTestCase{uint16(150), false, false, ""}, - gtTestCase{uint16(151), true, false, ""}, - - gtTestCase{uint32(0), false, false, ""}, - gtTestCase{uint32(149), false, false, ""}, - gtTestCase{uint32(150), false, false, ""}, - gtTestCase{uint32(151), true, false, ""}, - - gtTestCase{uint64(0), false, false, ""}, - gtTestCase{uint64(149), false, false, ""}, - gtTestCase{uint64(150), false, false, ""}, - gtTestCase{uint64(151), true, false, ""}, - - // Floating point. - gtTestCase{float32(-1), false, false, ""}, - gtTestCase{float32(149), false, false, ""}, - gtTestCase{float32(149.9), false, false, ""}, - gtTestCase{float32(150), false, false, ""}, - gtTestCase{float32(150.1), true, false, ""}, - gtTestCase{float32(151), true, false, ""}, - - gtTestCase{float64(-1), false, false, ""}, - gtTestCase{float64(149), false, false, ""}, - gtTestCase{float64(149.9), false, false, ""}, - gtTestCase{float64(150), false, false, ""}, - gtTestCase{float64(150.1), true, false, ""}, - gtTestCase{float64(151), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// Float literals -//////////////////////////////////////////////////////////////////////// - -func (t *GreaterThanTest) NegativeFloatLiteral() { - matcher := GreaterThan(-150.1) - desc := matcher.Description() - expectedDesc := "greater than -150.1" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []gtTestCase{ - // Signed integers. - gtTestCase{-(1 << 30), false, false, ""}, - gtTestCase{-151, false, false, ""}, - gtTestCase{-150.1, false, false, ""}, - gtTestCase{-150, true, false, ""}, - gtTestCase{-149, true, false, ""}, - gtTestCase{0, true, false, ""}, - gtTestCase{17, true, false, ""}, - - gtTestCase{int(-(1 << 30)), false, false, ""}, - gtTestCase{int(-151), false, false, ""}, - gtTestCase{int(-150), true, false, ""}, - gtTestCase{int(-149), true, false, ""}, - gtTestCase{int(0), true, false, ""}, - gtTestCase{int(17), true, false, ""}, - - gtTestCase{int8(-127), true, false, ""}, - gtTestCase{int8(0), true, false, ""}, - gtTestCase{int8(17), true, false, ""}, - - gtTestCase{int16(-(1 << 14)), false, false, ""}, - gtTestCase{int16(-151), false, false, ""}, - gtTestCase{int16(-150), true, false, ""}, - gtTestCase{int16(-149), true, false, ""}, - gtTestCase{int16(0), true, false, ""}, - gtTestCase{int16(17), true, false, ""}, - - gtTestCase{int32(-(1 << 30)), false, false, ""}, - gtTestCase{int32(-151), false, false, ""}, - gtTestCase{int32(-150), true, false, ""}, - gtTestCase{int32(-149), true, false, ""}, - gtTestCase{int32(0), true, false, ""}, - gtTestCase{int32(17), true, false, ""}, - - gtTestCase{int64(-(1 << 30)), false, false, ""}, - gtTestCase{int64(-151), false, false, ""}, - gtTestCase{int64(-150), true, false, ""}, - gtTestCase{int64(-149), true, false, ""}, - gtTestCase{int64(0), true, false, ""}, - gtTestCase{int64(17), true, false, ""}, - - // Unsigned integers. - gtTestCase{uint((1 << 32) - 151), true, false, ""}, - gtTestCase{uint(0), true, false, ""}, - gtTestCase{uint(17), true, false, ""}, - - gtTestCase{uint8(0), true, false, ""}, - gtTestCase{uint8(17), true, false, ""}, - gtTestCase{uint8(253), true, false, ""}, - - gtTestCase{uint16((1 << 16) - 151), true, false, ""}, - gtTestCase{uint16(0), true, false, ""}, - gtTestCase{uint16(17), true, false, ""}, - - gtTestCase{uint32((1 << 32) - 151), true, false, ""}, - gtTestCase{uint32(0), true, false, ""}, - gtTestCase{uint32(17), true, false, ""}, - - gtTestCase{uint64((1 << 64) - 151), true, false, ""}, - gtTestCase{uint64(0), true, false, ""}, - gtTestCase{uint64(17), true, false, ""}, - - // Floating point. - gtTestCase{float32(-(1 << 30)), false, false, ""}, - gtTestCase{float32(-151), false, false, ""}, - gtTestCase{float32(-150.2), false, false, ""}, - gtTestCase{float32(-150.1), false, false, ""}, - gtTestCase{float32(-150), true, false, ""}, - gtTestCase{float32(0), true, false, ""}, - gtTestCase{float32(17), true, false, ""}, - gtTestCase{float32(160), true, false, ""}, - - gtTestCase{float64(-(1 << 30)), false, false, ""}, - gtTestCase{float64(-151), false, false, ""}, - gtTestCase{float64(-150.2), false, false, ""}, - gtTestCase{float64(-150.1), false, false, ""}, - gtTestCase{float64(-150), true, false, ""}, - gtTestCase{float64(0), true, false, ""}, - gtTestCase{float64(17), true, false, ""}, - gtTestCase{float64(160), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterThanTest) PositiveFloatLiteral() { - matcher := GreaterThan(149.9) - desc := matcher.Description() - expectedDesc := "greater than 149.9" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []gtTestCase{ - // Signed integers. - gtTestCase{-1, false, false, ""}, - gtTestCase{149, false, false, ""}, - gtTestCase{149.9, false, false, ""}, - gtTestCase{150, true, false, ""}, - gtTestCase{151, true, false, ""}, - - gtTestCase{int(-1), false, false, ""}, - gtTestCase{int(149), false, false, ""}, - gtTestCase{int(150), true, false, ""}, - gtTestCase{int(151), true, false, ""}, - - gtTestCase{int8(-1), false, false, ""}, - gtTestCase{int8(0), false, false, ""}, - gtTestCase{int8(17), false, false, ""}, - gtTestCase{int8(127), false, false, ""}, - - gtTestCase{int16(-1), false, false, ""}, - gtTestCase{int16(149), false, false, ""}, - gtTestCase{int16(150), true, false, ""}, - gtTestCase{int16(151), true, false, ""}, - - gtTestCase{int32(-1), false, false, ""}, - gtTestCase{int32(149), false, false, ""}, - gtTestCase{int32(150), true, false, ""}, - gtTestCase{int32(151), true, false, ""}, - - gtTestCase{int64(-1), false, false, ""}, - gtTestCase{int64(149), false, false, ""}, - gtTestCase{int64(150), true, false, ""}, - gtTestCase{int64(151), true, false, ""}, - - // Unsigned integers. - gtTestCase{uint(0), false, false, ""}, - gtTestCase{uint(149), false, false, ""}, - gtTestCase{uint(150), true, false, ""}, - gtTestCase{uint(151), true, false, ""}, - - gtTestCase{uint8(0), false, false, ""}, - gtTestCase{uint8(127), false, false, ""}, - - gtTestCase{uint16(0), false, false, ""}, - gtTestCase{uint16(149), false, false, ""}, - gtTestCase{uint16(150), true, false, ""}, - gtTestCase{uint16(151), true, false, ""}, - - gtTestCase{uint32(0), false, false, ""}, - gtTestCase{uint32(149), false, false, ""}, - gtTestCase{uint32(150), true, false, ""}, - gtTestCase{uint32(151), true, false, ""}, - - gtTestCase{uint64(0), false, false, ""}, - gtTestCase{uint64(149), false, false, ""}, - gtTestCase{uint64(150), true, false, ""}, - gtTestCase{uint64(151), true, false, ""}, - - // Floating point. - gtTestCase{float32(-1), false, false, ""}, - gtTestCase{float32(149), false, false, ""}, - gtTestCase{float32(149.8), false, false, ""}, - gtTestCase{float32(149.9), false, false, ""}, - gtTestCase{float32(150), true, false, ""}, - gtTestCase{float32(151), true, false, ""}, - - gtTestCase{float64(-1), false, false, ""}, - gtTestCase{float64(149), false, false, ""}, - gtTestCase{float64(149.8), false, false, ""}, - gtTestCase{float64(149.9), false, false, ""}, - gtTestCase{float64(150), true, false, ""}, - gtTestCase{float64(151), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// Subtle cases -//////////////////////////////////////////////////////////////////////// - -func (t *GreaterThanTest) Int64NotExactlyRepresentableBySinglePrecision() { - // Single-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo25 = 1 << 25 - matcher := GreaterThan(int64(kTwoTo25 + 1)) - - desc := matcher.Description() - expectedDesc := "greater than 33554433" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []gtTestCase{ - // Signed integers. - gtTestCase{-1, false, false, ""}, - gtTestCase{kTwoTo25 + 0, false, false, ""}, - gtTestCase{kTwoTo25 + 1, false, false, ""}, - gtTestCase{kTwoTo25 + 2, true, false, ""}, - - gtTestCase{int(-1), false, false, ""}, - gtTestCase{int(kTwoTo25 + 0), false, false, ""}, - gtTestCase{int(kTwoTo25 + 1), false, false, ""}, - gtTestCase{int(kTwoTo25 + 2), true, false, ""}, - - gtTestCase{int8(-1), false, false, ""}, - gtTestCase{int8(127), false, false, ""}, - - gtTestCase{int16(-1), false, false, ""}, - gtTestCase{int16(0), false, false, ""}, - gtTestCase{int16(32767), false, false, ""}, - - gtTestCase{int32(-1), false, false, ""}, - gtTestCase{int32(kTwoTo25 + 0), false, false, ""}, - gtTestCase{int32(kTwoTo25 + 1), false, false, ""}, - gtTestCase{int32(kTwoTo25 + 2), true, false, ""}, - - gtTestCase{int64(-1), false, false, ""}, - gtTestCase{int64(kTwoTo25 + 0), false, false, ""}, - gtTestCase{int64(kTwoTo25 + 1), false, false, ""}, - gtTestCase{int64(kTwoTo25 + 2), true, false, ""}, - - // Unsigned integers. - gtTestCase{uint(0), false, false, ""}, - gtTestCase{uint(kTwoTo25 + 0), false, false, ""}, - gtTestCase{uint(kTwoTo25 + 1), false, false, ""}, - gtTestCase{uint(kTwoTo25 + 2), true, false, ""}, - - gtTestCase{uint8(0), false, false, ""}, - gtTestCase{uint8(255), false, false, ""}, - - gtTestCase{uint16(0), false, false, ""}, - gtTestCase{uint16(65535), false, false, ""}, - - gtTestCase{uint32(0), false, false, ""}, - gtTestCase{uint32(kTwoTo25 + 0), false, false, ""}, - gtTestCase{uint32(kTwoTo25 + 1), false, false, ""}, - gtTestCase{uint32(kTwoTo25 + 2), true, false, ""}, - - gtTestCase{uint64(0), false, false, ""}, - gtTestCase{uint64(kTwoTo25 + 0), false, false, ""}, - gtTestCase{uint64(kTwoTo25 + 1), false, false, ""}, - gtTestCase{uint64(kTwoTo25 + 2), true, false, ""}, - - // Floating point. - gtTestCase{float32(-1), false, false, ""}, - gtTestCase{float32(kTwoTo25 - 2), false, false, ""}, - gtTestCase{float32(kTwoTo25 - 1), false, false, ""}, - gtTestCase{float32(kTwoTo25 + 0), false, false, ""}, - gtTestCase{float32(kTwoTo25 + 1), false, false, ""}, - gtTestCase{float32(kTwoTo25 + 2), false, false, ""}, - gtTestCase{float32(kTwoTo25 + 3), true, false, ""}, - - gtTestCase{float64(-1), false, false, ""}, - gtTestCase{float64(kTwoTo25 - 2), false, false, ""}, - gtTestCase{float64(kTwoTo25 - 1), false, false, ""}, - gtTestCase{float64(kTwoTo25 + 0), false, false, ""}, - gtTestCase{float64(kTwoTo25 + 1), false, false, ""}, - gtTestCase{float64(kTwoTo25 + 2), true, false, ""}, - gtTestCase{float64(kTwoTo25 + 3), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterThanTest) Int64NotExactlyRepresentableByDoublePrecision() { - // Double-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo54 = 1 << 54 - matcher := GreaterThan(int64(kTwoTo54 + 1)) - - desc := matcher.Description() - expectedDesc := "greater than 18014398509481985" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []gtTestCase{ - // Signed integers. - gtTestCase{-1, false, false, ""}, - gtTestCase{1 << 30, false, false, ""}, - - gtTestCase{int(-1), false, false, ""}, - gtTestCase{int(math.MaxInt32), false, false, ""}, - - gtTestCase{int8(-1), false, false, ""}, - gtTestCase{int8(127), false, false, ""}, - - gtTestCase{int16(-1), false, false, ""}, - gtTestCase{int16(0), false, false, ""}, - gtTestCase{int16(32767), false, false, ""}, - - gtTestCase{int32(-1), false, false, ""}, - gtTestCase{int32(math.MaxInt32), false, false, ""}, - - gtTestCase{int64(-1), false, false, ""}, - gtTestCase{int64(kTwoTo54 - 1), false, false, ""}, - gtTestCase{int64(kTwoTo54 + 0), false, false, ""}, - gtTestCase{int64(kTwoTo54 + 1), false, false, ""}, - gtTestCase{int64(kTwoTo54 + 2), true, false, ""}, - - // Unsigned integers. - gtTestCase{uint(0), false, false, ""}, - gtTestCase{uint(math.MaxUint32), false, false, ""}, - - gtTestCase{uint8(0), false, false, ""}, - gtTestCase{uint8(255), false, false, ""}, - - gtTestCase{uint16(0), false, false, ""}, - gtTestCase{uint16(65535), false, false, ""}, - - gtTestCase{uint32(0), false, false, ""}, - gtTestCase{uint32(math.MaxUint32), false, false, ""}, - - gtTestCase{uint64(0), false, false, ""}, - gtTestCase{uint64(kTwoTo54 - 1), false, false, ""}, - gtTestCase{uint64(kTwoTo54 + 0), false, false, ""}, - gtTestCase{uint64(kTwoTo54 + 1), false, false, ""}, - gtTestCase{uint64(kTwoTo54 + 2), true, false, ""}, - - // Floating point. - gtTestCase{float64(-1), false, false, ""}, - gtTestCase{float64(kTwoTo54 - 2), false, false, ""}, - gtTestCase{float64(kTwoTo54 - 1), false, false, ""}, - gtTestCase{float64(kTwoTo54 + 0), false, false, ""}, - gtTestCase{float64(kTwoTo54 + 1), false, false, ""}, - gtTestCase{float64(kTwoTo54 + 2), false, false, ""}, - gtTestCase{float64(kTwoTo54 + 3), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterThanTest) Uint64NotExactlyRepresentableBySinglePrecision() { - // Single-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo25 = 1 << 25 - matcher := GreaterThan(uint64(kTwoTo25 + 1)) - - desc := matcher.Description() - expectedDesc := "greater than 33554433" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []gtTestCase{ - // Signed integers. - gtTestCase{-1, false, false, ""}, - gtTestCase{kTwoTo25 + 0, false, false, ""}, - gtTestCase{kTwoTo25 + 1, false, false, ""}, - gtTestCase{kTwoTo25 + 2, true, false, ""}, - - gtTestCase{int(-1), false, false, ""}, - gtTestCase{int(kTwoTo25 + 0), false, false, ""}, - gtTestCase{int(kTwoTo25 + 1), false, false, ""}, - gtTestCase{int(kTwoTo25 + 2), true, false, ""}, - - gtTestCase{int8(-1), false, false, ""}, - gtTestCase{int8(127), false, false, ""}, - - gtTestCase{int16(-1), false, false, ""}, - gtTestCase{int16(0), false, false, ""}, - gtTestCase{int16(32767), false, false, ""}, - - gtTestCase{int32(-1), false, false, ""}, - gtTestCase{int32(kTwoTo25 + 0), false, false, ""}, - gtTestCase{int32(kTwoTo25 + 1), false, false, ""}, - gtTestCase{int32(kTwoTo25 + 2), true, false, ""}, - - gtTestCase{int64(-1), false, false, ""}, - gtTestCase{int64(kTwoTo25 + 0), false, false, ""}, - gtTestCase{int64(kTwoTo25 + 1), false, false, ""}, - gtTestCase{int64(kTwoTo25 + 2), true, false, ""}, - - // Unsigned integers. - gtTestCase{uint(0), false, false, ""}, - gtTestCase{uint(kTwoTo25 + 0), false, false, ""}, - gtTestCase{uint(kTwoTo25 + 1), false, false, ""}, - gtTestCase{uint(kTwoTo25 + 2), true, false, ""}, - - gtTestCase{uint8(0), false, false, ""}, - gtTestCase{uint8(255), false, false, ""}, - - gtTestCase{uint16(0), false, false, ""}, - gtTestCase{uint16(65535), false, false, ""}, - - gtTestCase{uint32(0), false, false, ""}, - gtTestCase{uint32(kTwoTo25 + 0), false, false, ""}, - gtTestCase{uint32(kTwoTo25 + 1), false, false, ""}, - gtTestCase{uint32(kTwoTo25 + 2), true, false, ""}, - - gtTestCase{uint64(0), false, false, ""}, - gtTestCase{uint64(kTwoTo25 + 0), false, false, ""}, - gtTestCase{uint64(kTwoTo25 + 1), false, false, ""}, - gtTestCase{uint64(kTwoTo25 + 2), true, false, ""}, - - // Floating point. - gtTestCase{float32(-1), false, false, ""}, - gtTestCase{float32(kTwoTo25 - 2), false, false, ""}, - gtTestCase{float32(kTwoTo25 - 1), false, false, ""}, - gtTestCase{float32(kTwoTo25 + 0), false, false, ""}, - gtTestCase{float32(kTwoTo25 + 1), false, false, ""}, - gtTestCase{float32(kTwoTo25 + 2), false, false, ""}, - gtTestCase{float32(kTwoTo25 + 3), true, false, ""}, - - gtTestCase{float64(-1), false, false, ""}, - gtTestCase{float64(kTwoTo25 - 2), false, false, ""}, - gtTestCase{float64(kTwoTo25 - 1), false, false, ""}, - gtTestCase{float64(kTwoTo25 + 0), false, false, ""}, - gtTestCase{float64(kTwoTo25 + 1), false, false, ""}, - gtTestCase{float64(kTwoTo25 + 2), true, false, ""}, - gtTestCase{float64(kTwoTo25 + 3), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterThanTest) Uint64NotExactlyRepresentableByDoublePrecision() { - // Double-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo54 = 1 << 54 - matcher := GreaterThan(uint64(kTwoTo54 + 1)) - - desc := matcher.Description() - expectedDesc := "greater than 18014398509481985" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []gtTestCase{ - // Signed integers. - gtTestCase{-1, false, false, ""}, - gtTestCase{1 << 30, false, false, ""}, - - gtTestCase{int(-1), false, false, ""}, - gtTestCase{int(math.MaxInt32), false, false, ""}, - - gtTestCase{int8(-1), false, false, ""}, - gtTestCase{int8(127), false, false, ""}, - - gtTestCase{int16(-1), false, false, ""}, - gtTestCase{int16(0), false, false, ""}, - gtTestCase{int16(32767), false, false, ""}, - - gtTestCase{int32(-1), false, false, ""}, - gtTestCase{int32(math.MaxInt32), false, false, ""}, - - gtTestCase{int64(-1), false, false, ""}, - gtTestCase{int64(kTwoTo54 - 1), false, false, ""}, - gtTestCase{int64(kTwoTo54 + 0), false, false, ""}, - gtTestCase{int64(kTwoTo54 + 1), false, false, ""}, - gtTestCase{int64(kTwoTo54 + 2), true, false, ""}, - - // Unsigned integers. - gtTestCase{uint(0), false, false, ""}, - gtTestCase{uint(math.MaxUint32), false, false, ""}, - - gtTestCase{uint8(0), false, false, ""}, - gtTestCase{uint8(255), false, false, ""}, - - gtTestCase{uint16(0), false, false, ""}, - gtTestCase{uint16(65535), false, false, ""}, - - gtTestCase{uint32(0), false, false, ""}, - gtTestCase{uint32(math.MaxUint32), false, false, ""}, - - gtTestCase{uint64(0), false, false, ""}, - gtTestCase{uint64(kTwoTo54 - 1), false, false, ""}, - gtTestCase{uint64(kTwoTo54 + 0), false, false, ""}, - gtTestCase{uint64(kTwoTo54 + 1), false, false, ""}, - gtTestCase{uint64(kTwoTo54 + 2), true, false, ""}, - - // Floating point. - gtTestCase{float64(-1), false, false, ""}, - gtTestCase{float64(kTwoTo54 - 2), false, false, ""}, - gtTestCase{float64(kTwoTo54 - 1), false, false, ""}, - gtTestCase{float64(kTwoTo54 + 0), false, false, ""}, - gtTestCase{float64(kTwoTo54 + 1), false, false, ""}, - gtTestCase{float64(kTwoTo54 + 2), false, false, ""}, - gtTestCase{float64(kTwoTo54 + 3), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterThanTest) Float32AboveExactIntegerRange() { - // Single-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo25 = 1 << 25 - matcher := GreaterThan(float32(kTwoTo25 + 1)) - - desc := matcher.Description() - expectedDesc := "greater than 3.3554432e+07" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []gtTestCase{ - // Signed integers. - gtTestCase{int64(-1), false, false, ""}, - gtTestCase{int64(kTwoTo25 - 2), false, false, ""}, - gtTestCase{int64(kTwoTo25 - 1), false, false, ""}, - gtTestCase{int64(kTwoTo25 + 0), false, false, ""}, - gtTestCase{int64(kTwoTo25 + 1), false, false, ""}, - gtTestCase{int64(kTwoTo25 + 2), false, false, ""}, - gtTestCase{int64(kTwoTo25 + 3), true, false, ""}, - - // Unsigned integers. - gtTestCase{uint64(0), false, false, ""}, - gtTestCase{uint64(kTwoTo25 - 2), false, false, ""}, - gtTestCase{uint64(kTwoTo25 - 1), false, false, ""}, - gtTestCase{uint64(kTwoTo25 + 0), false, false, ""}, - gtTestCase{uint64(kTwoTo25 + 1), false, false, ""}, - gtTestCase{uint64(kTwoTo25 + 2), false, false, ""}, - gtTestCase{uint64(kTwoTo25 + 3), true, false, ""}, - - // Floating point. - gtTestCase{float32(-1), false, false, ""}, - gtTestCase{float32(kTwoTo25 - 2), false, false, ""}, - gtTestCase{float32(kTwoTo25 - 1), false, false, ""}, - gtTestCase{float32(kTwoTo25 + 0), false, false, ""}, - gtTestCase{float32(kTwoTo25 + 1), false, false, ""}, - gtTestCase{float32(kTwoTo25 + 2), false, false, ""}, - gtTestCase{float32(kTwoTo25 + 3), true, false, ""}, - - gtTestCase{float64(-1), false, false, ""}, - gtTestCase{float64(kTwoTo25 - 2), false, false, ""}, - gtTestCase{float64(kTwoTo25 - 1), false, false, ""}, - gtTestCase{float64(kTwoTo25 + 0), false, false, ""}, - gtTestCase{float64(kTwoTo25 + 1), false, false, ""}, - gtTestCase{float64(kTwoTo25 + 2), false, false, ""}, - gtTestCase{float64(kTwoTo25 + 3), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterThanTest) Float64AboveExactIntegerRange() { - // Double-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo54 = 1 << 54 - matcher := GreaterThan(float64(kTwoTo54 + 1)) - - desc := matcher.Description() - expectedDesc := "greater than 1.8014398509481984e+16" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []gtTestCase{ - // Signed integers. - gtTestCase{int64(-1), false, false, ""}, - gtTestCase{int64(kTwoTo54 - 2), false, false, ""}, - gtTestCase{int64(kTwoTo54 - 1), false, false, ""}, - gtTestCase{int64(kTwoTo54 + 0), false, false, ""}, - gtTestCase{int64(kTwoTo54 + 1), false, false, ""}, - gtTestCase{int64(kTwoTo54 + 2), false, false, ""}, - gtTestCase{int64(kTwoTo54 + 3), true, false, ""}, - - // Unsigned integers. - gtTestCase{uint64(0), false, false, ""}, - gtTestCase{uint64(kTwoTo54 - 2), false, false, ""}, - gtTestCase{uint64(kTwoTo54 - 1), false, false, ""}, - gtTestCase{uint64(kTwoTo54 + 0), false, false, ""}, - gtTestCase{uint64(kTwoTo54 + 1), false, false, ""}, - gtTestCase{uint64(kTwoTo54 + 2), false, false, ""}, - gtTestCase{uint64(kTwoTo54 + 3), true, false, ""}, - - // Floating point. - gtTestCase{float64(-1), false, false, ""}, - gtTestCase{float64(kTwoTo54 - 2), false, false, ""}, - gtTestCase{float64(kTwoTo54 - 1), false, false, ""}, - gtTestCase{float64(kTwoTo54 + 0), false, false, ""}, - gtTestCase{float64(kTwoTo54 + 1), false, false, ""}, - gtTestCase{float64(kTwoTo54 + 2), false, false, ""}, - gtTestCase{float64(kTwoTo54 + 3), true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// String literals -//////////////////////////////////////////////////////////////////////// - -func (t *GreaterThanTest) EmptyString() { - matcher := GreaterThan("") - desc := matcher.Description() - expectedDesc := "greater than \"\"" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []gtTestCase{ - gtTestCase{"", false, false, ""}, - gtTestCase{"\x00", true, false, ""}, - gtTestCase{"a", true, false, ""}, - gtTestCase{"foo", true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterThanTest) SingleNullByte() { - matcher := GreaterThan("\x00") - desc := matcher.Description() - expectedDesc := "greater than \"\x00\"" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []gtTestCase{ - gtTestCase{"", false, false, ""}, - gtTestCase{"\x00", false, false, ""}, - gtTestCase{"\x00\x00", true, false, ""}, - gtTestCase{"a", true, false, ""}, - gtTestCase{"foo", true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *GreaterThanTest) LongerString() { - matcher := GreaterThan("foo\x00") - desc := matcher.Description() - expectedDesc := "greater than \"foo\x00\"" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []gtTestCase{ - gtTestCase{"", false, false, ""}, - gtTestCase{"\x00", false, false, ""}, - gtTestCase{"bar", false, false, ""}, - gtTestCase{"foo", false, false, ""}, - gtTestCase{"foo\x00", false, false, ""}, - gtTestCase{"foo\x00\x00", true, false, ""}, - gtTestCase{"fooa", true, false, ""}, - gtTestCase{"qux", true, false, ""}, - } - - t.checkTestCases(matcher, cases) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/has_substr_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/has_substr_test.go deleted file mode 100644 index be9f317006b..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/has_substr_test.go +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type HasSubstrTest struct { -} - -func init() { RegisterTestSuite(&HasSubstrTest{}) } - -//////////////////////////////////////////////////////////////////////// -// Tests -//////////////////////////////////////////////////////////////////////// - -func (t *HasSubstrTest) Description() { - matcher := HasSubstr("taco") - ExpectThat(matcher.Description(), Equals("has substring \"taco\"")) -} - -func (t *HasSubstrTest) CandidateIsNil() { - matcher := HasSubstr("") - err := matcher.Matches(nil) - - ExpectThat(err, Error(Equals("which is not a string"))) - ExpectTrue(isFatal(err)) -} - -func (t *HasSubstrTest) CandidateIsInteger() { - matcher := HasSubstr("") - err := matcher.Matches(17) - - ExpectThat(err, Error(Equals("which is not a string"))) - ExpectTrue(isFatal(err)) -} - -func (t *HasSubstrTest) CandidateIsByteSlice() { - matcher := HasSubstr("") - err := matcher.Matches([]byte{17}) - - ExpectThat(err, Error(Equals("which is not a string"))) - ExpectTrue(isFatal(err)) -} - -func (t *HasSubstrTest) CandidateDoesntHaveSubstring() { - matcher := HasSubstr("taco") - err := matcher.Matches("tac") - - ExpectThat(err, Error(Equals(""))) - ExpectFalse(isFatal(err)) -} - -func (t *HasSubstrTest) CandidateEqualsArg() { - matcher := HasSubstr("taco") - err := matcher.Matches("taco") - - ExpectThat(err, Equals(nil)) -} - -func (t *HasSubstrTest) CandidateHasProperSubstring() { - matcher := HasSubstr("taco") - err := matcher.Matches("burritos and tacos") - - ExpectThat(err, Equals(nil)) -} - -func (t *HasSubstrTest) EmptyStringIsAlwaysSubString() { - matcher := HasSubstr("") - err := matcher.Matches("asdf") - - ExpectThat(err, Equals(nil)) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/identical_to_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/identical_to_test.go deleted file mode 100644 index 19236671437..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/identical_to_test.go +++ /dev/null @@ -1,849 +0,0 @@ -// Copyright 2012 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - "fmt" - "io" - "unsafe" - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type IdenticalToTest struct { -} - -func init() { RegisterTestSuite(&IdenticalToTest{}) } - -//////////////////////////////////////////////////////////////////////// -// Tests -//////////////////////////////////////////////////////////////////////// - -func (t *IdenticalToTest) TypesNotIdentical() { - var m Matcher - var err error - - type intAlias int - - // Type alias expected value - m = IdenticalTo(intAlias(17)) - err = m.Matches(int(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int"))) - - // Type alias candidate - m = IdenticalTo(int(17)) - err = m.Matches(intAlias(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type oglematchers_test.intAlias"))) - - // int and uint - m = IdenticalTo(int(17)) - err = m.Matches(uint(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type uint"))) -} - -func (t *IdenticalToTest) PredeclaredNilIdentifier() { - var m Matcher - var err error - - // Nil literal - m = IdenticalTo(nil) - err = m.Matches(nil) - ExpectEq(nil, err) - - // Zero interface var (which is the same as above since IdenticalTo takes an - // interface{} as an arg) - var nilReader io.Reader - var nilWriter io.Writer - - m = IdenticalTo(nilReader) - err = m.Matches(nilWriter) - ExpectEq(nil, err) - - // Typed nil value. - m = IdenticalTo(nil) - err = m.Matches((chan int)(nil)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type chan int"))) - - // Non-nil value. - m = IdenticalTo(nil) - err = m.Matches("taco") - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type string"))) -} - -func (t *IdenticalToTest) Slices() { - var m Matcher - var err error - - // Nil expected value - m = IdenticalTo(([]int)(nil)) - ExpectEq("identical to <[]int> []", m.Description()) - - err = m.Matches(([]int)(nil)) - ExpectEq(nil, err) - - err = m.Matches([]int{}) - ExpectThat(err, Error(Equals("which is not an identical reference"))) - - // Non-nil expected value - o1 := make([]int, 1) - o2 := make([]int, 1) - m = IdenticalTo(o1) - ExpectEq(fmt.Sprintf("identical to <[]int> %v", o1), m.Description()) - - err = m.Matches(o1) - ExpectEq(nil, err) - - err = m.Matches(o2) - ExpectThat(err, Error(Equals("which is not an identical reference"))) -} - -func (t *IdenticalToTest) Maps() { - var m Matcher - var err error - - // Nil expected value - m = IdenticalTo((map[int]int)(nil)) - ExpectEq("identical to map[]", m.Description()) - - err = m.Matches((map[int]int)(nil)) - ExpectEq(nil, err) - - err = m.Matches(map[int]int{}) - ExpectThat(err, Error(Equals("which is not an identical reference"))) - - // Non-nil expected value - o1 := map[int]int{} - o2 := map[int]int{} - m = IdenticalTo(o1) - ExpectEq(fmt.Sprintf("identical to %v", o1), m.Description()) - - err = m.Matches(o1) - ExpectEq(nil, err) - - err = m.Matches(o2) - ExpectThat(err, Error(Equals("which is not an identical reference"))) -} - -func (t *IdenticalToTest) Functions() { - var m Matcher - var err error - - // Nil expected value - m = IdenticalTo((func())(nil)) - ExpectEq("identical to ", m.Description()) - - err = m.Matches((func())(nil)) - ExpectEq(nil, err) - - err = m.Matches(func() {}) - ExpectThat(err, Error(Equals("which is not an identical reference"))) - - // Non-nil expected value - o1 := func() {} - o2 := func() {} - m = IdenticalTo(o1) - ExpectEq(fmt.Sprintf("identical to %v", o1), m.Description()) - - err = m.Matches(o1) - ExpectEq(nil, err) - - err = m.Matches(o2) - ExpectThat(err, Error(Equals("which is not an identical reference"))) -} - -func (t *IdenticalToTest) Channels() { - var m Matcher - var err error - - // Nil expected value - m = IdenticalTo((chan int)(nil)) - ExpectEq("identical to ", m.Description()) - - err = m.Matches((chan int)(nil)) - ExpectEq(nil, err) - - err = m.Matches(make(chan int)) - ExpectThat(err, Error(Equals("which is not an identical reference"))) - - // Non-nil expected value - o1 := make(chan int) - o2 := make(chan int) - m = IdenticalTo(o1) - ExpectEq(fmt.Sprintf("identical to %v", o1), m.Description()) - - err = m.Matches(o1) - ExpectEq(nil, err) - - err = m.Matches(o2) - ExpectThat(err, Error(Equals("which is not an identical reference"))) -} - -func (t *IdenticalToTest) Bools() { - var m Matcher - var err error - - // false - m = IdenticalTo(false) - ExpectEq("identical to false", m.Description()) - - err = m.Matches(false) - ExpectEq(nil, err) - - err = m.Matches(true) - ExpectThat(err, Error(Equals(""))) - - // true - m = IdenticalTo(true) - ExpectEq("identical to true", m.Description()) - - err = m.Matches(false) - ExpectThat(err, Error(Equals(""))) - - err = m.Matches(true) - ExpectEq(nil, err) -} - -func (t *IdenticalToTest) Ints() { - var m Matcher - var err error - - m = IdenticalTo(int(17)) - ExpectEq("identical to 17", m.Description()) - - // Identical value - err = m.Matches(int(17)) - ExpectEq(nil, err) - - // Type alias - type myType int - err = m.Matches(myType(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) - - // Completely wrong type - err = m.Matches(int32(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int32"))) -} - -func (t *IdenticalToTest) Int8s() { - var m Matcher - var err error - - m = IdenticalTo(int8(17)) - ExpectEq("identical to 17", m.Description()) - - // Identical value - err = m.Matches(int8(17)) - ExpectEq(nil, err) - - // Type alias - type myType int8 - err = m.Matches(myType(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) - - // Completely wrong type - err = m.Matches(int32(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int32"))) -} - -func (t *IdenticalToTest) Int16s() { - var m Matcher - var err error - - m = IdenticalTo(int16(17)) - ExpectEq("identical to 17", m.Description()) - - // Identical value - err = m.Matches(int16(17)) - ExpectEq(nil, err) - - // Type alias - type myType int16 - err = m.Matches(myType(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) - - // Completely wrong type - err = m.Matches(int32(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int32"))) -} - -func (t *IdenticalToTest) Int32s() { - var m Matcher - var err error - - m = IdenticalTo(int32(17)) - ExpectEq("identical to 17", m.Description()) - - // Identical value - err = m.Matches(int32(17)) - ExpectEq(nil, err) - - // Type alias - type myType int32 - err = m.Matches(myType(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) - - // Completely wrong type - err = m.Matches(int16(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int16"))) -} - -func (t *IdenticalToTest) Int64s() { - var m Matcher - var err error - - m = IdenticalTo(int64(17)) - ExpectEq("identical to 17", m.Description()) - - // Identical value - err = m.Matches(int64(17)) - ExpectEq(nil, err) - - // Type alias - type myType int64 - err = m.Matches(myType(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) - - // Completely wrong type - err = m.Matches(int32(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int32"))) -} - -func (t *IdenticalToTest) Uints() { - var m Matcher - var err error - - m = IdenticalTo(uint(17)) - ExpectEq("identical to 17", m.Description()) - - // Identical value - err = m.Matches(uint(17)) - ExpectEq(nil, err) - - // Type alias - type myType uint - err = m.Matches(myType(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) - - // Completely wrong type - err = m.Matches(int32(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int32"))) -} - -func (t *IdenticalToTest) Uint8s() { - var m Matcher - var err error - - m = IdenticalTo(uint8(17)) - ExpectEq("identical to 17", m.Description()) - - // Identical value - err = m.Matches(uint8(17)) - ExpectEq(nil, err) - - // Type alias - type myType uint8 - err = m.Matches(myType(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) - - // Completely wrong type - err = m.Matches(int32(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int32"))) -} - -func (t *IdenticalToTest) Uint16s() { - var m Matcher - var err error - - m = IdenticalTo(uint16(17)) - ExpectEq("identical to 17", m.Description()) - - // Identical value - err = m.Matches(uint16(17)) - ExpectEq(nil, err) - - // Type alias - type myType uint16 - err = m.Matches(myType(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) - - // Completely wrong type - err = m.Matches(int32(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int32"))) -} - -func (t *IdenticalToTest) Uint32s() { - var m Matcher - var err error - - m = IdenticalTo(uint32(17)) - ExpectEq("identical to 17", m.Description()) - - // Identical value - err = m.Matches(uint32(17)) - ExpectEq(nil, err) - - // Type alias - type myType uint32 - err = m.Matches(myType(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) - - // Completely wrong type - err = m.Matches(int32(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int32"))) -} - -func (t *IdenticalToTest) Uint64s() { - var m Matcher - var err error - - m = IdenticalTo(uint64(17)) - ExpectEq("identical to 17", m.Description()) - - // Identical value - err = m.Matches(uint64(17)) - ExpectEq(nil, err) - - // Type alias - type myType uint64 - err = m.Matches(myType(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) - - // Completely wrong type - err = m.Matches(int32(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int32"))) -} - -func (t *IdenticalToTest) Uintptrs() { - var m Matcher - var err error - - m = IdenticalTo(uintptr(17)) - ExpectEq("identical to 17", m.Description()) - - // Identical value - err = m.Matches(uintptr(17)) - ExpectEq(nil, err) - - // Type alias - type myType uintptr - err = m.Matches(myType(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) - - // Completely wrong type - err = m.Matches(int32(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int32"))) -} - -func (t *IdenticalToTest) Float32s() { - var m Matcher - var err error - - m = IdenticalTo(float32(17)) - ExpectEq("identical to 17", m.Description()) - - // Identical value - err = m.Matches(float32(17)) - ExpectEq(nil, err) - - // Type alias - type myType float32 - err = m.Matches(myType(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) - - // Completely wrong type - err = m.Matches(int32(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int32"))) -} - -func (t *IdenticalToTest) Float64s() { - var m Matcher - var err error - - m = IdenticalTo(float64(17)) - ExpectEq("identical to 17", m.Description()) - - // Identical value - err = m.Matches(float64(17)) - ExpectEq(nil, err) - - // Type alias - type myType float64 - err = m.Matches(myType(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) - - // Completely wrong type - err = m.Matches(int32(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int32"))) -} - -func (t *IdenticalToTest) Complex64s() { - var m Matcher - var err error - - m = IdenticalTo(complex64(17)) - ExpectEq("identical to (17+0i)", m.Description()) - - // Identical value - err = m.Matches(complex64(17)) - ExpectEq(nil, err) - - // Type alias - type myType complex64 - err = m.Matches(myType(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) - - // Completely wrong type - err = m.Matches(int32(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int32"))) -} - -func (t *IdenticalToTest) Complex128s() { - var m Matcher - var err error - - m = IdenticalTo(complex128(17)) - ExpectEq("identical to (17+0i)", m.Description()) - - // Identical value - err = m.Matches(complex128(17)) - ExpectEq(nil, err) - - // Type alias - type myType complex128 - err = m.Matches(myType(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) - - // Completely wrong type - err = m.Matches(int32(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int32"))) -} - -func (t *IdenticalToTest) EmptyComparableArrays() { - var m Matcher - var err error - - m = IdenticalTo([0]int{}) - ExpectEq("identical to <[0]int> []", m.Description()) - - // Identical value - err = m.Matches([0]int{}) - ExpectEq(nil, err) - - // Length too long - err = m.Matches([1]int{17}) - ExpectThat(err, Error(Equals("which is of type [1]int"))) - - // Element type alias - type myType int - err = m.Matches([0]myType{}) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type [0]oglematchers_test.myType"))) - - // Completely wrong element type - err = m.Matches([0]int32{}) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type [0]int32"))) -} - -func (t *IdenticalToTest) NonEmptyComparableArrays() { - var m Matcher - var err error - - m = IdenticalTo([2]int{17, 19}) - ExpectEq("identical to <[2]int> [17 19]", m.Description()) - - // Identical value - err = m.Matches([2]int{17, 19}) - ExpectEq(nil, err) - - // Length too short - err = m.Matches([1]int{17}) - ExpectThat(err, Error(Equals("which is of type [1]int"))) - - // Length too long - err = m.Matches([3]int{17, 19, 23}) - ExpectThat(err, Error(Equals("which is of type [3]int"))) - - // First element different - err = m.Matches([2]int{13, 19}) - ExpectThat(err, Error(Equals(""))) - - // Second element different - err = m.Matches([2]int{17, 23}) - ExpectThat(err, Error(Equals(""))) - - // Element type alias - type myType int - err = m.Matches([2]myType{17, 19}) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type [2]oglematchers_test.myType"))) - - // Completely wrong element type - err = m.Matches([2]int32{17, 19}) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type [2]int32"))) -} - -func (t *IdenticalToTest) NonEmptyArraysOfComparableArrays() { - var m Matcher - var err error - - x := [2][2]int{ - [2]int{17, 19}, - [2]int{23, 29}, - } - m = IdenticalTo(x) - ExpectEq("identical to <[2][2]int> [[17 19] [23 29]]", m.Description()) - - // Identical value - err = m.Matches([2][2]int{[2]int{17, 19}, [2]int{23, 29}}) - ExpectEq(nil, err) - - // Outer length too short - err = m.Matches([1][2]int{[2]int{17, 19}}) - ExpectThat(err, Error(Equals("which is of type [1][2]int"))) - - // Inner length too short - err = m.Matches([2][1]int{[1]int{17}, [1]int{23}}) - ExpectThat(err, Error(Equals("which is of type [2][1]int"))) - - // First element different - err = m.Matches([2][2]int{[2]int{13, 19}, [2]int{23, 29}}) - ExpectThat(err, Error(Equals(""))) - - // Element type alias - type myType int - err = m.Matches([2][2]myType{[2]myType{17, 19}, [2]myType{23, 29}}) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type [2][2]oglematchers_test.myType"))) -} - -func (t *IdenticalToTest) NonComparableArrays() { - x := [0]func(){} - f := func() { IdenticalTo(x) } - ExpectThat(f, Panics(HasSubstr("is not comparable"))) -} - -func (t *IdenticalToTest) ArraysOfNonComparableArrays() { - x := [0][0]func(){} - f := func() { IdenticalTo(x) } - ExpectThat(f, Panics(HasSubstr("is not comparable"))) -} - -func (t *IdenticalToTest) Strings() { - var m Matcher - var err error - - m = IdenticalTo("taco") - ExpectEq("identical to taco", m.Description()) - - // Identical value - err = m.Matches("ta" + "co") - ExpectEq(nil, err) - - // Type alias - type myType string - err = m.Matches(myType("taco")) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) - - // Completely wrong type - err = m.Matches(int32(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int32"))) -} - -func (t *IdenticalToTest) ComparableStructs() { - var m Matcher - var err error - - type subStruct struct { - i int - } - - type myStruct struct { - u uint - s subStruct - } - - x := myStruct{17, subStruct{19}} - m = IdenticalTo(x) - ExpectEq("identical to {17 {19}}", m.Description()) - - // Identical value - err = m.Matches(myStruct{17, subStruct{19}}) - ExpectEq(nil, err) - - // Wrong outer field - err = m.Matches(myStruct{13, subStruct{19}}) - ExpectThat(err, Error(Equals(""))) - - // Wrong inner field - err = m.Matches(myStruct{17, subStruct{23}}) - ExpectThat(err, Error(Equals(""))) - - // Type alias - type myType myStruct - err = m.Matches(myType{17, subStruct{19}}) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) - - // Completely wrong type - err = m.Matches(int32(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int32"))) -} - -func (t *IdenticalToTest) NonComparableStructs() { - type subStruct struct { - s []int - } - - type myStruct struct { - u uint - s subStruct - } - - x := myStruct{17, subStruct{[]int{19}}} - f := func() { IdenticalTo(x) } - ExpectThat(f, Panics(AllOf(HasSubstr("IdenticalTo"), HasSubstr("comparable")))) -} - -func (t *IdenticalToTest) NilUnsafePointer() { - var m Matcher - var err error - - x := unsafe.Pointer(nil) - m = IdenticalTo(x) - ExpectEq(fmt.Sprintf("identical to %v", x), m.Description()) - - // Identical value - err = m.Matches(unsafe.Pointer(nil)) - ExpectEq(nil, err) - - // Wrong value - j := 17 - err = m.Matches(unsafe.Pointer(&j)) - ExpectThat(err, Error(Equals(""))) - - // Type alias - type myType unsafe.Pointer - err = m.Matches(myType(unsafe.Pointer(nil))) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) - - // Completely wrong type - err = m.Matches(int32(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int32"))) -} - -func (t *IdenticalToTest) NonNilUnsafePointer() { - var m Matcher - var err error - - i := 17 - x := unsafe.Pointer(&i) - m = IdenticalTo(x) - ExpectEq(fmt.Sprintf("identical to %v", x), m.Description()) - - // Identical value - err = m.Matches(unsafe.Pointer(&i)) - ExpectEq(nil, err) - - // Nil value - err = m.Matches(unsafe.Pointer(nil)) - ExpectThat(err, Error(Equals(""))) - - // Wrong value - j := 17 - err = m.Matches(unsafe.Pointer(&j)) - ExpectThat(err, Error(Equals(""))) - - // Type alias - type myType unsafe.Pointer - err = m.Matches(myType(unsafe.Pointer(&i))) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) - - // Completely wrong type - err = m.Matches(int32(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int32"))) -} - -func (t *IdenticalToTest) IntAlias() { - var m Matcher - var err error - - type intAlias int - - m = IdenticalTo(intAlias(17)) - ExpectEq("identical to 17", m.Description()) - - // Identical value - err = m.Matches(intAlias(17)) - ExpectEq(nil, err) - - // Int - err = m.Matches(int(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int"))) - - // Completely wrong type - err = m.Matches(int32(17)) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("which is of type int32"))) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/less_or_equal_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/less_or_equal_test.go deleted file mode 100644 index 1fb9d128b0a..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/less_or_equal_test.go +++ /dev/null @@ -1,1079 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - "math" - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type LessOrEqualTest struct { -} - -func init() { RegisterTestSuite(&LessOrEqualTest{}) } - -type leTestCase struct { - candidate interface{} - expectedResult bool - shouldBeFatal bool - expectedError string -} - -func (t *LessOrEqualTest) checkTestCases(matcher Matcher, cases []leTestCase) { - for i, c := range cases { - err := matcher.Matches(c.candidate) - - ExpectThat( - (err == nil), - Equals(c.expectedResult), - "Case %d (candidate %v)", - i, - c.candidate) - - if err == nil { - continue - } - - _, isFatal := err.(*FatalError) - ExpectEq( - c.shouldBeFatal, - isFatal, - "Case %d (candidate %v)", - i, - c.candidate) - - ExpectThat( - err, - Error(Equals(c.expectedError)), - "Case %d (candidate %v)", - i, - c.candidate) - } -} - -//////////////////////////////////////////////////////////////////////// -// Integer literals -//////////////////////////////////////////////////////////////////////// - -func (t *LessOrEqualTest) IntegerCandidateBadTypes() { - matcher := LessOrEqual(int(-150)) - - cases := []leTestCase{ - leTestCase{true, false, true, "which is not comparable"}, - leTestCase{uintptr(17), false, true, "which is not comparable"}, - leTestCase{complex64(-151), false, true, "which is not comparable"}, - leTestCase{complex128(-151), false, true, "which is not comparable"}, - leTestCase{[...]int{-151}, false, true, "which is not comparable"}, - leTestCase{make(chan int), false, true, "which is not comparable"}, - leTestCase{func() {}, false, true, "which is not comparable"}, - leTestCase{map[int]int{}, false, true, "which is not comparable"}, - leTestCase{&leTestCase{}, false, true, "which is not comparable"}, - leTestCase{make([]int, 0), false, true, "which is not comparable"}, - leTestCase{"-151", false, true, "which is not comparable"}, - leTestCase{leTestCase{}, false, true, "which is not comparable"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessOrEqualTest) FloatCandidateBadTypes() { - matcher := LessOrEqual(float32(-150)) - - cases := []leTestCase{ - leTestCase{true, false, true, "which is not comparable"}, - leTestCase{uintptr(17), false, true, "which is not comparable"}, - leTestCase{complex64(-151), false, true, "which is not comparable"}, - leTestCase{complex128(-151), false, true, "which is not comparable"}, - leTestCase{[...]int{-151}, false, true, "which is not comparable"}, - leTestCase{make(chan int), false, true, "which is not comparable"}, - leTestCase{func() {}, false, true, "which is not comparable"}, - leTestCase{map[int]int{}, false, true, "which is not comparable"}, - leTestCase{&leTestCase{}, false, true, "which is not comparable"}, - leTestCase{make([]int, 0), false, true, "which is not comparable"}, - leTestCase{"-151", false, true, "which is not comparable"}, - leTestCase{leTestCase{}, false, true, "which is not comparable"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessOrEqualTest) StringCandidateBadTypes() { - matcher := LessOrEqual("17") - - cases := []leTestCase{ - leTestCase{true, false, true, "which is not comparable"}, - leTestCase{int(0), false, true, "which is not comparable"}, - leTestCase{int8(0), false, true, "which is not comparable"}, - leTestCase{int16(0), false, true, "which is not comparable"}, - leTestCase{int32(0), false, true, "which is not comparable"}, - leTestCase{int64(0), false, true, "which is not comparable"}, - leTestCase{uint(0), false, true, "which is not comparable"}, - leTestCase{uint8(0), false, true, "which is not comparable"}, - leTestCase{uint16(0), false, true, "which is not comparable"}, - leTestCase{uint32(0), false, true, "which is not comparable"}, - leTestCase{uint64(0), false, true, "which is not comparable"}, - leTestCase{uintptr(17), false, true, "which is not comparable"}, - leTestCase{float32(0), false, true, "which is not comparable"}, - leTestCase{float64(0), false, true, "which is not comparable"}, - leTestCase{complex64(-151), false, true, "which is not comparable"}, - leTestCase{complex128(-151), false, true, "which is not comparable"}, - leTestCase{[...]int{-151}, false, true, "which is not comparable"}, - leTestCase{make(chan int), false, true, "which is not comparable"}, - leTestCase{func() {}, false, true, "which is not comparable"}, - leTestCase{map[int]int{}, false, true, "which is not comparable"}, - leTestCase{&leTestCase{}, false, true, "which is not comparable"}, - leTestCase{make([]int, 0), false, true, "which is not comparable"}, - leTestCase{leTestCase{}, false, true, "which is not comparable"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessOrEqualTest) BadArgument() { - panicked := false - - defer func() { - ExpectThat(panicked, Equals(true)) - }() - - defer func() { - if r := recover(); r != nil { - panicked = true - } - }() - - LessOrEqual(complex128(0)) -} - -//////////////////////////////////////////////////////////////////////// -// Integer literals -//////////////////////////////////////////////////////////////////////// - -func (t *LessOrEqualTest) NegativeIntegerLiteral() { - matcher := LessOrEqual(-150) - desc := matcher.Description() - expectedDesc := "less than or equal to -150" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []leTestCase{ - // Signed integers. - leTestCase{-(1 << 30), true, false, ""}, - leTestCase{-151, true, false, ""}, - leTestCase{-150, true, false, ""}, - leTestCase{-149, false, false, ""}, - leTestCase{0, false, false, ""}, - leTestCase{17, false, false, ""}, - - leTestCase{int(-(1 << 30)), true, false, ""}, - leTestCase{int(-151), true, false, ""}, - leTestCase{int(-150), true, false, ""}, - leTestCase{int(-149), false, false, ""}, - leTestCase{int(0), false, false, ""}, - leTestCase{int(17), false, false, ""}, - - leTestCase{int8(-127), false, false, ""}, - leTestCase{int8(0), false, false, ""}, - leTestCase{int8(17), false, false, ""}, - - leTestCase{int16(-(1 << 14)), true, false, ""}, - leTestCase{int16(-151), true, false, ""}, - leTestCase{int16(-150), true, false, ""}, - leTestCase{int16(-149), false, false, ""}, - leTestCase{int16(0), false, false, ""}, - leTestCase{int16(17), false, false, ""}, - - leTestCase{int32(-(1 << 30)), true, false, ""}, - leTestCase{int32(-151), true, false, ""}, - leTestCase{int32(-150), true, false, ""}, - leTestCase{int32(-149), false, false, ""}, - leTestCase{int32(0), false, false, ""}, - leTestCase{int32(17), false, false, ""}, - - leTestCase{int64(-(1 << 30)), true, false, ""}, - leTestCase{int64(-151), true, false, ""}, - leTestCase{int64(-150), true, false, ""}, - leTestCase{int64(-149), false, false, ""}, - leTestCase{int64(0), false, false, ""}, - leTestCase{int64(17), false, false, ""}, - - // Unsigned integers. - leTestCase{uint((1 << 32) - 151), false, false, ""}, - leTestCase{uint(0), false, false, ""}, - leTestCase{uint(17), false, false, ""}, - - leTestCase{uint8(0), false, false, ""}, - leTestCase{uint8(17), false, false, ""}, - leTestCase{uint8(253), false, false, ""}, - - leTestCase{uint16((1 << 16) - 151), false, false, ""}, - leTestCase{uint16(0), false, false, ""}, - leTestCase{uint16(17), false, false, ""}, - - leTestCase{uint32((1 << 32) - 151), false, false, ""}, - leTestCase{uint32(0), false, false, ""}, - leTestCase{uint32(17), false, false, ""}, - - leTestCase{uint64((1 << 64) - 151), false, false, ""}, - leTestCase{uint64(0), false, false, ""}, - leTestCase{uint64(17), false, false, ""}, - - // Floating point. - leTestCase{float32(-(1 << 30)), true, false, ""}, - leTestCase{float32(-151), true, false, ""}, - leTestCase{float32(-150.1), true, false, ""}, - leTestCase{float32(-150), true, false, ""}, - leTestCase{float32(-149.9), false, false, ""}, - leTestCase{float32(0), false, false, ""}, - leTestCase{float32(17), false, false, ""}, - leTestCase{float32(160), false, false, ""}, - - leTestCase{float64(-(1 << 30)), true, false, ""}, - leTestCase{float64(-151), true, false, ""}, - leTestCase{float64(-150.1), true, false, ""}, - leTestCase{float64(-150), true, false, ""}, - leTestCase{float64(-149.9), false, false, ""}, - leTestCase{float64(0), false, false, ""}, - leTestCase{float64(17), false, false, ""}, - leTestCase{float64(160), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessOrEqualTest) ZeroIntegerLiteral() { - matcher := LessOrEqual(0) - desc := matcher.Description() - expectedDesc := "less than or equal to 0" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []leTestCase{ - // Signed integers. - leTestCase{-(1 << 30), true, false, ""}, - leTestCase{-1, true, false, ""}, - leTestCase{0, true, false, ""}, - leTestCase{1, false, false, ""}, - leTestCase{17, false, false, ""}, - leTestCase{(1 << 30), false, false, ""}, - - leTestCase{int(-(1 << 30)), true, false, ""}, - leTestCase{int(-1), true, false, ""}, - leTestCase{int(0), true, false, ""}, - leTestCase{int(1), false, false, ""}, - leTestCase{int(17), false, false, ""}, - - leTestCase{int8(-1), true, false, ""}, - leTestCase{int8(0), true, false, ""}, - leTestCase{int8(1), false, false, ""}, - - leTestCase{int16(-(1 << 14)), true, false, ""}, - leTestCase{int16(-1), true, false, ""}, - leTestCase{int16(0), true, false, ""}, - leTestCase{int16(1), false, false, ""}, - leTestCase{int16(17), false, false, ""}, - - leTestCase{int32(-(1 << 30)), true, false, ""}, - leTestCase{int32(-1), true, false, ""}, - leTestCase{int32(0), true, false, ""}, - leTestCase{int32(1), false, false, ""}, - leTestCase{int32(17), false, false, ""}, - - leTestCase{int64(-(1 << 30)), true, false, ""}, - leTestCase{int64(-1), true, false, ""}, - leTestCase{int64(0), true, false, ""}, - leTestCase{int64(1), false, false, ""}, - leTestCase{int64(17), false, false, ""}, - - // Unsigned integers. - leTestCase{uint((1 << 32) - 1), false, false, ""}, - leTestCase{uint(0), true, false, ""}, - leTestCase{uint(1), false, false, ""}, - leTestCase{uint(17), false, false, ""}, - - leTestCase{uint8(0), true, false, ""}, - leTestCase{uint8(1), false, false, ""}, - leTestCase{uint8(17), false, false, ""}, - leTestCase{uint8(253), false, false, ""}, - - leTestCase{uint16((1 << 16) - 1), false, false, ""}, - leTestCase{uint16(0), true, false, ""}, - leTestCase{uint16(1), false, false, ""}, - leTestCase{uint16(17), false, false, ""}, - - leTestCase{uint32((1 << 32) - 1), false, false, ""}, - leTestCase{uint32(0), true, false, ""}, - leTestCase{uint32(1), false, false, ""}, - leTestCase{uint32(17), false, false, ""}, - - leTestCase{uint64((1 << 64) - 1), false, false, ""}, - leTestCase{uint64(0), true, false, ""}, - leTestCase{uint64(1), false, false, ""}, - leTestCase{uint64(17), false, false, ""}, - - // Floating point. - leTestCase{float32(-(1 << 30)), true, false, ""}, - leTestCase{float32(-1), true, false, ""}, - leTestCase{float32(-0.1), true, false, ""}, - leTestCase{float32(-0.0), true, false, ""}, - leTestCase{float32(0), true, false, ""}, - leTestCase{float32(0.1), false, false, ""}, - leTestCase{float32(17), false, false, ""}, - leTestCase{float32(160), false, false, ""}, - - leTestCase{float64(-(1 << 30)), true, false, ""}, - leTestCase{float64(-1), true, false, ""}, - leTestCase{float64(-0.1), true, false, ""}, - leTestCase{float64(-0), true, false, ""}, - leTestCase{float64(0), true, false, ""}, - leTestCase{float64(0.1), false, false, ""}, - leTestCase{float64(17), false, false, ""}, - leTestCase{float64(160), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessOrEqualTest) PositiveIntegerLiteral() { - matcher := LessOrEqual(150) - desc := matcher.Description() - expectedDesc := "less than or equal to 150" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []leTestCase{ - // Signed integers. - leTestCase{-1, true, false, ""}, - leTestCase{149, true, false, ""}, - leTestCase{150, true, false, ""}, - leTestCase{151, false, false, ""}, - - leTestCase{int(-1), true, false, ""}, - leTestCase{int(149), true, false, ""}, - leTestCase{int(150), true, false, ""}, - leTestCase{int(151), false, false, ""}, - - leTestCase{int8(-1), true, false, ""}, - leTestCase{int8(0), true, false, ""}, - leTestCase{int8(17), true, false, ""}, - leTestCase{int8(127), true, false, ""}, - - leTestCase{int16(-1), true, false, ""}, - leTestCase{int16(149), true, false, ""}, - leTestCase{int16(150), true, false, ""}, - leTestCase{int16(151), false, false, ""}, - - leTestCase{int32(-1), true, false, ""}, - leTestCase{int32(149), true, false, ""}, - leTestCase{int32(150), true, false, ""}, - leTestCase{int32(151), false, false, ""}, - - leTestCase{int64(-1), true, false, ""}, - leTestCase{int64(149), true, false, ""}, - leTestCase{int64(150), true, false, ""}, - leTestCase{int64(151), false, false, ""}, - - // Unsigned integers. - leTestCase{uint(0), true, false, ""}, - leTestCase{uint(149), true, false, ""}, - leTestCase{uint(150), true, false, ""}, - leTestCase{uint(151), false, false, ""}, - - leTestCase{uint8(0), true, false, ""}, - leTestCase{uint8(127), true, false, ""}, - - leTestCase{uint16(0), true, false, ""}, - leTestCase{uint16(149), true, false, ""}, - leTestCase{uint16(150), true, false, ""}, - leTestCase{uint16(151), false, false, ""}, - - leTestCase{uint32(0), true, false, ""}, - leTestCase{uint32(149), true, false, ""}, - leTestCase{uint32(150), true, false, ""}, - leTestCase{uint32(151), false, false, ""}, - - leTestCase{uint64(0), true, false, ""}, - leTestCase{uint64(149), true, false, ""}, - leTestCase{uint64(150), true, false, ""}, - leTestCase{uint64(151), false, false, ""}, - - // Floating point. - leTestCase{float32(-1), true, false, ""}, - leTestCase{float32(149), true, false, ""}, - leTestCase{float32(149.9), true, false, ""}, - leTestCase{float32(150), true, false, ""}, - leTestCase{float32(150.1), false, false, ""}, - leTestCase{float32(151), false, false, ""}, - - leTestCase{float64(-1), true, false, ""}, - leTestCase{float64(149), true, false, ""}, - leTestCase{float64(149.9), true, false, ""}, - leTestCase{float64(150), true, false, ""}, - leTestCase{float64(150.1), false, false, ""}, - leTestCase{float64(151), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// Float literals -//////////////////////////////////////////////////////////////////////// - -func (t *LessOrEqualTest) NegativeFloatLiteral() { - matcher := LessOrEqual(-150.1) - desc := matcher.Description() - expectedDesc := "less than or equal to -150.1" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []leTestCase{ - // Signed integers. - leTestCase{-(1 << 30), true, false, ""}, - leTestCase{-151, true, false, ""}, - leTestCase{-150.1, true, false, ""}, - leTestCase{-150, false, false, ""}, - leTestCase{-149, false, false, ""}, - leTestCase{0, false, false, ""}, - leTestCase{17, false, false, ""}, - - leTestCase{int(-(1 << 30)), true, false, ""}, - leTestCase{int(-151), true, false, ""}, - leTestCase{int(-150), false, false, ""}, - leTestCase{int(-149), false, false, ""}, - leTestCase{int(0), false, false, ""}, - leTestCase{int(17), false, false, ""}, - - leTestCase{int8(-127), false, false, ""}, - leTestCase{int8(0), false, false, ""}, - leTestCase{int8(17), false, false, ""}, - - leTestCase{int16(-(1 << 14)), true, false, ""}, - leTestCase{int16(-151), true, false, ""}, - leTestCase{int16(-150), false, false, ""}, - leTestCase{int16(-149), false, false, ""}, - leTestCase{int16(0), false, false, ""}, - leTestCase{int16(17), false, false, ""}, - - leTestCase{int32(-(1 << 30)), true, false, ""}, - leTestCase{int32(-151), true, false, ""}, - leTestCase{int32(-150), false, false, ""}, - leTestCase{int32(-149), false, false, ""}, - leTestCase{int32(0), false, false, ""}, - leTestCase{int32(17), false, false, ""}, - - leTestCase{int64(-(1 << 30)), true, false, ""}, - leTestCase{int64(-151), true, false, ""}, - leTestCase{int64(-150), false, false, ""}, - leTestCase{int64(-149), false, false, ""}, - leTestCase{int64(0), false, false, ""}, - leTestCase{int64(17), false, false, ""}, - - // Unsigned integers. - leTestCase{uint((1 << 32) - 151), false, false, ""}, - leTestCase{uint(0), false, false, ""}, - leTestCase{uint(17), false, false, ""}, - - leTestCase{uint8(0), false, false, ""}, - leTestCase{uint8(17), false, false, ""}, - leTestCase{uint8(253), false, false, ""}, - - leTestCase{uint16((1 << 16) - 151), false, false, ""}, - leTestCase{uint16(0), false, false, ""}, - leTestCase{uint16(17), false, false, ""}, - - leTestCase{uint32((1 << 32) - 151), false, false, ""}, - leTestCase{uint32(0), false, false, ""}, - leTestCase{uint32(17), false, false, ""}, - - leTestCase{uint64((1 << 64) - 151), false, false, ""}, - leTestCase{uint64(0), false, false, ""}, - leTestCase{uint64(17), false, false, ""}, - - // Floating point. - leTestCase{float32(-(1 << 30)), true, false, ""}, - leTestCase{float32(-151), true, false, ""}, - leTestCase{float32(-150.2), true, false, ""}, - leTestCase{float32(-150.1), true, false, ""}, - leTestCase{float32(-150), false, false, ""}, - leTestCase{float32(0), false, false, ""}, - leTestCase{float32(17), false, false, ""}, - leTestCase{float32(160), false, false, ""}, - - leTestCase{float64(-(1 << 30)), true, false, ""}, - leTestCase{float64(-151), true, false, ""}, - leTestCase{float64(-150.2), true, false, ""}, - leTestCase{float64(-150.1), true, false, ""}, - leTestCase{float64(-150), false, false, ""}, - leTestCase{float64(0), false, false, ""}, - leTestCase{float64(17), false, false, ""}, - leTestCase{float64(160), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessOrEqualTest) PositiveFloatLiteral() { - matcher := LessOrEqual(149.9) - desc := matcher.Description() - expectedDesc := "less than or equal to 149.9" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []leTestCase{ - // Signed integers. - leTestCase{-1, true, false, ""}, - leTestCase{149, true, false, ""}, - leTestCase{149.9, true, false, ""}, - leTestCase{150, false, false, ""}, - leTestCase{151, false, false, ""}, - - leTestCase{int(-1), true, false, ""}, - leTestCase{int(149), true, false, ""}, - leTestCase{int(150), false, false, ""}, - leTestCase{int(151), false, false, ""}, - - leTestCase{int8(-1), true, false, ""}, - leTestCase{int8(0), true, false, ""}, - leTestCase{int8(17), true, false, ""}, - leTestCase{int8(127), true, false, ""}, - - leTestCase{int16(-1), true, false, ""}, - leTestCase{int16(149), true, false, ""}, - leTestCase{int16(150), false, false, ""}, - leTestCase{int16(151), false, false, ""}, - - leTestCase{int32(-1), true, false, ""}, - leTestCase{int32(149), true, false, ""}, - leTestCase{int32(150), false, false, ""}, - leTestCase{int32(151), false, false, ""}, - - leTestCase{int64(-1), true, false, ""}, - leTestCase{int64(149), true, false, ""}, - leTestCase{int64(150), false, false, ""}, - leTestCase{int64(151), false, false, ""}, - - // Unsigned integers. - leTestCase{uint(0), true, false, ""}, - leTestCase{uint(149), true, false, ""}, - leTestCase{uint(150), false, false, ""}, - leTestCase{uint(151), false, false, ""}, - - leTestCase{uint8(0), true, false, ""}, - leTestCase{uint8(127), true, false, ""}, - - leTestCase{uint16(0), true, false, ""}, - leTestCase{uint16(149), true, false, ""}, - leTestCase{uint16(150), false, false, ""}, - leTestCase{uint16(151), false, false, ""}, - - leTestCase{uint32(0), true, false, ""}, - leTestCase{uint32(149), true, false, ""}, - leTestCase{uint32(150), false, false, ""}, - leTestCase{uint32(151), false, false, ""}, - - leTestCase{uint64(0), true, false, ""}, - leTestCase{uint64(149), true, false, ""}, - leTestCase{uint64(150), false, false, ""}, - leTestCase{uint64(151), false, false, ""}, - - // Floating point. - leTestCase{float32(-1), true, false, ""}, - leTestCase{float32(149), true, false, ""}, - leTestCase{float32(149.8), true, false, ""}, - leTestCase{float32(149.9), true, false, ""}, - leTestCase{float32(150), false, false, ""}, - leTestCase{float32(151), false, false, ""}, - - leTestCase{float64(-1), true, false, ""}, - leTestCase{float64(149), true, false, ""}, - leTestCase{float64(149.8), true, false, ""}, - leTestCase{float64(149.9), true, false, ""}, - leTestCase{float64(150), false, false, ""}, - leTestCase{float64(151), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// Subtle cases -//////////////////////////////////////////////////////////////////////// - -func (t *LessOrEqualTest) Int64NotExactlyRepresentableBySinglePrecision() { - // Single-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo25 = 1 << 25 - matcher := LessOrEqual(int64(kTwoTo25 + 1)) - - desc := matcher.Description() - expectedDesc := "less than or equal to 33554433" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []leTestCase{ - // Signed integers. - leTestCase{-1, true, false, ""}, - leTestCase{kTwoTo25 + 0, true, false, ""}, - leTestCase{kTwoTo25 + 1, true, false, ""}, - leTestCase{kTwoTo25 + 2, false, false, ""}, - - leTestCase{int(-1), true, false, ""}, - leTestCase{int(kTwoTo25 + 0), true, false, ""}, - leTestCase{int(kTwoTo25 + 1), true, false, ""}, - leTestCase{int(kTwoTo25 + 2), false, false, ""}, - - leTestCase{int8(-1), true, false, ""}, - leTestCase{int8(127), true, false, ""}, - - leTestCase{int16(-1), true, false, ""}, - leTestCase{int16(0), true, false, ""}, - leTestCase{int16(32767), true, false, ""}, - - leTestCase{int32(-1), true, false, ""}, - leTestCase{int32(kTwoTo25 + 0), true, false, ""}, - leTestCase{int32(kTwoTo25 + 1), true, false, ""}, - leTestCase{int32(kTwoTo25 + 2), false, false, ""}, - - leTestCase{int64(-1), true, false, ""}, - leTestCase{int64(kTwoTo25 + 0), true, false, ""}, - leTestCase{int64(kTwoTo25 + 1), true, false, ""}, - leTestCase{int64(kTwoTo25 + 2), false, false, ""}, - - // Unsigned integers. - leTestCase{uint(0), true, false, ""}, - leTestCase{uint(kTwoTo25 + 0), true, false, ""}, - leTestCase{uint(kTwoTo25 + 1), true, false, ""}, - leTestCase{uint(kTwoTo25 + 2), false, false, ""}, - - leTestCase{uint8(0), true, false, ""}, - leTestCase{uint8(255), true, false, ""}, - - leTestCase{uint16(0), true, false, ""}, - leTestCase{uint16(65535), true, false, ""}, - - leTestCase{uint32(0), true, false, ""}, - leTestCase{uint32(kTwoTo25 + 0), true, false, ""}, - leTestCase{uint32(kTwoTo25 + 1), true, false, ""}, - leTestCase{uint32(kTwoTo25 + 2), false, false, ""}, - - leTestCase{uint64(0), true, false, ""}, - leTestCase{uint64(kTwoTo25 + 0), true, false, ""}, - leTestCase{uint64(kTwoTo25 + 1), true, false, ""}, - leTestCase{uint64(kTwoTo25 + 2), false, false, ""}, - - // Floating point. - leTestCase{float32(-1), true, false, ""}, - leTestCase{float32(kTwoTo25 - 2), true, false, ""}, - leTestCase{float32(kTwoTo25 - 1), true, false, ""}, - leTestCase{float32(kTwoTo25 + 0), true, false, ""}, - leTestCase{float32(kTwoTo25 + 1), true, false, ""}, - leTestCase{float32(kTwoTo25 + 2), true, false, ""}, - leTestCase{float32(kTwoTo25 + 3), false, false, ""}, - - leTestCase{float64(-1), true, false, ""}, - leTestCase{float64(kTwoTo25 - 2), true, false, ""}, - leTestCase{float64(kTwoTo25 - 1), true, false, ""}, - leTestCase{float64(kTwoTo25 + 0), true, false, ""}, - leTestCase{float64(kTwoTo25 + 1), true, false, ""}, - leTestCase{float64(kTwoTo25 + 2), false, false, ""}, - leTestCase{float64(kTwoTo25 + 3), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessOrEqualTest) Int64NotExactlyRepresentableByDoublePrecision() { - // Double-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo54 = 1 << 54 - matcher := LessOrEqual(int64(kTwoTo54 + 1)) - - desc := matcher.Description() - expectedDesc := "less than or equal to 18014398509481985" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []leTestCase{ - // Signed integers. - leTestCase{-1, true, false, ""}, - leTestCase{1 << 30, true, false, ""}, - - leTestCase{int(-1), true, false, ""}, - leTestCase{int(math.MaxInt32), true, false, ""}, - - leTestCase{int8(-1), true, false, ""}, - leTestCase{int8(127), true, false, ""}, - - leTestCase{int16(-1), true, false, ""}, - leTestCase{int16(0), true, false, ""}, - leTestCase{int16(32767), true, false, ""}, - - leTestCase{int32(-1), true, false, ""}, - leTestCase{int32(math.MaxInt32), true, false, ""}, - - leTestCase{int64(-1), true, false, ""}, - leTestCase{int64(kTwoTo54 - 1), true, false, ""}, - leTestCase{int64(kTwoTo54 + 0), true, false, ""}, - leTestCase{int64(kTwoTo54 + 1), true, false, ""}, - leTestCase{int64(kTwoTo54 + 2), false, false, ""}, - - // Unsigned integers. - leTestCase{uint(0), true, false, ""}, - leTestCase{uint(math.MaxUint32), true, false, ""}, - - leTestCase{uint8(0), true, false, ""}, - leTestCase{uint8(255), true, false, ""}, - - leTestCase{uint16(0), true, false, ""}, - leTestCase{uint16(65535), true, false, ""}, - - leTestCase{uint32(0), true, false, ""}, - leTestCase{uint32(math.MaxUint32), true, false, ""}, - - leTestCase{uint64(0), true, false, ""}, - leTestCase{uint64(kTwoTo54 - 1), true, false, ""}, - leTestCase{uint64(kTwoTo54 + 0), true, false, ""}, - leTestCase{uint64(kTwoTo54 + 1), true, false, ""}, - leTestCase{uint64(kTwoTo54 + 2), false, false, ""}, - - // Floating point. - leTestCase{float64(-1), true, false, ""}, - leTestCase{float64(kTwoTo54 - 2), true, false, ""}, - leTestCase{float64(kTwoTo54 - 1), true, false, ""}, - leTestCase{float64(kTwoTo54 + 0), true, false, ""}, - leTestCase{float64(kTwoTo54 + 1), true, false, ""}, - leTestCase{float64(kTwoTo54 + 2), true, false, ""}, - leTestCase{float64(kTwoTo54 + 3), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessOrEqualTest) Uint64NotExactlyRepresentableBySinglePrecision() { - // Single-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo25 = 1 << 25 - matcher := LessOrEqual(uint64(kTwoTo25 + 1)) - - desc := matcher.Description() - expectedDesc := "less than or equal to 33554433" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []leTestCase{ - // Signed integers. - leTestCase{-1, true, false, ""}, - leTestCase{kTwoTo25 + 0, true, false, ""}, - leTestCase{kTwoTo25 + 1, true, false, ""}, - leTestCase{kTwoTo25 + 2, false, false, ""}, - - leTestCase{int(-1), true, false, ""}, - leTestCase{int(kTwoTo25 + 0), true, false, ""}, - leTestCase{int(kTwoTo25 + 1), true, false, ""}, - leTestCase{int(kTwoTo25 + 2), false, false, ""}, - - leTestCase{int8(-1), true, false, ""}, - leTestCase{int8(127), true, false, ""}, - - leTestCase{int16(-1), true, false, ""}, - leTestCase{int16(0), true, false, ""}, - leTestCase{int16(32767), true, false, ""}, - - leTestCase{int32(-1), true, false, ""}, - leTestCase{int32(kTwoTo25 + 0), true, false, ""}, - leTestCase{int32(kTwoTo25 + 1), true, false, ""}, - leTestCase{int32(kTwoTo25 + 2), false, false, ""}, - - leTestCase{int64(-1), true, false, ""}, - leTestCase{int64(kTwoTo25 + 0), true, false, ""}, - leTestCase{int64(kTwoTo25 + 1), true, false, ""}, - leTestCase{int64(kTwoTo25 + 2), false, false, ""}, - - // Unsigned integers. - leTestCase{uint(0), true, false, ""}, - leTestCase{uint(kTwoTo25 + 0), true, false, ""}, - leTestCase{uint(kTwoTo25 + 1), true, false, ""}, - leTestCase{uint(kTwoTo25 + 2), false, false, ""}, - - leTestCase{uint8(0), true, false, ""}, - leTestCase{uint8(255), true, false, ""}, - - leTestCase{uint16(0), true, false, ""}, - leTestCase{uint16(65535), true, false, ""}, - - leTestCase{uint32(0), true, false, ""}, - leTestCase{uint32(kTwoTo25 + 0), true, false, ""}, - leTestCase{uint32(kTwoTo25 + 1), true, false, ""}, - leTestCase{uint32(kTwoTo25 + 2), false, false, ""}, - - leTestCase{uint64(0), true, false, ""}, - leTestCase{uint64(kTwoTo25 + 0), true, false, ""}, - leTestCase{uint64(kTwoTo25 + 1), true, false, ""}, - leTestCase{uint64(kTwoTo25 + 2), false, false, ""}, - - // Floating point. - leTestCase{float32(-1), true, false, ""}, - leTestCase{float32(kTwoTo25 - 2), true, false, ""}, - leTestCase{float32(kTwoTo25 - 1), true, false, ""}, - leTestCase{float32(kTwoTo25 + 0), true, false, ""}, - leTestCase{float32(kTwoTo25 + 1), true, false, ""}, - leTestCase{float32(kTwoTo25 + 2), true, false, ""}, - leTestCase{float32(kTwoTo25 + 3), false, false, ""}, - - leTestCase{float64(-1), true, false, ""}, - leTestCase{float64(kTwoTo25 - 2), true, false, ""}, - leTestCase{float64(kTwoTo25 - 1), true, false, ""}, - leTestCase{float64(kTwoTo25 + 0), true, false, ""}, - leTestCase{float64(kTwoTo25 + 1), true, false, ""}, - leTestCase{float64(kTwoTo25 + 2), false, false, ""}, - leTestCase{float64(kTwoTo25 + 3), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessOrEqualTest) Uint64NotExactlyRepresentableByDoublePrecision() { - // Double-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo54 = 1 << 54 - matcher := LessOrEqual(uint64(kTwoTo54 + 1)) - - desc := matcher.Description() - expectedDesc := "less than or equal to 18014398509481985" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []leTestCase{ - // Signed integers. - leTestCase{-1, true, false, ""}, - leTestCase{1 << 30, true, false, ""}, - - leTestCase{int(-1), true, false, ""}, - leTestCase{int(math.MaxInt32), true, false, ""}, - - leTestCase{int8(-1), true, false, ""}, - leTestCase{int8(127), true, false, ""}, - - leTestCase{int16(-1), true, false, ""}, - leTestCase{int16(0), true, false, ""}, - leTestCase{int16(32767), true, false, ""}, - - leTestCase{int32(-1), true, false, ""}, - leTestCase{int32(math.MaxInt32), true, false, ""}, - - leTestCase{int64(-1), true, false, ""}, - leTestCase{int64(kTwoTo54 - 1), true, false, ""}, - leTestCase{int64(kTwoTo54 + 0), true, false, ""}, - leTestCase{int64(kTwoTo54 + 1), true, false, ""}, - leTestCase{int64(kTwoTo54 + 2), false, false, ""}, - - // Unsigned integers. - leTestCase{uint(0), true, false, ""}, - leTestCase{uint(math.MaxUint32), true, false, ""}, - - leTestCase{uint8(0), true, false, ""}, - leTestCase{uint8(255), true, false, ""}, - - leTestCase{uint16(0), true, false, ""}, - leTestCase{uint16(65535), true, false, ""}, - - leTestCase{uint32(0), true, false, ""}, - leTestCase{uint32(math.MaxUint32), true, false, ""}, - - leTestCase{uint64(0), true, false, ""}, - leTestCase{uint64(kTwoTo54 - 1), true, false, ""}, - leTestCase{uint64(kTwoTo54 + 0), true, false, ""}, - leTestCase{uint64(kTwoTo54 + 1), true, false, ""}, - leTestCase{uint64(kTwoTo54 + 2), false, false, ""}, - - // Floating point. - leTestCase{float64(-1), true, false, ""}, - leTestCase{float64(kTwoTo54 - 2), true, false, ""}, - leTestCase{float64(kTwoTo54 - 1), true, false, ""}, - leTestCase{float64(kTwoTo54 + 0), true, false, ""}, - leTestCase{float64(kTwoTo54 + 1), true, false, ""}, - leTestCase{float64(kTwoTo54 + 2), true, false, ""}, - leTestCase{float64(kTwoTo54 + 3), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessOrEqualTest) Float32AboveExactIntegerRange() { - // Single-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo25 = 1 << 25 - matcher := LessOrEqual(float32(kTwoTo25 + 1)) - - desc := matcher.Description() - expectedDesc := "less than or equal to 3.3554432e+07" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []leTestCase{ - // Signed integers. - leTestCase{int64(-1), true, false, ""}, - leTestCase{int64(kTwoTo25 - 2), true, false, ""}, - leTestCase{int64(kTwoTo25 - 1), true, false, ""}, - leTestCase{int64(kTwoTo25 + 0), true, false, ""}, - leTestCase{int64(kTwoTo25 + 1), true, false, ""}, - leTestCase{int64(kTwoTo25 + 2), true, false, ""}, - leTestCase{int64(kTwoTo25 + 3), false, false, ""}, - - // Unsigned integers. - leTestCase{uint64(0), true, false, ""}, - leTestCase{uint64(kTwoTo25 - 2), true, false, ""}, - leTestCase{uint64(kTwoTo25 - 1), true, false, ""}, - leTestCase{uint64(kTwoTo25 + 0), true, false, ""}, - leTestCase{uint64(kTwoTo25 + 1), true, false, ""}, - leTestCase{uint64(kTwoTo25 + 2), true, false, ""}, - leTestCase{uint64(kTwoTo25 + 3), false, false, ""}, - - // Floating point. - leTestCase{float32(-1), true, false, ""}, - leTestCase{float32(kTwoTo25 - 2), true, false, ""}, - leTestCase{float32(kTwoTo25 - 1), true, false, ""}, - leTestCase{float32(kTwoTo25 + 0), true, false, ""}, - leTestCase{float32(kTwoTo25 + 1), true, false, ""}, - leTestCase{float32(kTwoTo25 + 2), true, false, ""}, - leTestCase{float32(kTwoTo25 + 3), false, false, ""}, - - leTestCase{float64(-1), true, false, ""}, - leTestCase{float64(kTwoTo25 - 2), true, false, ""}, - leTestCase{float64(kTwoTo25 - 1), true, false, ""}, - leTestCase{float64(kTwoTo25 + 0), true, false, ""}, - leTestCase{float64(kTwoTo25 + 1), true, false, ""}, - leTestCase{float64(kTwoTo25 + 2), true, false, ""}, - leTestCase{float64(kTwoTo25 + 3), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessOrEqualTest) Float64AboveExactIntegerRange() { - // Double-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo54 = 1 << 54 - matcher := LessOrEqual(float64(kTwoTo54 + 1)) - - desc := matcher.Description() - expectedDesc := "less than or equal to 1.8014398509481984e+16" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []leTestCase{ - // Signed integers. - leTestCase{int64(-1), true, false, ""}, - leTestCase{int64(kTwoTo54 - 2), true, false, ""}, - leTestCase{int64(kTwoTo54 - 1), true, false, ""}, - leTestCase{int64(kTwoTo54 + 0), true, false, ""}, - leTestCase{int64(kTwoTo54 + 1), true, false, ""}, - leTestCase{int64(kTwoTo54 + 2), true, false, ""}, - leTestCase{int64(kTwoTo54 + 3), false, false, ""}, - - // Unsigned integers. - leTestCase{uint64(0), true, false, ""}, - leTestCase{uint64(kTwoTo54 - 2), true, false, ""}, - leTestCase{uint64(kTwoTo54 - 1), true, false, ""}, - leTestCase{uint64(kTwoTo54 + 0), true, false, ""}, - leTestCase{uint64(kTwoTo54 + 1), true, false, ""}, - leTestCase{uint64(kTwoTo54 + 2), true, false, ""}, - leTestCase{uint64(kTwoTo54 + 3), false, false, ""}, - - // Floating point. - leTestCase{float64(-1), true, false, ""}, - leTestCase{float64(kTwoTo54 - 2), true, false, ""}, - leTestCase{float64(kTwoTo54 - 1), true, false, ""}, - leTestCase{float64(kTwoTo54 + 0), true, false, ""}, - leTestCase{float64(kTwoTo54 + 1), true, false, ""}, - leTestCase{float64(kTwoTo54 + 2), true, false, ""}, - leTestCase{float64(kTwoTo54 + 3), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// String literals -//////////////////////////////////////////////////////////////////////// - -func (t *LessOrEqualTest) EmptyString() { - matcher := LessOrEqual("") - desc := matcher.Description() - expectedDesc := "less than or equal to \"\"" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []leTestCase{ - leTestCase{"", true, false, ""}, - leTestCase{"\x00", false, false, ""}, - leTestCase{"a", false, false, ""}, - leTestCase{"foo", false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessOrEqualTest) SingleNullByte() { - matcher := LessOrEqual("\x00") - desc := matcher.Description() - expectedDesc := "less than or equal to \"\x00\"" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []leTestCase{ - leTestCase{"", true, false, ""}, - leTestCase{"\x00", true, false, ""}, - leTestCase{"\x00\x00", false, false, ""}, - leTestCase{"a", false, false, ""}, - leTestCase{"foo", false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessOrEqualTest) LongerString() { - matcher := LessOrEqual("foo\x00") - desc := matcher.Description() - expectedDesc := "less than or equal to \"foo\x00\"" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []leTestCase{ - leTestCase{"", true, false, ""}, - leTestCase{"\x00", true, false, ""}, - leTestCase{"bar", true, false, ""}, - leTestCase{"foo", true, false, ""}, - leTestCase{"foo\x00", true, false, ""}, - leTestCase{"foo\x00\x00", false, false, ""}, - leTestCase{"fooa", false, false, ""}, - leTestCase{"qux", false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/less_than_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/less_than_test.go deleted file mode 100644 index 63bc7f44f0f..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/less_than_test.go +++ /dev/null @@ -1,1059 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - "math" - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type LessThanTest struct { -} - -func init() { RegisterTestSuite(&LessThanTest{}) } - -type ltTestCase struct { - candidate interface{} - expectedResult bool - shouldBeFatal bool - expectedError string -} - -func (t *LessThanTest) checkTestCases(matcher Matcher, cases []ltTestCase) { - for i, c := range cases { - err := matcher.Matches(c.candidate) - - ExpectThat( - (err == nil), - Equals(c.expectedResult), - "Case %d (candidate %v)", - i, - c.candidate) - - if err == nil { - continue - } - - _, isFatal := err.(*FatalError) - ExpectEq( - c.shouldBeFatal, - isFatal, - "Case %d (candidate %v)", - i, - c.candidate) - - ExpectThat( - err, - Error(Equals(c.expectedError)), - "Case %d (candidate %v)", - i, - c.candidate) - } -} - -//////////////////////////////////////////////////////////////////////// -// Integer literals -//////////////////////////////////////////////////////////////////////// - -func (t *LessThanTest) IntegerCandidateBadTypes() { - matcher := LessThan(int(-150)) - - cases := []ltTestCase{ - ltTestCase{true, false, true, "which is not comparable"}, - ltTestCase{uintptr(17), false, true, "which is not comparable"}, - ltTestCase{complex64(-151), false, true, "which is not comparable"}, - ltTestCase{complex128(-151), false, true, "which is not comparable"}, - ltTestCase{[...]int{-151}, false, true, "which is not comparable"}, - ltTestCase{make(chan int), false, true, "which is not comparable"}, - ltTestCase{func() {}, false, true, "which is not comparable"}, - ltTestCase{map[int]int{}, false, true, "which is not comparable"}, - ltTestCase{<TestCase{}, false, true, "which is not comparable"}, - ltTestCase{make([]int, 0), false, true, "which is not comparable"}, - ltTestCase{"-151", false, true, "which is not comparable"}, - ltTestCase{ltTestCase{}, false, true, "which is not comparable"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessThanTest) FloatCandidateBadTypes() { - matcher := LessThan(float32(-150)) - - cases := []ltTestCase{ - ltTestCase{true, false, true, "which is not comparable"}, - ltTestCase{uintptr(17), false, true, "which is not comparable"}, - ltTestCase{complex64(-151), false, true, "which is not comparable"}, - ltTestCase{complex128(-151), false, true, "which is not comparable"}, - ltTestCase{[...]int{-151}, false, true, "which is not comparable"}, - ltTestCase{make(chan int), false, true, "which is not comparable"}, - ltTestCase{func() {}, false, true, "which is not comparable"}, - ltTestCase{map[int]int{}, false, true, "which is not comparable"}, - ltTestCase{<TestCase{}, false, true, "which is not comparable"}, - ltTestCase{make([]int, 0), false, true, "which is not comparable"}, - ltTestCase{"-151", false, true, "which is not comparable"}, - ltTestCase{ltTestCase{}, false, true, "which is not comparable"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessThanTest) StringCandidateBadTypes() { - matcher := LessThan("17") - - cases := []ltTestCase{ - ltTestCase{true, false, true, "which is not comparable"}, - ltTestCase{int(0), false, true, "which is not comparable"}, - ltTestCase{int8(0), false, true, "which is not comparable"}, - ltTestCase{int16(0), false, true, "which is not comparable"}, - ltTestCase{int32(0), false, true, "which is not comparable"}, - ltTestCase{int64(0), false, true, "which is not comparable"}, - ltTestCase{uint(0), false, true, "which is not comparable"}, - ltTestCase{uint8(0), false, true, "which is not comparable"}, - ltTestCase{uint16(0), false, true, "which is not comparable"}, - ltTestCase{uint32(0), false, true, "which is not comparable"}, - ltTestCase{uint64(0), false, true, "which is not comparable"}, - ltTestCase{uintptr(17), false, true, "which is not comparable"}, - ltTestCase{float32(0), false, true, "which is not comparable"}, - ltTestCase{float64(0), false, true, "which is not comparable"}, - ltTestCase{complex64(-151), false, true, "which is not comparable"}, - ltTestCase{complex128(-151), false, true, "which is not comparable"}, - ltTestCase{[...]int{-151}, false, true, "which is not comparable"}, - ltTestCase{make(chan int), false, true, "which is not comparable"}, - ltTestCase{func() {}, false, true, "which is not comparable"}, - ltTestCase{map[int]int{}, false, true, "which is not comparable"}, - ltTestCase{<TestCase{}, false, true, "which is not comparable"}, - ltTestCase{make([]int, 0), false, true, "which is not comparable"}, - ltTestCase{ltTestCase{}, false, true, "which is not comparable"}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessThanTest) BadArgument() { - panicked := false - - defer func() { - ExpectThat(panicked, Equals(true)) - }() - - defer func() { - if r := recover(); r != nil { - panicked = true - } - }() - - LessThan(complex128(0)) -} - -//////////////////////////////////////////////////////////////////////// -// Integer literals -//////////////////////////////////////////////////////////////////////// - -func (t *LessThanTest) NegativeIntegerLiteral() { - matcher := LessThan(-150) - desc := matcher.Description() - expectedDesc := "less than -150" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []ltTestCase{ - // Signed integers. - ltTestCase{-(1 << 30), true, false, ""}, - ltTestCase{-151, true, false, ""}, - ltTestCase{-150, false, false, ""}, - ltTestCase{0, false, false, ""}, - ltTestCase{17, false, false, ""}, - - ltTestCase{int(-(1 << 30)), true, false, ""}, - ltTestCase{int(-151), true, false, ""}, - ltTestCase{int(-150), false, false, ""}, - ltTestCase{int(0), false, false, ""}, - ltTestCase{int(17), false, false, ""}, - - ltTestCase{int8(-127), false, false, ""}, - ltTestCase{int8(0), false, false, ""}, - ltTestCase{int8(17), false, false, ""}, - - ltTestCase{int16(-(1 << 14)), true, false, ""}, - ltTestCase{int16(-151), true, false, ""}, - ltTestCase{int16(-150), false, false, ""}, - ltTestCase{int16(0), false, false, ""}, - ltTestCase{int16(17), false, false, ""}, - - ltTestCase{int32(-(1 << 30)), true, false, ""}, - ltTestCase{int32(-151), true, false, ""}, - ltTestCase{int32(-150), false, false, ""}, - ltTestCase{int32(0), false, false, ""}, - ltTestCase{int32(17), false, false, ""}, - - ltTestCase{int64(-(1 << 30)), true, false, ""}, - ltTestCase{int64(-151), true, false, ""}, - ltTestCase{int64(-150), false, false, ""}, - ltTestCase{int64(0), false, false, ""}, - ltTestCase{int64(17), false, false, ""}, - - // Unsigned integers. - ltTestCase{uint((1 << 32) - 151), false, false, ""}, - ltTestCase{uint(0), false, false, ""}, - ltTestCase{uint(17), false, false, ""}, - - ltTestCase{uint8(0), false, false, ""}, - ltTestCase{uint8(17), false, false, ""}, - ltTestCase{uint8(253), false, false, ""}, - - ltTestCase{uint16((1 << 16) - 151), false, false, ""}, - ltTestCase{uint16(0), false, false, ""}, - ltTestCase{uint16(17), false, false, ""}, - - ltTestCase{uint32((1 << 32) - 151), false, false, ""}, - ltTestCase{uint32(0), false, false, ""}, - ltTestCase{uint32(17), false, false, ""}, - - ltTestCase{uint64((1 << 64) - 151), false, false, ""}, - ltTestCase{uint64(0), false, false, ""}, - ltTestCase{uint64(17), false, false, ""}, - - // Floating point. - ltTestCase{float32(-(1 << 30)), true, false, ""}, - ltTestCase{float32(-151), true, false, ""}, - ltTestCase{float32(-150.1), true, false, ""}, - ltTestCase{float32(-150), false, false, ""}, - ltTestCase{float32(-149.9), false, false, ""}, - ltTestCase{float32(0), false, false, ""}, - ltTestCase{float32(17), false, false, ""}, - ltTestCase{float32(160), false, false, ""}, - - ltTestCase{float64(-(1 << 30)), true, false, ""}, - ltTestCase{float64(-151), true, false, ""}, - ltTestCase{float64(-150.1), true, false, ""}, - ltTestCase{float64(-150), false, false, ""}, - ltTestCase{float64(-149.9), false, false, ""}, - ltTestCase{float64(0), false, false, ""}, - ltTestCase{float64(17), false, false, ""}, - ltTestCase{float64(160), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessThanTest) ZeroIntegerLiteral() { - matcher := LessThan(0) - desc := matcher.Description() - expectedDesc := "less than 0" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []ltTestCase{ - // Signed integers. - ltTestCase{-(1 << 30), true, false, ""}, - ltTestCase{-1, true, false, ""}, - ltTestCase{0, false, false, ""}, - ltTestCase{1, false, false, ""}, - ltTestCase{17, false, false, ""}, - ltTestCase{(1 << 30), false, false, ""}, - - ltTestCase{int(-(1 << 30)), true, false, ""}, - ltTestCase{int(-1), true, false, ""}, - ltTestCase{int(0), false, false, ""}, - ltTestCase{int(1), false, false, ""}, - ltTestCase{int(17), false, false, ""}, - - ltTestCase{int8(-1), true, false, ""}, - ltTestCase{int8(0), false, false, ""}, - ltTestCase{int8(1), false, false, ""}, - - ltTestCase{int16(-(1 << 14)), true, false, ""}, - ltTestCase{int16(-1), true, false, ""}, - ltTestCase{int16(0), false, false, ""}, - ltTestCase{int16(1), false, false, ""}, - ltTestCase{int16(17), false, false, ""}, - - ltTestCase{int32(-(1 << 30)), true, false, ""}, - ltTestCase{int32(-1), true, false, ""}, - ltTestCase{int32(0), false, false, ""}, - ltTestCase{int32(1), false, false, ""}, - ltTestCase{int32(17), false, false, ""}, - - ltTestCase{int64(-(1 << 30)), true, false, ""}, - ltTestCase{int64(-1), true, false, ""}, - ltTestCase{int64(0), false, false, ""}, - ltTestCase{int64(1), false, false, ""}, - ltTestCase{int64(17), false, false, ""}, - - // Unsigned integers. - ltTestCase{uint((1 << 32) - 1), false, false, ""}, - ltTestCase{uint(0), false, false, ""}, - ltTestCase{uint(17), false, false, ""}, - - ltTestCase{uint8(0), false, false, ""}, - ltTestCase{uint8(17), false, false, ""}, - ltTestCase{uint8(253), false, false, ""}, - - ltTestCase{uint16((1 << 16) - 1), false, false, ""}, - ltTestCase{uint16(0), false, false, ""}, - ltTestCase{uint16(17), false, false, ""}, - - ltTestCase{uint32((1 << 32) - 1), false, false, ""}, - ltTestCase{uint32(0), false, false, ""}, - ltTestCase{uint32(17), false, false, ""}, - - ltTestCase{uint64((1 << 64) - 1), false, false, ""}, - ltTestCase{uint64(0), false, false, ""}, - ltTestCase{uint64(17), false, false, ""}, - - // Floating point. - ltTestCase{float32(-(1 << 30)), true, false, ""}, - ltTestCase{float32(-1), true, false, ""}, - ltTestCase{float32(-0.1), true, false, ""}, - ltTestCase{float32(-0.0), false, false, ""}, - ltTestCase{float32(0), false, false, ""}, - ltTestCase{float32(0.1), false, false, ""}, - ltTestCase{float32(17), false, false, ""}, - ltTestCase{float32(160), false, false, ""}, - - ltTestCase{float64(-(1 << 30)), true, false, ""}, - ltTestCase{float64(-1), true, false, ""}, - ltTestCase{float64(-0.1), true, false, ""}, - ltTestCase{float64(-0), false, false, ""}, - ltTestCase{float64(0), false, false, ""}, - ltTestCase{float64(17), false, false, ""}, - ltTestCase{float64(160), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessThanTest) PositiveIntegerLiteral() { - matcher := LessThan(150) - desc := matcher.Description() - expectedDesc := "less than 150" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []ltTestCase{ - // Signed integers. - ltTestCase{-1, true, false, ""}, - ltTestCase{149, true, false, ""}, - ltTestCase{150, false, false, ""}, - ltTestCase{151, false, false, ""}, - - ltTestCase{int(-1), true, false, ""}, - ltTestCase{int(149), true, false, ""}, - ltTestCase{int(150), false, false, ""}, - ltTestCase{int(151), false, false, ""}, - - ltTestCase{int8(-1), true, false, ""}, - ltTestCase{int8(0), true, false, ""}, - ltTestCase{int8(17), true, false, ""}, - ltTestCase{int8(127), true, false, ""}, - - ltTestCase{int16(-1), true, false, ""}, - ltTestCase{int16(149), true, false, ""}, - ltTestCase{int16(150), false, false, ""}, - ltTestCase{int16(151), false, false, ""}, - - ltTestCase{int32(-1), true, false, ""}, - ltTestCase{int32(149), true, false, ""}, - ltTestCase{int32(150), false, false, ""}, - ltTestCase{int32(151), false, false, ""}, - - ltTestCase{int64(-1), true, false, ""}, - ltTestCase{int64(149), true, false, ""}, - ltTestCase{int64(150), false, false, ""}, - ltTestCase{int64(151), false, false, ""}, - - // Unsigned integers. - ltTestCase{uint(0), true, false, ""}, - ltTestCase{uint(149), true, false, ""}, - ltTestCase{uint(150), false, false, ""}, - ltTestCase{uint(151), false, false, ""}, - - ltTestCase{uint8(0), true, false, ""}, - ltTestCase{uint8(127), true, false, ""}, - - ltTestCase{uint16(0), true, false, ""}, - ltTestCase{uint16(149), true, false, ""}, - ltTestCase{uint16(150), false, false, ""}, - ltTestCase{uint16(151), false, false, ""}, - - ltTestCase{uint32(0), true, false, ""}, - ltTestCase{uint32(149), true, false, ""}, - ltTestCase{uint32(150), false, false, ""}, - ltTestCase{uint32(151), false, false, ""}, - - ltTestCase{uint64(0), true, false, ""}, - ltTestCase{uint64(149), true, false, ""}, - ltTestCase{uint64(150), false, false, ""}, - ltTestCase{uint64(151), false, false, ""}, - - // Floating point. - ltTestCase{float32(-1), true, false, ""}, - ltTestCase{float32(149), true, false, ""}, - ltTestCase{float32(149.9), true, false, ""}, - ltTestCase{float32(150), false, false, ""}, - ltTestCase{float32(150.1), false, false, ""}, - ltTestCase{float32(151), false, false, ""}, - - ltTestCase{float64(-1), true, false, ""}, - ltTestCase{float64(149), true, false, ""}, - ltTestCase{float64(149.9), true, false, ""}, - ltTestCase{float64(150), false, false, ""}, - ltTestCase{float64(150.1), false, false, ""}, - ltTestCase{float64(151), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// Float literals -//////////////////////////////////////////////////////////////////////// - -func (t *LessThanTest) NegativeFloatLiteral() { - matcher := LessThan(-150.1) - desc := matcher.Description() - expectedDesc := "less than -150.1" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []ltTestCase{ - // Signed integers. - ltTestCase{-(1 << 30), true, false, ""}, - ltTestCase{-151, true, false, ""}, - ltTestCase{-150, false, false, ""}, - ltTestCase{0, false, false, ""}, - ltTestCase{17, false, false, ""}, - - ltTestCase{int(-(1 << 30)), true, false, ""}, - ltTestCase{int(-151), true, false, ""}, - ltTestCase{int(-150), false, false, ""}, - ltTestCase{int(0), false, false, ""}, - ltTestCase{int(17), false, false, ""}, - - ltTestCase{int8(-127), false, false, ""}, - ltTestCase{int8(0), false, false, ""}, - ltTestCase{int8(17), false, false, ""}, - - ltTestCase{int16(-(1 << 14)), true, false, ""}, - ltTestCase{int16(-151), true, false, ""}, - ltTestCase{int16(-150), false, false, ""}, - ltTestCase{int16(0), false, false, ""}, - ltTestCase{int16(17), false, false, ""}, - - ltTestCase{int32(-(1 << 30)), true, false, ""}, - ltTestCase{int32(-151), true, false, ""}, - ltTestCase{int32(-150), false, false, ""}, - ltTestCase{int32(0), false, false, ""}, - ltTestCase{int32(17), false, false, ""}, - - ltTestCase{int64(-(1 << 30)), true, false, ""}, - ltTestCase{int64(-151), true, false, ""}, - ltTestCase{int64(-150), false, false, ""}, - ltTestCase{int64(0), false, false, ""}, - ltTestCase{int64(17), false, false, ""}, - - // Unsigned integers. - ltTestCase{uint((1 << 32) - 151), false, false, ""}, - ltTestCase{uint(0), false, false, ""}, - ltTestCase{uint(17), false, false, ""}, - - ltTestCase{uint8(0), false, false, ""}, - ltTestCase{uint8(17), false, false, ""}, - ltTestCase{uint8(253), false, false, ""}, - - ltTestCase{uint16((1 << 16) - 151), false, false, ""}, - ltTestCase{uint16(0), false, false, ""}, - ltTestCase{uint16(17), false, false, ""}, - - ltTestCase{uint32((1 << 32) - 151), false, false, ""}, - ltTestCase{uint32(0), false, false, ""}, - ltTestCase{uint32(17), false, false, ""}, - - ltTestCase{uint64((1 << 64) - 151), false, false, ""}, - ltTestCase{uint64(0), false, false, ""}, - ltTestCase{uint64(17), false, false, ""}, - - // Floating point. - ltTestCase{float32(-(1 << 30)), true, false, ""}, - ltTestCase{float32(-151), true, false, ""}, - ltTestCase{float32(-150.2), true, false, ""}, - ltTestCase{float32(-150.1), false, false, ""}, - ltTestCase{float32(-150), false, false, ""}, - ltTestCase{float32(0), false, false, ""}, - ltTestCase{float32(17), false, false, ""}, - ltTestCase{float32(160), false, false, ""}, - - ltTestCase{float64(-(1 << 30)), true, false, ""}, - ltTestCase{float64(-151), true, false, ""}, - ltTestCase{float64(-150.2), true, false, ""}, - ltTestCase{float64(-150.1), false, false, ""}, - ltTestCase{float64(-150), false, false, ""}, - ltTestCase{float64(0), false, false, ""}, - ltTestCase{float64(17), false, false, ""}, - ltTestCase{float64(160), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessThanTest) PositiveFloatLiteral() { - matcher := LessThan(149.9) - desc := matcher.Description() - expectedDesc := "less than 149.9" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []ltTestCase{ - // Signed integers. - ltTestCase{-1, true, false, ""}, - ltTestCase{149, true, false, ""}, - ltTestCase{150, false, false, ""}, - ltTestCase{151, false, false, ""}, - - ltTestCase{int(-1), true, false, ""}, - ltTestCase{int(149), true, false, ""}, - ltTestCase{int(150), false, false, ""}, - ltTestCase{int(151), false, false, ""}, - - ltTestCase{int8(-1), true, false, ""}, - ltTestCase{int8(0), true, false, ""}, - ltTestCase{int8(17), true, false, ""}, - ltTestCase{int8(127), true, false, ""}, - - ltTestCase{int16(-1), true, false, ""}, - ltTestCase{int16(149), true, false, ""}, - ltTestCase{int16(150), false, false, ""}, - ltTestCase{int16(151), false, false, ""}, - - ltTestCase{int32(-1), true, false, ""}, - ltTestCase{int32(149), true, false, ""}, - ltTestCase{int32(150), false, false, ""}, - ltTestCase{int32(151), false, false, ""}, - - ltTestCase{int64(-1), true, false, ""}, - ltTestCase{int64(149), true, false, ""}, - ltTestCase{int64(150), false, false, ""}, - ltTestCase{int64(151), false, false, ""}, - - // Unsigned integers. - ltTestCase{uint(0), true, false, ""}, - ltTestCase{uint(149), true, false, ""}, - ltTestCase{uint(150), false, false, ""}, - ltTestCase{uint(151), false, false, ""}, - - ltTestCase{uint8(0), true, false, ""}, - ltTestCase{uint8(127), true, false, ""}, - - ltTestCase{uint16(0), true, false, ""}, - ltTestCase{uint16(149), true, false, ""}, - ltTestCase{uint16(150), false, false, ""}, - ltTestCase{uint16(151), false, false, ""}, - - ltTestCase{uint32(0), true, false, ""}, - ltTestCase{uint32(149), true, false, ""}, - ltTestCase{uint32(150), false, false, ""}, - ltTestCase{uint32(151), false, false, ""}, - - ltTestCase{uint64(0), true, false, ""}, - ltTestCase{uint64(149), true, false, ""}, - ltTestCase{uint64(150), false, false, ""}, - ltTestCase{uint64(151), false, false, ""}, - - // Floating point. - ltTestCase{float32(-1), true, false, ""}, - ltTestCase{float32(149), true, false, ""}, - ltTestCase{float32(149.8), true, false, ""}, - ltTestCase{float32(149.9), false, false, ""}, - ltTestCase{float32(150), false, false, ""}, - ltTestCase{float32(151), false, false, ""}, - - ltTestCase{float64(-1), true, false, ""}, - ltTestCase{float64(149), true, false, ""}, - ltTestCase{float64(149.8), true, false, ""}, - ltTestCase{float64(149.9), false, false, ""}, - ltTestCase{float64(150), false, false, ""}, - ltTestCase{float64(151), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// Subtle cases -//////////////////////////////////////////////////////////////////////// - -func (t *LessThanTest) Int64NotExactlyRepresentableBySinglePrecision() { - // Single-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo25 = 1 << 25 - matcher := LessThan(int64(kTwoTo25 + 1)) - - desc := matcher.Description() - expectedDesc := "less than 33554433" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []ltTestCase{ - // Signed integers. - ltTestCase{-1, true, false, ""}, - ltTestCase{kTwoTo25 + 0, true, false, ""}, - ltTestCase{kTwoTo25 + 1, false, false, ""}, - ltTestCase{kTwoTo25 + 2, false, false, ""}, - - ltTestCase{int(-1), true, false, ""}, - ltTestCase{int(kTwoTo25 + 0), true, false, ""}, - ltTestCase{int(kTwoTo25 + 1), false, false, ""}, - ltTestCase{int(kTwoTo25 + 2), false, false, ""}, - - ltTestCase{int8(-1), true, false, ""}, - ltTestCase{int8(127), true, false, ""}, - - ltTestCase{int16(-1), true, false, ""}, - ltTestCase{int16(0), true, false, ""}, - ltTestCase{int16(32767), true, false, ""}, - - ltTestCase{int32(-1), true, false, ""}, - ltTestCase{int32(kTwoTo25 + 0), true, false, ""}, - ltTestCase{int32(kTwoTo25 + 1), false, false, ""}, - ltTestCase{int32(kTwoTo25 + 2), false, false, ""}, - - ltTestCase{int64(-1), true, false, ""}, - ltTestCase{int64(kTwoTo25 + 0), true, false, ""}, - ltTestCase{int64(kTwoTo25 + 1), false, false, ""}, - ltTestCase{int64(kTwoTo25 + 2), false, false, ""}, - - // Unsigned integers. - ltTestCase{uint(0), true, false, ""}, - ltTestCase{uint(kTwoTo25 + 0), true, false, ""}, - ltTestCase{uint(kTwoTo25 + 1), false, false, ""}, - ltTestCase{uint(kTwoTo25 + 2), false, false, ""}, - - ltTestCase{uint8(0), true, false, ""}, - ltTestCase{uint8(255), true, false, ""}, - - ltTestCase{uint16(0), true, false, ""}, - ltTestCase{uint16(65535), true, false, ""}, - - ltTestCase{uint32(0), true, false, ""}, - ltTestCase{uint32(kTwoTo25 + 0), true, false, ""}, - ltTestCase{uint32(kTwoTo25 + 1), false, false, ""}, - ltTestCase{uint32(kTwoTo25 + 2), false, false, ""}, - - ltTestCase{uint64(0), true, false, ""}, - ltTestCase{uint64(kTwoTo25 + 0), true, false, ""}, - ltTestCase{uint64(kTwoTo25 + 1), false, false, ""}, - ltTestCase{uint64(kTwoTo25 + 2), false, false, ""}, - - // Floating point. - ltTestCase{float32(-1), true, false, ""}, - ltTestCase{float32(kTwoTo25 - 2), true, false, ""}, - ltTestCase{float32(kTwoTo25 - 1), false, false, ""}, - ltTestCase{float32(kTwoTo25 + 0), false, false, ""}, - ltTestCase{float32(kTwoTo25 + 1), false, false, ""}, - ltTestCase{float32(kTwoTo25 + 2), false, false, ""}, - ltTestCase{float32(kTwoTo25 + 3), false, false, ""}, - - ltTestCase{float64(-1), true, false, ""}, - ltTestCase{float64(kTwoTo25 - 2), true, false, ""}, - ltTestCase{float64(kTwoTo25 - 1), true, false, ""}, - ltTestCase{float64(kTwoTo25 + 0), true, false, ""}, - ltTestCase{float64(kTwoTo25 + 1), false, false, ""}, - ltTestCase{float64(kTwoTo25 + 2), false, false, ""}, - ltTestCase{float64(kTwoTo25 + 3), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessThanTest) Int64NotExactlyRepresentableByDoublePrecision() { - // Double-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo54 = 1 << 54 - matcher := LessThan(int64(kTwoTo54 + 1)) - - desc := matcher.Description() - expectedDesc := "less than 18014398509481985" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []ltTestCase{ - // Signed integers. - ltTestCase{-1, true, false, ""}, - ltTestCase{1 << 30, true, false, ""}, - - ltTestCase{int(-1), true, false, ""}, - ltTestCase{int(math.MaxInt32), true, false, ""}, - - ltTestCase{int8(-1), true, false, ""}, - ltTestCase{int8(127), true, false, ""}, - - ltTestCase{int16(-1), true, false, ""}, - ltTestCase{int16(0), true, false, ""}, - ltTestCase{int16(32767), true, false, ""}, - - ltTestCase{int32(-1), true, false, ""}, - ltTestCase{int32(math.MaxInt32), true, false, ""}, - - ltTestCase{int64(-1), true, false, ""}, - ltTestCase{int64(kTwoTo54 - 1), true, false, ""}, - ltTestCase{int64(kTwoTo54 + 0), true, false, ""}, - ltTestCase{int64(kTwoTo54 + 1), false, false, ""}, - ltTestCase{int64(kTwoTo54 + 2), false, false, ""}, - - // Unsigned integers. - ltTestCase{uint(0), true, false, ""}, - ltTestCase{uint(math.MaxUint32), true, false, ""}, - - ltTestCase{uint8(0), true, false, ""}, - ltTestCase{uint8(255), true, false, ""}, - - ltTestCase{uint16(0), true, false, ""}, - ltTestCase{uint16(65535), true, false, ""}, - - ltTestCase{uint32(0), true, false, ""}, - ltTestCase{uint32(math.MaxUint32), true, false, ""}, - - ltTestCase{uint64(0), true, false, ""}, - ltTestCase{uint64(kTwoTo54 - 1), true, false, ""}, - ltTestCase{uint64(kTwoTo54 + 0), true, false, ""}, - ltTestCase{uint64(kTwoTo54 + 1), false, false, ""}, - ltTestCase{uint64(kTwoTo54 + 2), false, false, ""}, - - // Floating point. - ltTestCase{float64(-1), true, false, ""}, - ltTestCase{float64(kTwoTo54 - 2), true, false, ""}, - ltTestCase{float64(kTwoTo54 - 1), false, false, ""}, - ltTestCase{float64(kTwoTo54 + 0), false, false, ""}, - ltTestCase{float64(kTwoTo54 + 1), false, false, ""}, - ltTestCase{float64(kTwoTo54 + 2), false, false, ""}, - ltTestCase{float64(kTwoTo54 + 3), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessThanTest) Uint64NotExactlyRepresentableBySinglePrecision() { - // Single-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo25 = 1 << 25 - matcher := LessThan(uint64(kTwoTo25 + 1)) - - desc := matcher.Description() - expectedDesc := "less than 33554433" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []ltTestCase{ - // Signed integers. - ltTestCase{-1, true, false, ""}, - ltTestCase{kTwoTo25 + 0, true, false, ""}, - ltTestCase{kTwoTo25 + 1, false, false, ""}, - ltTestCase{kTwoTo25 + 2, false, false, ""}, - - ltTestCase{int(-1), true, false, ""}, - ltTestCase{int(kTwoTo25 + 0), true, false, ""}, - ltTestCase{int(kTwoTo25 + 1), false, false, ""}, - ltTestCase{int(kTwoTo25 + 2), false, false, ""}, - - ltTestCase{int8(-1), true, false, ""}, - ltTestCase{int8(127), true, false, ""}, - - ltTestCase{int16(-1), true, false, ""}, - ltTestCase{int16(0), true, false, ""}, - ltTestCase{int16(32767), true, false, ""}, - - ltTestCase{int32(-1), true, false, ""}, - ltTestCase{int32(kTwoTo25 + 0), true, false, ""}, - ltTestCase{int32(kTwoTo25 + 1), false, false, ""}, - ltTestCase{int32(kTwoTo25 + 2), false, false, ""}, - - ltTestCase{int64(-1), true, false, ""}, - ltTestCase{int64(kTwoTo25 + 0), true, false, ""}, - ltTestCase{int64(kTwoTo25 + 1), false, false, ""}, - ltTestCase{int64(kTwoTo25 + 2), false, false, ""}, - - // Unsigned integers. - ltTestCase{uint(0), true, false, ""}, - ltTestCase{uint(kTwoTo25 + 0), true, false, ""}, - ltTestCase{uint(kTwoTo25 + 1), false, false, ""}, - ltTestCase{uint(kTwoTo25 + 2), false, false, ""}, - - ltTestCase{uint8(0), true, false, ""}, - ltTestCase{uint8(255), true, false, ""}, - - ltTestCase{uint16(0), true, false, ""}, - ltTestCase{uint16(65535), true, false, ""}, - - ltTestCase{uint32(0), true, false, ""}, - ltTestCase{uint32(kTwoTo25 + 0), true, false, ""}, - ltTestCase{uint32(kTwoTo25 + 1), false, false, ""}, - ltTestCase{uint32(kTwoTo25 + 2), false, false, ""}, - - ltTestCase{uint64(0), true, false, ""}, - ltTestCase{uint64(kTwoTo25 + 0), true, false, ""}, - ltTestCase{uint64(kTwoTo25 + 1), false, false, ""}, - ltTestCase{uint64(kTwoTo25 + 2), false, false, ""}, - - // Floating point. - ltTestCase{float32(-1), true, false, ""}, - ltTestCase{float32(kTwoTo25 - 2), true, false, ""}, - ltTestCase{float32(kTwoTo25 - 1), false, false, ""}, - ltTestCase{float32(kTwoTo25 + 0), false, false, ""}, - ltTestCase{float32(kTwoTo25 + 1), false, false, ""}, - ltTestCase{float32(kTwoTo25 + 2), false, false, ""}, - ltTestCase{float32(kTwoTo25 + 3), false, false, ""}, - - ltTestCase{float64(-1), true, false, ""}, - ltTestCase{float64(kTwoTo25 - 2), true, false, ""}, - ltTestCase{float64(kTwoTo25 - 1), true, false, ""}, - ltTestCase{float64(kTwoTo25 + 0), true, false, ""}, - ltTestCase{float64(kTwoTo25 + 1), false, false, ""}, - ltTestCase{float64(kTwoTo25 + 2), false, false, ""}, - ltTestCase{float64(kTwoTo25 + 3), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessThanTest) Uint64NotExactlyRepresentableByDoublePrecision() { - // Double-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo54 = 1 << 54 - matcher := LessThan(uint64(kTwoTo54 + 1)) - - desc := matcher.Description() - expectedDesc := "less than 18014398509481985" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []ltTestCase{ - // Signed integers. - ltTestCase{-1, true, false, ""}, - ltTestCase{1 << 30, true, false, ""}, - - ltTestCase{int(-1), true, false, ""}, - ltTestCase{int(math.MaxInt32), true, false, ""}, - - ltTestCase{int8(-1), true, false, ""}, - ltTestCase{int8(127), true, false, ""}, - - ltTestCase{int16(-1), true, false, ""}, - ltTestCase{int16(0), true, false, ""}, - ltTestCase{int16(32767), true, false, ""}, - - ltTestCase{int32(-1), true, false, ""}, - ltTestCase{int32(math.MaxInt32), true, false, ""}, - - ltTestCase{int64(-1), true, false, ""}, - ltTestCase{int64(kTwoTo54 - 1), true, false, ""}, - ltTestCase{int64(kTwoTo54 + 0), true, false, ""}, - ltTestCase{int64(kTwoTo54 + 1), false, false, ""}, - ltTestCase{int64(kTwoTo54 + 2), false, false, ""}, - - // Unsigned integers. - ltTestCase{uint(0), true, false, ""}, - ltTestCase{uint(math.MaxUint32), true, false, ""}, - - ltTestCase{uint8(0), true, false, ""}, - ltTestCase{uint8(255), true, false, ""}, - - ltTestCase{uint16(0), true, false, ""}, - ltTestCase{uint16(65535), true, false, ""}, - - ltTestCase{uint32(0), true, false, ""}, - ltTestCase{uint32(math.MaxUint32), true, false, ""}, - - ltTestCase{uint64(0), true, false, ""}, - ltTestCase{uint64(kTwoTo54 - 1), true, false, ""}, - ltTestCase{uint64(kTwoTo54 + 0), true, false, ""}, - ltTestCase{uint64(kTwoTo54 + 1), false, false, ""}, - ltTestCase{uint64(kTwoTo54 + 2), false, false, ""}, - - // Floating point. - ltTestCase{float64(-1), true, false, ""}, - ltTestCase{float64(kTwoTo54 - 2), true, false, ""}, - ltTestCase{float64(kTwoTo54 - 1), false, false, ""}, - ltTestCase{float64(kTwoTo54 + 0), false, false, ""}, - ltTestCase{float64(kTwoTo54 + 1), false, false, ""}, - ltTestCase{float64(kTwoTo54 + 2), false, false, ""}, - ltTestCase{float64(kTwoTo54 + 3), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessThanTest) Float32AboveExactIntegerRange() { - // Single-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo25 = 1 << 25 - matcher := LessThan(float32(kTwoTo25 + 1)) - - desc := matcher.Description() - expectedDesc := "less than 3.3554432e+07" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []ltTestCase{ - // Signed integers. - ltTestCase{int64(-1), true, false, ""}, - ltTestCase{int64(kTwoTo25 - 2), true, false, ""}, - ltTestCase{int64(kTwoTo25 - 1), false, false, ""}, - ltTestCase{int64(kTwoTo25 + 0), false, false, ""}, - ltTestCase{int64(kTwoTo25 + 1), false, false, ""}, - ltTestCase{int64(kTwoTo25 + 2), false, false, ""}, - ltTestCase{int64(kTwoTo25 + 3), false, false, ""}, - - // Unsigned integers. - ltTestCase{uint64(0), true, false, ""}, - ltTestCase{uint64(kTwoTo25 - 2), true, false, ""}, - ltTestCase{uint64(kTwoTo25 - 1), false, false, ""}, - ltTestCase{uint64(kTwoTo25 + 0), false, false, ""}, - ltTestCase{uint64(kTwoTo25 + 1), false, false, ""}, - ltTestCase{uint64(kTwoTo25 + 2), false, false, ""}, - ltTestCase{uint64(kTwoTo25 + 3), false, false, ""}, - - // Floating point. - ltTestCase{float32(-1), true, false, ""}, - ltTestCase{float32(kTwoTo25 - 2), true, false, ""}, - ltTestCase{float32(kTwoTo25 - 1), false, false, ""}, - ltTestCase{float32(kTwoTo25 + 0), false, false, ""}, - ltTestCase{float32(kTwoTo25 + 1), false, false, ""}, - ltTestCase{float32(kTwoTo25 + 2), false, false, ""}, - ltTestCase{float32(kTwoTo25 + 3), false, false, ""}, - - ltTestCase{float64(-1), true, false, ""}, - ltTestCase{float64(kTwoTo25 - 2), true, false, ""}, - ltTestCase{float64(kTwoTo25 - 1), false, false, ""}, - ltTestCase{float64(kTwoTo25 + 0), false, false, ""}, - ltTestCase{float64(kTwoTo25 + 1), false, false, ""}, - ltTestCase{float64(kTwoTo25 + 2), false, false, ""}, - ltTestCase{float64(kTwoTo25 + 3), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessThanTest) Float64AboveExactIntegerRange() { - // Double-precision floats don't have enough bits to represent the integers - // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value - // and should be treated as equivalent when floats are in the mix. - const kTwoTo54 = 1 << 54 - matcher := LessThan(float64(kTwoTo54 + 1)) - - desc := matcher.Description() - expectedDesc := "less than 1.8014398509481984e+16" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []ltTestCase{ - // Signed integers. - ltTestCase{int64(-1), true, false, ""}, - ltTestCase{int64(kTwoTo54 - 2), true, false, ""}, - ltTestCase{int64(kTwoTo54 - 1), false, false, ""}, - ltTestCase{int64(kTwoTo54 + 0), false, false, ""}, - ltTestCase{int64(kTwoTo54 + 1), false, false, ""}, - ltTestCase{int64(kTwoTo54 + 2), false, false, ""}, - ltTestCase{int64(kTwoTo54 + 3), false, false, ""}, - - // Unsigned integers. - ltTestCase{uint64(0), true, false, ""}, - ltTestCase{uint64(kTwoTo54 - 2), true, false, ""}, - ltTestCase{uint64(kTwoTo54 - 1), false, false, ""}, - ltTestCase{uint64(kTwoTo54 + 0), false, false, ""}, - ltTestCase{uint64(kTwoTo54 + 1), false, false, ""}, - ltTestCase{uint64(kTwoTo54 + 2), false, false, ""}, - ltTestCase{uint64(kTwoTo54 + 3), false, false, ""}, - - // Floating point. - ltTestCase{float64(-1), true, false, ""}, - ltTestCase{float64(kTwoTo54 - 2), true, false, ""}, - ltTestCase{float64(kTwoTo54 - 1), false, false, ""}, - ltTestCase{float64(kTwoTo54 + 0), false, false, ""}, - ltTestCase{float64(kTwoTo54 + 1), false, false, ""}, - ltTestCase{float64(kTwoTo54 + 2), false, false, ""}, - ltTestCase{float64(kTwoTo54 + 3), false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -//////////////////////////////////////////////////////////////////////// -// String literals -//////////////////////////////////////////////////////////////////////// - -func (t *LessThanTest) EmptyString() { - matcher := LessThan("") - desc := matcher.Description() - expectedDesc := "less than \"\"" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []ltTestCase{ - ltTestCase{"", false, false, ""}, - ltTestCase{"\x00", false, false, ""}, - ltTestCase{"a", false, false, ""}, - ltTestCase{"foo", false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessThanTest) SingleNullByte() { - matcher := LessThan("\x00") - desc := matcher.Description() - expectedDesc := "less than \"\x00\"" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []ltTestCase{ - ltTestCase{"", true, false, ""}, - ltTestCase{"\x00", false, false, ""}, - ltTestCase{"a", false, false, ""}, - ltTestCase{"foo", false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} - -func (t *LessThanTest) LongerString() { - matcher := LessThan("foo\x00") - desc := matcher.Description() - expectedDesc := "less than \"foo\x00\"" - - ExpectThat(desc, Equals(expectedDesc)) - - cases := []ltTestCase{ - ltTestCase{"", true, false, ""}, - ltTestCase{"\x00", true, false, ""}, - ltTestCase{"bar", true, false, ""}, - ltTestCase{"foo", true, false, ""}, - ltTestCase{"foo\x00", false, false, ""}, - ltTestCase{"fooa", false, false, ""}, - ltTestCase{"qux", false, false, ""}, - } - - t.checkTestCases(matcher, cases) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/matches_regexp_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/matches_regexp_test.go deleted file mode 100644 index 35b9cf9ab9b..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/matches_regexp_test.go +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type MatchesRegexpTest struct { -} - -func init() { RegisterTestSuite(&MatchesRegexpTest{}) } - -//////////////////////////////////////////////////////////////////////// -// Tests -//////////////////////////////////////////////////////////////////////// - -func (t *MatchesRegexpTest) Description() { - m := MatchesRegexp("foo.*bar") - ExpectEq("matches regexp \"foo.*bar\"", m.Description()) -} - -func (t *MatchesRegexpTest) InvalidRegexp() { - ExpectThat( - func() { MatchesRegexp("(foo") }, - Panics(HasSubstr("missing closing )"))) -} - -func (t *MatchesRegexpTest) CandidateIsNil() { - m := MatchesRegexp("") - err := m.Matches(nil) - - ExpectThat(err, Error(Equals("which is not a string or []byte"))) - ExpectTrue(isFatal(err)) -} - -func (t *MatchesRegexpTest) CandidateIsInteger() { - m := MatchesRegexp("") - err := m.Matches(17) - - ExpectThat(err, Error(Equals("which is not a string or []byte"))) - ExpectTrue(isFatal(err)) -} - -func (t *MatchesRegexpTest) NonMatchingCandidates() { - m := MatchesRegexp("fo[op]\\s+x") - var err error - - err = m.Matches("fon x") - ExpectThat(err, Error(Equals(""))) - ExpectFalse(isFatal(err)) - - err = m.Matches("fopx") - ExpectThat(err, Error(Equals(""))) - ExpectFalse(isFatal(err)) - - err = m.Matches("fop ") - ExpectThat(err, Error(Equals(""))) - ExpectFalse(isFatal(err)) -} - -func (t *MatchesRegexpTest) MatchingCandidates() { - m := MatchesRegexp("fo[op]\\s+x") - var err error - - err = m.Matches("foo x") - ExpectEq(nil, err) - - err = m.Matches("fop x") - ExpectEq(nil, err) - - err = m.Matches("blah blah foo x blah blah") - ExpectEq(nil, err) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/not_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/not_test.go deleted file mode 100644 index 7569d687a74..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/not_test.go +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - "errors" - "testing" - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type fakeMatcher struct { - matchFunc func(interface{}) error - description string -} - -func (m *fakeMatcher) Matches(c interface{}) error { - return m.matchFunc(c) -} - -func (m *fakeMatcher) Description() string { - return m.description -} - -type NotTest struct { -} - -func init() { RegisterTestSuite(&NotTest{}) } -func TestOgletest(t *testing.T) { RunTests(t) } - -//////////////////////////////////////////////////////////////////////// -// Tests -//////////////////////////////////////////////////////////////////////// - -func (t *NotTest) CallsWrapped() { - var suppliedCandidate interface{} - matchFunc := func(c interface{}) error { - suppliedCandidate = c - return nil - } - - wrapped := &fakeMatcher{matchFunc, ""} - matcher := Not(wrapped) - - matcher.Matches(17) - ExpectThat(suppliedCandidate, Equals(17)) -} - -func (t *NotTest) WrappedReturnsTrue() { - matchFunc := func(c interface{}) error { - return nil - } - - wrapped := &fakeMatcher{matchFunc, ""} - matcher := Not(wrapped) - - err := matcher.Matches(0) - ExpectThat(err, Error(Equals(""))) -} - -func (t *NotTest) WrappedReturnsNonFatalError() { - matchFunc := func(c interface{}) error { - return errors.New("taco") - } - - wrapped := &fakeMatcher{matchFunc, ""} - matcher := Not(wrapped) - - err := matcher.Matches(0) - ExpectEq(nil, err) -} - -func (t *NotTest) WrappedReturnsFatalError() { - matchFunc := func(c interface{}) error { - return NewFatalError("taco") - } - - wrapped := &fakeMatcher{matchFunc, ""} - matcher := Not(wrapped) - - err := matcher.Matches(0) - ExpectThat(err, Error(Equals("taco"))) -} - -func (t *NotTest) Description() { - wrapped := &fakeMatcher{nil, "taco"} - matcher := Not(wrapped) - - ExpectEq("not(taco)", matcher.Description()) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/oglematchers.goconvey b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/oglematchers.goconvey deleted file mode 100644 index 79982854b53..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/oglematchers.goconvey +++ /dev/null @@ -1,2 +0,0 @@ -#ignore --timeout=1s diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/panics_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/panics_test.go deleted file mode 100644 index dff2eaeff82..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/panics_test.go +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - "errors" - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type PanicsTest struct { - matcherCalled bool - suppliedCandidate interface{} - wrappedError error - - matcher Matcher -} - -func init() { RegisterTestSuite(&PanicsTest{}) } - -func (t *PanicsTest) SetUp(i *TestInfo) { - wrapped := &fakeMatcher{ - func(c interface{}) error { - t.matcherCalled = true - t.suppliedCandidate = c - return t.wrappedError - }, - "foo", - } - - t.matcher = Panics(wrapped) -} - -//////////////////////////////////////////////////////////////////////// -// Tests -//////////////////////////////////////////////////////////////////////// - -func (t *PanicsTest) Description() { - ExpectThat(t.matcher.Description(), Equals("panics with: foo")) -} - -func (t *PanicsTest) CandidateIsNil() { - err := t.matcher.Matches(nil) - - ExpectThat(err, Error(Equals("which is not a zero-arg function"))) - ExpectTrue(isFatal(err)) -} - -func (t *PanicsTest) CandidateIsString() { - err := t.matcher.Matches("taco") - - ExpectThat(err, Error(Equals("which is not a zero-arg function"))) - ExpectTrue(isFatal(err)) -} - -func (t *PanicsTest) CandidateTakesArgs() { - err := t.matcher.Matches(func(i int) string { return "" }) - - ExpectThat(err, Error(Equals("which is not a zero-arg function"))) - ExpectTrue(isFatal(err)) -} - -func (t *PanicsTest) CallsFunction() { - callCount := 0 - t.matcher.Matches(func() string { - callCount++ - return "" - }) - - ExpectThat(callCount, Equals(1)) -} - -func (t *PanicsTest) FunctionDoesntPanic() { - err := t.matcher.Matches(func() {}) - - ExpectThat(err, Error(Equals("which didn't panic"))) - ExpectFalse(isFatal(err)) -} - -func (t *PanicsTest) CallsWrappedMatcher() { - expectedErr := 17 - t.wrappedError = errors.New("") - t.matcher.Matches(func() { panic(expectedErr) }) - - ExpectThat(t.suppliedCandidate, Equals(expectedErr)) -} - -func (t *PanicsTest) WrappedReturnsTrue() { - err := t.matcher.Matches(func() { panic("") }) - - ExpectEq(nil, err) -} - -func (t *PanicsTest) WrappedReturnsFatalErrorWithoutText() { - t.wrappedError = NewFatalError("") - err := t.matcher.Matches(func() { panic(17) }) - - ExpectThat(err, Error(Equals("which panicked with: 17"))) - ExpectFalse(isFatal(err)) -} - -func (t *PanicsTest) WrappedReturnsFatalErrorWithText() { - t.wrappedError = NewFatalError("which blah") - err := t.matcher.Matches(func() { panic(17) }) - - ExpectThat(err, Error(Equals("which panicked with: 17, which blah"))) - ExpectFalse(isFatal(err)) -} - -func (t *PanicsTest) WrappedReturnsNonFatalErrorWithoutText() { - t.wrappedError = errors.New("") - err := t.matcher.Matches(func() { panic(17) }) - - ExpectThat(err, Error(Equals("which panicked with: 17"))) - ExpectFalse(isFatal(err)) -} - -func (t *PanicsTest) WrappedReturnsNonFatalErrorWithText() { - t.wrappedError = errors.New("which blah") - err := t.matcher.Matches(func() { panic(17) }) - - ExpectThat(err, Error(Equals("which panicked with: 17, which blah"))) - ExpectFalse(isFatal(err)) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/pointee_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/pointee_test.go deleted file mode 100644 index 0ef31549532..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglematchers/pointee_test.go +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2012 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - "errors" - "testing" - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type PointeeTest struct{} - -func init() { RegisterTestSuite(&PointeeTest{}) } - -func TestPointee(t *testing.T) { RunTests(t) } - -//////////////////////////////////////////////////////////////////////// -// Tests -//////////////////////////////////////////////////////////////////////// - -func (t *PointeeTest) Description() { - wrapped := &fakeMatcher{nil, "taco"} - matcher := Pointee(wrapped) - - ExpectEq("pointee(taco)", matcher.Description()) -} - -func (t *PointeeTest) CandidateIsNotAPointer() { - matcher := Pointee(HasSubstr("")) - err := matcher.Matches([]byte{}) - - ExpectThat(err, Error(Equals("which is not a pointer"))) - ExpectTrue(isFatal(err)) -} - -func (t *PointeeTest) CandidateIsANilLiteral() { - matcher := Pointee(HasSubstr("")) - err := matcher.Matches(nil) - - ExpectThat(err, Error(Equals("which is not a pointer"))) - ExpectTrue(isFatal(err)) -} - -func (t *PointeeTest) CandidateIsANilPointer() { - matcher := Pointee(HasSubstr("")) - err := matcher.Matches((*int)(nil)) - - ExpectThat(err, Error(Equals(""))) - ExpectTrue(isFatal(err)) -} - -func (t *PointeeTest) CallsWrapped() { - var suppliedCandidate interface{} - matchFunc := func(c interface{}) error { - suppliedCandidate = c - return nil - } - - wrapped := &fakeMatcher{matchFunc, ""} - matcher := Pointee(wrapped) - - someSlice := []byte{} - matcher.Matches(&someSlice) - ExpectThat(suppliedCandidate, IdenticalTo(someSlice)) -} - -func (t *PointeeTest) WrappedReturnsOkay() { - matchFunc := func(c interface{}) error { - return nil - } - - wrapped := &fakeMatcher{matchFunc, ""} - matcher := Pointee(wrapped) - - err := matcher.Matches(new(int)) - ExpectEq(nil, err) -} - -func (t *PointeeTest) WrappedReturnsNonFatalNonEmptyError() { - matchFunc := func(c interface{}) error { - return errors.New("taco") - } - - wrapped := &fakeMatcher{matchFunc, ""} - matcher := Pointee(wrapped) - - i := 17 - err := matcher.Matches(&i) - ExpectFalse(isFatal(err)) - ExpectThat(err, Error(Equals("taco"))) -} - -func (t *PointeeTest) WrappedReturnsNonFatalEmptyError() { - matchFunc := func(c interface{}) error { - return errors.New("") - } - - wrapped := &fakeMatcher{matchFunc, ""} - matcher := Pointee(wrapped) - - i := 17 - err := matcher.Matches(&i) - ExpectFalse(isFatal(err)) - ExpectThat(err, Error(HasSubstr("whose pointee"))) - ExpectThat(err, Error(HasSubstr("17"))) -} - -func (t *PointeeTest) WrappedReturnsFatalNonEmptyError() { - matchFunc := func(c interface{}) error { - return NewFatalError("taco") - } - - wrapped := &fakeMatcher{matchFunc, ""} - matcher := Pointee(wrapped) - - i := 17 - err := matcher.Matches(&i) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(Equals("taco"))) -} - -func (t *PointeeTest) WrappedReturnsFatalEmptyError() { - matchFunc := func(c interface{}) error { - return NewFatalError("") - } - - wrapped := &fakeMatcher{matchFunc, ""} - matcher := Pointee(wrapped) - - i := 17 - err := matcher.Matches(&i) - ExpectTrue(isFatal(err)) - ExpectThat(err, Error(HasSubstr("whose pointee"))) - ExpectThat(err, Error(HasSubstr("17"))) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/.gitignore b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/.gitignore deleted file mode 100644 index dd8fc7468f4..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -*.6 -6.out -_obj/ -_test/ -_testmain.go diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/README.markdown b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/README.markdown deleted file mode 100644 index f7323af66b1..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/README.markdown +++ /dev/null @@ -1,101 +0,0 @@ -`oglemock` is a mocking framework for the Go programming language with the -following features: - - * An extensive and extensible set of matchers for expressing call - expectations (provided by the [oglematchers][] package). - - * Clean, readable output that tells you exactly what you need to know. - - * Style and semantics similar to [Google Mock][googlemock] and - [Google JS Test][google-js-test]. - - * Seamless integration with the [ogletest][] unit testing framework. - -It can be integrated into any testing framework (including Go's `testing` -package), but out of the box support is built in to [ogletest][] and that is the -easiest place to use it. - - -Installation ------------- - -First, make sure you have installed Go 1.0.2 or newer. See -[here][golang-install] for instructions. - -Use the following command to install `oglemock` and its dependencies, and to -keep them up to date: - - go get -u github.com/smartystreets/goconvey/convey/assertions/oglemock - go get -u github.com/smartystreets/goconvey/convey/assertions/oglemock/createmock - -Those commands will install the `oglemock` package itself, along with the -`createmock` tool that is used to auto-generate mock types. - - -Generating and using mock types -------------------------------- - -Automatically generating a mock implementation of an interface is easy. If you -want to mock interfaces `Bar` and `Baz` from package `foo`, simply run the -following: - - createmock foo Bar Baz - -That will print source code that can be saved to a file and used in your tests. -For example, to create a `mock_io` package containing mock implementations of -`io.Reader` and `io.Writer`: - - mkdir mock_io - createmock io Reader Writer > mock_io/mock_io.go - -The new package will be named `mock_io`, and contain types called `MockReader` -and `MockWriter`, which implement `io.Reader` and `io.Writer` respectively. - -For each generated mock type, there is a corresponding function for creating an -instance of that type given a `Controller` object (see below). For example, to -create a mock reader: - -```go -someController := [...] // See next section. -someReader := mock_io.NewMockReader(someController, "Mock file reader") -``` - -The snippet above creates a mock `io.Reader` that reports failures to -`someController`. The reader can subsequently have expectations set up and be -passed to your code under test that uses an `io.Reader`. - - -Getting ahold of a controller ------------------------------ - -[oglemock.Controller][controller-ref] is used to create mock objects, and to set -up and verify expectations for them. You can create one by calling -`NewController` with an `ErrorReporter`, which is the basic type used to -interface between `oglemock` and the testing framework within which it is being -used. - -If you are using [ogletest][] you don't need to worry about any of this, since -the `TestInfo` struct provided to your test's `SetUp` function already contains -a working `Controller` that you can use to create mock object, and you can use -the built-in `ExpectCall` function for setting expectations. (See the -[ogletest documentation][ogletest-docs] for more info.) Otherwise, you will need -to implement the simple [ErrorReporter interface][reporter-ref] for your test -environment. - - -Documentation -------------- - -For thorough documentation, including information on how to set up expectations, -see [here][oglemock-docs]. - - -[controller-ref]: http://gopkgdoc.appspot.com/pkg/github.com/smartystreets/goconvey/convey/assertions/oglemock#Controller -[reporter-ref]: http://gopkgdoc.appspot.com/pkg/github.com/smartystreets/goconvey/convey/assertions/oglemock#ErrorReporter -[golang-install]: http://golang.org/doc/install.html -[google-js-test]: http://code.google.com/p/google-js-test/ -[googlemock]: http://code.google.com/p/googlemock/ -[oglematchers]: https://github.com/smartystreets/goconvey/convey/assertions/oglematchers -[oglemock-docs]: http://gopkgdoc.appspot.com/pkg/github.com/smartystreets/goconvey/convey/assertions/oglemock -[ogletest]: https://github.com/smartystreets/goconvey/convey/assertions/oglematchers -[ogletest-docs]: http://gopkgdoc.appspot.com/pkg/github.com/smartystreets/goconvey/convey/assertions/ogletest diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/action.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/action.go deleted file mode 100644 index 9fd40d81fe8..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/action.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglemock - -import ( - "reflect" -) - -// Action represents an action to be taken in response to a call to a mock -// method. -type Action interface { - // Set the signature of the function with which this action is being used. - // This must be called before Invoke is called. - SetSignature(signature reflect.Type) error - - // Invoke runs the specified action, given the arguments to the mock method. - // It returns zero or more values that may be treated as the return values of - // the method. If the action doesn't return any values, it may return the nil - // slice. - // - // You must call SetSignature before calling Invoke. - Invoke(methodArgs []interface{}) []interface{} -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/controller.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/controller.go deleted file mode 100644 index 93a1d6239e1..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/controller.go +++ /dev/null @@ -1,480 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglemock - -import ( - "errors" - "fmt" - "log" - "math" - "reflect" - "sync" -) - -// PartialExpecation is a function that should be called exactly once with -// expected arguments or matchers in order to set up an expected method call. -// See Controller.ExpectMethodCall below. It returns an expectation that can be -// further modified (e.g. by calling WillOnce). -// -// If the arguments are of the wrong type, the function reports a fatal error -// and returns nil. -type PartialExpecation func(...interface{}) Expectation - -// Controller represents an object that implements the central logic of -// oglemock: recording and verifying expectations, responding to mock method -// calls, and so on. -type Controller interface { - // ExpectCall expresses an expectation that the method of the given name - // should be called on the supplied mock object. It returns a function that - // should be called with the expected arguments, matchers for the arguments, - // or a mix of both. - // - // fileName and lineNumber should indicate the line on which the expectation - // was made, if known. - // - // For example: - // - // mockWriter := [...] - // controller.ExpectCall(mockWriter, "Write", "foo.go", 17)(ElementsAre(0x1)) - // .WillOnce(Return(1, nil)) - // - // If the mock object doesn't have a method of the supplied name, the - // function reports a fatal error and returns nil. - ExpectCall( - o MockObject, - methodName string, - fileName string, - lineNumber int) PartialExpecation - - // Finish causes the controller to check for any unsatisfied expectations, - // and report them as errors if they exist. - // - // The controller may panic if any of its methods (including this one) are - // called after Finish is called. - Finish() - - // HandleMethodCall looks for a registered expectation matching the call of - // the given method on mock object o, invokes the appropriate action (if - // any), and returns the values returned by that action (if any). - // - // If the action returns nothing, the controller returns zero values. If - // there is no matching expectation, the controller reports an error and - // returns zero values. - // - // If the mock object doesn't have a method of the supplied name, the - // arguments are of the wrong type, or the action returns the wrong types, - // the function reports a fatal error. - // - // HandleMethodCall is exported for the sake of mock implementations, and - // should not be used directly. - HandleMethodCall( - o MockObject, - methodName string, - fileName string, - lineNumber int, - args []interface{}) []interface{} -} - -// methodMap represents a map from method name to set of expectations for that -// method. -type methodMap map[string][]*InternalExpectation - -// objectMap represents a map from mock object ID to a methodMap for that object. -type objectMap map[uintptr]methodMap - -// NewController sets up a fresh controller, without any expectations set, and -// configures the controller to use the supplied error reporter. -func NewController(reporter ErrorReporter) Controller { - return &controllerImpl{reporter, sync.RWMutex{}, objectMap{}} -} - -type controllerImpl struct { - reporter ErrorReporter - - mutex sync.RWMutex - expectationsByObject objectMap // Protected by mutex -} - -// Return the list of registered expectations for the named method of the -// supplied object, or an empty slice if none have been registered. When this -// method returns, it is guaranteed that c.expectationsByObject has an entry -// for the object. -// -// c.mutex must be held for reading. -func (c *controllerImpl) getExpectationsLocked( - o MockObject, - methodName string) []*InternalExpectation { - id := o.Oglemock_Id() - - // Look up the mock object. - expectationsByMethod, ok := c.expectationsByObject[id] - if !ok { - expectationsByMethod = methodMap{} - c.expectationsByObject[id] = expectationsByMethod - } - - result, ok := expectationsByMethod[methodName] - if !ok { - return []*InternalExpectation{} - } - - return result -} - -// Add an expectation to the list registered for the named method of the -// supplied mock object. -// -// c.mutex must be held for writing. -func (c *controllerImpl) addExpectationLocked( - o MockObject, - methodName string, - exp *InternalExpectation) { - // Get the existing list. - existing := c.getExpectationsLocked(o, methodName) - - // Store a modified list. - id := o.Oglemock_Id() - c.expectationsByObject[id][methodName] = append(existing, exp) -} - -func (c *controllerImpl) ExpectCall( - o MockObject, - methodName string, - fileName string, - lineNumber int) PartialExpecation { - // Find the signature for the requested method. - ov := reflect.ValueOf(o) - method := ov.MethodByName(methodName) - if method.Kind() == reflect.Invalid { - c.reporter.ReportFatalError( - fileName, - lineNumber, - errors.New("Unknown method: "+methodName)) - return nil - } - - partialAlreadyCalled := false // Protected by c.mutex - return func(args ...interface{}) Expectation { - c.mutex.Lock() - defer c.mutex.Unlock() - - // This function should only be called once. - if partialAlreadyCalled { - c.reporter.ReportFatalError( - fileName, - lineNumber, - errors.New("Partial expectation called more than once.")) - return nil - } - - partialAlreadyCalled = true - - // Make sure that the number of args is legal. Keep in mind that the - // method's type has an extra receiver arg. - if len(args) != method.Type().NumIn() { - c.reporter.ReportFatalError( - fileName, - lineNumber, - errors.New( - fmt.Sprintf( - "Expectation for %s given wrong number of arguments: "+ - "expected %d, got %d.", - methodName, - method.Type().NumIn(), - len(args)))) - return nil - } - - // Create an expectation and insert it into the controller's map. - exp := InternalNewExpectation( - c.reporter, - method.Type(), - args, - fileName, - lineNumber) - - c.addExpectationLocked(o, methodName, exp) - - // Return the expectation to the user. - return exp - } -} - -func (c *controllerImpl) Finish() { - c.mutex.Lock() - defer c.mutex.Unlock() - - // Check whether the minimum cardinality for each registered expectation has - // been satisfied. - for _, expectationsByMethod := range c.expectationsByObject { - for methodName, expectations := range expectationsByMethod { - for _, exp := range expectations { - exp.mutex.Lock() - defer exp.mutex.Unlock() - - minCardinality, _ := computeCardinalityLocked(exp) - if exp.NumMatches < minCardinality { - c.reporter.ReportError( - exp.FileName, - exp.LineNumber, - errors.New( - fmt.Sprintf( - "Unsatisfied expectation; expected %s to be called "+ - "at least %d times; called %d times.", - methodName, - minCardinality, - exp.NumMatches))) - } - } - } - } -} - -// expectationMatches checks the matchers for the expectation against the -// supplied arguments. -func expectationMatches(exp *InternalExpectation, args []interface{}) bool { - matchers := exp.ArgMatchers - if len(args) != len(matchers) { - panic("expectationMatches: len(args)") - } - - // Check each matcher. - for i, matcher := range matchers { - if err := matcher.Matches(args[i]); err != nil { - return false - } - } - - return true -} - -// Return the expectation that matches the supplied arguments. If there is more -// than one such expectation, the one furthest along in the list for the method -// is returned. If there is no such expectation, nil is returned. -// -// c.mutex must be held for reading. -func (c *controllerImpl) chooseExpectationLocked( - o MockObject, - methodName string, - args []interface{}) *InternalExpectation { - // Do we have any expectations for this method? - expectations := c.getExpectationsLocked(o, methodName) - if len(expectations) == 0 { - return nil - } - - for i := len(expectations) - 1; i >= 0; i-- { - if expectationMatches(expectations[i], args) { - return expectations[i] - } - } - - return nil -} - -// makeZeroReturnValues creates a []interface{} containing appropriate zero -// values for returning from the supplied method type. -func makeZeroReturnValues(signature reflect.Type) []interface{} { - result := make([]interface{}, signature.NumOut()) - - for i, _ := range result { - outType := signature.Out(i) - zeroVal := reflect.Zero(outType) - result[i] = zeroVal.Interface() - } - - return result -} - -// computeCardinality decides on the [min, max] range of the number of expected -// matches for the supplied expectations, according to the rules documented in -// expectation.go. -// -// exp.mutex must be held for reading. -func computeCardinalityLocked(exp *InternalExpectation) (min, max uint) { - // Explicit cardinality. - if exp.ExpectedNumMatches >= 0 { - min = uint(exp.ExpectedNumMatches) - max = min - return - } - - // Implicit count based on one-time actions. - if len(exp.OneTimeActions) != 0 { - min = uint(len(exp.OneTimeActions)) - max = min - - // If there is a fallback action, this is only a lower bound. - if exp.FallbackAction != nil { - max = math.MaxUint32 - } - - return - } - - // Implicit lack of restriction based on a fallback action being configured. - if exp.FallbackAction != nil { - min = 0 - max = math.MaxUint32 - return - } - - // Implicit cardinality of one. - min = 1 - max = 1 - return -} - -// chooseAction returns the action that should be invoked for the i'th match to -// the supplied expectation (counting from zero). If the implicit "return zero -// values" action should be used, it returns nil. -// -// exp.mutex must be held for reading. -func chooseActionLocked(i uint, exp *InternalExpectation) Action { - // Exhaust one-time actions first. - if i < uint(len(exp.OneTimeActions)) { - return exp.OneTimeActions[i] - } - - // Fallback action (or nil if none is configured). - return exp.FallbackAction -} - -// Find an action for the method call, updating expectation match state in the -// process. Return either an action that should be invoked or a set of zero -// values to return immediately. -// -// This is split out from HandleMethodCall in order to more easily avoid -// invoking the action with locks held. -func (c *controllerImpl) chooseActionAndUpdateExpectations( - o MockObject, - methodName string, - fileName string, - lineNumber int, - args []interface{}, -) (action Action, zeroVals []interface{}) { - c.mutex.Lock() - defer c.mutex.Unlock() - - // Find the signature for the requested method. - ov := reflect.ValueOf(o) - method := ov.MethodByName(methodName) - if method.Kind() == reflect.Invalid { - c.reporter.ReportFatalError( - fileName, - lineNumber, - errors.New("Unknown method: "+methodName), - ) - - // Should never get here in real code. - log.Println("ReportFatalError unexpectedly returned.") - return - } - - // HACK(jacobsa): Make sure we got the correct number of arguments. This will - // need to be refined when issue #5 (variadic methods) is handled. - if len(args) != method.Type().NumIn() { - c.reporter.ReportFatalError( - fileName, - lineNumber, - errors.New( - fmt.Sprintf( - "Wrong number of arguments: expected %d; got %d", - method.Type().NumIn(), - len(args), - ), - ), - ) - - // Should never get here in real code. - log.Println("ReportFatalError unexpectedly returned.") - return - } - - // Find an expectation matching this call. - expectation := c.chooseExpectationLocked(o, methodName, args) - if expectation == nil { - c.reporter.ReportError( - fileName, - lineNumber, - errors.New( - fmt.Sprintf("Unexpected call to %s with args: %v", methodName, args), - ), - ) - - zeroVals = makeZeroReturnValues(method.Type()) - return - } - - expectation.mutex.Lock() - defer expectation.mutex.Unlock() - - // Increase the number of matches recorded, and check whether we're over the - // number expected. - expectation.NumMatches++ - _, maxCardinality := computeCardinalityLocked(expectation) - if expectation.NumMatches > maxCardinality { - c.reporter.ReportError( - expectation.FileName, - expectation.LineNumber, - errors.New( - fmt.Sprintf( - "Unexpected call to %s: "+ - "expected to be called at most %d times; called %d times.", - methodName, - maxCardinality, - expectation.NumMatches, - ), - ), - ) - - zeroVals = makeZeroReturnValues(method.Type()) - return - } - - // Choose an action to invoke. If there is none, just return zero values. - action = chooseActionLocked(expectation.NumMatches-1, expectation) - if action == nil { - zeroVals = makeZeroReturnValues(method.Type()) - return - } - - // Let the action take over. - return -} - -func (c *controllerImpl) HandleMethodCall( - o MockObject, - methodName string, - fileName string, - lineNumber int, - args []interface{}, -) []interface{} { - // Figure out whether to invoke an action or return zero values. - action, zeroVals := c.chooseActionAndUpdateExpectations( - o, - methodName, - fileName, - lineNumber, - args, - ) - - if action != nil { - return action.Invoke(args) - } - - return zeroVals -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/createmock/createmock.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/createmock/createmock.go deleted file mode 100644 index 4117dba4f04..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/createmock/createmock.go +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright 2012 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// createmock is used to generate source code for mock versions of interfaces -// from installed packages. -package main - -import ( - "errors" - "flag" - "fmt" - "go/build" - "io/ioutil" - "log" - "os" - "os/exec" - "path" - "regexp" - "text/template" - - // Ensure that the generate package, which is used by the generated code, is - // installed by goinstall. - _ "github.com/smartystreets/goconvey/convey/assertions/oglemock/generate" -) - -// A template for generated code that is used to print the result. -const tmplStr = ` -{{$inputPkg := .InputPkg}} -{{$outputPkg := .OutputPkg}} - -package main - -import ( - {{range $identifier, $import := .Imports}} - {{$identifier}} "{{$import}}" - {{end}} -) - -func getTypeForPtr(ptr interface{}) reflect.Type { - return reflect.TypeOf(ptr).Elem() -} - -func main() { - // Reduce noise in logging output. - log.SetFlags(0) - - interfaces := []reflect.Type{ - {{range $typeName := .TypeNames}} - getTypeForPtr((*{{base $inputPkg}}.{{$typeName}})(nil)), - {{end}} - } - - err := generate.GenerateMockSource(os.Stdout, "{{$outputPkg}}", interfaces) - if err != nil { - log.Fatalf("Error generating mock source: %v", err) - } -} -` - -// A map from import identifier to package to use that identifier for, -// containing elements for each import needed by the generated code. -type importMap map[string]string - -type tmplArg struct { - InputPkg string - OutputPkg string - - // Imports needed by the generated code. - Imports importMap - - // Types to be mocked, relative to their package's name. - TypeNames []string -} - -var unknownPackageRegexp = regexp.MustCompile( - `tool\.go:\d+:\d+: cannot find package "([^"]+)"`) - -var undefinedInterfaceRegexp = regexp.MustCompile(`tool\.go:\d+: undefined: [\pL_0-9]+\.([\pL_0-9]+)`) - -// Does the 'go build' output indicate that a package wasn't found? If so, -// return the name of the package. -func findUnknownPackage(output []byte) *string { - if match := unknownPackageRegexp.FindSubmatch(output); match != nil { - res := string(match[1]) - return &res - } - - return nil -} - -// Does the 'go build' output indicate that an interface wasn't found? If so, -// return the name of the interface. -func findUndefinedInterface(output []byte) *string { - if match := undefinedInterfaceRegexp.FindSubmatch(output); match != nil { - res := string(match[1]) - return &res - } - - return nil -} - -// Split out from main so that deferred calls are executed even in the event of -// an error. -func run() error { - // Reduce noise in logging output. - log.SetFlags(0) - - // Check the command-line arguments. - flag.Parse() - - cmdLineArgs := flag.Args() - if len(cmdLineArgs) < 2 { - return errors.New("Usage: createmock [package] [interface ...]") - } - - // Create a temporary directory inside of $GOPATH to hold generated code. - buildPkg, err := build.Import("github.com/smartystreets/goconvey/convey/assertions/oglemock", "", build.FindOnly) - if err != nil { - return errors.New(fmt.Sprintf("Couldn't find oglemock in $GOPATH: %v", err)) - } - - tmpDir, err := ioutil.TempDir(buildPkg.SrcRoot, "tmp-createmock-") - if err != nil { - return errors.New(fmt.Sprintf("Creating temp dir: %v", err)) - } - - defer os.RemoveAll(tmpDir) - - // Create a file to hold generated code. - codeFile, err := os.Create(path.Join(tmpDir, "tool.go")) - if err != nil { - return errors.New(fmt.Sprintf("Couldn't create a file to hold code: %v", err)) - } - - // Create an appropriate path for the built binary. - binaryPath := path.Join(tmpDir, "tool") - - // Create an appropriate template argument. - var arg tmplArg - arg.InputPkg = cmdLineArgs[0] - arg.OutputPkg = "mock_" + path.Base(arg.InputPkg) - arg.TypeNames = cmdLineArgs[1:] - - arg.Imports = make(importMap) - arg.Imports[path.Base(arg.InputPkg)] = arg.InputPkg - arg.Imports["generate"] = "github.com/smartystreets/goconvey/convey/assertions/oglemock/generate" - arg.Imports["log"] = "log" - arg.Imports["os"] = "os" - arg.Imports["reflect"] = "reflect" - - // Execute the template to generate code that will itself generate the mock - // code. Write the code to the temp file. - tmpl := template.Must( - template.New("code").Funcs( - template.FuncMap{ - "base": path.Base, - }).Parse(tmplStr)) - if err := tmpl.Execute(codeFile, arg); err != nil { - return errors.New(fmt.Sprintf("Error executing template: %v", err)) - } - - codeFile.Close() - - // Attempt to build the code. - cmd := exec.Command("go", "build", "-o", binaryPath) - cmd.Dir = tmpDir - buildOutput, err := cmd.CombinedOutput() - - if err != nil { - // Did the compilation fail due to the user-specified package not being found? - if pkg := findUnknownPackage(buildOutput); pkg != nil && *pkg == arg.InputPkg { - return errors.New(fmt.Sprintf("Unknown package: %s", *pkg)) - } - - // Did the compilation fail due to an unknown interface? - if in := findUndefinedInterface(buildOutput); in != nil { - return errors.New(fmt.Sprintf("Unknown interface: %s", *in)) - } - - // Otherwise return a generic error. - return errors.New(fmt.Sprintf( - "%s\n\nError building generated code:\n\n"+ - " %v\n\nPlease report this oglemock bug.", - buildOutput, - err)) - } - - // Run the binary. - cmd = exec.Command(binaryPath) - binaryOutput, err := cmd.CombinedOutput() - - if err != nil { - return errors.New(fmt.Sprintf( - "%s\n\nError running generated code:\n\n"+ - " %v\n\n Please report this oglemock bug.", - binaryOutput, - err)) - } - - // Copy its output. - _, err = os.Stdout.Write(binaryOutput) - if err != nil { - return errors.New(fmt.Sprintf("Error copying binary output: %v", err)) - } - - return nil -} - -func main() { - if err := run(); err != nil { - fmt.Println(err.Error()) - os.Exit(1) - } -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/createmock/test_cases/golden.no_interfaces b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/createmock/test_cases/golden.no_interfaces deleted file mode 100644 index b70535fae6b..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/createmock/test_cases/golden.no_interfaces +++ /dev/null @@ -1 +0,0 @@ -Usage: createmock [package] [interface ...] diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/createmock/test_cases/golden.no_package b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/createmock/test_cases/golden.no_package deleted file mode 100644 index b70535fae6b..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/createmock/test_cases/golden.no_package +++ /dev/null @@ -1 +0,0 @@ -Usage: createmock [package] [interface ...] diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/createmock/test_cases/golden.unknown_interface b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/createmock/test_cases/golden.unknown_interface deleted file mode 100644 index c32950a1790..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/createmock/test_cases/golden.unknown_interface +++ /dev/null @@ -1 +0,0 @@ -Unknown interface: Frobnicator diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/createmock/test_cases/golden.unknown_package b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/createmock/test_cases/golden.unknown_package deleted file mode 100644 index d07e915d2cf..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/createmock/test_cases/golden.unknown_package +++ /dev/null @@ -1 +0,0 @@ -Unknown package: foo/bar diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/error_reporter.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/error_reporter.go deleted file mode 100644 index 0c3a65ee187..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/error_reporter.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglemock - -// ErrorReporter is an interface that wraps methods for reporting errors that -// should cause test failures. -type ErrorReporter interface { - // Report that some failure (e.g. an unsatisfied expectation) occurred. If - // known, fileName and lineNumber should contain information about where it - // occurred. The test may continue if the test framework supports it. - ReportError(fileName string, lineNumber int, err error) - - // Like ReportError, but the test should be halted immediately. It is assumed - // that this method does not return. - ReportFatalError(fileName string, lineNumber int, err error) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/expectation.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/expectation.go deleted file mode 100644 index d18bfb8bce9..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/expectation.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglemock - -// Expectation is an expectation for zero or more calls to a mock method with -// particular arguments or sets of arguments. -type Expectation interface { - // Times expresses that a matching method call should happen exactly N times. - // Times must not be called more than once, and must not be called after - // WillOnce or WillRepeatedly. - // - // The full rules for the cardinality of an expectation are as follows: - // - // 1. If an explicit cardinality is set with Times(N), then anything other - // than exactly N matching calls will cause a test failure. - // - // 2. Otherwise, if there are any one-time actions set up, then it is - // expected there will be at least that many matching calls. If there is - // not also a fallback action, then it is expected that there will be - // exactly that many. - // - // 3. Otherwise, if there is a fallback action configured, any number of - // matching calls (including zero) is allowed. - // - // 4. Otherwise, the implicit cardinality is one. - // - Times(n uint) Expectation - - // WillOnce configures a "one-time action". WillOnce can be called zero or - // more times, but must be called after any call to Times and before any call - // to WillRepeatedly. - // - // When matching method calls are made on the mock object, one-time actions - // are invoked one per matching call in the order that they were set up until - // they are exhausted. Afterward the fallback action, if any, will be used. - WillOnce(a Action) Expectation - - // WillRepeatedly configures a "fallback action". WillRepeatedly can be - // called zero or one times, and must not be called before Times or WillOnce. - // - // Once all one-time actions are exhausted (see above), the fallback action - // will be invoked for any further method calls. If WillRepeatedly is not - // called, the fallback action is implicitly an action that returns zero - // values for the method's return values. - WillRepeatedly(a Action) Expectation -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/generate.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/generate.go deleted file mode 100644 index 0c383f9f63e..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/generate.go +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright 2012 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package generate implements code generation for mock classes. This is an -// implementation detail of the createmock command, which you probably want to -// use directly instead. -package generate - -import ( - "bytes" - "errors" - "go/ast" - "go/parser" - "go/printer" - "go/token" - "io" - "reflect" - "regexp" - "text/template" -) - -const tmplStr = ` -// This file was auto-generated using createmock. See the following page for -// more information: -// -// https://github.com/smartystreets/goconvey/convey/assertions/oglemock -// - -package {{.Pkg}} - -import ( - {{range $identifier, $import := .Imports}}{{$identifier}} "{{$import}}" - {{end}} -) - -{{range .Interfaces}} - {{$interfaceName := printf "Mock%s" .Name}} - {{$structName := printf "mock%s" .Name}} - - type {{$interfaceName}} interface { - {{getTypeString .}} - oglemock.MockObject - } - - type {{$structName}} struct { - controller oglemock.Controller - description string - } - - func New{{printf "Mock%s" .Name}}( - c oglemock.Controller, - desc string) {{$interfaceName}} { - return &{{$structName}}{ - controller: c, - description: desc, - } - } - - func (m *{{$structName}}) Oglemock_Id() uintptr { - return uintptr(unsafe.Pointer(m)) - } - - func (m *{{$structName}}) Oglemock_Description() string { - return m.description - } - - {{range getMethods .}} - {{$funcType := .Type}} - {{$inputTypes := getInputs $funcType}} - {{$outputTypes := getOutputs $funcType}} - - func (m *{{$structName}}) {{.Name}}({{range $i, $type := $inputTypes}}p{{$i}} {{getInputTypeString $i $funcType}}, {{end}}) ({{range $i, $type := $outputTypes}}o{{$i}} {{getTypeString $type}}, {{end}}) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "{{.Name}}", - file, - line, - []interface{}{ {{range $i, $type := $inputTypes}}p{{$i}}, {{end}} }) - - if len(retVals) != {{len $outputTypes}} { - panic(fmt.Sprintf("{{$structName}}.{{.Name}}: invalid return values: %v", retVals)) - } - - {{range $i, $type := $outputTypes}} - // o{{$i}} {{getTypeString $type}} - if retVals[{{$i}}] != nil { - o{{$i}} = retVals[{{$i}}].({{getTypeString $type}}) - } - {{end}} - - return - } - {{end}} -{{end}} -` - -type tmplArg struct { - // The package of the generated code. - Pkg string - - // Imports needed by the interfaces. - Imports importMap - - // The set of interfaces to mock. - Interfaces []reflect.Type -} - -var tmpl *template.Template - -func init() { - extraFuncs := make(template.FuncMap) - extraFuncs["getMethods"] = getMethods - extraFuncs["getInputs"] = getInputs - extraFuncs["getOutputs"] = getOutputs - extraFuncs["getInputTypeString"] = getInputTypeString - extraFuncs["getTypeString"] = getTypeString - - tmpl = template.New("code") - tmpl.Funcs(extraFuncs) - tmpl.Parse(tmplStr) -} - -func getInputTypeString(i int, ft reflect.Type) string { - numInputs := ft.NumIn() - if i == numInputs-1 && ft.IsVariadic() { - return "..." + getTypeString(ft.In(i).Elem()) - } - - return getTypeString(ft.In(i)) -} - -func getTypeString(t reflect.Type) string { - return t.String() -} - -func getMethods(it reflect.Type) []reflect.Method { - numMethods := it.NumMethod() - methods := make([]reflect.Method, numMethods) - - for i := 0; i < numMethods; i++ { - methods[i] = it.Method(i) - } - - return methods -} - -func getInputs(ft reflect.Type) []reflect.Type { - numIn := ft.NumIn() - inputs := make([]reflect.Type, numIn) - - for i := 0; i < numIn; i++ { - inputs[i] = ft.In(i) - } - - return inputs -} - -func getOutputs(ft reflect.Type) []reflect.Type { - numOut := ft.NumOut() - outputs := make([]reflect.Type, numOut) - - for i := 0; i < numOut; i++ { - outputs[i] = ft.Out(i) - } - - return outputs -} - -// A map from import identifier to package to use that identifier for, -// containing elements for each import needed by a set of mocked interfaces. -type importMap map[string]string - -var typePackageIdentifierRegexp = regexp.MustCompile(`^([\pL_0-9]+)\.[\pL_0-9]+$`) - -// Add an import for the supplied type, without recursing. -func addImportForType(imports importMap, t reflect.Type) { - // If there is no package path, this is a built-in type and we don't need an - // import. - pkgPath := t.PkgPath() - if pkgPath == "" { - return - } - - // Work around a bug in Go: - // - // http://code.google.com/p/go/issues/detail?id=2660 - // - var errorPtr *error - if t == reflect.TypeOf(errorPtr).Elem() { - return - } - - // Use the identifier that's part of the type's string representation as the - // import identifier. This means that we'll do the right thing for package - // "foo/bar" with declaration "package baz". - match := typePackageIdentifierRegexp.FindStringSubmatch(t.String()) - if match == nil { - return - } - - imports[match[1]] = pkgPath -} - -// Add all necessary imports for the type, recursing as appropriate. -func addImportsForType(imports importMap, t reflect.Type) { - // Add any import needed for the type itself. - addImportForType(imports, t) - - // Handle special cases where recursion is needed. - switch t.Kind() { - case reflect.Array, reflect.Chan, reflect.Ptr, reflect.Slice: - addImportsForType(imports, t.Elem()) - - case reflect.Func: - // Input parameters. - for i := 0; i < t.NumIn(); i++ { - addImportsForType(imports, t.In(i)) - } - - // Return values. - for i := 0; i < t.NumOut(); i++ { - addImportsForType(imports, t.Out(i)) - } - - case reflect.Map: - addImportsForType(imports, t.Key()) - addImportsForType(imports, t.Elem()) - } -} - -// Add imports for each of the methods of the interface, but not the interface -// itself. -func addImportsForInterfaceMethods(imports importMap, it reflect.Type) { - // Handle each method. - for i := 0; i < it.NumMethod(); i++ { - m := it.Method(i) - addImportsForType(imports, m.Type) - } -} - -// Given a set of interfaces, return a map from import identifier to package to -// use that identifier for, containing elements for each import needed by the -// mock versions of those interfaces. -func getImports(interfaces []reflect.Type) importMap { - imports := make(importMap) - for _, it := range interfaces { - addImportForType(imports, it) - addImportsForInterfaceMethods(imports, it) - } - - // Make sure there are imports for other types used by the generated code - // itself. - imports["fmt"] = "fmt" - imports["oglemock"] = "github.com/smartystreets/goconvey/convey/assertions/oglemock" - imports["runtime"] = "runtime" - imports["unsafe"] = "unsafe" - - return imports -} - -// Given a set of interfaces to mock, write out source code for a package named -// `pkg` that contains mock implementations of those interfaces. -func GenerateMockSource(w io.Writer, pkg string, interfaces []reflect.Type) error { - // Sanity-check arguments. - if pkg == "" { - return errors.New("Package name must be non-empty.") - } - - if len(interfaces) == 0 { - return errors.New("List of interfaces must be non-empty.") - } - - // Make sure each type is indeed an interface. - for _, it := range interfaces { - if it.Kind() != reflect.Interface { - return errors.New("Invalid type: " + it.String()) - } - } - - // Create an appropriate template arg, then execute the template. Write the - // raw output into a buffer. - var arg tmplArg - arg.Pkg = pkg - arg.Imports = getImports(interfaces) - arg.Interfaces = interfaces - - buf := new(bytes.Buffer) - if err := tmpl.Execute(buf, arg); err != nil { - return err - } - - // Parse the output. - fset := token.NewFileSet() - astFile, err := parser.ParseFile(fset, pkg+".go", buf, parser.ParseComments) - if err != nil { - return errors.New("Error parsing generated code: " + err.Error()) - } - - // Sort the import lines in the AST in the same way that gofmt does. - ast.SortImports(fset, astFile) - - // Pretty-print the AST, using the same options that gofmt does by default. - cfg := &printer.Config{ - Mode: printer.UseSpaces | printer.TabIndent, - Tabwidth: 8, - } - - if err = cfg.Fprint(w, fset, astFile); err != nil { - return errors.New("Error pretty printing: " + err.Error()) - } - - return nil -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/test_cases/complicated_pkg/complicated_pkg.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/test_cases/complicated_pkg/complicated_pkg.go deleted file mode 100644 index d86b25de4a4..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/test_cases/complicated_pkg/complicated_pkg.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2012 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package complicated_pkg contains an interface with lots of interesting -// cases, for use in integration testing. -package complicated_pkg - -import ( - "image" - "io" - "net" - - "github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/test_cases/renamed_pkg" -) - -type Byte uint8 - -type ComplicatedThing interface { - Channels(a chan chan<- <-chan net.Conn) chan int - Pointers(a *int, b *net.Conn, c **io.Reader) (*int, error) - Functions(a func(int, image.Image) int) func(string, int) net.Conn - Maps(a map[string]*int) (map[int]*string, error) - Arrays(a [3]string) ([3]int, error) - Slices(a []string) ([]int, error) - NamedScalarType(a Byte) ([]Byte, error) - EmptyInterface(a interface{}) (interface{}, error) - RenamedPackage(a tony.SomeUint8Alias) - Variadic(a int, b ...net.Conn) int -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/test_cases/golden.complicated_pkg.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/test_cases/golden.complicated_pkg.go deleted file mode 100644 index 2a06efb3626..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/test_cases/golden.complicated_pkg.go +++ /dev/null @@ -1,312 +0,0 @@ -// This file was auto-generated using createmock. See the following page for -// more information: -// -// https://github.com/smartystreets/goconvey/convey/assertions/oglemock -// - -package some_pkg - -import ( - fmt "fmt" - image "image" - io "io" - net "net" - runtime "runtime" - unsafe "unsafe" - - oglemock "github.com/smartystreets/goconvey/convey/assertions/oglemock" - complicated_pkg "github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/test_cases/complicated_pkg" - tony "github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/test_cases/renamed_pkg" -) - -type MockComplicatedThing interface { - complicated_pkg.ComplicatedThing - oglemock.MockObject -} - -type mockComplicatedThing struct { - controller oglemock.Controller - description string -} - -func NewMockComplicatedThing( - c oglemock.Controller, - desc string) MockComplicatedThing { - return &mockComplicatedThing{ - controller: c, - description: desc, - } -} - -func (m *mockComplicatedThing) Oglemock_Id() uintptr { - return uintptr(unsafe.Pointer(m)) -} - -func (m *mockComplicatedThing) Oglemock_Description() string { - return m.description -} - -func (m *mockComplicatedThing) Arrays(p0 [3]string) (o0 [3]int, o1 error) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "Arrays", - file, - line, - []interface{}{p0}) - - if len(retVals) != 2 { - panic(fmt.Sprintf("mockComplicatedThing.Arrays: invalid return values: %v", retVals)) - } - - // o0 [3]int - if retVals[0] != nil { - o0 = retVals[0].([3]int) - } - - // o1 error - if retVals[1] != nil { - o1 = retVals[1].(error) - } - - return -} - -func (m *mockComplicatedThing) Channels(p0 chan chan<- <-chan net.Conn) (o0 chan int) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "Channels", - file, - line, - []interface{}{p0}) - - if len(retVals) != 1 { - panic(fmt.Sprintf("mockComplicatedThing.Channels: invalid return values: %v", retVals)) - } - - // o0 chan int - if retVals[0] != nil { - o0 = retVals[0].(chan int) - } - - return -} - -func (m *mockComplicatedThing) EmptyInterface(p0 interface{}) (o0 interface{}, o1 error) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "EmptyInterface", - file, - line, - []interface{}{p0}) - - if len(retVals) != 2 { - panic(fmt.Sprintf("mockComplicatedThing.EmptyInterface: invalid return values: %v", retVals)) - } - - // o0 interface {} - if retVals[0] != nil { - o0 = retVals[0].(interface{}) - } - - // o1 error - if retVals[1] != nil { - o1 = retVals[1].(error) - } - - return -} - -func (m *mockComplicatedThing) Functions(p0 func(int, image.Image) int) (o0 func(string, int) net.Conn) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "Functions", - file, - line, - []interface{}{p0}) - - if len(retVals) != 1 { - panic(fmt.Sprintf("mockComplicatedThing.Functions: invalid return values: %v", retVals)) - } - - // o0 func(string, int) net.Conn - if retVals[0] != nil { - o0 = retVals[0].(func(string, int) net.Conn) - } - - return -} - -func (m *mockComplicatedThing) Maps(p0 map[string]*int) (o0 map[int]*string, o1 error) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "Maps", - file, - line, - []interface{}{p0}) - - if len(retVals) != 2 { - panic(fmt.Sprintf("mockComplicatedThing.Maps: invalid return values: %v", retVals)) - } - - // o0 map[int]*string - if retVals[0] != nil { - o0 = retVals[0].(map[int]*string) - } - - // o1 error - if retVals[1] != nil { - o1 = retVals[1].(error) - } - - return -} - -func (m *mockComplicatedThing) NamedScalarType(p0 complicated_pkg.Byte) (o0 []complicated_pkg.Byte, o1 error) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "NamedScalarType", - file, - line, - []interface{}{p0}) - - if len(retVals) != 2 { - panic(fmt.Sprintf("mockComplicatedThing.NamedScalarType: invalid return values: %v", retVals)) - } - - // o0 []complicated_pkg.Byte - if retVals[0] != nil { - o0 = retVals[0].([]complicated_pkg.Byte) - } - - // o1 error - if retVals[1] != nil { - o1 = retVals[1].(error) - } - - return -} - -func (m *mockComplicatedThing) Pointers(p0 *int, p1 *net.Conn, p2 **io.Reader) (o0 *int, o1 error) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "Pointers", - file, - line, - []interface{}{p0, p1, p2}) - - if len(retVals) != 2 { - panic(fmt.Sprintf("mockComplicatedThing.Pointers: invalid return values: %v", retVals)) - } - - // o0 *int - if retVals[0] != nil { - o0 = retVals[0].(*int) - } - - // o1 error - if retVals[1] != nil { - o1 = retVals[1].(error) - } - - return -} - -func (m *mockComplicatedThing) RenamedPackage(p0 tony.SomeUint8Alias) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "RenamedPackage", - file, - line, - []interface{}{p0}) - - if len(retVals) != 0 { - panic(fmt.Sprintf("mockComplicatedThing.RenamedPackage: invalid return values: %v", retVals)) - } - - return -} - -func (m *mockComplicatedThing) Slices(p0 []string) (o0 []int, o1 error) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "Slices", - file, - line, - []interface{}{p0}) - - if len(retVals) != 2 { - panic(fmt.Sprintf("mockComplicatedThing.Slices: invalid return values: %v", retVals)) - } - - // o0 []int - if retVals[0] != nil { - o0 = retVals[0].([]int) - } - - // o1 error - if retVals[1] != nil { - o1 = retVals[1].(error) - } - - return -} - -func (m *mockComplicatedThing) Variadic(p0 int, p1 ...net.Conn) (o0 int) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "Variadic", - file, - line, - []interface{}{p0, p1}) - - if len(retVals) != 1 { - panic(fmt.Sprintf("mockComplicatedThing.Variadic: invalid return values: %v", retVals)) - } - - // o0 int - if retVals[0] != nil { - o0 = retVals[0].(int) - } - - return -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/test_cases/golden.image.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/test_cases/golden.image.go deleted file mode 100644 index 360fbfa5b4a..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/test_cases/golden.image.go +++ /dev/null @@ -1,239 +0,0 @@ -// This file was auto-generated using createmock. See the following page for -// more information: -// -// https://github.com/smartystreets/goconvey/convey/assertions/oglemock -// - -package some_pkg - -import ( - fmt "fmt" - image "image" - color "image/color" - runtime "runtime" - unsafe "unsafe" - - oglemock "github.com/smartystreets/goconvey/convey/assertions/oglemock" -) - -type MockImage interface { - image.Image - oglemock.MockObject -} - -type mockImage struct { - controller oglemock.Controller - description string -} - -func NewMockImage( - c oglemock.Controller, - desc string) MockImage { - return &mockImage{ - controller: c, - description: desc, - } -} - -func (m *mockImage) Oglemock_Id() uintptr { - return uintptr(unsafe.Pointer(m)) -} - -func (m *mockImage) Oglemock_Description() string { - return m.description -} - -func (m *mockImage) At(p0 int, p1 int) (o0 color.Color) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "At", - file, - line, - []interface{}{p0, p1}) - - if len(retVals) != 1 { - panic(fmt.Sprintf("mockImage.At: invalid return values: %v", retVals)) - } - - // o0 color.Color - if retVals[0] != nil { - o0 = retVals[0].(color.Color) - } - - return -} - -func (m *mockImage) Bounds() (o0 image.Rectangle) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "Bounds", - file, - line, - []interface{}{}) - - if len(retVals) != 1 { - panic(fmt.Sprintf("mockImage.Bounds: invalid return values: %v", retVals)) - } - - // o0 image.Rectangle - if retVals[0] != nil { - o0 = retVals[0].(image.Rectangle) - } - - return -} - -func (m *mockImage) ColorModel() (o0 color.Model) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "ColorModel", - file, - line, - []interface{}{}) - - if len(retVals) != 1 { - panic(fmt.Sprintf("mockImage.ColorModel: invalid return values: %v", retVals)) - } - - // o0 color.Model - if retVals[0] != nil { - o0 = retVals[0].(color.Model) - } - - return -} - -type MockPalettedImage interface { - image.PalettedImage - oglemock.MockObject -} - -type mockPalettedImage struct { - controller oglemock.Controller - description string -} - -func NewMockPalettedImage( - c oglemock.Controller, - desc string) MockPalettedImage { - return &mockPalettedImage{ - controller: c, - description: desc, - } -} - -func (m *mockPalettedImage) Oglemock_Id() uintptr { - return uintptr(unsafe.Pointer(m)) -} - -func (m *mockPalettedImage) Oglemock_Description() string { - return m.description -} - -func (m *mockPalettedImage) At(p0 int, p1 int) (o0 color.Color) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "At", - file, - line, - []interface{}{p0, p1}) - - if len(retVals) != 1 { - panic(fmt.Sprintf("mockPalettedImage.At: invalid return values: %v", retVals)) - } - - // o0 color.Color - if retVals[0] != nil { - o0 = retVals[0].(color.Color) - } - - return -} - -func (m *mockPalettedImage) Bounds() (o0 image.Rectangle) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "Bounds", - file, - line, - []interface{}{}) - - if len(retVals) != 1 { - panic(fmt.Sprintf("mockPalettedImage.Bounds: invalid return values: %v", retVals)) - } - - // o0 image.Rectangle - if retVals[0] != nil { - o0 = retVals[0].(image.Rectangle) - } - - return -} - -func (m *mockPalettedImage) ColorIndexAt(p0 int, p1 int) (o0 uint8) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "ColorIndexAt", - file, - line, - []interface{}{p0, p1}) - - if len(retVals) != 1 { - panic(fmt.Sprintf("mockPalettedImage.ColorIndexAt: invalid return values: %v", retVals)) - } - - // o0 uint8 - if retVals[0] != nil { - o0 = retVals[0].(uint8) - } - - return -} - -func (m *mockPalettedImage) ColorModel() (o0 color.Model) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "ColorModel", - file, - line, - []interface{}{}) - - if len(retVals) != 1 { - panic(fmt.Sprintf("mockPalettedImage.ColorModel: invalid return values: %v", retVals)) - } - - // o0 color.Model - if retVals[0] != nil { - o0 = retVals[0].(color.Model) - } - - return -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/test_cases/golden.io_reader_writer.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/test_cases/golden.io_reader_writer.go deleted file mode 100644 index 304dcd48560..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/test_cases/golden.io_reader_writer.go +++ /dev/null @@ -1,128 +0,0 @@ -// This file was auto-generated using createmock. See the following page for -// more information: -// -// https://github.com/smartystreets/goconvey/convey/assertions/oglemock -// - -package some_pkg - -import ( - fmt "fmt" - io "io" - runtime "runtime" - unsafe "unsafe" - - oglemock "github.com/smartystreets/goconvey/convey/assertions/oglemock" -) - -type MockReader interface { - io.Reader - oglemock.MockObject -} - -type mockReader struct { - controller oglemock.Controller - description string -} - -func NewMockReader( - c oglemock.Controller, - desc string) MockReader { - return &mockReader{ - controller: c, - description: desc, - } -} - -func (m *mockReader) Oglemock_Id() uintptr { - return uintptr(unsafe.Pointer(m)) -} - -func (m *mockReader) Oglemock_Description() string { - return m.description -} - -func (m *mockReader) Read(p0 []uint8) (o0 int, o1 error) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "Read", - file, - line, - []interface{}{p0}) - - if len(retVals) != 2 { - panic(fmt.Sprintf("mockReader.Read: invalid return values: %v", retVals)) - } - - // o0 int - if retVals[0] != nil { - o0 = retVals[0].(int) - } - - // o1 error - if retVals[1] != nil { - o1 = retVals[1].(error) - } - - return -} - -type MockWriter interface { - io.Writer - oglemock.MockObject -} - -type mockWriter struct { - controller oglemock.Controller - description string -} - -func NewMockWriter( - c oglemock.Controller, - desc string) MockWriter { - return &mockWriter{ - controller: c, - description: desc, - } -} - -func (m *mockWriter) Oglemock_Id() uintptr { - return uintptr(unsafe.Pointer(m)) -} - -func (m *mockWriter) Oglemock_Description() string { - return m.description -} - -func (m *mockWriter) Write(p0 []uint8) (o0 int, o1 error) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "Write", - file, - line, - []interface{}{p0}) - - if len(retVals) != 2 { - panic(fmt.Sprintf("mockWriter.Write: invalid return values: %v", retVals)) - } - - // o0 int - if retVals[0] != nil { - o0 = retVals[0].(int) - } - - // o1 error - if retVals[1] != nil { - o1 = retVals[1].(error) - } - - return -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/test_cases/golden.renamed_pkg.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/test_cases/golden.renamed_pkg.go deleted file mode 100644 index 03a53da0ac6..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/test_cases/golden.renamed_pkg.go +++ /dev/null @@ -1,67 +0,0 @@ -// This file was auto-generated using createmock. See the following page for -// more information: -// -// https://github.com/smartystreets/goconvey/convey/assertions/oglemock -// - -package some_pkg - -import ( - fmt "fmt" - runtime "runtime" - unsafe "unsafe" - - oglemock "github.com/smartystreets/goconvey/convey/assertions/oglemock" - tony "github.com/smartystreets/goconvey/convey/assertions/oglemock/generate/test_cases/renamed_pkg" -) - -type MockSomeInterface interface { - tony.SomeInterface - oglemock.MockObject -} - -type mockSomeInterface struct { - controller oglemock.Controller - description string -} - -func NewMockSomeInterface( - c oglemock.Controller, - desc string) MockSomeInterface { - return &mockSomeInterface{ - controller: c, - description: desc, - } -} - -func (m *mockSomeInterface) Oglemock_Id() uintptr { - return uintptr(unsafe.Pointer(m)) -} - -func (m *mockSomeInterface) Oglemock_Description() string { - return m.description -} - -func (m *mockSomeInterface) DoFoo(p0 int) (o0 int) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "DoFoo", - file, - line, - []interface{}{p0}) - - if len(retVals) != 1 { - panic(fmt.Sprintf("mockSomeInterface.DoFoo: invalid return values: %v", retVals)) - } - - // o0 int - if retVals[0] != nil { - o0 = retVals[0].(int) - } - - return -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/internal_expectation.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/internal_expectation.go deleted file mode 100644 index 070ecb69b08..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/internal_expectation.go +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglemock - -import ( - "errors" - "fmt" - "reflect" - "sync" - - "github.com/smartystreets/goconvey/convey/assertions/oglematchers" -) - -// InternalExpectation is exported for purposes of testing only. You should not -// touch it. -// -// InternalExpectation represents an expectation for zero or more calls to a -// mock method, and a set of actions to be taken when those calls are received. -type InternalExpectation struct { - // The signature of the method to which this expectation is bound, for - // checking action types. - methodSignature reflect.Type - - // An error reporter to use for reporting errors in the way that expectations - // are set. - errorReporter ErrorReporter - - // A mutex protecting mutable fields of the struct. - mutex sync.Mutex - - // Matchers that the arguments to the mock method must satisfy in order to - // match this expectation. - ArgMatchers []oglematchers.Matcher - - // The name of the file in which this expectation was expressed. - FileName string - - // The line number at which this expectation was expressed. - LineNumber int - - // The number of times this expectation should be matched, as explicitly - // listed by the user. If there was no explicit number expressed, this is -1. - ExpectedNumMatches int - - // Actions to be taken for the first N calls, one per call in order, where N - // is the length of this slice. - OneTimeActions []Action - - // An action to be taken when the one-time actions have expired, or nil if - // there is no such action. - FallbackAction Action - - // The number of times this expectation has been matched so far. - NumMatches uint -} - -// InternalNewExpectation is exported for purposes of testing only. You should -// not touch it. -func InternalNewExpectation( - reporter ErrorReporter, - methodSignature reflect.Type, - args []interface{}, - fileName string, - lineNumber int) *InternalExpectation { - result := &InternalExpectation{} - - // Store fields that can be stored directly. - result.methodSignature = methodSignature - result.errorReporter = reporter - result.FileName = fileName - result.LineNumber = lineNumber - - // Set up defaults. - result.ExpectedNumMatches = -1 - result.OneTimeActions = make([]Action, 0) - - // Set up the ArgMatchers slice, using Equals(x) for each x that is not a - // matcher itself. - result.ArgMatchers = make([]oglematchers.Matcher, len(args)) - for i, x := range args { - if matcher, ok := x.(oglematchers.Matcher); ok { - result.ArgMatchers[i] = matcher - } else { - result.ArgMatchers[i] = oglematchers.Equals(x) - } - } - - return result -} - -func (e *InternalExpectation) Times(n uint) Expectation { - e.mutex.Lock() - defer e.mutex.Unlock() - - // It is illegal to call this more than once. - if e.ExpectedNumMatches != -1 { - e.reportFatalError("Times called more than once.") - return nil - } - - // It is illegal to call this after any actions are configured. - if len(e.OneTimeActions) != 0 { - e.reportFatalError("Times called after WillOnce.") - return nil - } - - if e.FallbackAction != nil { - e.reportFatalError("Times called after WillRepeatedly.") - return nil - } - - // Make sure the number is reasonable (and will fit in an int). - if n > 1000 { - e.reportFatalError("Expectation.Times: N must be at most 1000") - return nil - } - - e.ExpectedNumMatches = int(n) - return e -} - -func (e *InternalExpectation) WillOnce(a Action) Expectation { - e.mutex.Lock() - defer e.mutex.Unlock() - - // It is illegal to call this after WillRepeatedly. - if e.FallbackAction != nil { - e.reportFatalError("WillOnce called after WillRepeatedly.") - return nil - } - - // Tell the action about the method's signature. - if err := a.SetSignature(e.methodSignature); err != nil { - e.reportFatalError(fmt.Sprintf("WillOnce given invalid action: %v", err)) - return nil - } - - // Store the action. - e.OneTimeActions = append(e.OneTimeActions, a) - - return e -} - -func (e *InternalExpectation) WillRepeatedly(a Action) Expectation { - e.mutex.Lock() - defer e.mutex.Unlock() - - // It is illegal to call this twice. - if e.FallbackAction != nil { - e.reportFatalError("WillRepeatedly called more than once.") - return nil - } - - // Tell the action about the method's signature. - if err := a.SetSignature(e.methodSignature); err != nil { - e.reportFatalError(fmt.Sprintf("WillRepeatedly given invalid action: %v", err)) - return nil - } - - // Store the action. - e.FallbackAction = a - - return e -} - -func (e *InternalExpectation) reportFatalError(errorText string) { - e.errorReporter.ReportFatalError(e.FileName, e.LineNumber, errors.New(errorText)) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/invoke.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/invoke.go deleted file mode 100644 index 07630cbbb7e..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/invoke.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2012 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglemock - -import ( - "errors" - "fmt" - "reflect" -) - -// Create an Action that invokes the supplied function, returning whatever it -// returns. The signature of the function must match that of the mocked method -// exactly. -func Invoke(f interface{}) Action { - // Make sure f is a function. - fv := reflect.ValueOf(f) - fk := fv.Kind() - - if fk != reflect.Func { - desc := "" - if fk != reflect.Invalid { - desc = fv.Type().String() - } - - panic(fmt.Sprintf("Invoke: expected function, got %s", desc)) - } - - return &invokeAction{fv} -} - -type invokeAction struct { - f reflect.Value -} - -func (a *invokeAction) SetSignature(signature reflect.Type) error { - // The signature must match exactly. - ft := a.f.Type() - if ft != signature { - return errors.New(fmt.Sprintf("Invoke: expected %v, got %v", signature, ft)) - } - - return nil -} - -func (a *invokeAction) Invoke(vals []interface{}) []interface{} { - // Create a slice of args for the function. - in := make([]reflect.Value, len(vals)) - for i, x := range vals { - in[i] = reflect.ValueOf(x) - } - - // Call the function and return its return values. - out := a.f.Call(in) - result := make([]interface{}, len(out)) - for i, v := range out { - result[i] = v.Interface() - } - - return result -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/mock_object.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/mock_object.go deleted file mode 100644 index de995efc667..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/mock_object.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglemock - -// MockObject is an interface that mock object implementations must conform to -// in order to register expectations with and hand off calls to a -// MockController. Users should not interact with this interface directly. -type MockObject interface { - // Oglemock_Id returns an identifier for the mock object that is guaranteed - // to be unique within the process at least until the mock object is garbage - // collected. - Oglemock_Id() uintptr - - // Oglemock_Description returns a description of the mock object that may be - // helpful in test failure messages. - Oglemock_Description() string -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/oglemock.goconvey b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/oglemock.goconvey deleted file mode 100644 index 79982854b53..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/oglemock.goconvey +++ /dev/null @@ -1,2 +0,0 @@ -#ignore --timeout=1s diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/return.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/return.go deleted file mode 100644 index c66d248f44a..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/return.go +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglemock - -import ( - "errors" - "fmt" - "math" - "reflect" -) - -var intType = reflect.TypeOf(int(0)) -var float64Type = reflect.TypeOf(float64(0)) -var complex128Type = reflect.TypeOf(complex128(0)) - -// Return creates an Action that returns the values passed to Return as -// arguments, after suitable legal type conversions. The following rules apply. -// Given an argument x to Return and a corresponding type T in the method's -// signature, at least one of the following must hold: -// -// * x is assignable to T. (See "Assignability" in the language spec.) Note -// that this in particular applies that x may be a type that implements an -// interface T. It also implies that the nil literal can be used if T is a -// pointer, function, interface, slice, channel, or map type. -// -// * T is any numeric type, and x is an int that is in-range for that type. -// This facilities using raw integer constants: Return(17). -// -// * T is a floating-point or complex number type, and x is a float64. This -// facilities using raw floating-point constants: Return(17.5). -// -// * T is a complex number type, and x is a complex128. This facilities using -// raw complex constants: Return(17+2i). -// -func Return(vals ...interface{}) Action { - return &returnAction{vals, nil} -} - -type returnAction struct { - returnVals []interface{} - signature reflect.Type -} - -func (a *returnAction) Invoke(vals []interface{}) []interface{} { - if a.signature == nil { - panic("You must first call SetSignature with a valid signature.") - } - - res, err := a.buildInvokeResult(a.signature) - if err != nil { - panic(err) - } - - return res -} - -func (a *returnAction) SetSignature(signature reflect.Type) error { - if _, err := a.buildInvokeResult(signature); err != nil { - return err - } - - a.signature = signature - return nil -} - -// A version of Invoke that does error checking, used by both public methods. -func (a *returnAction) buildInvokeResult( - sig reflect.Type) (res []interface{}, err error) { - // Check the length of the return value. - numOut := sig.NumOut() - numVals := len(a.returnVals) - - if numOut != numVals { - err = errors.New( - fmt.Sprintf("Return given %d vals; expected %d.", numVals, numOut)) - return - } - - // Attempt to coerce each return value. - res = make([]interface{}, numOut) - - for i, val := range a.returnVals { - resType := sig.Out(i) - res[i], err = a.coerce(val, resType) - - if err != nil { - res = nil - err = errors.New(fmt.Sprintf("Return: arg %d: %v", i, err)) - return - } - } - - return -} - -func (a *returnAction) coerce(x interface{}, t reflect.Type) (interface{}, error) { - xv := reflect.ValueOf(x) - rv := reflect.New(t).Elem() - - // Special case: the language spec says that the predeclared identifier nil - // is assignable to pointers, functions, interface, slices, channels, and map - // types. However, reflect.ValueOf(nil) returns an invalid value that will - // not cooperate below. So handle invalid values here, assuming that they - // resulted from Return(nil). - if !xv.IsValid() { - switch t.Kind() { - case reflect.Ptr, reflect.Func, reflect.Interface, reflect.Chan, reflect.Slice, reflect.Map, reflect.UnsafePointer: - return rv.Interface(), nil - } - - return nil, errors.New(fmt.Sprintf("expected %v, given ", t)) - } - - // If x is assignable to type t, let the reflect package do the heavy - // lifting. - if reflect.TypeOf(x).AssignableTo(t) { - rv.Set(xv) - return rv.Interface(), nil - } - - // Handle numeric types as described in the documentation on Return. - switch { - case xv.Type() == intType && a.isNumeric(t): - return a.coerceInt(xv.Int(), t) - - case xv.Type() == float64Type && (a.isFloatingPoint(t) || a.isComplex(t)): - return a.coerceFloat(xv.Float(), t) - - case xv.Type() == complex128Type && a.isComplex(t): - return a.coerceComplex(xv.Complex(), t) - } - - // The value wasn't of a legal type. - return nil, errors.New(fmt.Sprintf("expected %v, given %v", t, xv.Type())) -} - -func (a *returnAction) isNumeric(t reflect.Type) bool { - return (t.Kind() >= reflect.Int && t.Kind() <= reflect.Uint64) || - a.isFloatingPoint(t) || - a.isComplex(t) -} - -func (a *returnAction) isFloatingPoint(t reflect.Type) bool { - return t.Kind() == reflect.Float32 || t.Kind() == reflect.Float64 -} - -func (a *returnAction) isComplex(t reflect.Type) bool { - return t.Kind() == reflect.Complex64 || t.Kind() == reflect.Complex128 -} - -func (a *returnAction) coerceInt(x int64, t reflect.Type) (interface{}, error) { - k := t.Kind() - - // Floating point and complex numbers: promote appropriately. - if a.isFloatingPoint(t) || a.isComplex(t) { - return a.coerceFloat(float64(x), t) - } - - // Integers: range check. - var min, max int64 - unsigned := false - - switch k { - case reflect.Int8: - min = math.MinInt8 - max = math.MaxInt8 - - case reflect.Int16: - min = math.MinInt16 - max = math.MaxInt16 - - case reflect.Int32: - min = math.MinInt32 - max = math.MaxInt32 - - case reflect.Int64: - min = math.MinInt64 - max = math.MaxInt64 - - case reflect.Uint: - unsigned = true - min = 0 - max = math.MaxUint32 - - case reflect.Uint8: - unsigned = true - min = 0 - max = math.MaxUint8 - - case reflect.Uint16: - unsigned = true - min = 0 - max = math.MaxUint16 - - case reflect.Uint32: - unsigned = true - min = 0 - max = math.MaxUint32 - - case reflect.Uint64: - unsigned = true - min = 0 - max = math.MaxInt64 - - default: - panic(fmt.Sprintf("Unexpected type: %v", t)) - } - - if x < min || x > max { - return nil, errors.New("int value out of range") - } - - rv := reflect.New(t).Elem() - if unsigned { - rv.SetUint(uint64(x)) - } else { - rv.SetInt(x) - } - - return rv.Interface(), nil -} - -func (a *returnAction) coerceFloat(x float64, t reflect.Type) (interface{}, error) { - // Promote complex numbers. - if a.isComplex(t) { - return a.coerceComplex(complex(x, 0), t) - } - - rv := reflect.New(t).Elem() - rv.SetFloat(x) - return rv.Interface(), nil -} - -func (a *returnAction) coerceComplex(x complex128, t reflect.Type) (interface{}, error) { - rv := reflect.New(t).Elem() - rv.SetComplex(x) - return rv.Interface(), nil -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/sample/README.markdown b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/sample/README.markdown deleted file mode 100644 index 60d5d2cb1ab..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/sample/README.markdown +++ /dev/null @@ -1,6 +0,0 @@ -This directory contains sample code generated with the `createmock` command. For -example, the file `mock_io.go` can be regenerated with: - - createmock io Reader > sample/mock_io/mock_io.go - -The files are also used by `integration_test.go`. diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/sample/mock_io/mock_io.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/sample/mock_io/mock_io.go deleted file mode 100644 index c6d5ca78d67..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/oglemock/sample/mock_io/mock_io.go +++ /dev/null @@ -1,72 +0,0 @@ -// This file was auto-generated using createmock. See the following page for -// more information: -// -// https://github.com/smartystreets/goconvey/convey/assertions/oglemock -// - -package mock_io - -import ( - fmt "fmt" - io "io" - runtime "runtime" - unsafe "unsafe" - - oglemock "github.com/smartystreets/goconvey/convey/assertions/oglemock" -) - -type MockReader interface { - io.Reader - oglemock.MockObject -} - -type mockReader struct { - controller oglemock.Controller - description string -} - -func NewMockReader( - c oglemock.Controller, - desc string) MockReader { - return &mockReader{ - controller: c, - description: desc, - } -} - -func (m *mockReader) Oglemock_Id() uintptr { - return uintptr(unsafe.Pointer(m)) -} - -func (m *mockReader) Oglemock_Description() string { - return m.description -} - -func (m *mockReader) Read(p0 []uint8) (o0 int, o1 error) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "Read", - file, - line, - []interface{}{p0}) - - if len(retVals) != 2 { - panic(fmt.Sprintf("mockReader.Read: invalid return values: %v", retVals)) - } - - // o0 int - if retVals[0] != nil { - o0 = retVals[0].(int) - } - - // o1 error - if retVals[1] != nil { - o1 = retVals[1].(error) - } - - return -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/.gitignore b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/.gitignore deleted file mode 100644 index dd8fc7468f4..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -*.6 -6.out -_obj/ -_test/ -_testmain.go diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/README.markdown b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/README.markdown deleted file mode 100644 index 56f12d62462..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/README.markdown +++ /dev/null @@ -1,149 +0,0 @@ -`ogletest` is a unit testing framework for Go with the following features: - - * An extensive and extensible set of matchers for expressing expectations. - * Automatic failure messages; no need to say `t.Errorf("Expected %v, got - %v"...)`. - * Clean, readable output that tells you exactly what you need to know. - * Built-in support for mocking through the [oglemock][] package. - * Style and semantics similar to [Google Test][googletest] and - [Google JS Test][google-js-test]. - -It integrates with Go's built-in `testing` package, so it works with the -`go test` command, and even with other types of test within your package. Unlike -the `testing` package which offers only basic capabilities for signalling -failures, it offers ways to express expectations and get nice failure messages -automatically. - - -Installation ------------- - -First, make sure you have installed Go 1.0.2 or newer. See -[here][golang-install] for instructions. - -Use the following command to install `ogletest` and its dependencies, and to -keep them up to date: - - go get -u github.com/smartystreets/goconvey/convey/assertions/ogletest - - -Documentation -------------- - -See [here][reference] for package documentation hosted on GoPkgDoc containing an -exhaustive list of exported symbols. Alternatively, you can install the package -and then use `go doc`: - - go doc github.com/smartystreets/goconvey/convey/assertions/ogletest - -An important part of `ogletest` is its use of matchers provided by the -[oglematchers][matcher-reference] package. See that package's documentation -for information on the built-in matchers available, and check out the -`oglematchers.Matcher` interface if you want to define your own. - - -Example -------- - -Let's say you have a function in your package `people` with the following -signature: - -```go -// GetRandomPerson returns the name and phone number of Tony, Dennis, or Scott. -func GetRandomPerson() (name, phone string) { - [...] -} -``` - -A silly function, but it will do for an example. You can write a couple of tests -for it as follows: - -```go -package people - -import ( - "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - "github.com/smartystreets/goconvey/convey/assertions/ogletest" - "testing" -) - -// Give ogletest a chance to run your tests when invoked by 'go test'. -func TestOgletest(t *testing.T) { ogletest.RunTests(t) } - -// Create a test suite, which groups together logically related test methods -// (defined below). You can share common setup and teardown code here; see the -// package docs for more info. -type PeopleTest struct {} -func init() { ogletest.RegisterTestSuite(&PeopleTest{}) } - -func (t *PeopleTest) ReturnsCorrectNames() { - // Call the function a few times, and make sure it never strays from the set - // of expected names. - for i := 0; i < 25; i++ { - name, _ := GetRandomPerson() - ogletest.ExpectThat(name, oglematchers.AnyOf("Tony", "Dennis", "Scott")) - } -} - -func (t *PeopleTest) FormatsPhoneNumbersCorrectly() { - // Call the function a few times, and make sure it returns phone numbers in a - // standard US format. - for i := 0; i < 25; i++ { - _, phone := GetRandomPerson() - ogletest.ExpectThat(phone, oglematchers.MatchesRegexp(`^\(\d{3}\) \d{3}-\d{4}$`)) -} -``` - -Note that test control functions (`RunTests`, `ExpectThat`, and so on) are part -of the `ogletest` package, whereas built-in matchers (`AnyOf`, `MatchesRegexp`, -and more) are part of the [oglematchers][matcher-reference] library. You can of -course use dot imports so that you don't need to prefix each function with its -package name: - -```go -import ( - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) -``` - -If you save the test in a file whose name ends in `_test.go`, you can run your -tests by simply invoking the following in your package directory: - - go test - -Here's what the failure output of ogletest looks like, if your function's -implementation is bad. - - [----------] Running tests from PeopleTest - [ RUN ] PeopleTest.FormatsPhoneNumbersCorrectly - people_test.go:32: - Expected: matches regexp "^\(\d{3}\) \d{3}-\d{4}$" - Actual: +1 800 555 5555 - - [ FAILED ] PeopleTest.FormatsPhoneNumbersCorrectly - [ RUN ] PeopleTest.ReturnsCorrectNames - people_test.go:23: - Expected: or(Tony, Dennis, Scott) - Actual: Bart - - [ FAILED ] PeopleTest.ReturnsCorrectNames - [----------] Finished with tests from PeopleTest - -And if the test passes: - - [----------] Running tests from PeopleTest - [ RUN ] PeopleTest.FormatsPhoneNumbersCorrectly - [ OK ] PeopleTest.FormatsPhoneNumbersCorrectly - [ RUN ] PeopleTest.ReturnsCorrectNames - [ OK ] PeopleTest.ReturnsCorrectNames - [----------] Finished with tests from PeopleTest - - -[reference]: http://gopkgdoc.appspot.com/pkg/github.com/smartystreets/goconvey/convey/assertions/ogletest -[matcher-reference]: http://gopkgdoc.appspot.com/pkg/github.com/smartystreets/goconvey/convey/assertions/oglematchers -[golang-install]: http://golang.org/doc/install.html -[googletest]: http://code.google.com/p/googletest/ -[google-js-test]: http://code.google.com/p/google-js-test/ -[howtowrite]: http://golang.org/doc/code.html -[oglemock]: https://github.com/smartystreets/goconvey/convey/assertions/oglemock diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/assert_aliases.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/assert_aliases.go deleted file mode 100644 index a014d544de8..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/assert_aliases.go +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ogletest - -import ( - "github.com/smartystreets/goconvey/convey/assertions/oglematchers" -) - -// AssertEq(e, a) is equivalent to AssertThat(a, oglematchers.Equals(e)). -func AssertEq(expected, actual interface{}, errorParts ...interface{}) ExpectationResult { - res := ExpectThat(actual, oglematchers.Equals(expected), errorParts...) - res.SetCaller(getCallerForAlias()) - - matcherErr := res.MatchResult() - if matcherErr != nil { - panic(&assertThatError{}) - } - - return res -} - -// AssertNe(e, a) is equivalent to AssertThat(a, oglematchers.Not(oglematchers.Equals(e))). -func AssertNe(expected, actual interface{}, errorParts ...interface{}) ExpectationResult { - res := ExpectThat(actual, oglematchers.Not(oglematchers.Equals(expected)), errorParts...) - res.SetCaller(getCallerForAlias()) - - matcherErr := res.MatchResult() - if matcherErr != nil { - panic(&assertThatError{}) - } - - return res -} - -// AssertLt(x, y) is equivalent to AssertThat(x, oglematchers.LessThan(y)). -func AssertLt(x, y interface{}, errorParts ...interface{}) ExpectationResult { - res := ExpectThat(x, oglematchers.LessThan(y), errorParts...) - res.SetCaller(getCallerForAlias()) - - matcherErr := res.MatchResult() - if matcherErr != nil { - panic(&assertThatError{}) - } - - return res -} - -// AssertLe(x, y) is equivalent to AssertThat(x, oglematchers.LessOrEqual(y)). -func AssertLe(x, y interface{}, errorParts ...interface{}) ExpectationResult { - res := ExpectThat(x, oglematchers.LessOrEqual(y), errorParts...) - res.SetCaller(getCallerForAlias()) - - matcherErr := res.MatchResult() - if matcherErr != nil { - panic(&assertThatError{}) - } - - return res -} - -// AssertGt(x, y) is equivalent to AssertThat(x, oglematchers.GreaterThan(y)). -func AssertGt(x, y interface{}, errorParts ...interface{}) ExpectationResult { - res := ExpectThat(x, oglematchers.GreaterThan(y), errorParts...) - res.SetCaller(getCallerForAlias()) - - matcherErr := res.MatchResult() - if matcherErr != nil { - panic(&assertThatError{}) - } - - return res -} - -// AssertGe(x, y) is equivalent to AssertThat(x, oglematchers.GreaterOrEqual(y)). -func AssertGe(x, y interface{}, errorParts ...interface{}) ExpectationResult { - res := ExpectThat(x, oglematchers.GreaterOrEqual(y), errorParts...) - res.SetCaller(getCallerForAlias()) - - matcherErr := res.MatchResult() - if matcherErr != nil { - panic(&assertThatError{}) - } - - return res -} - -// AssertTrue(b) is equivalent to AssertThat(b, oglematchers.Equals(true)). -func AssertTrue(b interface{}, errorParts ...interface{}) ExpectationResult { - res := ExpectThat(b, oglematchers.Equals(true), errorParts...) - res.SetCaller(getCallerForAlias()) - - matcherErr := res.MatchResult() - if matcherErr != nil { - panic(&assertThatError{}) - } - - return res -} - -// AssertFalse(b) is equivalent to AssertThat(b, oglematchers.Equals(false)). -func AssertFalse(b interface{}, errorParts ...interface{}) ExpectationResult { - res := ExpectThat(b, oglematchers.Equals(false), errorParts...) - res.SetCaller(getCallerForAlias()) - - matcherErr := res.MatchResult() - if matcherErr != nil { - panic(&assertThatError{}) - } - - return res -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/assert_that.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/assert_that.go deleted file mode 100644 index 319abfc7479..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/assert_that.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ogletest - -import ( - "github.com/smartystreets/goconvey/convey/assertions/oglematchers" -) - -// AssertThat is identical to ExpectThat, except that in the event of failure -// it halts the currently running test immediately. It is thus useful for -// things like bounds checking: -// -// someSlice := [...] -// AssertEq(1, len(someSlice)) // Protects next line from panicking. -// ExpectEq("taco", someSlice[0]) -// -func AssertThat( - x interface{}, - m oglematchers.Matcher, - errorParts ...interface{}) ExpectationResult { - res := ExpectThat(x, m, errorParts...) - res.SetCaller(getCallerForAlias()) - - matcherErr := res.MatchResult() - if matcherErr != nil { - panic(&assertThatError{}) - } - - return res -} - -// assertThatError is a sentinel type that is used in a conspiracy between -// AssertThat and runTests. If runTests sees a *assertThatError as the value -// given to a panic() call, it will avoid printing the panic error. -type assertThatError struct { -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/doc.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/doc.go deleted file mode 100644 index bf6507fae4d..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/doc.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package ogletest provides a framework for writing expressive unit tests. It -// integrates with the builtin testing package, so it works with the gotest -// command. Unlike the testing package which offers only basic capabilities for -// signalling failures, it offers ways to express expectations and get nice -// failure messages automatically. -// -// For example: -// -// //////////////////////////////////////////////////////////////////////// -// // testing package test -// //////////////////////////////////////////////////////////////////////// -// -// someStr, err := ComputeSomeString() -// if err != nil { -// t.Errorf("ComputeSomeString: expected nil error, got %v", err) -// } -// -// !strings.Contains(someStr, "foo") { -// t.Errorf("ComputeSomeString: expected substring foo, got %v", someStr) -// } -// -// //////////////////////////////////////////////////////////////////////// -// // ogletest test -// //////////////////////////////////////////////////////////////////////// -// -// someStr, err := ComputeSomeString() -// ExpectEq(nil, err) -// ExpectThat(someStr, HasSubstr("foo") -// -// Failure messages require no work from the user, and look like the following: -// -// foo_test.go:103: -// Expected: has substring "foo" -// Actual: "bar baz" -// -package ogletest diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/expect_aliases.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/expect_aliases.go deleted file mode 100644 index 050ae10466b..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/expect_aliases.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ogletest - -import ( - "path" - "runtime" - - "github.com/smartystreets/goconvey/convey/assertions/oglematchers" -) - -func getCallerForAlias() (fileName string, lineNumber int) { - _, fileName, lineNumber, _ = runtime.Caller(2) - fileName = path.Base(fileName) - return -} - -// ExpectEq(e, a) is equivalent to ExpectThat(a, oglematchers.Equals(e)). -func ExpectEq(expected, actual interface{}, errorParts ...interface{}) ExpectationResult { - res := ExpectThat(actual, oglematchers.Equals(expected), errorParts...) - res.SetCaller(getCallerForAlias()) - return res -} - -// ExpectNe(e, a) is equivalent to ExpectThat(a, oglematchers.Not(oglematchers.Equals(e))). -func ExpectNe(expected, actual interface{}, errorParts ...interface{}) ExpectationResult { - res := ExpectThat(actual, oglematchers.Not(oglematchers.Equals(expected)), errorParts...) - res.SetCaller(getCallerForAlias()) - return res -} - -// ExpectLt(x, y) is equivalent to ExpectThat(x, oglematchers.LessThan(y)). -func ExpectLt(x, y interface{}, errorParts ...interface{}) ExpectationResult { - res := ExpectThat(x, oglematchers.LessThan(y), errorParts...) - res.SetCaller(getCallerForAlias()) - return res -} - -// ExpectLe(x, y) is equivalent to ExpectThat(x, oglematchers.LessOrEqual(y)). -func ExpectLe(x, y interface{}, errorParts ...interface{}) ExpectationResult { - res := ExpectThat(x, oglematchers.LessOrEqual(y), errorParts...) - res.SetCaller(getCallerForAlias()) - return res -} - -// ExpectGt(x, y) is equivalent to ExpectThat(x, oglematchers.GreaterThan(y)). -func ExpectGt(x, y interface{}, errorParts ...interface{}) ExpectationResult { - res := ExpectThat(x, oglematchers.GreaterThan(y), errorParts...) - res.SetCaller(getCallerForAlias()) - return res -} - -// ExpectGe(x, y) is equivalent to ExpectThat(x, oglematchers.GreaterOrEqual(y)). -func ExpectGe(x, y interface{}, errorParts ...interface{}) ExpectationResult { - res := ExpectThat(x, oglematchers.GreaterOrEqual(y), errorParts...) - res.SetCaller(getCallerForAlias()) - return res -} - -// ExpectTrue(b) is equivalent to ExpectThat(b, oglematchers.Equals(true)). -func ExpectTrue(b interface{}, errorParts ...interface{}) ExpectationResult { - res := ExpectThat(b, oglematchers.Equals(true), errorParts...) - res.SetCaller(getCallerForAlias()) - return res -} - -// ExpectFalse(b) is equivalent to ExpectThat(b, oglematchers.Equals(false)). -func ExpectFalse(b interface{}, errorParts ...interface{}) ExpectationResult { - res := ExpectThat(b, oglematchers.Equals(false), errorParts...) - res.SetCaller(getCallerForAlias()) - return res -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/expect_call.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/expect_call.go deleted file mode 100644 index 8bb8101d569..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/expect_call.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2012 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ogletest - -import ( - "runtime" - - "github.com/smartystreets/goconvey/convey/assertions/oglemock" -) - -// ExpectCall expresses an expectation that the method of the given name -// should be called on the supplied mock object. It returns a function that -// should be called with the expected arguments, matchers for the arguments, -// or a mix of both. -// -// For example: -// -// mockWriter := [...] -// ogletest.ExpectCall(mockWriter, "Write")(oglematchers.ElementsAre(0x1)) -// .WillOnce(oglemock.Return(1, nil)) -// -// This is a shortcut for calling i.MockController.ExpectCall, where i is the -// TestInfo struct for the currently-running test. Unlike that direct approach, -// this function automatically sets the correct file name and line number for -// the expectation. -func ExpectCall(o oglemock.MockObject, method string) oglemock.PartialExpecation { - // Get information about the call site. - _, file, lineNumber, ok := runtime.Caller(1) - if !ok { - panic("ExpectCall: runtime.Caller") - } - - // Grab the current test info. - info := currentlyRunningTest - if info == nil { - panic("ExpectCall: no test info.") - } - - // Grab the mock controller. - controller := currentlyRunningTest.MockController - if controller == nil { - panic("ExpectCall: no mock controller.") - } - - // Report the expectation. - return controller.ExpectCall(o, method, file, lineNumber) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/expect_that.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/expect_that.go deleted file mode 100644 index c0adc5aa6cf..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/expect_that.go +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ogletest - -import ( - "fmt" - "path" - "reflect" - "runtime" - - "github.com/smartystreets/goconvey/convey/assertions/oglematchers" -) - -// ExpectationResult is an interface returned by ExpectThat that allows callers -// to get information about the result of the expectation and set their own -// custom information. This is not useful to the average consumer, but may be -// helpful if you're writing widely used test utility functions. -type ExpectationResult interface { - // SetCaller updates the file name and line number associated with the - // expectation. This allows, for example, a utility function to express that - // *its* caller should have its line number printed if the expectation fails, - // instead of the line number of the ExpectThat call within the utility - // function. - SetCaller(fileName string, lineNumber int) - - // MatchResult returns the result returned by the expectation's matcher for - // the supplied candidate. - MatchResult() error -} - -// ExpectThat confirms that the supplied matcher matches the value x, adding a -// failure record to the currently running test if it does not. If additional -// parameters are supplied, the first will be used as a format string for the -// later ones, and the user-supplied error message will be added to the test -// output in the event of a failure. -// -// For example: -// -// ExpectThat(userName, Equals("jacobsa")) -// ExpectThat(users[i], Equals("jacobsa"), "while processing user %d", i) -// -func ExpectThat( - x interface{}, - m oglematchers.Matcher, - errorParts ...interface{}) ExpectationResult { - res := &expectationResultImpl{} - - // Get information about the call site. - _, file, lineNumber, ok := runtime.Caller(1) - if !ok { - panic("ExpectThat: runtime.Caller") - } - - // Assemble the user error, if any. - userError := "" - if len(errorParts) != 0 { - v := reflect.ValueOf(errorParts[0]) - if v.Kind() != reflect.String { - panic(fmt.Sprintf("ExpectThat: invalid format string type %v", v.Kind())) - } - - userError = fmt.Sprintf(v.String(), errorParts[1:]...) - } - - // Grab the current test info. - info := currentlyRunningTest - if info == nil { - panic("ExpectThat: no test info.") - } - - // Check whether the value matches. - matcherErr := m.Matches(x) - res.matchError = matcherErr - - // Return immediately on success. - if matcherErr == nil { - return res - } - - // Form an appropriate failure message. Make sure that the expected and - // actual values align properly. - var record failureRecord - relativeClause := "" - if matcherErr.Error() != "" { - relativeClause = fmt.Sprintf(", %s", matcherErr.Error()) - } - - record.GeneratedError = fmt.Sprintf( - "Expected: %s\nActual: %v%s", - m.Description(), - x, - relativeClause) - - // Record additional failure info. - record.FileName = path.Base(file) - record.LineNumber = lineNumber - record.UserError = userError - - // Store the failure. - info.mutex.Lock() - defer info.mutex.Unlock() - - info.failureRecords = append(info.failureRecords, &record) - res.failureRecord = &record - - return res -} - -type expectationResultImpl struct { - // The failure record created by the expectation, or nil if none. - failureRecord *failureRecord - - // The result of the matcher. - matchError error -} - -func (r *expectationResultImpl) SetCaller(fileName string, lineNumber int) { - if r.failureRecord == nil { - return - } - - r.failureRecord.FileName = fileName - r.failureRecord.LineNumber = lineNumber -} - -func (r *expectationResultImpl) MatchResult() error { - return r.matchError -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/methods.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/methods.go deleted file mode 100644 index ad58dd840d4..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/methods.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2012 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ogletest - -import ( - "fmt" - "reflect" - "runtime" - "sort" -) - -func getLine(m reflect.Method) int { - pc := m.Func.Pointer() - - f := runtime.FuncForPC(pc) - if f == nil { - panic(fmt.Sprintf("Couldn't get runtime func for method (pc=%d): %v", pc, m)) - } - - _, line := f.FileLine(pc) - return line -} - -type sortableMethodSet []reflect.Method - -func (s sortableMethodSet) Len() int { - return len(s) -} - -func (s sortableMethodSet) Less(i, j int) bool { - return getLine(s[i]) < getLine(s[j]) -} - -func (s sortableMethodSet) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -// Given a type t, return all of the methods of t sorted such that source file -// order is preserved. Order across files is undefined. Order within lines is -// undefined. -func getMethodsInSourceOrder(t reflect.Type) []reflect.Method { - // Build the list of methods. - methods := sortableMethodSet{} - for i := 0; i < t.NumMethod(); i++ { - methods = append(methods, t.Method(i)) - } - - // Sort it. - sort.Sort(methods) - - return methods -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/ogletest.goconvey b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/ogletest.goconvey deleted file mode 100644 index 79982854b53..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/ogletest.goconvey +++ /dev/null @@ -1,2 +0,0 @@ -#ignore --timeout=1s diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/register_test_suite.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/register_test_suite.go deleted file mode 100644 index 0e253a2c162..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/register_test_suite.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ogletest - -// RegisterTestSuite tells ogletest about a test suite containing tests that it -// should run. Any exported method on the type pointed to by the supplied -// prototype value will be treated as test methods, with the exception of the -// following methods (which need not be present): -// -// * SetUpTestSuite() -- called exactly once, before the first test method is -// run. The receiver of this method will be a zero value of the test suite -// type, and is not shared with any other methods. Use this method to set -// up any necessary global state shared by all of the test methods. -// -// * TearDownTestSuite() -- called exactly once, after the last test method -// is run. The receiver of this method will be a zero value of the test -// suite type, and is not shared with any other methods. Use this method to -// clean up after any necessary global state shared by all of the test -// methods. -// -// * SetUp(testInfo) -- called before each test method is invoked, with the -// same receiver as that test method, and with a TestInfo arg. At the time -// this method is invoked, the receiver is a zero value for the test suite -// type. Use this method for common setup code that works on data not -// shared across tests. -// -// * TearDown() -- called after each test method is invoked, with the same -// receiver as that test method. Use this method for common cleanup code -// that works on data not shared across tests. -// -// Each test method is invoked on a different receiver, which is initially a -// zero value of the test suite type. -// -// Example: -// -// // Some value that is needed by the tests but is expensive to compute. -// var someExpensiveThing uint -// -// type FooTest struct { -// // Path to a temporary file used by the tests. Each test gets a -// // different temporary file. -// tempFile string -// } -// func init() { ogletest.RegisterTestSuite(&FooTest{}) } -// -// func (t *FooTest) SetUpTestSuite() { -// someExpensiveThing = ComputeSomeExpensiveThing() -// } -// -// func (t *FooTest) SetUp() { -// t.tempFile = CreateTempFile() -// } -// -// func (t *FooTest) TearDown() { -// DeleteTempFile(t.tempFile) -// } -// -// func (t *FooTest) FrobinicatorIsSuccessfullyTweaked() { -// res := DoSomethingWithExpensiveThing(someExpensiveThing, t.tempFile) -// ExpectThat(res, Equals(true)) -// } -// -func RegisterTestSuite(p interface{}) { - if p == nil { - panic("RegisterTestSuite called with nil suite.") - } - - testSuites = append(testSuites, p) -} - -// The set of test suites previously registered. -var testSuites = make([]interface{}, 0) diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/run_tests.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/run_tests.go deleted file mode 100644 index 75e0f0a262b..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/run_tests.go +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ogletest - -import ( - "bytes" - "flag" - "fmt" - "path" - "reflect" - "regexp" - "runtime" - "sync" - "testing" - "time" -) - -var testFilter = flag.String("ogletest.run", "", "Regexp for matching tests to run.") - -// runTestsOnce protects RunTests from executing multiple times. -var runTestsOnce sync.Once - -func isAssertThatError(x interface{}) bool { - _, ok := x.(*assertThatError) - return ok -} - -// runTest runs a single test, returning a slice of failure records for that test. -func runTest(suite interface{}, method reflect.Method) (failures []*failureRecord) { - suiteValue := reflect.ValueOf(suite) - suiteType := suiteValue.Type() - - // Set up a clean slate for this test. Make sure to reset it after everything - // below is finished, so we don't accidentally use it elsewhere. - currentlyRunningTest = newTestInfo() - defer func() { - currentlyRunningTest = nil - }() - - // Create a receiver. - suiteInstance := reflect.New(suiteType.Elem()) - - // Run the SetUp method, paying attention to whether it panics. - setUpPanicked := runWithProtection( - func() { - runMethodIfExists(suiteInstance, "SetUp", currentlyRunningTest) - }, - ) - - // Run the test method itself, but only if the SetUp method didn't panic. - // (This includes AssertThat errors.) - if !setUpPanicked { - runWithProtection( - func() { - runMethodIfExists(suiteInstance, method.Name) - }, - ) - } - - // Run the TearDown method unconditionally. - runWithProtection( - func() { - runMethodIfExists(suiteInstance, "TearDown") - }, - ) - - // Tell the mock controller for the tests to report any errors it's sitting - // on. - currentlyRunningTest.MockController.Finish() - - return currentlyRunningTest.failureRecords -} - -// RunTests runs the test suites registered with ogletest, communicating -// failures to the supplied testing.T object. This is the bridge between -// ogletest and the testing package (and gotest); you should ensure that it's -// called at least once by creating a gotest-compatible test function and -// calling it there. -// -// For example: -// -// import ( -// "github.com/smartystreets/goconvey/convey/assertions/ogletest" -// "testing" -// ) -// -// func TestOgletest(t *testing.T) { -// ogletest.RunTests(t) -// } -// -func RunTests(t *testing.T) { - runTestsOnce.Do(func() { runTestsInternal(t) }) -} - -// runTestsInternal does the real work of RunTests, which simply wraps it in a -// sync.Once. -func runTestsInternal(t *testing.T) { - // Process each registered suite. - for _, suite := range testSuites { - val := reflect.ValueOf(suite) - typ := val.Type() - suiteName := typ.Elem().Name() - - // Grab methods for the suite, filtering them to just the ones that we - // don't need to skip. - testMethods := filterMethods(suiteName, getMethodsInSourceOrder(typ)) - - // Is there anything left to do? - if len(testMethods) == 0 { - continue - } - - fmt.Printf("[----------] Running tests from %s\n", suiteName) - - // Run the SetUpTestSuite method, if any. - runMethodIfExists(val, "SetUpTestSuite") - - // Run each method. - for _, method := range testMethods { - // Print a banner for the start of this test. - fmt.Printf("[ RUN ] %s.%s\n", suiteName, method.Name) - - // Run the test. - startTime := time.Now() - failures := runTest(suite, method) - runDuration := time.Since(startTime) - - // Print any failures, and mark the test as having failed if there are any. - for _, record := range failures { - t.Fail() - userErrorSection := "" - if record.UserError != "" { - userErrorSection = record.UserError + "\n" - } - - fmt.Printf( - "%s:%d:\n%s\n%s\n", - record.FileName, - record.LineNumber, - record.GeneratedError, - userErrorSection) - } - - // Print a banner for the end of the test. - bannerMessage := "[ OK ]" - if len(failures) != 0 { - bannerMessage = "[ FAILED ]" - } - - // Print a summary of the time taken, if long enough. - var timeMessage string - if runDuration >= 25*time.Millisecond { - timeMessage = fmt.Sprintf(" (%s)", runDuration.String()) - } - - fmt.Printf( - "%s %s.%s%s\n", - bannerMessage, - suiteName, - method.Name, - timeMessage) - } - - // Run the TearDownTestSuite method, if any. - runMethodIfExists(val, "TearDownTestSuite") - - fmt.Printf("[----------] Finished with tests from %s\n", suiteName) - } -} - -// Run the supplied function, catching panics (including AssertThat errors) and -// reporting them to the currently-running test as appropriate. Return true iff -// the function panicked. -func runWithProtection(f func()) (panicked bool) { - defer func() { - // If the test didn't panic, we're done. - r := recover() - if r == nil { - return - } - - panicked = true - - // We modify the currently running test below. - currentlyRunningTest.mutex.Lock() - defer currentlyRunningTest.mutex.Unlock() - - // If the function panicked (and the panic was not due to an AssertThat - // failure), add a failure for the panic. - if !isAssertThatError(r) { - // The stack looks like this: - // - // - // panic(r) - // - // - _, fileName, lineNumber, ok := runtime.Caller(2) - var panicRecord failureRecord - if ok { - panicRecord.FileName = path.Base(fileName) - panicRecord.LineNumber = lineNumber - } - - panicRecord.GeneratedError = fmt.Sprintf( - "panic: %v\n\n%s", r, formatPanicStack()) - - currentlyRunningTest.failureRecords = append( - currentlyRunningTest.failureRecords, - &panicRecord) - } - }() - - f() - return -} - -func runMethodIfExists(v reflect.Value, name string, args ...interface{}) { - method := v.MethodByName(name) - if method.Kind() == reflect.Invalid { - return - } - - if method.Type().NumIn() != len(args) { - panic(fmt.Sprintf( - "%s: expected %d args, actually %d.", - name, - len(args), - method.Type().NumIn())) - } - - // Create a slice of reflect.Values to pass to the method. Simultaneously - // check types. - argVals := make([]reflect.Value, len(args)) - for i, arg := range args { - argVal := reflect.ValueOf(arg) - - if argVal.Type() != method.Type().In(i) { - panic(fmt.Sprintf( - "%s: expected arg %d to have type %v.", - name, - i, - argVal.Type())) - } - - argVals[i] = argVal - } - - method.Call(argVals) -} - -func formatPanicStack() string { - buf := new(bytes.Buffer) - - // Walk the stack from top to bottom. - panicPassed := false - for i := 0; ; i++ { - pc, file, line, ok := runtime.Caller(i) - if !ok { - break - } - - // Choose a function name to display. - funcName := "(unknown)" - if f := runtime.FuncForPC(pc); f != nil { - funcName = f.Name() - } - - // Avoid stack frames at panic and above. - if funcName == "runtime.panic" { - panicPassed = true - continue - } - - if !panicPassed { - continue - } - - // Stop if we've gotten as far as the test runner code. - if funcName == "github.com/smartystreets/goconvey/convey/assertions/ogletest.runMethodIfExists" { - break - } - - // Add an entry for this frame. - fmt.Fprintf(buf, "%s\n\t%s:%d\n", funcName, file, line) - } - - return buf.String() -} - -func filterMethods(suiteName string, in []reflect.Method) (out []reflect.Method) { - for _, m := range in { - // Skip set up, tear down, and unexported methods. - if isSpecialMethod(m.Name) || !isExportedMethod(m.Name) { - continue - } - - // Has the user told us to skip this method? - fullName := fmt.Sprintf("%s.%s", suiteName, m.Name) - matched, err := regexp.MatchString(*testFilter, fullName) - if err != nil { - panic("Invalid value for --ogletest.run: " + err.Error()) - } - - if !matched { - continue - } - - out = append(out, m) - } - - return -} - -func isSpecialMethod(name string) bool { - return (name == "SetUpTestSuite") || - (name == "TearDownTestSuite") || - (name == "SetUp") || - (name == "TearDown") -} - -func isExportedMethod(name string) bool { - return len(name) > 0 && name[0] >= 'A' && name[0] <= 'Z' -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/failing.test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/failing.test.go deleted file mode 100644 index 6cfa4d81cc8..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/failing.test.go +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - "fmt" - "testing" - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -func TestFailingTest(t *testing.T) { RunTests(t) } - -//////////////////////////////////////////////////////////////////////// -// Usual failures -//////////////////////////////////////////////////////////////////////// - -type FailingTest struct { -} - -func init() { RegisterTestSuite(&FailingTest{}) } - -func (t *FailingTest) TearDown() { - fmt.Println("TearDown running.") -} - -func (t *FailingTest) PassingMethod() { -} - -func (t *FailingTest) Equals() { - ExpectThat(17, Equals(17.5)) - ExpectThat(17, Equals("taco")) -} - -func (t *FailingTest) LessThan() { - ExpectThat(18, LessThan(17)) - ExpectThat(18, LessThan("taco")) -} - -func (t *FailingTest) HasSubstr() { - ExpectThat("taco", HasSubstr("ac")) - ExpectThat(17, HasSubstr("ac")) -} - -func (t *FailingTest) ExpectWithUserErrorMessages() { - ExpectThat(17, Equals(19), "foo bar: %d", 112) - ExpectEq(17, 17.5, "foo bar: %d", 112) - ExpectLe(17, 16.9, "foo bar: %d", 112) - ExpectLt(17, 16.9, "foo bar: %d", 112) - ExpectGe(17, 17.1, "foo bar: %d", 112) - ExpectGt(17, "taco", "foo bar: %d", 112) - ExpectNe(17, 17.0, "foo bar: %d", 112) - ExpectFalse(true, "foo bar: %d", 112) - ExpectTrue(false, "foo bar: %d", 112) -} - -func (t *FailingTest) AssertWithUserErrorMessages() { - AssertThat(17, Equals(19), "foo bar: %d", 112) -} - -func (t *FailingTest) ModifiedExpectation() { - ExpectThat(17, HasSubstr("ac")).SetCaller("foo.go", 112) - ExpectEq(17, 19).SetCaller("bar.go", 117) -} - -func (t *FailingTest) ExpectationAliases() { - ExpectEq(17, 17.5) - ExpectEq("taco", 17.5) - - ExpectLe(17, 16.9) - ExpectLt(17, 16.9) - ExpectLt(17, "taco") - - ExpectGe(17, 17.1) - ExpectGt(17, 17.1) - ExpectGt(17, "taco") - - ExpectNe(17, 17.0) - ExpectNe(17, "taco") - - ExpectFalse(true) - ExpectFalse("taco") - - ExpectTrue(false) - ExpectTrue("taco") -} - -func (t *FailingTest) AssertThatFailure() { - AssertThat(17, Equals(19)) - panic("Shouldn't get here.") -} - -func (t *FailingTest) AssertEqFailure() { - AssertEq(19, 17) - panic("Shouldn't get here.") -} - -func (t *FailingTest) AssertNeFailure() { - AssertNe(19, 19) - panic("Shouldn't get here.") -} - -func (t *FailingTest) AssertLeFailure() { - AssertLe(19, 17) - panic("Shouldn't get here.") -} - -func (t *FailingTest) AssertLtFailure() { - AssertLt(19, 17) - panic("Shouldn't get here.") -} - -func (t *FailingTest) AssertGeFailure() { - AssertGe(17, 19) - panic("Shouldn't get here.") -} - -func (t *FailingTest) AssertGtFailure() { - AssertGt(17, 19) - panic("Shouldn't get here.") -} - -func (t *FailingTest) AssertTrueFailure() { - AssertTrue("taco") - panic("Shouldn't get here.") -} - -func (t *FailingTest) AssertFalseFailure() { - AssertFalse("taco") - panic("Shouldn't get here.") -} - -//////////////////////////////////////////////////////////////////////// -// Expectation failure during SetUp -//////////////////////////////////////////////////////////////////////// - -type ExpectFailDuringSetUpTest struct { -} - -func init() { RegisterTestSuite(&ExpectFailDuringSetUpTest{}) } - -func (t *ExpectFailDuringSetUpTest) SetUp(i *TestInfo) { - ExpectFalse(true) -} - -func (t *ExpectFailDuringSetUpTest) TearDown() { - fmt.Println("TearDown running.") -} - -func (t *ExpectFailDuringSetUpTest) PassingMethod() { - fmt.Println("Method running.") -} - -//////////////////////////////////////////////////////////////////////// -// Assertion failure during SetUp -//////////////////////////////////////////////////////////////////////// - -type AssertFailDuringSetUpTest struct { -} - -func init() { RegisterTestSuite(&AssertFailDuringSetUpTest{}) } - -func (t *AssertFailDuringSetUpTest) SetUp(i *TestInfo) { - AssertFalse(true) -} - -func (t *AssertFailDuringSetUpTest) TearDown() { - fmt.Println("TearDown running.") -} - -func (t *AssertFailDuringSetUpTest) PassingMethod() { - fmt.Println("Method running.") -} - -//////////////////////////////////////////////////////////////////////// -// Expectation failure during TearDown -//////////////////////////////////////////////////////////////////////// - -type ExpectFailDuringTearDownTest struct { -} - -func init() { RegisterTestSuite(&ExpectFailDuringTearDownTest{}) } - -func (t *ExpectFailDuringTearDownTest) SetUp(i *TestInfo) { - fmt.Println("SetUp running.") -} - -func (t *ExpectFailDuringTearDownTest) TearDown() { - ExpectFalse(true) -} - -func (t *ExpectFailDuringTearDownTest) PassingMethod() { - fmt.Println("Method running.") -} - -//////////////////////////////////////////////////////////////////////// -// Assertion failure during TearDown -//////////////////////////////////////////////////////////////////////// - -type AssertFailDuringTearDownTest struct { -} - -func init() { RegisterTestSuite(&AssertFailDuringTearDownTest{}) } - -func (t *AssertFailDuringTearDownTest) SetUp(i *TestInfo) { - fmt.Println("SetUp running.") -} - -func (t *AssertFailDuringTearDownTest) TearDown() { - AssertFalse(true) -} - -func (t *AssertFailDuringTearDownTest) PassingMethod() { - fmt.Println("Method running.") -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/filtered.test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/filtered.test.go deleted file mode 100644 index 64e97a5bb8f..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/filtered.test.go +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - "fmt" - "testing" - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -func TestFiltered(t *testing.T) { RunTests(t) } - -//////////////////////////////////////////////////////////////////////// -// Partially filtered out -//////////////////////////////////////////////////////////////////////// - -type PartiallyFilteredTest struct { -} - -func init() { RegisterTestSuite(&PartiallyFilteredTest{}) } - -func (t *PartiallyFilteredTest) PassingTestFoo() { - ExpectThat(19, Equals(19)) -} - -func (t *PartiallyFilteredTest) PassingTestBar() { - ExpectThat(17, Equals(17)) -} - -func (t *PartiallyFilteredTest) PartiallyFilteredTestFoo() { - ExpectThat(18, LessThan(17)) -} - -func (t *PartiallyFilteredTest) PartiallyFilteredTestBar() { - ExpectThat("taco", HasSubstr("blah")) -} - -func (t *PartiallyFilteredTest) PartiallyFilteredTestBaz() { - ExpectThat(18, LessThan(17)) -} - -//////////////////////////////////////////////////////////////////////// -// Completely filtered out -//////////////////////////////////////////////////////////////////////// - -type CompletelyFilteredTest struct { -} - -func init() { RegisterTestSuite(&CompletelyFilteredTest{}) } - -func (t *CompletelyFilteredTest) SetUpTestSuite() { - fmt.Println("SetUpTestSuite run!") -} - -func (t *CompletelyFilteredTest) TearDownTestSuite() { - fmt.Println("TearDownTestSuite run!") -} - -func (t *PartiallyFilteredTest) SomePassingTest() { - ExpectThat(19, Equals(19)) -} - -func (t *PartiallyFilteredTest) SomeFailingTest() { - ExpectThat(19, Equals(17)) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.failing_test b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.failing_test deleted file mode 100644 index de89466fb7d..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.failing_test +++ /dev/null @@ -1,266 +0,0 @@ -[----------] Running tests from FailingTest -[ RUN ] FailingTest.PassingMethod -TearDown running. -[ OK ] FailingTest.PassingMethod -[ RUN ] FailingTest.Equals -TearDown running. -failing_test.go:44: -Expected: 17.5 -Actual: 17 - -failing_test.go:45: -Expected: taco -Actual: 17, which is not a string - -[ FAILED ] FailingTest.Equals -[ RUN ] FailingTest.LessThan -TearDown running. -failing_test.go:49: -Expected: less than 17 -Actual: 18 - -failing_test.go:50: -Expected: less than "taco" -Actual: 18, which is not comparable - -[ FAILED ] FailingTest.LessThan -[ RUN ] FailingTest.HasSubstr -TearDown running. -failing_test.go:55: -Expected: has substring "ac" -Actual: 17, which is not a string - -[ FAILED ] FailingTest.HasSubstr -[ RUN ] FailingTest.ExpectWithUserErrorMessages -TearDown running. -failing_test.go:59: -Expected: 19 -Actual: 17 -foo bar: 112 - -failing_test.go:60: -Expected: 17 -Actual: 17.5 -foo bar: 112 - -failing_test.go:61: -Expected: less than or equal to 16.9 -Actual: 17 -foo bar: 112 - -failing_test.go:62: -Expected: less than 16.9 -Actual: 17 -foo bar: 112 - -failing_test.go:63: -Expected: greater than or equal to 17.1 -Actual: 17 -foo bar: 112 - -failing_test.go:64: -Expected: greater than "taco" -Actual: 17, which is not comparable -foo bar: 112 - -failing_test.go:65: -Expected: not(17) -Actual: 17 -foo bar: 112 - -failing_test.go:66: -Expected: false -Actual: true -foo bar: 112 - -failing_test.go:67: -Expected: true -Actual: false -foo bar: 112 - -[ FAILED ] FailingTest.ExpectWithUserErrorMessages -[ RUN ] FailingTest.AssertWithUserErrorMessages -TearDown running. -failing_test.go:71: -Expected: 19 -Actual: 17 -foo bar: 112 - -[ FAILED ] FailingTest.AssertWithUserErrorMessages -[ RUN ] FailingTest.ModifiedExpectation -TearDown running. -foo.go:112: -Expected: has substring "ac" -Actual: 17, which is not a string - -bar.go:117: -Expected: 17 -Actual: 19 - -[ FAILED ] FailingTest.ModifiedExpectation -[ RUN ] FailingTest.ExpectationAliases -TearDown running. -failing_test.go:80: -Expected: 17 -Actual: 17.5 - -failing_test.go:81: -Expected: taco -Actual: 17.5, which is not a string - -failing_test.go:83: -Expected: less than or equal to 16.9 -Actual: 17 - -failing_test.go:84: -Expected: less than 16.9 -Actual: 17 - -failing_test.go:85: -Expected: less than "taco" -Actual: 17, which is not comparable - -failing_test.go:87: -Expected: greater than or equal to 17.1 -Actual: 17 - -failing_test.go:88: -Expected: greater than 17.1 -Actual: 17 - -failing_test.go:89: -Expected: greater than "taco" -Actual: 17, which is not comparable - -failing_test.go:91: -Expected: not(17) -Actual: 17 - -failing_test.go:92: -Expected: not(17) -Actual: taco, which is not numeric - -failing_test.go:94: -Expected: false -Actual: true - -failing_test.go:95: -Expected: false -Actual: taco, which is not a bool - -failing_test.go:97: -Expected: true -Actual: false - -failing_test.go:98: -Expected: true -Actual: taco, which is not a bool - -[ FAILED ] FailingTest.ExpectationAliases -[ RUN ] FailingTest.AssertThatFailure -TearDown running. -failing_test.go:102: -Expected: 19 -Actual: 17 - -[ FAILED ] FailingTest.AssertThatFailure -[ RUN ] FailingTest.AssertEqFailure -TearDown running. -failing_test.go:107: -Expected: 19 -Actual: 17 - -[ FAILED ] FailingTest.AssertEqFailure -[ RUN ] FailingTest.AssertNeFailure -TearDown running. -failing_test.go:112: -Expected: not(19) -Actual: 19 - -[ FAILED ] FailingTest.AssertNeFailure -[ RUN ] FailingTest.AssertLeFailure -TearDown running. -failing_test.go:117: -Expected: less than or equal to 17 -Actual: 19 - -[ FAILED ] FailingTest.AssertLeFailure -[ RUN ] FailingTest.AssertLtFailure -TearDown running. -failing_test.go:122: -Expected: less than 17 -Actual: 19 - -[ FAILED ] FailingTest.AssertLtFailure -[ RUN ] FailingTest.AssertGeFailure -TearDown running. -failing_test.go:127: -Expected: greater than or equal to 19 -Actual: 17 - -[ FAILED ] FailingTest.AssertGeFailure -[ RUN ] FailingTest.AssertGtFailure -TearDown running. -failing_test.go:132: -Expected: greater than 19 -Actual: 17 - -[ FAILED ] FailingTest.AssertGtFailure -[ RUN ] FailingTest.AssertTrueFailure -TearDown running. -failing_test.go:137: -Expected: true -Actual: taco, which is not a bool - -[ FAILED ] FailingTest.AssertTrueFailure -[ RUN ] FailingTest.AssertFalseFailure -TearDown running. -failing_test.go:142: -Expected: false -Actual: taco, which is not a bool - -[ FAILED ] FailingTest.AssertFalseFailure -[----------] Finished with tests from FailingTest -[----------] Running tests from ExpectFailDuringSetUpTest -[ RUN ] ExpectFailDuringSetUpTest.PassingMethod -Method running. -TearDown running. -failing_test.go:156: -Expected: false -Actual: true - -[ FAILED ] ExpectFailDuringSetUpTest.PassingMethod -[----------] Finished with tests from ExpectFailDuringSetUpTest -[----------] Running tests from AssertFailDuringSetUpTest -[ RUN ] AssertFailDuringSetUpTest.PassingMethod -TearDown running. -failing_test.go:177: -Expected: false -Actual: true - -[ FAILED ] AssertFailDuringSetUpTest.PassingMethod -[----------] Finished with tests from AssertFailDuringSetUpTest -[----------] Running tests from ExpectFailDuringTearDownTest -[ RUN ] ExpectFailDuringTearDownTest.PassingMethod -SetUp running. -Method running. -failing_test.go:202: -Expected: false -Actual: true - -[ FAILED ] ExpectFailDuringTearDownTest.PassingMethod -[----------] Finished with tests from ExpectFailDuringTearDownTest -[----------] Running tests from AssertFailDuringTearDownTest -[ RUN ] AssertFailDuringTearDownTest.PassingMethod -SetUp running. -Method running. -failing_test.go:223: -Expected: false -Actual: true - -[ FAILED ] AssertFailDuringTearDownTest.PassingMethod -[----------] Finished with tests from AssertFailDuringTearDownTest ---- FAIL: somepkg (1.23 seconds) -FAIL -exit status 1 -FAIL somepkg 1.234s diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.filtered_test b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.filtered_test deleted file mode 100644 index 9e99dc38d49..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.filtered_test +++ /dev/null @@ -1,20 +0,0 @@ -[----------] Running tests from PartiallyFilteredTest -[ RUN ] PartiallyFilteredTest.PassingTestBar -[ OK ] PartiallyFilteredTest.PassingTestBar -[ RUN ] PartiallyFilteredTest.PartiallyFilteredTestBar -filtered_test.go:49: -Expected: has substring "blah" -Actual: taco - -[ FAILED ] PartiallyFilteredTest.PartiallyFilteredTestBar -[ RUN ] PartiallyFilteredTest.PartiallyFilteredTestBaz -filtered_test.go:53: -Expected: less than 17 -Actual: 18 - -[ FAILED ] PartiallyFilteredTest.PartiallyFilteredTestBaz -[----------] Finished with tests from PartiallyFilteredTest ---- FAIL: somepkg (1.23 seconds) -FAIL -exit status 1 -FAIL somepkg 1.234s diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.mock_test b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.mock_test deleted file mode 100644 index e9f3b11bc13..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.mock_test +++ /dev/null @@ -1,25 +0,0 @@ -[----------] Running tests from MockTest -[ RUN ] MockTest.ExpectationSatisfied -[ OK ] MockTest.ExpectationSatisfied -[ RUN ] MockTest.MockExpectationNotSatisfied -/some/path/mock_test.go:56: -Unsatisfied expectation; expected At to be called at least 1 times; called 0 times. - -[ FAILED ] MockTest.MockExpectationNotSatisfied -[ RUN ] MockTest.ExpectCallForUnknownMethod -/some/path/mock_test.go:61: -Unknown method: FooBar - -[ FAILED ] MockTest.ExpectCallForUnknownMethod -[ RUN ] MockTest.UnexpectedCall -/some/path/mock_test.go:65: -Unexpected call to At with args: [11 23] - -[ FAILED ] MockTest.UnexpectedCall -[ RUN ] MockTest.InvokeFunction -[ OK ] MockTest.InvokeFunction -[----------] Finished with tests from MockTest ---- FAIL: somepkg (1.23 seconds) -FAIL -exit status 1 -FAIL somepkg 1.234s diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.no_cases_test b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.no_cases_test deleted file mode 100644 index f8161adb19a..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.no_cases_test +++ /dev/null @@ -1,2 +0,0 @@ -PASS -ok somepkg 1.234s diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.panicking_test b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.panicking_test deleted file mode 100644 index 7d3ca2f56f5..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.panicking_test +++ /dev/null @@ -1,23 +0,0 @@ -[----------] Running tests from PanickingTest -[ RUN ] PanickingTest.PanickingTest -TearDown running. -panicking_test.go:44: -panic: foobar - -github.com/smartystreets/goconvey/convey/assertions/ogletest/somepkg_test.(*PanickingTest).PanickingTest - some_file.txt:0 -reflect.Value.call - some_file.txt:0 -reflect.Value.Call - some_file.txt:0 - - -[ FAILED ] PanickingTest.PanickingTest -[ RUN ] PanickingTest.ZzzSomeOtherTest -TearDown running. -[ OK ] PanickingTest.ZzzSomeOtherTest -[----------] Finished with tests from PanickingTest ---- FAIL: somepkg (1.23 seconds) -FAIL -exit status 1 -FAIL somepkg 1.234s diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.passing_test b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.passing_test deleted file mode 100644 index 5204c2f07a2..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.passing_test +++ /dev/null @@ -1,14 +0,0 @@ -[----------] Running tests from PassingTest -[ RUN ] PassingTest.EmptyTestMethod -[ OK ] PassingTest.EmptyTestMethod -[ RUN ] PassingTest.SuccessfullMatches -[ OK ] PassingTest.SuccessfullMatches -[ RUN ] PassingTest.ExpectAliases -[ OK ] PassingTest.ExpectAliases -[ RUN ] PassingTest.AssertAliases -[ OK ] PassingTest.AssertAliases -[ RUN ] PassingTest.SlowTest -[ OK ] PassingTest.SlowTest (1234ms) -[----------] Finished with tests from PassingTest -PASS -ok somepkg 1.234s diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.run_twice_test b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.run_twice_test deleted file mode 100644 index db3a1980b46..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.run_twice_test +++ /dev/null @@ -1,14 +0,0 @@ -[----------] Running tests from RunTwiceTest -[ RUN ] RunTwiceTest.PassingMethod -[ OK ] RunTwiceTest.PassingMethod -[ RUN ] RunTwiceTest.FailingMethod -run_twice_test.go:46: -Expected: 17.5 -Actual: 17 - -[ FAILED ] RunTwiceTest.FailingMethod -[----------] Finished with tests from RunTwiceTest ---- FAIL: somepkg (1.23 seconds) -FAIL -exit status 1 -FAIL somepkg 1.234s diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.unexported_test b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.unexported_test deleted file mode 100644 index 765e4377cfc..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/golden.unexported_test +++ /dev/null @@ -1,12 +0,0 @@ -[----------] Running tests from UnexportedTest -[ RUN ] UnexportedTest.SomeTest -unexported_test.go:42: -Expected: 4 -Actual: 3 - -[ FAILED ] UnexportedTest.SomeTest -[----------] Finished with tests from UnexportedTest ---- FAIL: somepkg (1.23 seconds) -FAIL -exit status 1 -FAIL somepkg 1.234s diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/mock.test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/mock.test.go deleted file mode 100644 index 295c37c3762..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/mock.test.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - "image/color" - "testing" - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - "github.com/smartystreets/goconvey/convey/assertions/oglemock" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" - "github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/mock_image" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type MockTest struct { - controller oglemock.Controller - image mock_image.MockImage -} - -func init() { RegisterTestSuite(&MockTest{}) } -func TestMockTest(t *testing.T) { RunTests(t) } - -func (t *MockTest) SetUp(i *TestInfo) { - t.controller = i.MockController - t.image = mock_image.NewMockImage(t.controller, "some mock image") -} - -//////////////////////////////////////////////////////////////////////// -// Tests -//////////////////////////////////////////////////////////////////////// - -func (t *MockTest) ExpectationSatisfied() { - ExpectCall(t.image, "At")(11, GreaterThan(19)). - WillOnce(oglemock.Return(color.Gray{0})) - - ExpectThat(t.image.At(11, 23), IdenticalTo(color.Gray{0})) -} - -func (t *MockTest) MockExpectationNotSatisfied() { - ExpectCall(t.image, "At")(11, GreaterThan(19)). - WillOnce(oglemock.Return(color.Gray{0})) -} - -func (t *MockTest) ExpectCallForUnknownMethod() { - ExpectCall(t.image, "FooBar")(11) -} - -func (t *MockTest) UnexpectedCall() { - t.image.At(11, 23) -} - -func (t *MockTest) InvokeFunction() { - var suppliedX, suppliedY int - f := func(x, y int) color.Color { - suppliedX = x - suppliedY = y - return color.Gray{17} - } - - ExpectCall(t.image, "At")(Any(), Any()). - WillOnce(oglemock.Invoke(f)) - - ExpectThat(t.image.At(-1, 12), IdenticalTo(color.Gray{17})) - ExpectEq(-1, suppliedX) - ExpectEq(12, suppliedY) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/mock_image/mock_image.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/mock_image/mock_image.go deleted file mode 100644 index dabcba35e1f..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/mock_image/mock_image.go +++ /dev/null @@ -1,116 +0,0 @@ -// This file was auto-generated using createmock. See the following page for -// more information: -// -// https://github.com/smartystreets/goconvey/convey/assertions/oglemock -// - -package mock_image - -import ( - fmt "fmt" - image "image" - color "image/color" - runtime "runtime" - unsafe "unsafe" - - oglemock "github.com/smartystreets/goconvey/convey/assertions/oglemock" -) - -type MockImage interface { - image.Image - oglemock.MockObject -} - -type mockImage struct { - controller oglemock.Controller - description string -} - -func NewMockImage( - c oglemock.Controller, - desc string) MockImage { - return &mockImage{ - controller: c, - description: desc, - } -} - -func (m *mockImage) Oglemock_Id() uintptr { - return uintptr(unsafe.Pointer(m)) -} - -func (m *mockImage) Oglemock_Description() string { - return m.description -} - -func (m *mockImage) At(p0 int, p1 int) (o0 color.Color) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "At", - file, - line, - []interface{}{p0, p1}) - - if len(retVals) != 1 { - panic(fmt.Sprintf("mockImage.At: invalid return values: %v", retVals)) - } - - // o0 color.Color - if retVals[0] != nil { - o0 = retVals[0].(color.Color) - } - - return -} - -func (m *mockImage) Bounds() (o0 image.Rectangle) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "Bounds", - file, - line, - []interface{}{}) - - if len(retVals) != 1 { - panic(fmt.Sprintf("mockImage.Bounds: invalid return values: %v", retVals)) - } - - // o0 image.Rectangle - if retVals[0] != nil { - o0 = retVals[0].(image.Rectangle) - } - - return -} - -func (m *mockImage) ColorModel() (o0 color.Model) { - // Get a file name and line number for the caller. - _, file, line, _ := runtime.Caller(1) - - // Hand the call off to the controller, which does most of the work. - retVals := m.controller.HandleMethodCall( - m, - "ColorModel", - file, - line, - []interface{}{}) - - if len(retVals) != 1 { - panic(fmt.Sprintf("mockImage.ColorModel: invalid return values: %v", retVals)) - } - - // o0 color.Model - if retVals[0] != nil { - o0 = retVals[0].(color.Model) - } - - return -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/panicking.test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/panicking.test.go deleted file mode 100644 index 8a32aadec11..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/panicking.test.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - "fmt" - "testing" - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type PanickingTest struct { -} - -func init() { RegisterTestSuite(&PanickingTest{}) } -func TestPanickingTest(t *testing.T) { RunTests(t) } - -func (t *PanickingTest) TearDown() { - fmt.Println("TearDown running.") -} - -//////////////////////////////////////////////////////////////////////// -// Tests -//////////////////////////////////////////////////////////////////////// - -func (t *PanickingTest) PanickingTest() { - panic("foobar") -} - -func (t *PanickingTest) ZzzSomeOtherTest() { - ExpectThat(17, Equals(17.0)) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/passing.test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/passing.test.go deleted file mode 100644 index 0615e5e1e30..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/passing.test.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - "testing" - "time" - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type PassingTest struct { -} - -func init() { RegisterTestSuite(&PassingTest{}) } -func TestPassingTest(t *testing.T) { RunTests(t) } - -//////////////////////////////////////////////////////////////////////// -// Tests -//////////////////////////////////////////////////////////////////////// - -func (t *PassingTest) EmptyTestMethod() { -} - -func (t *PassingTest) SuccessfullMatches() { - ExpectThat(17, Equals(17.0)) - ExpectThat(16.9, LessThan(17)) - ExpectThat("taco", HasSubstr("ac")) - - AssertThat(17, Equals(17.0)) - AssertThat(16.9, LessThan(17)) - AssertThat("taco", HasSubstr("ac")) -} - -func (t *PassingTest) ExpectAliases() { - ExpectEq(17, 17.0) - - ExpectLe(17, 17.0) - ExpectLe(17, 18.0) - ExpectLt(17, 18.0) - - ExpectGe(17, 17.0) - ExpectGe(17, 16.0) - ExpectGt(17, 16.0) - - ExpectNe(17, 18.0) - - ExpectTrue(true) - ExpectFalse(false) -} - -func (t *PassingTest) AssertAliases() { - AssertEq(17, 17.0) - - AssertLe(17, 17.0) - AssertLe(17, 18.0) - AssertLt(17, 18.0) - - AssertGe(17, 17.0) - AssertGe(17, 16.0) - AssertGt(17, 16.0) - - AssertNe(17, 18.0) - - AssertTrue(true) - AssertFalse(false) -} - -func (t *PassingTest) SlowTest() { - time.Sleep(37 * time.Millisecond) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/run_twice.test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/run_twice.test.go deleted file mode 100644 index cfa7c80fb3b..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/run_twice.test.go +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - "testing" - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type RunTwiceTest struct { -} - -func init() { RegisterTestSuite(&RunTwiceTest{}) } - -// Set up two helpers that call RunTests. The test should still only be run -// once. -func TestOgletest(t *testing.T) { RunTests(t) } -func TestOgletest2(t *testing.T) { RunTests(t) } - -//////////////////////////////////////////////////////////////////////// -// Tests -//////////////////////////////////////////////////////////////////////// - -func (t *RunTwiceTest) PassingMethod() { -} - -func (t *RunTwiceTest) FailingMethod() { - ExpectThat(17, Equals(17.5)) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/unexported.test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/unexported.test.go deleted file mode 100644 index 7fbbd4e8709..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_cases/unexported.test.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oglematchers_test - -import ( - "testing" - . "github.com/smartystreets/goconvey/convey/assertions/oglematchers" - . "github.com/smartystreets/goconvey/convey/assertions/ogletest" -) - -//////////////////////////////////////////////////////////////////////// -// Helpers -//////////////////////////////////////////////////////////////////////// - -type UnexportedTest struct { -} - -func init() { RegisterTestSuite(&UnexportedTest{}) } -func TestUnexportedTest(t *testing.T) { RunTests(t) } - -func (t *UnexportedTest) someUnexportedMethod() { -} - -//////////////////////////////////////////////////////////////////////// -// Tests -//////////////////////////////////////////////////////////////////////// - -func (t *UnexportedTest) SomeTest() { - ExpectThat(3, Equals(4)) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_info.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_info.go deleted file mode 100644 index c7473103e49..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/ogletest/test_info.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2011 Aaron Jacobs. All Rights Reserved. -// Author: aaronjjacobs@gmail.com (Aaron Jacobs) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ogletest - -import ( - "sync" - - "github.com/smartystreets/goconvey/convey/assertions/oglemock" -) - -// TestInfo represents information about a currently running or previously-run -// test. -type TestInfo struct { - // A mock controller that is set up to report errors to the ogletest test - // runner. This can be used for setting up mock expectations and handling - // mock calls. The Finish method should not be run by the user; ogletest will - // do that automatically after the test's TearDown method is run. - // - // Note that this feature is still experimental, and is subject to change. - MockController oglemock.Controller - - // A mutex protecting shared state. - mutex sync.RWMutex - - // A set of failure records that the test has produced. - failureRecords []*failureRecord // Protected by mutex -} - -// currentlyRunningTest is the state for the currently running test, if any. -var currentlyRunningTest *TestInfo - -// newTestInfo creates a valid but empty TestInfo struct. -func newTestInfo() *TestInfo { - info := &TestInfo{} - info.failureRecords = make([]*failureRecord, 0) - info.MockController = oglemock.NewController(&testInfoErrorReporter{info}) - return info -} - -// failureRecord represents a single failed expectation for a test. -type failureRecord struct { - // The file name within which the expectation failed, e.g. "foo_test.go". - FileName string - - // The line number at which the expectation failed. - LineNumber int - - // The error generated by the testing framework. For example: - // - // Expected: 17 - // Actual: "taco", which is not numeric - // - GeneratedError string - - // A user-specified string to print out with the error, if any. - UserError string -} - -// testInfoErrorReporter is an oglemock.ErrorReporter that writes failure -// records into a test info struct. -type testInfoErrorReporter struct { - testInfo *TestInfo -} - -func (r *testInfoErrorReporter) ReportError( - fileName string, - lineNumber int, - err error) { - r.testInfo.mutex.Lock() - defer r.testInfo.mutex.Unlock() - - record := &failureRecord{ - FileName: fileName, - LineNumber: lineNumber, - GeneratedError: err.Error(), - } - - r.testInfo.failureRecords = append(r.testInfo.failureRecords, record) -} - -func (r *testInfoErrorReporter) ReportFatalError( - fileName string, - lineNumber int, - err error) { - r.ReportError(fileName, lineNumber, err) - panic(&assertThatError{}) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/panic_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/panic_test.go deleted file mode 100644 index 15eafac4fbb..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/panic_test.go +++ /dev/null @@ -1,53 +0,0 @@ -package assertions - -import ( - "fmt" - "testing" -) - -func TestShouldPanic(t *testing.T) { - fail(t, so(func() {}, ShouldPanic, 1), "This assertion requires exactly 0 comparison values (you provided 1).") - fail(t, so(func() {}, ShouldPanic, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).") - - fail(t, so(1, ShouldPanic), shouldUseVoidNiladicFunction) - fail(t, so(func(i int) {}, ShouldPanic), shouldUseVoidNiladicFunction) - fail(t, so(func() int { panic("hi") }, ShouldPanic), shouldUseVoidNiladicFunction) - - fail(t, so(func() {}, ShouldPanic), shouldHavePanicked) - pass(t, so(func() { panic("hi") }, ShouldPanic)) -} - -func TestShouldNotPanic(t *testing.T) { - fail(t, so(func() {}, ShouldNotPanic, 1), "This assertion requires exactly 0 comparison values (you provided 1).") - fail(t, so(func() {}, ShouldNotPanic, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).") - - fail(t, so(1, ShouldNotPanic), shouldUseVoidNiladicFunction) - fail(t, so(func(i int) {}, ShouldNotPanic), shouldUseVoidNiladicFunction) - - fail(t, so(func() { panic("hi") }, ShouldNotPanic), fmt.Sprintf(shouldNotHavePanicked, "hi")) - pass(t, so(func() {}, ShouldNotPanic)) -} - -func TestShouldPanicWith(t *testing.T) { - fail(t, so(func() {}, ShouldPanicWith), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so(func() {}, ShouldPanicWith, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") - - fail(t, so(1, ShouldPanicWith, 1), shouldUseVoidNiladicFunction) - fail(t, so(func(i int) {}, ShouldPanicWith, "hi"), shouldUseVoidNiladicFunction) - fail(t, so(func() {}, ShouldPanicWith, "bye"), shouldHavePanicked) - fail(t, so(func() { panic("hi") }, ShouldPanicWith, "bye"), "bye|hi|Expected func() to panic with 'bye' (but it panicked with 'hi')!") - - pass(t, so(func() { panic("hi") }, ShouldPanicWith, "hi")) -} - -func TestShouldNotPanicWith(t *testing.T) { - fail(t, so(func() {}, ShouldNotPanicWith), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so(func() {}, ShouldNotPanicWith, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") - - fail(t, so(1, ShouldNotPanicWith, 1), shouldUseVoidNiladicFunction) - fail(t, so(func(i int) {}, ShouldNotPanicWith, "hi"), shouldUseVoidNiladicFunction) - fail(t, so(func() { panic("hi") }, ShouldNotPanicWith, "hi"), "Expected func() NOT to panic with 'hi' (but it did)!") - - pass(t, so(func() {}, ShouldNotPanicWith, "bye")) - pass(t, so(func() { panic("hi") }, ShouldNotPanicWith, "bye")) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/quantity_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/quantity_test.go deleted file mode 100644 index 7546e7250a8..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/quantity_test.go +++ /dev/null @@ -1,145 +0,0 @@ -package assertions - -import "testing" - -func TestShouldBeGreaterThan(t *testing.T) { - fail(t, so(1, ShouldBeGreaterThan), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so(1, ShouldBeGreaterThan, 0, 0), "This assertion requires exactly 1 comparison values (you provided 2).") - - pass(t, so(1, ShouldBeGreaterThan, 0)) - pass(t, so(1.1, ShouldBeGreaterThan, 1)) - pass(t, so(1, ShouldBeGreaterThan, uint(0))) - pass(t, so("b", ShouldBeGreaterThan, "a")) - - fail(t, so(0, ShouldBeGreaterThan, 1), "Expected '0' to be greater than '1' (but it wasn't)!") - fail(t, so(1, ShouldBeGreaterThan, 1.1), "Expected '1' to be greater than '1.1' (but it wasn't)!") - fail(t, so(uint(0), ShouldBeGreaterThan, 1.1), "Expected '0' to be greater than '1.1' (but it wasn't)!") - fail(t, so("a", ShouldBeGreaterThan, "b"), "Expected 'a' to be greater than 'b' (but it wasn't)!") -} - -func TestShouldBeGreaterThanOrEqual(t *testing.T) { - fail(t, so(1, ShouldBeGreaterThanOrEqualTo), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so(1, ShouldBeGreaterThanOrEqualTo, 0, 0), "This assertion requires exactly 1 comparison values (you provided 2).") - - pass(t, so(1, ShouldBeGreaterThanOrEqualTo, 1)) - pass(t, so(1.1, ShouldBeGreaterThanOrEqualTo, 1.1)) - pass(t, so(1, ShouldBeGreaterThanOrEqualTo, uint(1))) - pass(t, so("b", ShouldBeGreaterThanOrEqualTo, "b")) - - pass(t, so(1, ShouldBeGreaterThanOrEqualTo, 0)) - pass(t, so(1.1, ShouldBeGreaterThanOrEqualTo, 1)) - pass(t, so(1, ShouldBeGreaterThanOrEqualTo, uint(0))) - pass(t, so("b", ShouldBeGreaterThanOrEqualTo, "a")) - - fail(t, so(0, ShouldBeGreaterThanOrEqualTo, 1), "Expected '0' to be greater than or equal to '1' (but it wasn't)!") - fail(t, so(1, ShouldBeGreaterThanOrEqualTo, 1.1), "Expected '1' to be greater than or equal to '1.1' (but it wasn't)!") - fail(t, so(uint(0), ShouldBeGreaterThanOrEqualTo, 1.1), "Expected '0' to be greater than or equal to '1.1' (but it wasn't)!") - fail(t, so("a", ShouldBeGreaterThanOrEqualTo, "b"), "Expected 'a' to be greater than or equal to 'b' (but it wasn't)!") -} - -func TestShouldBeLessThan(t *testing.T) { - fail(t, so(1, ShouldBeLessThan), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so(1, ShouldBeLessThan, 0, 0), "This assertion requires exactly 1 comparison values (you provided 2).") - - pass(t, so(0, ShouldBeLessThan, 1)) - pass(t, so(1, ShouldBeLessThan, 1.1)) - pass(t, so(uint(0), ShouldBeLessThan, 1)) - pass(t, so("a", ShouldBeLessThan, "b")) - - fail(t, so(1, ShouldBeLessThan, 0), "Expected '1' to be less than '0' (but it wasn't)!") - fail(t, so(1.1, ShouldBeLessThan, 1), "Expected '1.1' to be less than '1' (but it wasn't)!") - fail(t, so(1.1, ShouldBeLessThan, uint(0)), "Expected '1.1' to be less than '0' (but it wasn't)!") - fail(t, so("b", ShouldBeLessThan, "a"), "Expected 'b' to be less than 'a' (but it wasn't)!") -} - -func TestShouldBeLessThanOrEqualTo(t *testing.T) { - fail(t, so(1, ShouldBeLessThanOrEqualTo), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so(1, ShouldBeLessThanOrEqualTo, 0, 0), "This assertion requires exactly 1 comparison values (you provided 2).") - - pass(t, so(1, ShouldBeLessThanOrEqualTo, 1)) - pass(t, so(1.1, ShouldBeLessThanOrEqualTo, 1.1)) - pass(t, so(uint(1), ShouldBeLessThanOrEqualTo, 1)) - pass(t, so("b", ShouldBeLessThanOrEqualTo, "b")) - - pass(t, so(0, ShouldBeLessThanOrEqualTo, 1)) - pass(t, so(1, ShouldBeLessThanOrEqualTo, 1.1)) - pass(t, so(uint(0), ShouldBeLessThanOrEqualTo, 1)) - pass(t, so("a", ShouldBeLessThanOrEqualTo, "b")) - - fail(t, so(1, ShouldBeLessThanOrEqualTo, 0), "Expected '1' to be less than '0' (but it wasn't)!") - fail(t, so(1.1, ShouldBeLessThanOrEqualTo, 1), "Expected '1.1' to be less than '1' (but it wasn't)!") - fail(t, so(1.1, ShouldBeLessThanOrEqualTo, uint(0)), "Expected '1.1' to be less than '0' (but it wasn't)!") - fail(t, so("b", ShouldBeLessThanOrEqualTo, "a"), "Expected 'b' to be less than 'a' (but it wasn't)!") -} - -func TestShouldBeBetween(t *testing.T) { - fail(t, so(1, ShouldBeBetween), "This assertion requires exactly 2 comparison values (you provided 0).") - fail(t, so(1, ShouldBeBetween, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") - - fail(t, so(4, ShouldBeBetween, 1, 1), "The lower and upper bounds must be different values (they were both '1').") - - fail(t, so(7, ShouldBeBetween, 8, 12), "Expected '7' to be between '8' and '12' (but it wasn't)!") - fail(t, so(8, ShouldBeBetween, 8, 12), "Expected '8' to be between '8' and '12' (but it wasn't)!") - pass(t, so(9, ShouldBeBetween, 8, 12)) - pass(t, so(10, ShouldBeBetween, 8, 12)) - pass(t, so(11, ShouldBeBetween, 8, 12)) - fail(t, so(12, ShouldBeBetween, 8, 12), "Expected '12' to be between '8' and '12' (but it wasn't)!") - fail(t, so(13, ShouldBeBetween, 8, 12), "Expected '13' to be between '8' and '12' (but it wasn't)!") - - pass(t, so(1, ShouldBeBetween, 2, 0)) - fail(t, so(-1, ShouldBeBetween, 2, 0), "Expected '-1' to be between '0' and '2' (but it wasn't)!") -} - -func TestShouldNotBeBetween(t *testing.T) { - fail(t, so(1, ShouldNotBeBetween), "This assertion requires exactly 2 comparison values (you provided 0).") - fail(t, so(1, ShouldNotBeBetween, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") - - fail(t, so(4, ShouldNotBeBetween, 1, 1), "The lower and upper bounds must be different values (they were both '1').") - - pass(t, so(7, ShouldNotBeBetween, 8, 12)) - pass(t, so(8, ShouldNotBeBetween, 8, 12)) - fail(t, so(9, ShouldNotBeBetween, 8, 12), "Expected '9' NOT to be between '8' and '12' (but it was)!") - fail(t, so(10, ShouldNotBeBetween, 8, 12), "Expected '10' NOT to be between '8' and '12' (but it was)!") - fail(t, so(11, ShouldNotBeBetween, 8, 12), "Expected '11' NOT to be between '8' and '12' (but it was)!") - pass(t, so(12, ShouldNotBeBetween, 8, 12)) - pass(t, so(13, ShouldNotBeBetween, 8, 12)) - - pass(t, so(-1, ShouldNotBeBetween, 2, 0)) - fail(t, so(1, ShouldNotBeBetween, 2, 0), "Expected '1' NOT to be between '0' and '2' (but it was)!") -} - -func TestShouldBeBetweenOrEqual(t *testing.T) { - fail(t, so(1, ShouldBeBetweenOrEqual), "This assertion requires exactly 2 comparison values (you provided 0).") - fail(t, so(1, ShouldBeBetweenOrEqual, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") - - fail(t, so(4, ShouldBeBetweenOrEqual, 1, 1), "The lower and upper bounds must be different values (they were both '1').") - - fail(t, so(7, ShouldBeBetweenOrEqual, 8, 12), "Expected '7' to be between '8' and '12' or equal to one of them (but it wasn't)!") - pass(t, so(8, ShouldBeBetweenOrEqual, 8, 12)) - pass(t, so(9, ShouldBeBetweenOrEqual, 8, 12)) - pass(t, so(10, ShouldBeBetweenOrEqual, 8, 12)) - pass(t, so(11, ShouldBeBetweenOrEqual, 8, 12)) - pass(t, so(12, ShouldBeBetweenOrEqual, 8, 12)) - fail(t, so(13, ShouldBeBetweenOrEqual, 8, 12), "Expected '13' to be between '8' and '12' or equal to one of them (but it wasn't)!") - - pass(t, so(1, ShouldBeBetweenOrEqual, 2, 0)) - fail(t, so(-1, ShouldBeBetweenOrEqual, 2, 0), "Expected '-1' to be between '0' and '2' or equal to one of them (but it wasn't)!") -} - -func TestShouldNotBeBetweenOrEqual(t *testing.T) { - fail(t, so(1, ShouldNotBeBetweenOrEqual), "This assertion requires exactly 2 comparison values (you provided 0).") - fail(t, so(1, ShouldNotBeBetweenOrEqual, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") - - fail(t, so(4, ShouldNotBeBetweenOrEqual, 1, 1), "The lower and upper bounds must be different values (they were both '1').") - - pass(t, so(7, ShouldNotBeBetweenOrEqual, 8, 12)) - fail(t, so(8, ShouldNotBeBetweenOrEqual, 8, 12), "Expected '8' NOT to be between '8' and '12' or equal to one of them (but it was)!") - fail(t, so(9, ShouldNotBeBetweenOrEqual, 8, 12), "Expected '9' NOT to be between '8' and '12' or equal to one of them (but it was)!") - fail(t, so(10, ShouldNotBeBetweenOrEqual, 8, 12), "Expected '10' NOT to be between '8' and '12' or equal to one of them (but it was)!") - fail(t, so(11, ShouldNotBeBetweenOrEqual, 8, 12), "Expected '11' NOT to be between '8' and '12' or equal to one of them (but it was)!") - fail(t, so(12, ShouldNotBeBetweenOrEqual, 8, 12), "Expected '12' NOT to be between '8' and '12' or equal to one of them (but it was)!") - pass(t, so(13, ShouldNotBeBetweenOrEqual, 8, 12)) - - pass(t, so(-1, ShouldNotBeBetweenOrEqual, 2, 0)) - fail(t, so(1, ShouldNotBeBetweenOrEqual, 2, 0), "Expected '1' NOT to be between '0' and '2' or equal to one of them (but it was)!") -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/serializer_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/serializer_test.go deleted file mode 100644 index 798345d6ca6..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/serializer_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package assertions - -import ( - "encoding/json" - "fmt" - "testing" - - "github.com/smartystreets/goconvey/convey/reporting" -) - -func TestSerializerCreatesSerializedVersionOfAssertionResult(t *testing.T) { - thing1 := Thing1{"Hi"} - thing2 := Thing2{"Bye"} - message := "Super-hip failure message." - serializer := newSerializer() - - actualResult := serializer.serialize(thing1, thing2, message) - - expectedResult, _ := json.Marshal(reporting.FailureView{ - Message: message, - Expected: fmt.Sprintf("%+v", thing1), - Actual: fmt.Sprintf("%+v", thing2), - }) - - if actualResult != string(expectedResult) { - t.Errorf("\nExpected: %s\nActual: %s", string(expectedResult), actualResult) - } - - actualResult = serializer.serializeDetailed(thing1, thing2, message) - expectedResult, _ = json.Marshal(reporting.FailureView{ - Message: message, - Expected: fmt.Sprintf("%#v", thing1), - Actual: fmt.Sprintf("%#v", thing2), - }) - if actualResult != string(expectedResult) { - t.Errorf("\nExpected: %s\nActual: %s", string(expectedResult), actualResult) - } -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/strings_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/strings_test.go deleted file mode 100644 index eec9440ed0a..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/strings_test.go +++ /dev/null @@ -1,102 +0,0 @@ -package assertions - -import "testing" - -func TestShouldStartWith(t *testing.T) { - serializer = newFakeSerializer() - - fail(t, so("", ShouldStartWith), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so("", ShouldStartWith, "asdf", "asdf"), "This assertion requires exactly 1 comparison values (you provided 2).") - - pass(t, so("", ShouldStartWith, "")) - fail(t, so("", ShouldStartWith, "x"), "x||Expected '' to start with 'x' (but it didn't)!") - pass(t, so("abc", ShouldStartWith, "abc")) - fail(t, so("abc", ShouldStartWith, "abcd"), "abcd|abc|Expected 'abc' to start with 'abcd' (but it didn't)!") - - pass(t, so("superman", ShouldStartWith, "super")) - fail(t, so("superman", ShouldStartWith, "bat"), "bat|sup...|Expected 'superman' to start with 'bat' (but it didn't)!") - fail(t, so("superman", ShouldStartWith, "man"), "man|sup...|Expected 'superman' to start with 'man' (but it didn't)!") - - fail(t, so(1, ShouldStartWith, 2), "Both arguments to this assertion must be strings (you provided int and int).") -} - -func TestShouldNotStartWith(t *testing.T) { - fail(t, so("", ShouldNotStartWith), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so("", ShouldNotStartWith, "asdf", "asdf"), "This assertion requires exactly 1 comparison values (you provided 2).") - - fail(t, so("", ShouldNotStartWith, ""), "Expected '' NOT to start with '' (but it did)!") - fail(t, so("superman", ShouldNotStartWith, "super"), "Expected 'superman' NOT to start with 'super' (but it did)!") - pass(t, so("superman", ShouldNotStartWith, "bat")) - pass(t, so("superman", ShouldNotStartWith, "man")) - - fail(t, so(1, ShouldNotStartWith, 2), "Both arguments to this assertion must be strings (you provided int and int).") -} - -func TestShouldEndWith(t *testing.T) { - serializer = newFakeSerializer() - - fail(t, so("", ShouldEndWith), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so("", ShouldEndWith, "", ""), "This assertion requires exactly 1 comparison values (you provided 2).") - - pass(t, so("", ShouldEndWith, "")) - fail(t, so("", ShouldEndWith, "z"), "z||Expected '' to end with 'z' (but it didn't)!") - pass(t, so("xyz", ShouldEndWith, "xyz")) - fail(t, so("xyz", ShouldEndWith, "wxyz"), "wxyz|xyz|Expected 'xyz' to end with 'wxyz' (but it didn't)!") - - pass(t, so("superman", ShouldEndWith, "man")) - fail(t, so("superman", ShouldEndWith, "super"), "super|...erman|Expected 'superman' to end with 'super' (but it didn't)!") - fail(t, so("superman", ShouldEndWith, "blah"), "blah|...rman|Expected 'superman' to end with 'blah' (but it didn't)!") - - fail(t, so(1, ShouldEndWith, 2), "Both arguments to this assertion must be strings (you provided int and int).") -} - -func TestShouldNotEndWith(t *testing.T) { - fail(t, so("", ShouldNotEndWith), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so("", ShouldNotEndWith, "", ""), "This assertion requires exactly 1 comparison values (you provided 2).") - - fail(t, so("", ShouldNotEndWith, ""), "Expected '' NOT to end with '' (but it did)!") - fail(t, so("superman", ShouldNotEndWith, "man"), "Expected 'superman' NOT to end with 'man' (but it did)!") - pass(t, so("superman", ShouldNotEndWith, "super")) - - fail(t, so(1, ShouldNotEndWith, 2), "Both arguments to this assertion must be strings (you provided int and int).") -} - -func TestShouldContainSubstring(t *testing.T) { - serializer = newFakeSerializer() - - fail(t, so("asdf", ShouldContainSubstring), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so("asdf", ShouldContainSubstring, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") - - fail(t, so(123, ShouldContainSubstring, 23), "Both arguments to this assertion must be strings (you provided int and int).") - - pass(t, so("asdf", ShouldContainSubstring, "sd")) - fail(t, so("qwer", ShouldContainSubstring, "sd"), "sd|qwer|Expected 'qwer' to contain substring 'sd' (but it didn't)!") -} - -func TestShouldNotContainSubstring(t *testing.T) { - fail(t, so("asdf", ShouldNotContainSubstring), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so("asdf", ShouldNotContainSubstring, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") - - fail(t, so(123, ShouldNotContainSubstring, 23), "Both arguments to this assertion must be strings (you provided int and int).") - - pass(t, so("qwer", ShouldNotContainSubstring, "sd")) - fail(t, so("asdf", ShouldNotContainSubstring, "sd"), "Expected 'asdf' NOT to contain substring 'sd' (but it didn't)!") -} - -func TestShouldBeBlank(t *testing.T) { - serializer = newFakeSerializer() - - fail(t, so("", ShouldBeBlank, "adsf"), "This assertion requires exactly 0 comparison values (you provided 1).") - fail(t, so(1, ShouldBeBlank), "The argument to this assertion must be a string (you provided int).") - - fail(t, so("asdf", ShouldBeBlank), "|asdf|Expected 'asdf' to be blank (but it wasn't)!") - pass(t, so("", ShouldBeBlank)) -} - -func TestShouldNotBeBlank(t *testing.T) { - fail(t, so("", ShouldNotBeBlank, "adsf"), "This assertion requires exactly 0 comparison values (you provided 1).") - fail(t, so(1, ShouldNotBeBlank), "The argument to this assertion must be a string (you provided int).") - - fail(t, so("", ShouldNotBeBlank), "Expected value to NOT be blank (but it was)!") - pass(t, so("asdf", ShouldNotBeBlank)) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/time_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/time_test.go deleted file mode 100644 index f9dda8f8f34..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/time_test.go +++ /dev/null @@ -1,159 +0,0 @@ -package assertions - -import ( - "fmt" - "testing" - "time" -) - -func TestShouldHappenBefore(t *testing.T) { - fail(t, so(0, ShouldHappenBefore), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so(0, ShouldHappenBefore, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") - - fail(t, so(0, ShouldHappenBefore, 1), shouldUseTimes) - fail(t, so(0, ShouldHappenBefore, time.Now()), shouldUseTimes) - fail(t, so(time.Now(), ShouldHappenBefore, 0), shouldUseTimes) - - fail(t, so(january3, ShouldHappenBefore, january1), fmt.Sprintf("Expected '%s' to happen before '%s' (it happened '48h0m0s' after)!", pretty(january3), pretty(january1))) - fail(t, so(january3, ShouldHappenBefore, january3), fmt.Sprintf("Expected '%s' to happen before '%s' (it happened '0' after)!", pretty(january3), pretty(january3))) - pass(t, so(january1, ShouldHappenBefore, january3)) -} - -func TestShouldHappenOnOrBefore(t *testing.T) { - fail(t, so(0, ShouldHappenOnOrBefore), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so(0, ShouldHappenOnOrBefore, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") - - fail(t, so(0, ShouldHappenOnOrBefore, 1), shouldUseTimes) - fail(t, so(0, ShouldHappenOnOrBefore, time.Now()), shouldUseTimes) - fail(t, so(time.Now(), ShouldHappenOnOrBefore, 0), shouldUseTimes) - - fail(t, so(january3, ShouldHappenOnOrBefore, january1), fmt.Sprintf("Expected '%s' to happen before '%s' (it happened '48h0m0s' after)!", pretty(january3), pretty(january1))) - pass(t, so(january3, ShouldHappenOnOrBefore, january3)) - pass(t, so(january1, ShouldHappenOnOrBefore, january3)) -} - -func TestShouldHappenAfter(t *testing.T) { - fail(t, so(0, ShouldHappenAfter), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so(0, ShouldHappenAfter, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") - - fail(t, so(0, ShouldHappenAfter, 1), shouldUseTimes) - fail(t, so(0, ShouldHappenAfter, time.Now()), shouldUseTimes) - fail(t, so(time.Now(), ShouldHappenAfter, 0), shouldUseTimes) - - fail(t, so(january1, ShouldHappenAfter, january2), fmt.Sprintf("Expected '%s' to happen after '%s' (it happened '24h0m0s' before)!", pretty(january1), pretty(january2))) - fail(t, so(january1, ShouldHappenAfter, january1), fmt.Sprintf("Expected '%s' to happen after '%s' (it happened '0' before)!", pretty(january1), pretty(january1))) - pass(t, so(january3, ShouldHappenAfter, january1)) -} - -func TestShouldHappenOnOrAfter(t *testing.T) { - fail(t, so(0, ShouldHappenOnOrAfter), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so(0, ShouldHappenOnOrAfter, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") - - fail(t, so(0, ShouldHappenOnOrAfter, 1), shouldUseTimes) - fail(t, so(0, ShouldHappenOnOrAfter, time.Now()), shouldUseTimes) - fail(t, so(time.Now(), ShouldHappenOnOrAfter, 0), shouldUseTimes) - - fail(t, so(january1, ShouldHappenOnOrAfter, january2), fmt.Sprintf("Expected '%s' to happen after '%s' (it happened '24h0m0s' before)!", pretty(january1), pretty(january2))) - pass(t, so(january1, ShouldHappenOnOrAfter, january1)) - pass(t, so(january3, ShouldHappenOnOrAfter, january1)) -} - -func TestShouldHappenBetween(t *testing.T) { - fail(t, so(0, ShouldHappenBetween), "This assertion requires exactly 2 comparison values (you provided 0).") - fail(t, so(0, ShouldHappenBetween, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") - - fail(t, so(0, ShouldHappenBetween, 1, 2), shouldUseTimes) - fail(t, so(0, ShouldHappenBetween, time.Now(), time.Now()), shouldUseTimes) - fail(t, so(time.Now(), ShouldHappenBetween, 0, time.Now()), shouldUseTimes) - fail(t, so(time.Now(), ShouldHappenBetween, time.Now(), 9), shouldUseTimes) - - fail(t, so(january1, ShouldHappenBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january1), pretty(january2), pretty(january4))) - fail(t, so(january2, ShouldHappenBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '0' outside threshold)!", pretty(january2), pretty(january2), pretty(january4))) - pass(t, so(january3, ShouldHappenBetween, january2, january4)) - fail(t, so(january4, ShouldHappenBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '0' outside threshold)!", pretty(january4), pretty(january2), pretty(january4))) - fail(t, so(january5, ShouldHappenBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january5), pretty(january2), pretty(january4))) -} - -func TestShouldHappenOnOrBetween(t *testing.T) { - fail(t, so(0, ShouldHappenOnOrBetween), "This assertion requires exactly 2 comparison values (you provided 0).") - fail(t, so(0, ShouldHappenOnOrBetween, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") - - fail(t, so(0, ShouldHappenOnOrBetween, 1, time.Now()), shouldUseTimes) - fail(t, so(0, ShouldHappenOnOrBetween, time.Now(), 1), shouldUseTimes) - fail(t, so(time.Now(), ShouldHappenOnOrBetween, 0, 1), shouldUseTimes) - - fail(t, so(january1, ShouldHappenOnOrBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january1), pretty(january2), pretty(january4))) - pass(t, so(january2, ShouldHappenOnOrBetween, january2, january4)) - pass(t, so(january3, ShouldHappenOnOrBetween, january2, january4)) - pass(t, so(january4, ShouldHappenOnOrBetween, january2, january4)) - fail(t, so(january5, ShouldHappenOnOrBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january5), pretty(january2), pretty(january4))) -} - -func TestShouldNotHappenOnOrBetween(t *testing.T) { - fail(t, so(0, ShouldNotHappenOnOrBetween), "This assertion requires exactly 2 comparison values (you provided 0).") - fail(t, so(0, ShouldNotHappenOnOrBetween, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") - - fail(t, so(0, ShouldNotHappenOnOrBetween, 1, time.Now()), shouldUseTimes) - fail(t, so(0, ShouldNotHappenOnOrBetween, time.Now(), 1), shouldUseTimes) - fail(t, so(time.Now(), ShouldNotHappenOnOrBetween, 0, 1), shouldUseTimes) - - pass(t, so(january1, ShouldNotHappenOnOrBetween, january2, january4)) - fail(t, so(january2, ShouldNotHappenOnOrBetween, january2, january4), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january2), pretty(january2), pretty(january4))) - fail(t, so(january3, ShouldNotHappenOnOrBetween, january2, january4), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january3), pretty(january2), pretty(january4))) - fail(t, so(january4, ShouldNotHappenOnOrBetween, january2, january4), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january4), pretty(january2), pretty(january4))) - pass(t, so(january5, ShouldNotHappenOnOrBetween, january2, january4)) -} - -func TestShouldHappenWithin(t *testing.T) { - fail(t, so(0, ShouldHappenWithin), "This assertion requires exactly 2 comparison values (you provided 0).") - fail(t, so(0, ShouldHappenWithin, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") - - fail(t, so(0, ShouldHappenWithin, 1, 2), shouldUseDurationAndTime) - fail(t, so(0, ShouldHappenWithin, oneDay, time.Now()), shouldUseDurationAndTime) - fail(t, so(time.Now(), ShouldHappenWithin, 0, time.Now()), shouldUseDurationAndTime) - - fail(t, so(january1, ShouldHappenWithin, oneDay, january3), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january1), pretty(january2), pretty(january4))) - pass(t, so(january2, ShouldHappenWithin, oneDay, january3)) - pass(t, so(january3, ShouldHappenWithin, oneDay, january3)) - pass(t, so(january4, ShouldHappenWithin, oneDay, january3)) - fail(t, so(january5, ShouldHappenWithin, oneDay, january3), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january5), pretty(january2), pretty(january4))) -} - -func TestShouldNotHappenWithin(t *testing.T) { - fail(t, so(0, ShouldNotHappenWithin), "This assertion requires exactly 2 comparison values (you provided 0).") - fail(t, so(0, ShouldNotHappenWithin, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") - - fail(t, so(0, ShouldNotHappenWithin, 1, 2), shouldUseDurationAndTime) - fail(t, so(0, ShouldNotHappenWithin, oneDay, time.Now()), shouldUseDurationAndTime) - fail(t, so(time.Now(), ShouldNotHappenWithin, 0, time.Now()), shouldUseDurationAndTime) - - pass(t, so(january1, ShouldNotHappenWithin, oneDay, january3)) - fail(t, so(january2, ShouldNotHappenWithin, oneDay, january3), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january2), pretty(january2), pretty(january4))) - fail(t, so(january3, ShouldNotHappenWithin, oneDay, january3), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january3), pretty(january2), pretty(january4))) - fail(t, so(january4, ShouldNotHappenWithin, oneDay, january3), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january4), pretty(january2), pretty(january4))) - pass(t, so(january5, ShouldNotHappenWithin, oneDay, january3)) -} - -func TestShouldBeChronological(t *testing.T) { - fail(t, so(0, ShouldBeChronological, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).") - fail(t, so(0, ShouldBeChronological), shouldUseTimeSlice) - fail(t, so([]time.Time{january5, january1}, ShouldBeChronological), - "The 'Time' at index [1] should have happened after the previous one (but it didn't!):\n [0]: 2013-01-05 00:00:00 +0000 UTC\n [1]: 2013-01-01 00:00:00 +0000 UTC (see, it happened before!)") - - pass(t, so([]time.Time{january1, january2, january3, january4, january5}, ShouldBeChronological)) -} - -const layout = "2006-01-02 15:04" - -var january1, _ = time.Parse(layout, "2013-01-01 00:00") -var january2, _ = time.Parse(layout, "2013-01-02 00:00") -var january3, _ = time.Parse(layout, "2013-01-03 00:00") -var january4, _ = time.Parse(layout, "2013-01-04 00:00") -var january5, _ = time.Parse(layout, "2013-01-05 00:00") - -var oneDay, _ = time.ParseDuration("24h0m0s") -var twoDays, _ = time.ParseDuration("48h0m0s") - -func pretty(t time.Time) string { - return fmt.Sprintf("%v", t) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/type_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/type_test.go deleted file mode 100644 index 4b8d1984670..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/type_test.go +++ /dev/null @@ -1,76 +0,0 @@ -package assertions - -import ( - "bytes" - "io" - "net/http" - "testing" -) - -func TestShouldHaveSameTypeAs(t *testing.T) { - serializer = newFakeSerializer() - - fail(t, so(1, ShouldHaveSameTypeAs), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so(1, ShouldHaveSameTypeAs, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") - - fail(t, so(nil, ShouldHaveSameTypeAs, 0), "int||Expected '' to be: 'int' (but was: '')!") - fail(t, so(1, ShouldHaveSameTypeAs, "asdf"), "string|int|Expected '1' to be: 'string' (but was: 'int')!") - - pass(t, so(1, ShouldHaveSameTypeAs, 0)) - pass(t, so(nil, ShouldHaveSameTypeAs, nil)) -} - -func TestShouldNotHaveSameTypeAs(t *testing.T) { - fail(t, so(1, ShouldNotHaveSameTypeAs), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so(1, ShouldNotHaveSameTypeAs, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") - - fail(t, so(1, ShouldNotHaveSameTypeAs, 0), "Expected '1' to NOT be: 'int' (but it was)!") - fail(t, so(nil, ShouldNotHaveSameTypeAs, nil), "Expected '' to NOT be: '' (but it was)!") - - pass(t, so(nil, ShouldNotHaveSameTypeAs, 0)) - pass(t, so(1, ShouldNotHaveSameTypeAs, "asdf")) -} - -func TestShouldImplement(t *testing.T) { - var ioReader *io.Reader = nil - var response http.Response = http.Response{} - var responsePtr *http.Response = new(http.Response) - var reader = bytes.NewBufferString("") - - fail(t, so(reader, ShouldImplement), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so(reader, ShouldImplement, ioReader, ioReader), "This assertion requires exactly 1 comparison values (you provided 2).") - fail(t, so(reader, ShouldImplement, ioReader, ioReader, ioReader), "This assertion requires exactly 1 comparison values (you provided 3).") - - fail(t, so(reader, ShouldImplement, "foo"), shouldCompareWithInterfacePointer) - fail(t, so(reader, ShouldImplement, 1), shouldCompareWithInterfacePointer) - fail(t, so(reader, ShouldImplement, nil), shouldCompareWithInterfacePointer) - - fail(t, so(nil, ShouldImplement, ioReader), shouldNotBeNilActual) - fail(t, so(1, ShouldImplement, ioReader), "Expected: 'io.Reader interface support'\nActual: '*int' does not implement the interface!") - - fail(t, so(response, ShouldImplement, ioReader), "Expected: 'io.Reader interface support'\nActual: '*http.Response' does not implement the interface!") - fail(t, so(responsePtr, ShouldImplement, ioReader), "Expected: 'io.Reader interface support'\nActual: '*http.Response' does not implement the interface!") - pass(t, so(reader, ShouldImplement, ioReader)) - pass(t, so(reader, ShouldImplement, (*io.Reader)(nil))) -} - -func TestShouldNotImplement(t *testing.T) { - var ioReader *io.Reader = nil - var response http.Response = http.Response{} - var responsePtr *http.Response = new(http.Response) - var reader io.Reader = bytes.NewBufferString("") - - fail(t, so(reader, ShouldNotImplement), "This assertion requires exactly 1 comparison values (you provided 0).") - fail(t, so(reader, ShouldNotImplement, ioReader, ioReader), "This assertion requires exactly 1 comparison values (you provided 2).") - fail(t, so(reader, ShouldNotImplement, ioReader, ioReader, ioReader), "This assertion requires exactly 1 comparison values (you provided 3).") - - fail(t, so(reader, ShouldNotImplement, "foo"), shouldCompareWithInterfacePointer) - fail(t, so(reader, ShouldNotImplement, 1), shouldCompareWithInterfacePointer) - fail(t, so(reader, ShouldNotImplement, nil), shouldCompareWithInterfacePointer) - - fail(t, so(reader, ShouldNotImplement, ioReader), "Expected '*bytes.Buffer'\nto NOT implement 'io.Reader' (but it did)!") - fail(t, so(nil, ShouldNotImplement, ioReader), shouldNotBeNilActual) - pass(t, so(1, ShouldNotImplement, ioReader)) - pass(t, so(response, ShouldNotImplement, ioReader)) - pass(t, so(responsePtr, ShouldNotImplement, ioReader)) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/utilities_for_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/utilities_for_test.go deleted file mode 100644 index 7243ebcb937..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/assertions/utilities_for_test.go +++ /dev/null @@ -1,75 +0,0 @@ -package assertions - -import ( - "fmt" - "path" - "runtime" - "strings" - "testing" -) - -func pass(t *testing.T, result string) { - if result != success { - _, file, line, _ := runtime.Caller(1) - base := path.Base(file) - t.Errorf("Expectation should have passed but failed (see %s: line %d): '%s'", base, line, result) - } -} - -func fail(t *testing.T, actual string, expected string) { - actual = format(actual) - expected = format(expected) - - if actual != expected { - if actual == "" { - actual = "(empty)" - } - _, file, line, _ := runtime.Caller(1) - base := path.Base(file) - t.Errorf("Expectation should have failed but passed (see %s: line %d). \nExpected: %s\nActual: %s\n", - base, line, expected, actual) - } -} -func format(message string) string { - message = strings.Replace(message, "\n", " ", -1) - for strings.Contains(message, " ") { - message = strings.Replace(message, " ", " ", -1) - } - return message -} - -type Thing1 struct { - a string -} -type Thing2 struct { - a string -} - -type Thinger interface { - Hi() -} - -type Thing struct{} - -func (self *Thing) Hi() {} - -type IntAlias int -type StringAlias string -type StringSliceAlias []string -type StringStringMapAlias map[string]string - -/******** FakeSerialzier ********/ - -type fakeSerializer struct{} - -func (self *fakeSerializer) serialize(expected, actual interface{}, message string) string { - return fmt.Sprintf("%v|%v|%s", expected, actual, message) -} - -func (self *fakeSerializer) serializeDetailed(expected, actual interface{}, message string) string { - return fmt.Sprintf("%v|%v|%s", expected, actual, message) -} - -func newFakeSerializer() *fakeSerializer { - return new(fakeSerializer) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/focused_execution_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/focused_execution_test.go deleted file mode 100644 index 294e32fa17e..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/focused_execution_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package convey - -import "testing" - -func TestFocusOnlyAtTopLevel(t *testing.T) { - output := prepare() - - FocusConvey("hi", t, func() { - output += "done" - }) - - expectEqual(t, "done", output) -} - -func TestFocus(t *testing.T) { - output := prepare() - - FocusConvey("hi", t, func() { - output += "1" - - Convey("bye", func() { - output += "2" - }) - }) - - expectEqual(t, "1", output) -} - -func TestNestedFocus(t *testing.T) { - output := prepare() - - FocusConvey("hi", t, func() { - output += "1" - - Convey("This shouldn't run", func() { - output += "boink!" - }) - - FocusConvey("This should run", func() { - output += "2" - - FocusConvey("The should run too", func() { - output += "3" - - }) - - Convey("The should NOT run", func() { - output += "blah blah blah!" - }) - }) - }) - - expectEqual(t, "123", output) -} - -func TestForgotTopLevelFocus(t *testing.T) { - output := prepare() - - Convey("1", t, func() { - output += "1" - - FocusConvey("This will be run because the top-level lacks Focus", func() { - output += "2" - }) - - Convey("3", func() { - output += "3" - }) - }) - - expectEqual(t, "1213", output) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/isolated_execution_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/isolated_execution_test.go deleted file mode 100644 index 7e22b3caa53..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/isolated_execution_test.go +++ /dev/null @@ -1,774 +0,0 @@ -package convey - -import ( - "strconv" - "testing" - "time" -) - -func TestSingleScope(t *testing.T) { - output := prepare() - - Convey("hi", t, func() { - output += "done" - }) - - expectEqual(t, "done", output) -} - -func TestSingleScopeWithMultipleConveys(t *testing.T) { - output := prepare() - - Convey("1", t, func() { - output += "1" - }) - - Convey("2", t, func() { - output += "2" - }) - - expectEqual(t, "12", output) -} - -func TestNestedScopes(t *testing.T) { - output := prepare() - - Convey("a", t, func() { - output += "a " - - Convey("bb", func() { - output += "bb " - - Convey("ccc", func() { - output += "ccc | " - }) - }) - }) - - expectEqual(t, "a bb ccc | ", output) -} - -func TestNestedScopesWithIsolatedExecution(t *testing.T) { - output := prepare() - - Convey("a", t, func() { - output += "a " - - Convey("aa", func() { - output += "aa " - - Convey("aaa", func() { - output += "aaa | " - }) - - Convey("aaa1", func() { - output += "aaa1 | " - }) - }) - - Convey("ab", func() { - output += "ab " - - Convey("abb", func() { - output += "abb | " - }) - }) - }) - - expectEqual(t, "a aa aaa | a aa aaa1 | a ab abb | ", output) -} - -func TestSingleScopeWithConveyAndNestedReset(t *testing.T) { - output := prepare() - - Convey("1", t, func() { - output += "1" - - Reset(func() { - output += "a" - }) - }) - - expectEqual(t, "1a", output) -} - -func TestPanicingReset(t *testing.T) { - output := prepare() - - Convey("1", t, func() { - output += "1" - - Reset(func() { - panic("nooo") - }) - - Convey("runs since the reset hasn't yet", func() { - output += "a" - }) - - Convey("but this doesnt", func() { - output += "nope" - }) - }) - - expectEqual(t, "1a", output) -} - -func TestSingleScopeWithMultipleRegistrationsAndReset(t *testing.T) { - output := prepare() - - Convey("reset after each nested convey", t, func() { - Convey("first output", func() { - output += "1" - }) - - Convey("second output", func() { - output += "2" - }) - - Reset(func() { - output += "a" - }) - }) - - expectEqual(t, "1a2a", output) -} - -func TestSingleScopeWithMultipleRegistrationsAndMultipleResets(t *testing.T) { - output := prepare() - - Convey("each reset is run at end of each nested convey", t, func() { - Convey("1", func() { - output += "1" - }) - - Convey("2", func() { - output += "2" - }) - - Reset(func() { - output += "a" - }) - - Reset(func() { - output += "b" - }) - }) - - expectEqual(t, "1ab2ab", output) -} - -func Test_Failure_AtHigherLevelScopePreventsChildScopesFromRunning(t *testing.T) { - output := prepare() - - Convey("This step fails", t, func() { - So(1, ShouldEqual, 2) - - Convey("this should NOT be executed", func() { - output += "a" - }) - }) - - expectEqual(t, "", output) -} - -func Test_Panic_AtHigherLevelScopePreventsChildScopesFromRunning(t *testing.T) { - output := prepare() - - Convey("This step panics", t, func() { - Convey("this happens, because the panic didn't happen yet", func() { - output += "1" - }) - - output += "a" - - Convey("this should NOT be executed", func() { - output += "2" - }) - - output += "b" - - panic("Hi") - - output += "nope" - }) - - expectEqual(t, "1ab", output) -} - -func Test_Panic_InChildScopeDoes_NOT_PreventExecutionOfSiblingScopes(t *testing.T) { - output := prepare() - - Convey("This is the parent", t, func() { - Convey("This step panics", func() { - panic("Hi") - output += "1" - }) - - Convey("This sibling should execute", func() { - output += "2" - }) - }) - - expectEqual(t, "2", output) -} - -func Test_Failure_InChildScopeDoes_NOT_PreventExecutionOfSiblingScopes(t *testing.T) { - output := prepare() - - Convey("This is the parent", t, func() { - Convey("This step fails", func() { - So(1, ShouldEqual, 2) - output += "1" - }) - - Convey("This sibling should execute", func() { - output += "2" - }) - }) - - expectEqual(t, "2", output) -} - -func TestResetsAreAlwaysExecutedAfterScope_Panics(t *testing.T) { - output := prepare() - - Convey("This is the parent", t, func() { - Convey("This step panics", func() { - panic("Hi") - output += "1" - }) - - Convey("This sibling step does not panic", func() { - output += "a" - - Reset(func() { - output += "b" - }) - }) - - Reset(func() { - output += "2" - }) - }) - - expectEqual(t, "2ab2", output) -} - -func TestResetsAreAlwaysExecutedAfterScope_Failures(t *testing.T) { - output := prepare() - - Convey("This is the parent", t, func() { - Convey("This step fails", func() { - So(1, ShouldEqual, 2) - output += "1" - }) - - Convey("This sibling step does not fail", func() { - output += "a" - - Reset(func() { - output += "b" - }) - }) - - Reset(func() { - output += "2" - }) - }) - - expectEqual(t, "2ab2", output) -} - -func TestSkipTopLevel(t *testing.T) { - output := prepare() - - SkipConvey("hi", t, func() { - output += "This shouldn't be executed!" - }) - - expectEqual(t, "", output) -} - -func TestSkipNestedLevel(t *testing.T) { - output := prepare() - - Convey("hi", t, func() { - output += "yes" - - SkipConvey("bye", func() { - output += "no" - }) - }) - - expectEqual(t, "yes", output) -} - -func TestSkipNestedLevelSkipsAllChildLevels(t *testing.T) { - output := prepare() - - Convey("hi", t, func() { - output += "yes" - - SkipConvey("bye", func() { - output += "no" - - Convey("byebye", func() { - output += "no-no" - }) - }) - }) - - expectEqual(t, "yes", output) -} - -func TestIterativeConveys(t *testing.T) { - output := prepare() - - Convey("Test", t, func() { - for x := 0; x < 10; x++ { - y := strconv.Itoa(x) - - Convey(y, func() { - output += y - }) - } - }) - - expectEqual(t, "0123456789", output) -} - -func TestClosureVariables(t *testing.T) { - output := prepare() - - i := 0 - - Convey("A", t, func() { - i = i + 1 - j := i - - output += "A" + strconv.Itoa(i) + " " - - Convey("B", func() { - k := j - j = j + 1 - - output += "B" + strconv.Itoa(k) + " " - - Convey("C", func() { - output += "C" + strconv.Itoa(k) + strconv.Itoa(j) + " " - }) - - Convey("D", func() { - output += "D" + strconv.Itoa(k) + strconv.Itoa(j) + " " - }) - }) - - Convey("C", func() { - output += "C" + strconv.Itoa(j) + " " - }) - }) - - output += "D" + strconv.Itoa(i) + " " - - expectEqual(t, "A1 B1 C12 A2 B2 D23 A3 C3 D3 ", output) -} - -func TestClosureVariablesWithReset(t *testing.T) { - output := prepare() - - i := 0 - - Convey("A", t, func() { - i = i + 1 - j := i - - output += "A" + strconv.Itoa(i) + " " - - Reset(func() { - output += "R" + strconv.Itoa(i) + strconv.Itoa(j) + " " - }) - - Convey("B", func() { - output += "B" + strconv.Itoa(j) + " " - }) - - Convey("C", func() { - output += "C" + strconv.Itoa(j) + " " - }) - }) - - output += "D" + strconv.Itoa(i) + " " - - expectEqual(t, "A1 B1 R11 A2 C2 R22 D2 ", output) -} - -func TestWrappedSimple(t *testing.T) { - prepare() - output := resetTestString{""} - - Convey("A", t, func() { - func() { - output.output += "A " - - Convey("B", func() { - output.output += "B " - - Convey("C", func() { - output.output += "C " - }) - - }) - - Convey("D", func() { - output.output += "D " - }) - }() - }) - - expectEqual(t, "A B C A D ", output.output) -} - -type resetTestString struct { - output string -} - -func addReset(o *resetTestString, f func()) func() { - return func() { - Reset(func() { - o.output += "R " - }) - - f() - } -} - -func TestWrappedReset(t *testing.T) { - prepare() - output := resetTestString{""} - - Convey("A", t, addReset(&output, func() { - output.output += "A " - - Convey("B", func() { - output.output += "B " - }) - - Convey("C", func() { - output.output += "C " - }) - })) - - expectEqual(t, "A B R A C R ", output.output) -} - -func TestWrappedReset2(t *testing.T) { - prepare() - output := resetTestString{""} - - Convey("A", t, func() { - Reset(func() { - output.output += "R " - }) - - func() { - output.output += "A " - - Convey("B", func() { - output.output += "B " - - Convey("C", func() { - output.output += "C " - }) - }) - - Convey("D", func() { - output.output += "D " - }) - }() - }) - - expectEqual(t, "A B C R A D R ", output.output) -} - -func TestInfiniteLoopWithTrailingFail(t *testing.T) { - done := make(chan int) - - go func() { - Convey("This fails", t, func() { - Convey("and this is run", func() { - So(true, ShouldEqual, true) - }) - - /* And this prevents the whole block to be marked as run */ - So(false, ShouldEqual, true) - }) - - done <- 1 - }() - - select { - case <-done: - return - case <-time.After(1 * time.Millisecond): - t.Fail() - } -} - -func TestOutermostResetInvokedForGrandchildren(t *testing.T) { - output := prepare() - - Convey("A", t, func() { - output += "A " - - Reset(func() { - output += "rA " - }) - - Convey("B", func() { - output += "B " - - Reset(func() { - output += "rB " - }) - - Convey("C", func() { - output += "C " - - Reset(func() { - output += "rC " - }) - }) - - Convey("D", func() { - output += "D " - - Reset(func() { - output += "rD " - }) - }) - }) - }) - - expectEqual(t, "A B C rC rB rA A B D rD rB rA ", output) -} - -func TestFailureOption(t *testing.T) { - output := prepare() - - Convey("A", t, FailureHalts, func() { - output += "A " - So(true, ShouldEqual, true) - output += "B " - So(false, ShouldEqual, true) - output += "C " - }) - - expectEqual(t, "A B ", output) -} - -func TestFailureOption2(t *testing.T) { - output := prepare() - - Convey("A", t, func() { - output += "A " - So(true, ShouldEqual, true) - output += "B " - So(false, ShouldEqual, true) - output += "C " - }) - - expectEqual(t, "A B ", output) -} - -func TestFailureOption3(t *testing.T) { - output := prepare() - - Convey("A", t, FailureContinues, func() { - output += "A " - So(true, ShouldEqual, true) - output += "B " - So(false, ShouldEqual, true) - output += "C " - }) - - expectEqual(t, "A B C ", output) -} - -func TestFailureOptionInherit(t *testing.T) { - output := prepare() - - Convey("A", t, FailureContinues, func() { - output += "A1 " - So(false, ShouldEqual, true) - output += "A2 " - - Convey("B", func() { - output += "B1 " - So(true, ShouldEqual, true) - output += "B2 " - So(false, ShouldEqual, true) - output += "B3 " - }) - }) - - expectEqual(t, "A1 A2 B1 B2 B3 ", output) -} - -func TestFailureOptionInherit2(t *testing.T) { - output := prepare() - - Convey("A", t, FailureHalts, func() { - output += "A1 " - So(false, ShouldEqual, true) - output += "A2 " - - Convey("B", func() { - output += "A1 " - So(true, ShouldEqual, true) - output += "A2 " - So(false, ShouldEqual, true) - output += "A3 " - }) - }) - - expectEqual(t, "A1 ", output) -} - -func TestFailureOptionInherit3(t *testing.T) { - output := prepare() - - Convey("A", t, FailureHalts, func() { - output += "A1 " - So(true, ShouldEqual, true) - output += "A2 " - - Convey("B", func() { - output += "B1 " - So(true, ShouldEqual, true) - output += "B2 " - So(false, ShouldEqual, true) - output += "B3 " - }) - }) - - expectEqual(t, "A1 A2 B1 B2 ", output) -} - -func TestFailureOptionNestedOverride(t *testing.T) { - output := prepare() - - Convey("A", t, FailureContinues, func() { - output += "A " - So(false, ShouldEqual, true) - output += "B " - - Convey("C", FailureHalts, func() { - output += "C " - So(true, ShouldEqual, true) - output += "D " - So(false, ShouldEqual, true) - output += "E " - }) - }) - - expectEqual(t, "A B C D ", output) -} - -func TestFailureOptionNestedOverride2(t *testing.T) { - output := prepare() - - Convey("A", t, FailureHalts, func() { - output += "A " - So(true, ShouldEqual, true) - output += "B " - - Convey("C", FailureContinues, func() { - output += "C " - So(true, ShouldEqual, true) - output += "D " - So(false, ShouldEqual, true) - output += "E " - }) - }) - - expectEqual(t, "A B C D E ", output) -} - -func TestMultipleInvocationInheritance(t *testing.T) { - output := prepare() - - Convey("A", t, FailureHalts, func() { - output += "A1 " - So(true, ShouldEqual, true) - output += "A2 " - - Convey("B", FailureContinues, func() { - output += "B1 " - So(true, ShouldEqual, true) - output += "B2 " - So(false, ShouldEqual, true) - output += "B3 " - }) - - Convey("C", func() { - output += "C1 " - So(true, ShouldEqual, true) - output += "C2 " - So(false, ShouldEqual, true) - output += "C3 " - }) - }) - - expectEqual(t, "A1 A2 B1 B2 B3 A1 A2 C1 C2 ", output) -} - -func TestMultipleInvocationInheritance2(t *testing.T) { - output := prepare() - - Convey("A", t, FailureContinues, func() { - output += "A1 " - So(true, ShouldEqual, true) - output += "A2 " - So(false, ShouldEqual, true) - output += "A3 " - - Convey("B", FailureHalts, func() { - output += "B1 " - So(true, ShouldEqual, true) - output += "B2 " - So(false, ShouldEqual, true) - output += "B3 " - }) - - Convey("C", func() { - output += "C1 " - So(true, ShouldEqual, true) - output += "C2 " - So(false, ShouldEqual, true) - output += "C3 " - }) - }) - - expectEqual(t, "A1 A2 A3 B1 B2 A1 A2 A3 C1 C2 C3 ", output) -} - -func TestSetDefaultFailureMode(t *testing.T) { - output := prepare() - - SetDefaultFailureMode(FailureContinues) // the default is normally FailureHalts - defer SetDefaultFailureMode(FailureHalts) - - Convey("A", t, func() { - output += "A1 " - So(true, ShouldBeFalse) - output += "A2 " - }) - - expectEqual(t, "A1 A2 ", output) -} - -func prepare() string { - testReporter = newNilReporter() - return "" -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/dot_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/dot_test.go deleted file mode 100644 index a8d20d46f08..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/dot_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package reporting - -import ( - "errors" - "testing" -) - -func TestDotReporterAssertionPrinting(t *testing.T) { - monochrome() - file := newMemoryFile() - printer := NewPrinter(file) - reporter := NewDotReporter(printer) - - reporter.Report(NewSuccessReport()) - reporter.Report(NewFailureReport("failed")) - reporter.Report(NewErrorReport(errors.New("error"))) - reporter.Report(NewSkipReport()) - - expected := dotSuccess + dotFailure + dotError + dotSkip - - if file.buffer != expected { - t.Errorf("\nExpected: '%s'\nActual: '%s'", expected, file.buffer) - } -} - -func TestDotReporterOnlyReportsAssertions(t *testing.T) { - monochrome() - file := newMemoryFile() - printer := NewPrinter(file) - reporter := NewDotReporter(printer) - - reporter.BeginStory(nil) - reporter.Enter(nil) - reporter.Exit() - reporter.EndStory() - - if file.buffer != "" { - t.Errorf("\nExpected: '(blank)'\nActual: '%s'", file.buffer) - } -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/gotest_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/gotest_test.go deleted file mode 100644 index fda189458e5..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/gotest_test.go +++ /dev/null @@ -1,66 +0,0 @@ -package reporting - -import "testing" - -func TestReporterReceivesSuccessfulReport(t *testing.T) { - reporter := NewGoTestReporter() - test := new(fakeTest) - reporter.BeginStory(NewStoryReport(test)) - reporter.Report(NewSuccessReport()) - - if test.failed { - t.Errorf("Should have have marked test as failed--the report reflected success.") - } -} - -func TestReporterReceivesFailureReport(t *testing.T) { - reporter := NewGoTestReporter() - test := new(fakeTest) - reporter.BeginStory(NewStoryReport(test)) - reporter.Report(NewFailureReport("This is a failure.")) - - if !test.failed { - t.Errorf("Test should have been marked as failed (but it wasn't).") - } -} - -func TestReporterReceivesErrorReport(t *testing.T) { - reporter := NewGoTestReporter() - test := new(fakeTest) - reporter.BeginStory(NewStoryReport(test)) - reporter.Report(NewErrorReport("This is an error.")) - - if !test.failed { - t.Errorf("Test should have been marked as failed (but it wasn't).") - } -} - -func TestReporterIsResetAtTheEndOfTheStory(t *testing.T) { - defer catch(t) - reporter := NewGoTestReporter() - test := new(fakeTest) - reporter.BeginStory(NewStoryReport(test)) - reporter.EndStory() - - reporter.Report(NewSuccessReport()) -} - -func TestReporterNoopMethods(t *testing.T) { - reporter := NewGoTestReporter() - reporter.Enter(NewScopeReport("title")) - reporter.Exit() -} - -func catch(t *testing.T) { - if r := recover(); r != nil { - t.Log("Getting to this point means we've passed (because we caught a panic appropriately).") - } -} - -type fakeTest struct { - failed bool -} - -func (self *fakeTest) Fail() { - self.failed = true -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/printer_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/printer_test.go deleted file mode 100644 index 94202d5ac97..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/printer_test.go +++ /dev/null @@ -1,181 +0,0 @@ -package reporting - -import "testing" - -func TestPrint(t *testing.T) { - file := newMemoryFile() - printer := NewPrinter(file) - const expected = "Hello, World!" - - printer.Print(expected) - - if file.buffer != expected { - t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) - } -} - -func TestPrintFormat(t *testing.T) { - file := newMemoryFile() - printer := NewPrinter(file) - template := "Hi, %s" - name := "Ralph" - expected := "Hi, Ralph" - - printer.Print(template, name) - - if file.buffer != expected { - t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) - } -} - -func TestPrintPreservesEncodedStrings(t *testing.T) { - file := newMemoryFile() - printer := NewPrinter(file) - const expected = "= -> %3D" - printer.Print(expected) - - if file.buffer != expected { - t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) - } -} - -func TestPrintln(t *testing.T) { - file := newMemoryFile() - printer := NewPrinter(file) - const expected = "Hello, World!" - - printer.Println(expected) - - if file.buffer != expected+"\n" { - t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) - } -} - -func TestPrintlnFormat(t *testing.T) { - file := newMemoryFile() - printer := NewPrinter(file) - template := "Hi, %s" - name := "Ralph" - expected := "Hi, Ralph\n" - - printer.Println(template, name) - - if file.buffer != expected { - t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) - } -} - -func TestPrintlnPreservesEncodedStrings(t *testing.T) { - file := newMemoryFile() - printer := NewPrinter(file) - const expected = "= -> %3D" - printer.Println(expected) - - if file.buffer != expected+"\n" { - t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) - } -} - -func TestPrintIndented(t *testing.T) { - file := newMemoryFile() - printer := NewPrinter(file) - const message = "Hello, World!\nGoodbye, World!" - const expected = " Hello, World!\n Goodbye, World!" - - printer.Indent() - printer.Print(message) - - if file.buffer != expected { - t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) - } -} - -func TestPrintDedented(t *testing.T) { - file := newMemoryFile() - printer := NewPrinter(file) - const expected = "Hello, World!\nGoodbye, World!" - - printer.Indent() - printer.Dedent() - printer.Print(expected) - - if file.buffer != expected { - t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) - } -} - -func TestPrintlnIndented(t *testing.T) { - file := newMemoryFile() - printer := NewPrinter(file) - const message = "Hello, World!\nGoodbye, World!" - const expected = " Hello, World!\n Goodbye, World!\n" - - printer.Indent() - printer.Println(message) - - if file.buffer != expected { - t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) - } -} - -func TestPrintlnDedented(t *testing.T) { - file := newMemoryFile() - printer := NewPrinter(file) - const expected = "Hello, World!\nGoodbye, World!" - - printer.Indent() - printer.Dedent() - printer.Println(expected) - - if file.buffer != expected+"\n" { - t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) - } -} - -func TestDedentTooFarShouldNotPanic(t *testing.T) { - defer func() { - if r := recover(); r != nil { - t.Error("Should not have panicked!") - } - }() - file := newMemoryFile() - printer := NewPrinter(file) - - printer.Dedent() - - t.Log("Getting to this point without panicking means we passed.") -} - -func TestInsert(t *testing.T) { - file := newMemoryFile() - printer := NewPrinter(file) - - printer.Indent() - printer.Print("Hi") - printer.Insert(" there") - printer.Dedent() - - expected := " Hi there" - if file.buffer != expected { - t.Errorf("Should have written '%s' but instead wrote '%s'.", expected, file.buffer) - } -} - -////////////////// memoryFile //////////////////// - -type memoryFile struct { - buffer string -} - -func (self *memoryFile) Write(p []byte) (n int, err error) { - self.buffer += string(p) - return len(p), nil -} - -func (self *memoryFile) String() string { - return self.buffer -} - -func newMemoryFile() *memoryFile { - return new(memoryFile) -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/problems_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/problems_test.go deleted file mode 100644 index 92f0ca35cca..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/problems_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package reporting - -import ( - "strings" - "testing" -) - -func TestNoopProblemReporterActions(t *testing.T) { - file, reporter := setup() - reporter.BeginStory(nil) - reporter.Enter(nil) - reporter.Exit() - expected := "" - actual := file.String() - if expected != actual { - t.Errorf("Expected: '(blank)'\nActual: '%s'", actual) - } -} - -func TestReporterPrintsFailuresAndErrorsAtTheEndOfTheStory(t *testing.T) { - file, reporter := setup() - reporter.Report(NewFailureReport("failed")) - reporter.Report(NewErrorReport("error")) - reporter.Report(NewSuccessReport()) - reporter.EndStory() - - result := file.String() - if !strings.Contains(result, "Errors:\n") { - t.Errorf("Expected errors, found none.") - } - if !strings.Contains(result, "Failures:\n") { - t.Errorf("Expected failures, found none.") - } - - // Each stack trace looks like: `* /path/to/file.go`, so look for `* `. - // With go 1.4+ there is a line in some stack traces that looks like this: - // `testing.(*M).Run(0x2082d60a0, 0x25b7c0)` - // So we can't just look for "*" anymore. - problemCount := strings.Count(result, "* ") - if problemCount != 2 { - t.Errorf("Expected one failure and one error (total of 2 '*' characters). Got %d", problemCount) - } -} - -func setup() (file *memoryFile, reporter *problem) { - monochrome() - file = newMemoryFile() - printer := NewPrinter(file) - reporter = NewProblemReporter(printer) - return -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/reporter_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/reporter_test.go deleted file mode 100644 index 4e5caf63b2b..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting/reporter_test.go +++ /dev/null @@ -1,94 +0,0 @@ -package reporting - -import ( - "runtime" - "testing" -) - -func TestEachNestedReporterReceivesTheCallFromTheContainingReporter(t *testing.T) { - fake1 := newFakeReporter() - fake2 := newFakeReporter() - reporter := NewReporters(fake1, fake2) - - reporter.BeginStory(nil) - assertTrue(t, fake1.begun) - assertTrue(t, fake2.begun) - - reporter.Enter(NewScopeReport("scope")) - assertTrue(t, fake1.entered) - assertTrue(t, fake2.entered) - - reporter.Report(NewSuccessReport()) - assertTrue(t, fake1.reported) - assertTrue(t, fake2.reported) - - reporter.Exit() - assertTrue(t, fake1.exited) - assertTrue(t, fake2.exited) - - reporter.EndStory() - assertTrue(t, fake1.ended) - assertTrue(t, fake2.ended) - - content := []byte("hi") - written, err := reporter.Write(content) - assertTrue(t, fake1.written) - assertTrue(t, fake2.written) - assertEqual(t, written, len(content)) - assertNil(t, err) - -} - -func assertTrue(t *testing.T, value bool) { - if !value { - _, _, line, _ := runtime.Caller(1) - t.Errorf("Value should have been true (but was false). See line %d", line) - } -} - -func assertEqual(t *testing.T, expected, actual int) { - if actual != expected { - _, _, line, _ := runtime.Caller(1) - t.Errorf("Value should have been %d (but was %d). See line %d", expected, actual, line) - } -} - -func assertNil(t *testing.T, err error) { - if err != nil { - _, _, line, _ := runtime.Caller(1) - t.Errorf("Error should have been (but wasn't). See line %d", err, line) - } -} - -type fakeReporter struct { - begun bool - entered bool - reported bool - exited bool - ended bool - written bool -} - -func newFakeReporter() *fakeReporter { - return &fakeReporter{} -} - -func (self *fakeReporter) BeginStory(story *StoryReport) { - self.begun = true -} -func (self *fakeReporter) Enter(scope *ScopeReport) { - self.entered = true -} -func (self *fakeReporter) Report(report *AssertionResult) { - self.reported = true -} -func (self *fakeReporter) Exit() { - self.exited = true -} -func (self *fakeReporter) EndStory() { - self.ended = true -} -func (self *fakeReporter) Write(content []byte) (int, error) { - self.written = true - return len(content), nil -} diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting_hooks_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting_hooks_test.go deleted file mode 100644 index 69125c3cf44..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/reporting_hooks_test.go +++ /dev/null @@ -1,317 +0,0 @@ -package convey - -import ( - "fmt" - "net/http" - "net/http/httptest" - "path" - "runtime" - "strconv" - "strings" - "testing" - - "github.com/smartystreets/goconvey/convey/reporting" -) - -func TestSingleScopeReported(t *testing.T) { - myReporter, test := setupFakeReporter() - - Convey("A", test, func() { - So(1, ShouldEqual, 1) - }) - - expectEqual(t, "Begin|A|Success|Exit|End", myReporter.wholeStory()) -} - -func TestNestedScopeReported(t *testing.T) { - myReporter, test := setupFakeReporter() - - Convey("A", test, func() { - Convey("B", func() { - So(1, ShouldEqual, 1) - }) - }) - - expectEqual(t, "Begin|A|B|Success|Exit|Exit|End", myReporter.wholeStory()) -} - -func TestFailureReported(t *testing.T) { - myReporter, test := setupFakeReporter() - - Convey("A", test, func() { - So(1, ShouldBeNil) - }) - - expectEqual(t, "Begin|A|Failure|Exit|End", myReporter.wholeStory()) -} - -func TestFirstFailureEndsScopeExecution(t *testing.T) { - myReporter, test := setupFakeReporter() - - Convey("A", test, func() { - So(1, ShouldBeNil) - So(nil, ShouldBeNil) - }) - - expectEqual(t, "Begin|A|Failure|Exit|End", myReporter.wholeStory()) -} - -func TestComparisonFailureDeserializedAndReported(t *testing.T) { - myReporter, test := setupFakeReporter() - - Convey("A", test, func() { - So("hi", ShouldEqual, "bye") - }) - - expectEqual(t, "Begin|A|Failure(bye/hi)|Exit|End", myReporter.wholeStory()) -} - -func TestNestedFailureReported(t *testing.T) { - myReporter, test := setupFakeReporter() - - Convey("A", test, func() { - Convey("B", func() { - So(2, ShouldBeNil) - }) - }) - - expectEqual(t, "Begin|A|B|Failure|Exit|Exit|End", myReporter.wholeStory()) -} - -func TestSuccessAndFailureReported(t *testing.T) { - myReporter, test := setupFakeReporter() - - Convey("A", test, func() { - So(nil, ShouldBeNil) - So(1, ShouldBeNil) - }) - - expectEqual(t, "Begin|A|Success|Failure|Exit|End", myReporter.wholeStory()) -} - -func TestIncompleteActionReportedAsSkipped(t *testing.T) { - myReporter, test := setupFakeReporter() - - Convey("A", test, func() { - Convey("B", nil) - }) - - expectEqual(t, "Begin|A|B|Skipped|Exit|Exit|End", myReporter.wholeStory()) -} - -func TestSkippedConveyReportedAsSkipped(t *testing.T) { - myReporter, test := setupFakeReporter() - - Convey("A", test, func() { - SkipConvey("B", func() { - So(1, ShouldEqual, 1) - }) - }) - - expectEqual(t, "Begin|A|B|Skipped|Exit|Exit|End", myReporter.wholeStory()) -} - -func TestMultipleSkipsAreReported(t *testing.T) { - myReporter, test := setupFakeReporter() - - Convey("A", test, func() { - Convey("0", func() { - So(nil, ShouldBeNil) - }) - - SkipConvey("1", func() {}) - SkipConvey("2", func() {}) - - Convey("3", nil) - Convey("4", nil) - - Convey("5", func() { - So(nil, ShouldBeNil) - }) - }) - - expected := "Begin" + - "|A|0|Success|Exit|Exit" + - "|A|1|Skipped|Exit|Exit" + - "|A|2|Skipped|Exit|Exit" + - "|A|3|Skipped|Exit|Exit" + - "|A|4|Skipped|Exit|Exit" + - "|A|5|Success|Exit|Exit" + - "|End" - - expectEqual(t, expected, myReporter.wholeStory()) -} - -func TestSkippedAssertionIsNotReported(t *testing.T) { - myReporter, test := setupFakeReporter() - - Convey("A", test, func() { - SkipSo(1, ShouldEqual, 1) - }) - - expectEqual(t, "Begin|A|Skipped|Exit|End", myReporter.wholeStory()) -} - -func TestMultipleSkippedAssertionsAreNotReported(t *testing.T) { - myReporter, test := setupFakeReporter() - - Convey("A", test, func() { - SkipSo(1, ShouldEqual, 1) - So(1, ShouldEqual, 1) - SkipSo(1, ShouldEqual, 1) - }) - - expectEqual(t, "Begin|A|Skipped|Success|Skipped|Exit|End", myReporter.wholeStory()) -} - -func TestErrorByManualPanicReported(t *testing.T) { - myReporter, test := setupFakeReporter() - - Convey("A", test, func() { - panic("Gopher alert!") - }) - - expectEqual(t, "Begin|A|Error|Exit|End", myReporter.wholeStory()) -} - -func TestIterativeConveysReported(t *testing.T) { - myReporter, test := setupFakeReporter() - - Convey("A", test, func() { - for x := 0; x < 3; x++ { - Convey(strconv.Itoa(x), func() { - So(x, ShouldEqual, x) - }) - } - }) - - expectEqual(t, "Begin|A|0|Success|Exit|Exit|A|1|Success|Exit|Exit|A|2|Success|Exit|Exit|End", myReporter.wholeStory()) -} - -func TestNestedIterativeConveysReported(t *testing.T) { - myReporter, test := setupFakeReporter() - - Convey("A", test, func() { - for x := 0; x < 3; x++ { - Convey(strconv.Itoa(x), func() { - for y := 0; y < 3; y++ { - Convey("< "+strconv.Itoa(y), func() { - So(x, ShouldBeLessThan, y) - }) - } - }) - } - }) - - expectEqual(t, ("Begin|" + - "A|0|< 0|Failure|Exit|Exit|Exit|" + - "A|0|< 1|Success|Exit|Exit|Exit|" + - "A|0|< 2|Success|Exit|Exit|Exit|" + - "A|1|< 0|Failure|Exit|Exit|Exit|" + - "A|1|< 1|Failure|Exit|Exit|Exit|" + - "A|1|< 2|Success|Exit|Exit|Exit|" + - "A|2|< 0|Failure|Exit|Exit|Exit|" + - "A|2|< 1|Failure|Exit|Exit|Exit|" + - "A|2|< 2|Failure|Exit|Exit|Exit|" + - "End"), myReporter.wholeStory()) -} - -func TestEmbeddedAssertionReported(t *testing.T) { - myReporter, test := setupFakeReporter() - - Convey("A", test, func(c C) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - c.So(r.FormValue("msg"), ShouldEqual, "ping") - })) - http.DefaultClient.Get(ts.URL + "?msg=ping") - }) - - expectEqual(t, "Begin|A|Success|Exit|End", myReporter.wholeStory()) -} - -func TestEmbeddedContextHelperReported(t *testing.T) { - myReporter, test := setupFakeReporter() - - helper := func(c C) http.HandlerFunc { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - c.Convey("Embedded", func() { - So(r.FormValue("msg"), ShouldEqual, "ping") - }) - }) - } - - Convey("A", test, func(c C) { - ts := httptest.NewServer(helper(c)) - http.DefaultClient.Get(ts.URL + "?msg=ping") - }) - - expectEqual(t, "Begin|A|Embedded|Success|Exit|Exit|End", myReporter.wholeStory()) -} - -func expectEqual(t *testing.T, expected interface{}, actual interface{}) { - if expected != actual { - _, file, line, _ := runtime.Caller(1) - t.Errorf("Expected '%v' to be '%v' but it wasn't. See '%s' at line %d.", - actual, expected, path.Base(file), line) - } -} - -func setupFakeReporter() (*fakeReporter, *fakeGoTest) { - myReporter := new(fakeReporter) - myReporter.calls = []string{} - testReporter = myReporter - return myReporter, new(fakeGoTest) -} - -type fakeReporter struct { - calls []string -} - -func (self *fakeReporter) BeginStory(story *reporting.StoryReport) { - self.calls = append(self.calls, "Begin") -} - -func (self *fakeReporter) Enter(scope *reporting.ScopeReport) { - self.calls = append(self.calls, scope.Title) -} - -func (self *fakeReporter) Report(report *reporting.AssertionResult) { - if report.Error != nil { - self.calls = append(self.calls, "Error") - } else if report.Failure != "" { - message := "Failure" - if report.Expected != "" || report.Actual != "" { - message += fmt.Sprintf("(%s/%s)", report.Expected, report.Actual) - } - self.calls = append(self.calls, message) - } else if report.Skipped { - self.calls = append(self.calls, "Skipped") - } else { - self.calls = append(self.calls, "Success") - } -} - -func (self *fakeReporter) Exit() { - self.calls = append(self.calls, "Exit") -} - -func (self *fakeReporter) EndStory() { - self.calls = append(self.calls, "End") -} - -func (self *fakeReporter) Write(content []byte) (int, error) { - return len(content), nil // no-op -} - -func (self *fakeReporter) wholeStory() string { - return strings.Join(self.calls, "|") -} - -//////////////////////////////// - -type fakeGoTest struct{} - -func (self *fakeGoTest) Fail() {} -func (self *fakeGoTest) Fatalf(format string, args ...interface{}) {} - -var test t = new(fakeGoTest) diff --git a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/story_conventions_test.go b/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/story_conventions_test.go deleted file mode 100644 index ff3a4e6e7a0..00000000000 --- a/Godeps/_workspace/src/github.com/smartystreets/goconvey/convey/story_conventions_test.go +++ /dev/null @@ -1,184 +0,0 @@ -package convey - -import ( - "reflect" - "testing" -) - -func expectPanic(t *testing.T, f string) interface{} { - r := recover() - if r != nil { - if cp, ok := r.(*conveyErr); ok { - if cp.fmt != f { - t.Error("Incorrect panic message.") - } - } else { - t.Errorf("Incorrect panic type. %s", reflect.TypeOf(r)) - } - } else { - t.Error("Expected panic but none occured") - } - return r -} - -func TestMissingTopLevelGoTestReferenceCausesPanic(t *testing.T) { - output := map[string]bool{} - - defer expectEqual(t, false, output["good"]) - defer expectPanic(t, missingGoTest) - - Convey("Hi", func() { - output["bad"] = true // this shouldn't happen - }) -} - -func requireGoTestReference(t *testing.T) { - err := recover() - if err == nil { - t.Error("We should have recovered a panic here (because of a missing *testing.T reference)!") - } else { - expectEqual(t, missingGoTest, err) - } -} - -func TestMissingTopLevelGoTestReferenceAfterGoodExample(t *testing.T) { - output := map[string]bool{} - - defer func() { - expectEqual(t, true, output["good"]) - expectEqual(t, false, output["bad"]) - }() - defer expectPanic(t, missingGoTest) - - Convey("Good example", t, func() { - output["good"] = true - }) - - Convey("Bad example", func() { - output["bad"] = true // shouldn't happen - }) -} - -func TestExtraReferencePanics(t *testing.T) { - output := map[string]bool{} - - defer expectEqual(t, false, output["bad"]) - defer expectPanic(t, extraGoTest) - - Convey("Good example", t, func() { - Convey("Bad example - passing in *testing.T a second time!", t, func() { - output["bad"] = true // shouldn't happen - }) - }) -} - -func TestParseRegistrationMissingRequiredElements(t *testing.T) { - defer expectPanic(t, parseError) - - Convey() -} - -func TestParseRegistration_MissingNameString(t *testing.T) { - defer expectPanic(t, parseError) - - Convey(func() {}) -} - -func TestParseRegistration_MissingActionFunc(t *testing.T) { - defer expectPanic(t, parseError) - - Convey("Hi there", 12345) -} - -func TestFailureModeNoContext(t *testing.T) { - Convey("Foo", t, func() { - done := make(chan int, 1) - go func() { - defer func() { done <- 1 }() - defer expectPanic(t, noStackContext) - So(len("I have no context"), ShouldBeGreaterThan, 0) - }() - <-done - }) -} - -func TestFailureModeDuplicateSuite(t *testing.T) { - Convey("cool", t, func() { - defer expectPanic(t, multipleIdenticalConvey) - - Convey("dup", nil) - Convey("dup", nil) - }) -} - -func TestFailureModeIndeterminentSuiteNames(t *testing.T) { - defer expectPanic(t, differentConveySituations) - - name := "bob" - Convey("cool", t, func() { - for i := 0; i < 3; i++ { - Convey(name, func() {}) - name += "bob" - } - }) -} - -func TestFailureModeNestedIndeterminentSuiteNames(t *testing.T) { - defer expectPanic(t, differentConveySituations) - - name := "bob" - Convey("cool", t, func() { - Convey("inner", func() { - for i := 0; i < 3; i++ { - Convey(name, func() {}) - name += "bob" - } - }) - }) -} - -func TestFailureModeParameterButMissing(t *testing.T) { - defer expectPanic(t, parseError) - - prepare() - - Convey("Foobar", t, FailureHalts) -} - -func TestFailureModeParameterWithAction(t *testing.T) { - prepare() - - Convey("Foobar", t, FailureHalts, func() {}) -} - -func TestExtraConveyParameters(t *testing.T) { - defer expectPanic(t, parseError) - - prepare() - - Convey("Foobar", t, FailureHalts, func() {}, "This is not supposed to be here") -} - -func TestExtraConveyParameters2(t *testing.T) { - defer expectPanic(t, parseError) - - prepare() - - Convey("Foobar", t, func() {}, "This is not supposed to be here") -} - -func TestExtraConveyParameters3(t *testing.T) { - defer expectPanic(t, parseError) - - output := prepare() - - Convey("A", t, func() { - output += "A " - - Convey("B", func() { - output += "B " - }, "This is not supposed to be here") - }) - - expectEqual(t, "A ", output) -} diff --git a/Godeps/_workspace/src/gopkg.in/ini.v1/.gitignore b/Godeps/_workspace/src/gopkg.in/ini.v1/.gitignore deleted file mode 100644 index 53b64215a3b..00000000000 --- a/Godeps/_workspace/src/gopkg.in/ini.v1/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -testdata/conf_out.ini -ini.sublime-project -ini.sublime-workspace diff --git a/Godeps/_workspace/src/gopkg.in/ini.v1/ini.go b/Godeps/_workspace/src/gopkg.in/ini.v1/ini.go deleted file mode 100644 index 6674baf0b00..00000000000 --- a/Godeps/_workspace/src/gopkg.in/ini.v1/ini.go +++ /dev/null @@ -1,1017 +0,0 @@ -// Copyright 2014 Unknwon -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -// Package ini provides INI file read and write functionality in Go. -package ini - -import ( - "bufio" - "bytes" - "errors" - "fmt" - "io" - "os" - "regexp" - "runtime" - "strconv" - "strings" - "sync" - "time" -) - -const ( - DEFAULT_SECTION = "DEFAULT" - // Maximum allowed depth when recursively substituing variable names. - _DEPTH_VALUES = 99 - - _VERSION = "1.2.6" -) - -func Version() string { - return _VERSION -} - -var ( - LineBreak = "\n" - - // Variable regexp pattern: %(variable)s - varPattern = regexp.MustCompile(`%\(([^\)]+)\)s`) - - // Write spaces around "=" to look better. - PrettyFormat = true -) - -func init() { - if runtime.GOOS == "windows" { - LineBreak = "\r\n" - } -} - -func inSlice(str string, s []string) bool { - for _, v := range s { - if str == v { - return true - } - } - return false -} - -// dataSource is a interface that returns file content. -type dataSource interface { - Reader() (io.Reader, error) -} - -type sourceFile struct { - name string -} - -func (s sourceFile) Reader() (io.Reader, error) { - return os.Open(s.name) -} - -type sourceData struct { - data []byte -} - -func (s *sourceData) Reader() (io.Reader, error) { - return bytes.NewReader(s.data), nil -} - -// ____ __. -// | |/ _|____ ___.__. -// | <_/ __ < | | -// | | \ ___/\___ | -// |____|__ \___ > ____| -// \/ \/\/ - -// Key represents a key under a section. -type Key struct { - s *Section - Comment string - name string - value string - isAutoIncr bool -} - -// Name returns name of key. -func (k *Key) Name() string { - return k.name -} - -// Value returns raw value of key for performance purpose. -func (k *Key) Value() string { - return k.value -} - -// String returns string representation of value. -func (k *Key) String() string { - val := k.value - if strings.Index(val, "%") == -1 { - return val - } - - for i := 0; i < _DEPTH_VALUES; i++ { - vr := varPattern.FindString(val) - if len(vr) == 0 { - break - } - - // Take off leading '%(' and trailing ')s'. - noption := strings.TrimLeft(vr, "%(") - noption = strings.TrimRight(noption, ")s") - - // Search in the same section. - nk, err := k.s.GetKey(noption) - if err != nil { - // Search again in default section. - nk, _ = k.s.f.Section("").GetKey(noption) - } - - // Substitute by new value and take off leading '%(' and trailing ')s'. - val = strings.Replace(val, vr, nk.value, -1) - } - return val -} - -// parseBool returns the boolean value represented by the string. -// -// It accepts 1, t, T, TRUE, true, True, YES, yes, Yes, ON, on, On, -// 0, f, F, FALSE, false, False, NO, no, No, OFF, off, Off. -// Any other value returns an error. -func parseBool(str string) (value bool, err error) { - switch str { - case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "ON", "on", "On": - return true, nil - case "0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "OFF", "off", "Off": - return false, nil - } - return false, fmt.Errorf("parsing \"%s\": invalid syntax", str) -} - -// Bool returns bool type value. -func (k *Key) Bool() (bool, error) { - return parseBool(k.String()) -} - -// Float64 returns float64 type value. -func (k *Key) Float64() (float64, error) { - return strconv.ParseFloat(k.String(), 64) -} - -// Int returns int type value. -func (k *Key) Int() (int, error) { - return strconv.Atoi(k.String()) -} - -// Int64 returns int64 type value. -func (k *Key) Int64() (int64, error) { - return strconv.ParseInt(k.String(), 10, 64) -} - -// TimeFormat parses with given format and returns time.Time type value. -func (k *Key) TimeFormat(format string) (time.Time, error) { - return time.Parse(format, k.String()) -} - -// Time parses with RFC3339 format and returns time.Time type value. -func (k *Key) Time() (time.Time, error) { - return k.TimeFormat(time.RFC3339) -} - -// MustString returns default value if key value is empty. -func (k *Key) MustString(defaultVal string) string { - val := k.String() - if len(val) == 0 { - return defaultVal - } - return val -} - -// MustBool always returns value without error, -// it returns false if error occurs. -func (k *Key) MustBool(defaultVal ...bool) bool { - val, err := k.Bool() - if len(defaultVal) > 0 && err != nil { - return defaultVal[0] - } - return val -} - -// MustFloat64 always returns value without error, -// it returns 0.0 if error occurs. -func (k *Key) MustFloat64(defaultVal ...float64) float64 { - val, err := k.Float64() - if len(defaultVal) > 0 && err != nil { - return defaultVal[0] - } - return val -} - -// MustInt always returns value without error, -// it returns 0 if error occurs. -func (k *Key) MustInt(defaultVal ...int) int { - val, err := k.Int() - if len(defaultVal) > 0 && err != nil { - return defaultVal[0] - } - return val -} - -// MustInt64 always returns value without error, -// it returns 0 if error occurs. -func (k *Key) MustInt64(defaultVal ...int64) int64 { - val, err := k.Int64() - if len(defaultVal) > 0 && err != nil { - return defaultVal[0] - } - return val -} - -// MustTimeFormat always parses with given format and returns value without error, -// it returns zero value if error occurs. -func (k *Key) MustTimeFormat(format string, defaultVal ...time.Time) time.Time { - val, err := k.TimeFormat(format) - if len(defaultVal) > 0 && err != nil { - return defaultVal[0] - } - return val -} - -// MustTime always parses with RFC3339 format and returns value without error, -// it returns zero value if error occurs. -func (k *Key) MustTime(defaultVal ...time.Time) time.Time { - return k.MustTimeFormat(time.RFC3339, defaultVal...) -} - -// In always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) In(defaultVal string, candidates []string) string { - val := k.String() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InFloat64 always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InFloat64(defaultVal float64, candidates []float64) float64 { - val := k.MustFloat64() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InInt always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InInt(defaultVal int, candidates []int) int { - val := k.MustInt() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InInt64 always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InInt64(defaultVal int64, candidates []int64) int64 { - val := k.MustInt64() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InTimeFormat always parses with given format and returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InTimeFormat(format string, defaultVal time.Time, candidates []time.Time) time.Time { - val := k.MustTimeFormat(format) - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InTime always parses with RFC3339 format and returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InTime(defaultVal time.Time, candidates []time.Time) time.Time { - return k.InTimeFormat(time.RFC3339, defaultVal, candidates) -} - -// RangeFloat64 checks if value is in given range inclusively, -// and returns default value if it's not. -func (k *Key) RangeFloat64(defaultVal, min, max float64) float64 { - val := k.MustFloat64() - if val < min || val > max { - return defaultVal - } - return val -} - -// RangeInt checks if value is in given range inclusively, -// and returns default value if it's not. -func (k *Key) RangeInt(defaultVal, min, max int) int { - val := k.MustInt() - if val < min || val > max { - return defaultVal - } - return val -} - -// RangeInt64 checks if value is in given range inclusively, -// and returns default value if it's not. -func (k *Key) RangeInt64(defaultVal, min, max int64) int64 { - val := k.MustInt64() - if val < min || val > max { - return defaultVal - } - return val -} - -// RangeTimeFormat checks if value with given format is in given range inclusively, -// and returns default value if it's not. -func (k *Key) RangeTimeFormat(format string, defaultVal, min, max time.Time) time.Time { - val := k.MustTimeFormat(format) - if val.Unix() < min.Unix() || val.Unix() > max.Unix() { - return defaultVal - } - return val -} - -// RangeTime checks if value with RFC3339 format is in given range inclusively, -// and returns default value if it's not. -func (k *Key) RangeTime(defaultVal, min, max time.Time) time.Time { - return k.RangeTimeFormat(time.RFC3339, defaultVal, min, max) -} - -// Strings returns list of string devide by given delimiter. -func (k *Key) Strings(delim string) []string { - str := k.String() - if len(str) == 0 { - return []string{} - } - - vals := strings.Split(str, delim) - for i := range vals { - vals[i] = strings.TrimSpace(vals[i]) - } - return vals -} - -// Float64s returns list of float64 devide by given delimiter. -func (k *Key) Float64s(delim string) []float64 { - strs := k.Strings(delim) - vals := make([]float64, len(strs)) - for i := range strs { - vals[i], _ = strconv.ParseFloat(strs[i], 64) - } - return vals -} - -// Ints returns list of int devide by given delimiter. -func (k *Key) Ints(delim string) []int { - strs := k.Strings(delim) - vals := make([]int, len(strs)) - for i := range strs { - vals[i], _ = strconv.Atoi(strs[i]) - } - return vals -} - -// Int64s returns list of int64 devide by given delimiter. -func (k *Key) Int64s(delim string) []int64 { - strs := k.Strings(delim) - vals := make([]int64, len(strs)) - for i := range strs { - vals[i], _ = strconv.ParseInt(strs[i], 10, 64) - } - return vals -} - -// TimesFormat parses with given format and returns list of time.Time devide by given delimiter. -func (k *Key) TimesFormat(format, delim string) []time.Time { - strs := k.Strings(delim) - vals := make([]time.Time, len(strs)) - for i := range strs { - vals[i], _ = time.Parse(format, strs[i]) - } - return vals -} - -// Times parses with RFC3339 format and returns list of time.Time devide by given delimiter. -func (k *Key) Times(delim string) []time.Time { - return k.TimesFormat(time.RFC3339, delim) -} - -// SetValue changes key value. -func (k *Key) SetValue(v string) { - k.value = v -} - -// _________ __ .__ -// / _____/ ____ _____/ |_|__| ____ ____ -// \_____ \_/ __ \_/ ___\ __\ |/ _ \ / \ -// / \ ___/\ \___| | | ( <_> ) | \ -// /_______ /\___ >\___ >__| |__|\____/|___| / -// \/ \/ \/ \/ - -// Section represents a config section. -type Section struct { - f *File - Comment string - name string - keys map[string]*Key - keyList []string - keysHash map[string]string -} - -func newSection(f *File, name string) *Section { - return &Section{f, "", name, make(map[string]*Key), make([]string, 0, 10), make(map[string]string)} -} - -// Name returns name of Section. -func (s *Section) Name() string { - return s.name -} - -// NewKey creates a new key to given section. -func (s *Section) NewKey(name, val string) (*Key, error) { - if len(name) == 0 { - return nil, errors.New("error creating new key: empty key name") - } - - if s.f.BlockMode { - s.f.lock.Lock() - defer s.f.lock.Unlock() - } - - if inSlice(name, s.keyList) { - s.keys[name].value = val - return s.keys[name], nil - } - - s.keyList = append(s.keyList, name) - s.keys[name] = &Key{s, "", name, val, false} - s.keysHash[name] = val - return s.keys[name], nil -} - -// GetKey returns key in section by given name. -func (s *Section) GetKey(name string) (*Key, error) { - // FIXME: change to section level lock? - if s.f.BlockMode { - s.f.lock.RLock() - defer s.f.lock.RUnlock() - } - - key := s.keys[name] - if key == nil { - // Check if it is a child-section. - if i := strings.LastIndex(s.name, "."); i > -1 { - return s.f.Section(s.name[:i]).GetKey(name) - } - return nil, fmt.Errorf("error when getting key of section '%s': key '%s' not exists", s.name, name) - } - return key, nil -} - -// Key assumes named Key exists in section and returns a zero-value when not. -func (s *Section) Key(name string) *Key { - key, err := s.GetKey(name) - if err != nil { - // It's OK here because the only possible error is empty key name, - // but if it's empty, this piece of code won't be executed. - key, _ = s.NewKey(name, "") - return key - } - return key -} - -// Keys returns list of keys of section. -func (s *Section) Keys() []*Key { - keys := make([]*Key, len(s.keyList)) - for i := range s.keyList { - keys[i] = s.Key(s.keyList[i]) - } - return keys -} - -// KeyStrings returns list of key names of section. -func (s *Section) KeyStrings() []string { - list := make([]string, len(s.keyList)) - copy(list, s.keyList) - return list -} - -// KeysHash returns keys hash consisting of names and values. -func (s *Section) KeysHash() map[string]string { - if s.f.BlockMode { - s.f.lock.RLock() - defer s.f.lock.RUnlock() - } - - hash := map[string]string{} - for key, value := range s.keysHash { - hash[key] = value - } - return hash -} - -// DeleteKey deletes a key from section. -func (s *Section) DeleteKey(name string) { - if s.f.BlockMode { - s.f.lock.Lock() - defer s.f.lock.Unlock() - } - - for i, k := range s.keyList { - if k == name { - s.keyList = append(s.keyList[:i], s.keyList[i+1:]...) - delete(s.keys, name) - return - } - } -} - -// ___________.__.__ -// \_ _____/|__| | ____ -// | __) | | | _/ __ \ -// | \ | | |_\ ___/ -// \___ / |__|____/\___ > -// \/ \/ - -// File represents a combination of a or more INI file(s) in memory. -type File struct { - // Should make things safe, but sometimes doesn't matter. - BlockMode bool - // Make sure data is safe in multiple goroutines. - lock sync.RWMutex - - // Allow combination of multiple data sources. - dataSources []dataSource - // Actual data is stored here. - sections map[string]*Section - - // To keep data in order. - sectionList []string - - NameMapper -} - -// newFile initializes File object with given data sources. -func newFile(dataSources []dataSource) *File { - return &File{ - BlockMode: true, - dataSources: dataSources, - sections: make(map[string]*Section), - sectionList: make([]string, 0, 10), - } -} - -func parseDataSource(source interface{}) (dataSource, error) { - switch s := source.(type) { - case string: - return sourceFile{s}, nil - case []byte: - return &sourceData{s}, nil - default: - return nil, fmt.Errorf("error parsing data source: unknown type '%s'", s) - } -} - -// Load loads and parses from INI data sources. -// Arguments can be mixed of file name with string type, or raw data in []byte. -func Load(source interface{}, others ...interface{}) (_ *File, err error) { - sources := make([]dataSource, len(others)+1) - sources[0], err = parseDataSource(source) - if err != nil { - return nil, err - } - for i := range others { - sources[i+1], err = parseDataSource(others[i]) - if err != nil { - return nil, err - } - } - f := newFile(sources) - return f, f.Reload() -} - -// Empty returns an empty file object. -func Empty() *File { - // Ignore error here, we sure our data is good. - f, _ := Load([]byte("")) - return f -} - -// NewSection creates a new section. -func (f *File) NewSection(name string) (*Section, error) { - if len(name) == 0 { - return nil, errors.New("error creating new section: empty section name") - } - - if f.BlockMode { - f.lock.Lock() - defer f.lock.Unlock() - } - - if inSlice(name, f.sectionList) { - return f.sections[name], nil - } - - f.sectionList = append(f.sectionList, name) - f.sections[name] = newSection(f, name) - return f.sections[name], nil -} - -// NewSections creates a list of sections. -func (f *File) NewSections(names ...string) (err error) { - for _, name := range names { - if _, err = f.NewSection(name); err != nil { - return err - } - } - return nil -} - -// GetSection returns section by given name. -func (f *File) GetSection(name string) (*Section, error) { - if len(name) == 0 { - name = DEFAULT_SECTION - } - - if f.BlockMode { - f.lock.RLock() - defer f.lock.RUnlock() - } - - sec := f.sections[name] - if sec == nil { - return nil, fmt.Errorf("error when getting section: section '%s' not exists", name) - } - return sec, nil -} - -// Section assumes named section exists and returns a zero-value when not. -func (f *File) Section(name string) *Section { - sec, err := f.GetSection(name) - if err != nil { - // It's OK here because the only possible error is empty section name, - // but if it's empty, this piece of code won't be executed. - sec, _ = f.NewSection(name) - return sec - } - return sec -} - -// Section returns list of Section. -func (f *File) Sections() []*Section { - sections := make([]*Section, len(f.sectionList)) - for i := range f.sectionList { - sections[i] = f.Section(f.sectionList[i]) - } - return sections -} - -// SectionStrings returns list of section names. -func (f *File) SectionStrings() []string { - list := make([]string, len(f.sectionList)) - copy(list, f.sectionList) - return list -} - -// DeleteSection deletes a section. -func (f *File) DeleteSection(name string) { - if f.BlockMode { - f.lock.Lock() - defer f.lock.Unlock() - } - - if len(name) == 0 { - name = DEFAULT_SECTION - } - - for i, s := range f.sectionList { - if s == name { - f.sectionList = append(f.sectionList[:i], f.sectionList[i+1:]...) - delete(f.sections, name) - return - } - } -} - -func cutComment(str string) string { - i := strings.Index(str, "#") - if i == -1 { - return str - } - return str[:i] -} - -// parse parses data through an io.Reader. -func (f *File) parse(reader io.Reader) error { - buf := bufio.NewReader(reader) - - // Handle BOM-UTF8. - // http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding - mask, err := buf.Peek(3) - if err == nil && len(mask) >= 3 && mask[0] == 239 && mask[1] == 187 && mask[2] == 191 { - buf.Read(mask) - } - - count := 1 - comments := "" - isEnd := false - - section, err := f.NewSection(DEFAULT_SECTION) - if err != nil { - return err - } - - for { - line, err := buf.ReadString('\n') - line = strings.TrimSpace(line) - length := len(line) - - // Check error and ignore io.EOF just for a moment. - if err != nil { - if err != io.EOF { - return fmt.Errorf("error reading next line: %v", err) - } - // The last line of file could be an empty line. - if length == 0 { - break - } - isEnd = true - } - - // Skip empty lines. - if length == 0 { - continue - } - - switch { - case line[0] == '#' || line[0] == ';': // Comments. - if len(comments) == 0 { - comments = line - } else { - comments += LineBreak + line - } - continue - case line[0] == '[' && line[length-1] == ']': // New sction. - name := strings.TrimSpace(line[1 : length-1]) - section, err = f.NewSection(name) - if err != nil { - return err - } - - if len(comments) > 0 { - section.Comment = comments - comments = "" - } - // Reset counter. - count = 1 - continue - } - - // Other possibilities. - var ( - i int - keyQuote string - kname string - valQuote string - val string - ) - - // Key name surrounded by quotes. - if line[0] == '"' { - if length > 6 && line[0:3] == `"""` { - keyQuote = `"""` - } else { - keyQuote = `"` - } - } else if line[0] == '`' { - keyQuote = "`" - } - if len(keyQuote) > 0 { - qLen := len(keyQuote) - pos := strings.Index(line[qLen:], keyQuote) - if pos == -1 { - return fmt.Errorf("error parsing line: missing closing key quote: %s", line) - } - pos = pos + qLen - i = strings.IndexAny(line[pos:], "=:") - if i < 0 { - return fmt.Errorf("error parsing line: key-value delimiter not found: %s", line) - } else if i == pos { - return fmt.Errorf("error parsing line: key is empty: %s", line) - } - i = i + pos - kname = line[qLen:pos] // Just keep spaces inside quotes. - } else { - i = strings.IndexAny(line, "=:") - if i < 0 { - return fmt.Errorf("error parsing line: key-value delimiter not found: %s", line) - } else if i == 0 { - return fmt.Errorf("error parsing line: key is empty: %s", line) - } - kname = strings.TrimSpace(line[0:i]) - } - - isAutoIncr := false - // Auto increment. - if kname == "-" { - isAutoIncr = true - kname = "#" + fmt.Sprint(count) - count++ - } - - lineRight := strings.TrimSpace(line[i+1:]) - lineRightLength := len(lineRight) - firstChar := "" - if lineRightLength >= 2 { - firstChar = lineRight[0:1] - } - if firstChar == "`" { - valQuote = "`" - } else if lineRightLength >= 6 && lineRight[0:3] == `"""` { - valQuote = `"""` - } - if len(valQuote) > 0 { - qLen := len(valQuote) - pos := strings.LastIndex(lineRight[qLen:], valQuote) - // For multiple lines value. - if pos == -1 { - isEnd := false - val = lineRight[qLen:] + "\n" - for { - next, err := buf.ReadString('\n') - if err != nil { - if err != io.EOF { - return err - } - isEnd = true - } - pos = strings.LastIndex(next, valQuote) - if pos > -1 { - val += next[:pos] - break - } - val += next - if isEnd { - return fmt.Errorf("error parsing line: missing closing key quote from '%s' to '%s'", line, next) - } - } - } else { - val = lineRight[qLen : pos+qLen] - } - } else { - val = strings.TrimSpace(cutComment(lineRight[0:])) - } - - k, err := section.NewKey(kname, val) - if err != nil { - return err - } - k.isAutoIncr = isAutoIncr - if len(comments) > 0 { - k.Comment = comments - comments = "" - } - - if isEnd { - break - } - } - return nil -} - -// Reload reloads and parses all data sources. -func (f *File) Reload() error { - for _, s := range f.dataSources { - r, err := s.Reader() - if err != nil { - return err - } - if err = f.parse(r); err != nil { - return err - } - } - return nil -} - -// Append appends one or more data sources and reloads automatically. -func (f *File) Append(source interface{}, others ...interface{}) error { - ds, err := parseDataSource(source) - if err != nil { - return err - } - f.dataSources = append(f.dataSources, ds) - for _, s := range others { - ds, err = parseDataSource(s) - if err != nil { - return err - } - f.dataSources = append(f.dataSources, ds) - } - return f.Reload() -} - -// SaveTo writes content to filesystem. -func (f *File) SaveTo(filename string) (err error) { - equalSign := "=" - if PrettyFormat { - equalSign = " = " - } - - // Use buffer to make sure target is safe until finish encoding. - buf := bytes.NewBuffer(nil) - for i, sname := range f.sectionList { - sec := f.Section(sname) - if len(sec.Comment) > 0 { - if sec.Comment[0] != '#' && sec.Comment[0] != ';' { - sec.Comment = "; " + sec.Comment - } - if _, err = buf.WriteString(sec.Comment + LineBreak); err != nil { - return err - } - } - - if i > 0 { - if _, err = buf.WriteString("[" + sname + "]" + LineBreak); err != nil { - return err - } - } else { - // Write nothing if default section is empty. - if len(sec.keyList) == 0 { - continue - } - } - - for _, kname := range sec.keyList { - key := sec.Key(kname) - if len(key.Comment) > 0 { - if key.Comment[0] != '#' && key.Comment[0] != ';' { - key.Comment = "; " + key.Comment - } - if _, err = buf.WriteString(key.Comment + LineBreak); err != nil { - return err - } - } - - switch { - case key.isAutoIncr: - kname = "-" - case strings.Contains(kname, "`") || strings.Contains(kname, `"`): - kname = `"""` + kname + `"""` - case strings.Contains(kname, `=`) || strings.Contains(kname, `:`): - kname = "`" + kname + "`" - } - - val := key.value - // In case key value contains "\n", "`" or "\"". - if strings.Contains(val, "\n") || strings.Contains(val, "`") || strings.Contains(val, `"`) { - val = `"""` + val + `"""` - } - if _, err = buf.WriteString(kname + equalSign + val + LineBreak); err != nil { - return err - } - } - - // Put a line between sections. - if _, err = buf.WriteString(LineBreak); err != nil { - return err - } - } - - fw, err := os.Create(filename) - if err != nil { - return err - } - if _, err = buf.WriteTo(fw); err != nil { - return err - } - return fw.Close() -} diff --git a/Godeps/_workspace/src/gopkg.in/ini.v1/ini_test.go b/Godeps/_workspace/src/gopkg.in/ini.v1/ini_test.go deleted file mode 100644 index c6daf81ca52..00000000000 --- a/Godeps/_workspace/src/gopkg.in/ini.v1/ini_test.go +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright 2014 Unknwon -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package ini - -import ( - "fmt" - "strings" - "testing" - "time" - - . "github.com/smartystreets/goconvey/convey" -) - -func Test_Version(t *testing.T) { - Convey("Get version", t, func() { - So(Version(), ShouldEqual, _VERSION) - }) -} - -const _CONF_DATA = ` -; Package name -NAME = ini -; Package version -VERSION = v1 -; Package import path -IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s - -# Information about package author -# Bio can be written in multiple lines. -[author] -NAME = Unknwon # Succeeding comment -E-MAIL = fake@localhost -GITHUB = https://github.com/%(NAME)s -BIO = """Gopher. -Coding addict. -Good man. -""" # Succeeding comment - -[package] -CLONE_URL = https://%(IMPORT_PATH)s - -[package.sub] -UNUSED_KEY = should be deleted - -[features] --: Support read/write comments of keys and sections --: Support auto-increment of key names --: Support load multiple files to overwrite key values - -[types] -STRING = str -BOOL = true -BOOL_FALSE = false -FLOAT64 = 1.25 -INT = 10 -TIME = 2015-01-01T20:17:05Z - -[array] -STRINGS = en, zh, de -FLOAT64S = 1.1, 2.2, 3.3 -INTS = 1, 2, 3 -TIMES = 2015-01-01T20:17:05Z,2015-01-01T20:17:05Z,2015-01-01T20:17:05Z - -[note] - -[advance] -true = """"2+3=5"""" -"1+1=2" = true -"""6+1=7""" = true -"""` + "`" + `5+5` + "`" + `""" = 10 -""""6+6"""" = 12 -` + "`" + `7-2=4` + "`" + ` = false -ADDRESS = ` + "`" + `404 road, -NotFound, State, 50000` + "`" - -func Test_Load(t *testing.T) { - Convey("Load from data sources", t, func() { - - Convey("Load with empty data", func() { - So(Empty(), ShouldNotBeNil) - }) - - Convey("Load with multiple data sources", func() { - cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini") - So(err, ShouldBeNil) - So(cfg, ShouldNotBeNil) - }) - }) - - Convey("Bad load process", t, func() { - - Convey("Load from invalid data sources", func() { - _, err := Load(_CONF_DATA) - So(err, ShouldNotBeNil) - - _, err = Load("testdata/404.ini") - So(err, ShouldNotBeNil) - - _, err = Load(1) - So(err, ShouldNotBeNil) - - _, err = Load([]byte(""), 1) - So(err, ShouldNotBeNil) - }) - - Convey("Load with empty section name", func() { - _, err := Load([]byte("[]")) - So(err, ShouldNotBeNil) - }) - - Convey("Load with bad keys", func() { - _, err := Load([]byte(`"""name`)) - So(err, ShouldNotBeNil) - - _, err = Load([]byte(`"""name"""`)) - So(err, ShouldNotBeNil) - - _, err = Load([]byte(`""=1`)) - So(err, ShouldNotBeNil) - - _, err = Load([]byte(`=`)) - So(err, ShouldNotBeNil) - - _, err = Load([]byte(`name`)) - So(err, ShouldNotBeNil) - }) - - Convey("Load with bad values", func() { - _, err := Load([]byte(`name="""Unknwon`)) - So(err, ShouldNotBeNil) - }) - }) -} - -func Test_Values(t *testing.T) { - Convey("Test getting and setting values", t, func() { - cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini") - So(err, ShouldBeNil) - So(cfg, ShouldNotBeNil) - - Convey("Get values in default section", func() { - sec := cfg.Section("") - So(sec, ShouldNotBeNil) - So(sec.Key("NAME").Value(), ShouldEqual, "ini") - So(sec.Key("NAME").String(), ShouldEqual, "ini") - So(sec.Key("NAME").Comment, ShouldEqual, "; Package name") - So(sec.Key("IMPORT_PATH").String(), ShouldEqual, "gopkg.in/ini.v1") - }) - - Convey("Get values in non-default section", func() { - sec := cfg.Section("author") - So(sec, ShouldNotBeNil) - So(sec.Key("NAME").String(), ShouldEqual, "Unknwon") - So(sec.Key("GITHUB").String(), ShouldEqual, "https://github.com/Unknwon") - - sec = cfg.Section("package") - So(sec, ShouldNotBeNil) - So(sec.Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1") - }) - - Convey("Get auto-increment key names", func() { - keys := cfg.Section("features").Keys() - for i, k := range keys { - So(k.Name(), ShouldEqual, fmt.Sprintf("#%d", i+1)) - } - }) - - Convey("Get overwrite value", func() { - So(cfg.Section("author").Key("E-MAIL").String(), ShouldEqual, "u@gogs.io") - }) - - Convey("Get sections", func() { - sections := cfg.Sections() - for i, name := range []string{DEFAULT_SECTION, "author", "package", "package.sub", "features", "types", "array", "note", "advance"} { - So(sections[i].Name(), ShouldEqual, name) - } - }) - - Convey("Get parent section value", func() { - So(cfg.Section("package.sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1") - }) - - Convey("Get multiple line value", func() { - So(cfg.Section("author").Key("BIO").String(), ShouldEqual, "Gopher.\nCoding addict.\nGood man.\n") - }) - - Convey("Get values with type", func() { - sec := cfg.Section("types") - v1, err := sec.Key("BOOL").Bool() - So(err, ShouldBeNil) - So(v1, ShouldBeTrue) - - v1, err = sec.Key("BOOL_FALSE").Bool() - So(err, ShouldBeNil) - So(v1, ShouldBeFalse) - - v2, err := sec.Key("FLOAT64").Float64() - So(err, ShouldBeNil) - So(v2, ShouldEqual, 1.25) - - v3, err := sec.Key("INT").Int() - So(err, ShouldBeNil) - So(v3, ShouldEqual, 10) - - v4, err := sec.Key("INT").Int64() - So(err, ShouldBeNil) - So(v4, ShouldEqual, 10) - - t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z") - So(err, ShouldBeNil) - v5, err := sec.Key("TIME").Time() - So(err, ShouldBeNil) - So(v5.String(), ShouldEqual, t.String()) - - Convey("Must get values with type", func() { - So(sec.Key("STRING").MustString("404"), ShouldEqual, "str") - So(sec.Key("BOOL").MustBool(), ShouldBeTrue) - So(sec.Key("FLOAT64").MustFloat64(), ShouldEqual, 1.25) - So(sec.Key("INT").MustInt(), ShouldEqual, 10) - So(sec.Key("INT").MustInt64(), ShouldEqual, 10) - So(sec.Key("TIME").MustTime().String(), ShouldEqual, t.String()) - - Convey("Must get values with default value", func() { - So(sec.Key("STRING_404").MustString("404"), ShouldEqual, "404") - So(sec.Key("BOOL_404").MustBool(true), ShouldBeTrue) - So(sec.Key("FLOAT64_404").MustFloat64(2.5), ShouldEqual, 2.5) - So(sec.Key("INT_404").MustInt(15), ShouldEqual, 15) - So(sec.Key("INT_404").MustInt64(15), ShouldEqual, 15) - - t, err := time.Parse(time.RFC3339, "2014-01-01T20:17:05Z") - So(err, ShouldBeNil) - So(sec.Key("TIME_404").MustTime(t).String(), ShouldEqual, t.String()) - }) - }) - }) - - Convey("Get value with candidates", func() { - sec := cfg.Section("types") - So(sec.Key("STRING").In("", []string{"str", "arr", "types"}), ShouldEqual, "str") - So(sec.Key("FLOAT64").InFloat64(0, []float64{1.25, 2.5, 3.75}), ShouldEqual, 1.25) - So(sec.Key("INT").InInt(0, []int{10, 20, 30}), ShouldEqual, 10) - So(sec.Key("INT").InInt64(0, []int64{10, 20, 30}), ShouldEqual, 10) - - zt, err := time.Parse(time.RFC3339, "0001-01-01T01:00:00Z") - So(err, ShouldBeNil) - t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z") - So(err, ShouldBeNil) - So(sec.Key("TIME").InTime(zt, []time.Time{t, time.Now(), time.Now().Add(1 * time.Second)}).String(), ShouldEqual, t.String()) - - Convey("Get value with candidates and default value", func() { - So(sec.Key("STRING_404").In("str", []string{"str", "arr", "types"}), ShouldEqual, "str") - So(sec.Key("FLOAT64_404").InFloat64(1.25, []float64{1.25, 2.5, 3.75}), ShouldEqual, 1.25) - So(sec.Key("INT_404").InInt(10, []int{10, 20, 30}), ShouldEqual, 10) - So(sec.Key("INT64_404").InInt64(10, []int64{10, 20, 30}), ShouldEqual, 10) - So(sec.Key("TIME_404").InTime(t, []time.Time{time.Now(), time.Now(), time.Now().Add(1 * time.Second)}).String(), ShouldEqual, t.String()) - }) - }) - - Convey("Get values in range", func() { - sec := cfg.Section("types") - So(sec.Key("FLOAT64").RangeFloat64(0, 1, 2), ShouldEqual, 1.25) - So(sec.Key("INT").RangeInt(0, 10, 20), ShouldEqual, 10) - So(sec.Key("INT").RangeInt64(0, 10, 20), ShouldEqual, 10) - - minT, err := time.Parse(time.RFC3339, "0001-01-01T01:00:00Z") - So(err, ShouldBeNil) - midT, err := time.Parse(time.RFC3339, "2013-01-01T01:00:00Z") - So(err, ShouldBeNil) - maxT, err := time.Parse(time.RFC3339, "9999-01-01T01:00:00Z") - So(err, ShouldBeNil) - t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z") - So(err, ShouldBeNil) - So(sec.Key("TIME").RangeTime(t, minT, maxT).String(), ShouldEqual, t.String()) - - Convey("Get value in range with default value", func() { - So(sec.Key("FLOAT64").RangeFloat64(5, 0, 1), ShouldEqual, 5) - So(sec.Key("INT").RangeInt(7, 0, 5), ShouldEqual, 7) - So(sec.Key("INT").RangeInt64(7, 0, 5), ShouldEqual, 7) - So(sec.Key("TIME").RangeTime(t, minT, midT).String(), ShouldEqual, t.String()) - }) - }) - - Convey("Get values into slice", func() { - sec := cfg.Section("array") - So(strings.Join(sec.Key("STRINGS").Strings(","), ","), ShouldEqual, "en,zh,de") - So(len(sec.Key("STRINGS_404").Strings(",")), ShouldEqual, 0) - - vals1 := sec.Key("FLOAT64S").Float64s(",") - for i, v := range []float64{1.1, 2.2, 3.3} { - So(vals1[i], ShouldEqual, v) - } - - vals2 := sec.Key("INTS").Ints(",") - for i, v := range []int{1, 2, 3} { - So(vals2[i], ShouldEqual, v) - } - - vals3 := sec.Key("INTS").Int64s(",") - for i, v := range []int64{1, 2, 3} { - So(vals3[i], ShouldEqual, v) - } - - t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z") - So(err, ShouldBeNil) - vals4 := sec.Key("TIMES").Times(",") - for i, v := range []time.Time{t, t, t} { - So(vals4[i].String(), ShouldEqual, v.String()) - } - }) - - Convey("Get key hash", func() { - cfg.Section("").KeysHash() - }) - - Convey("Set key value", func() { - k := cfg.Section("author").Key("NAME") - k.SetValue("无闻") - So(k.String(), ShouldEqual, "无闻") - }) - - Convey("Get key strings", func() { - So(strings.Join(cfg.Section("types").KeyStrings(), ","), ShouldEqual, "STRING,BOOL,BOOL_FALSE,FLOAT64,INT,TIME") - }) - - Convey("Delete a key", func() { - cfg.Section("package.sub").DeleteKey("UNUSED_KEY") - _, err := cfg.Section("package.sub").GetKey("UNUSED_KEY") - So(err, ShouldNotBeNil) - }) - - Convey("Get section strings", func() { - So(strings.Join(cfg.SectionStrings(), ","), ShouldEqual, "DEFAULT,author,package,package.sub,features,types,array,note,advance") - }) - - Convey("Delete a section", func() { - cfg.DeleteSection("") - So(cfg.SectionStrings()[0], ShouldNotEqual, DEFAULT_SECTION) - }) - - Convey("Create new sections", func() { - cfg.NewSections("test", "test2") - _, err := cfg.GetSection("test") - So(err, ShouldBeNil) - _, err = cfg.GetSection("test2") - So(err, ShouldBeNil) - }) - }) - - Convey("Test getting and setting bad values", t, func() { - cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini") - So(err, ShouldBeNil) - So(cfg, ShouldNotBeNil) - - Convey("Create new key with empty name", func() { - k, err := cfg.Section("").NewKey("", "") - So(err, ShouldNotBeNil) - So(k, ShouldBeNil) - }) - - Convey("Create new section with empty name", func() { - s, err := cfg.NewSection("") - So(err, ShouldNotBeNil) - So(s, ShouldBeNil) - }) - - Convey("Create new sections with empty name", func() { - So(cfg.NewSections(""), ShouldNotBeNil) - }) - - Convey("Get section that not exists", func() { - s, err := cfg.GetSection("404") - So(err, ShouldNotBeNil) - So(s, ShouldBeNil) - - s = cfg.Section("404") - So(s, ShouldNotBeNil) - }) - }) -} - -func Test_File_Append(t *testing.T) { - Convey("Append data sources", t, func() { - cfg, err := Load([]byte("")) - So(err, ShouldBeNil) - So(cfg, ShouldNotBeNil) - - So(cfg.Append([]byte(""), []byte("")), ShouldBeNil) - - Convey("Append bad data sources", func() { - So(cfg.Append(1), ShouldNotBeNil) - So(cfg.Append([]byte(""), 1), ShouldNotBeNil) - }) - }) -} - -func Test_File_SaveTo(t *testing.T) { - Convey("Save file", t, func() { - cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini") - So(err, ShouldBeNil) - So(cfg, ShouldNotBeNil) - - cfg.Section("").Key("NAME").Comment = "Package name" - cfg.Section("author").Comment = `Information about package author -# Bio can be written in multiple lines.` - So(cfg.SaveTo("testdata/conf_out.ini"), ShouldBeNil) - }) -} - -func Benchmark_Key_Value(b *testing.B) { - c, _ := Load([]byte(_CONF_DATA)) - for i := 0; i < b.N; i++ { - c.Section("").Key("NAME").Value() - } -} - -func Benchmark_Key_String(b *testing.B) { - c, _ := Load([]byte(_CONF_DATA)) - for i := 0; i < b.N; i++ { - c.Section("").Key("NAME").String() - } -} - -func Benchmark_Key_Value_NonBlock(b *testing.B) { - c, _ := Load([]byte(_CONF_DATA)) - c.BlockMode = false - for i := 0; i < b.N; i++ { - c.Section("").Key("NAME").Value() - } -} - -func Benchmark_Key_String_NonBlock(b *testing.B) { - c, _ := Load([]byte(_CONF_DATA)) - c.BlockMode = false - for i := 0; i < b.N; i++ { - c.Section("").Key("NAME").String() - } -} - -func Benchmark_Key_SetValue(b *testing.B) { - c, _ := Load([]byte(_CONF_DATA)) - for i := 0; i < b.N; i++ { - c.Section("").Key("NAME").SetValue("10") - } -} diff --git a/Godeps/_workspace/src/gopkg.in/ini.v1/struct.go b/Godeps/_workspace/src/gopkg.in/ini.v1/struct.go deleted file mode 100644 index 09ea816442b..00000000000 --- a/Godeps/_workspace/src/gopkg.in/ini.v1/struct.go +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright 2014 Unknwon -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package ini - -import ( - "errors" - "fmt" - "reflect" - "time" - "unicode" -) - -// NameMapper represents a ini tag name mapper. -type NameMapper func(string) string - -// Built-in name getters. -var ( - // AllCapsUnderscore converts to format ALL_CAPS_UNDERSCORE. - AllCapsUnderscore NameMapper = func(raw string) string { - newstr := make([]rune, 0, len(raw)) - for i, chr := range raw { - if isUpper := 'A' <= chr && chr <= 'Z'; isUpper { - if i > 0 { - newstr = append(newstr, '_') - } - } - newstr = append(newstr, unicode.ToUpper(chr)) - } - return string(newstr) - } - // TitleUnderscore converts to format title_underscore. - TitleUnderscore NameMapper = func(raw string) string { - newstr := make([]rune, 0, len(raw)) - for i, chr := range raw { - if isUpper := 'A' <= chr && chr <= 'Z'; isUpper { - if i > 0 { - newstr = append(newstr, '_') - } - chr -= ('A' - 'a') - } - newstr = append(newstr, chr) - } - return string(newstr) - } -) - -func (s *Section) parseFieldName(raw, actual string) string { - if len(actual) > 0 { - return actual - } - if s.f.NameMapper != nil { - return s.f.NameMapper(raw) - } - return raw -} - -func parseDelim(actual string) string { - if len(actual) > 0 { - return actual - } - return "," -} - -var reflectTime = reflect.TypeOf(time.Now()).Kind() - -// setWithProperType sets proper value to field based on its type, -// but it does not return error for failing parsing, -// because we want to use default value that is already assigned to strcut. -func setWithProperType(kind reflect.Kind, key *Key, field reflect.Value, delim string) error { - switch kind { - case reflect.String: - if len(key.String()) == 0 { - return nil - } - field.SetString(key.String()) - case reflect.Bool: - boolVal, err := key.Bool() - if err != nil { - return nil - } - field.SetBool(boolVal) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - intVal, err := key.Int64() - if err != nil { - return nil - } - field.SetInt(intVal) - case reflect.Float64: - floatVal, err := key.Float64() - if err != nil { - return nil - } - field.SetFloat(floatVal) - case reflectTime: - timeVal, err := key.Time() - if err != nil { - return nil - } - field.Set(reflect.ValueOf(timeVal)) - case reflect.Slice: - vals := key.Strings(delim) - numVals := len(vals) - if numVals == 0 { - return nil - } - - sliceOf := field.Type().Elem().Kind() - - var times []time.Time - if sliceOf == reflectTime { - times = key.Times(delim) - } - - slice := reflect.MakeSlice(field.Type(), numVals, numVals) - for i := 0; i < numVals; i++ { - switch sliceOf { - case reflectTime: - slice.Index(i).Set(reflect.ValueOf(times[i])) - default: - slice.Index(i).Set(reflect.ValueOf(vals[i])) - } - } - field.Set(slice) - default: - return fmt.Errorf("unsupported type '%s'", kind) - } - return nil -} - -func (s *Section) mapTo(val reflect.Value) error { - if val.Kind() == reflect.Ptr { - val = val.Elem() - } - typ := val.Type() - - for i := 0; i < typ.NumField(); i++ { - field := val.Field(i) - tpField := typ.Field(i) - - tag := tpField.Tag.Get("ini") - if tag == "-" { - continue - } - - fieldName := s.parseFieldName(tpField.Name, tag) - if len(fieldName) == 0 || !field.CanSet() { - continue - } - - if tpField.Type.Kind() == reflect.Struct { - if sec, err := s.f.GetSection(fieldName); err == nil { - if err = sec.mapTo(field); err != nil { - return fmt.Errorf("error mapping field(%s): %v", fieldName, err) - } - continue - } - } else if tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous { - field.Set(reflect.New(tpField.Type.Elem())) - if sec, err := s.f.GetSection(fieldName); err == nil { - if err = sec.mapTo(field); err != nil { - return fmt.Errorf("error mapping field(%s): %v", fieldName, err) - } - continue - } - } - - if key, err := s.GetKey(fieldName); err == nil { - if err = setWithProperType(tpField.Type.Kind(), key, field, parseDelim(tpField.Tag.Get("delim"))); err != nil { - return fmt.Errorf("error mapping field(%s): %v", fieldName, err) - } - } - } - return nil -} - -// MapTo maps section to given struct. -func (s *Section) MapTo(v interface{}) error { - typ := reflect.TypeOf(v) - val := reflect.ValueOf(v) - if typ.Kind() == reflect.Ptr { - typ = typ.Elem() - val = val.Elem() - } else { - return errors.New("cannot map to non-pointer struct") - } - - return s.mapTo(val) -} - -// MapTo maps file to given struct. -func (f *File) MapTo(v interface{}) error { - return f.Section("").MapTo(v) -} - -// MapTo maps data sources to given struct with name mapper. -func MapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error { - cfg, err := Load(source, others...) - if err != nil { - return err - } - cfg.NameMapper = mapper - return cfg.MapTo(v) -} - -// MapTo maps data sources to given struct. -func MapTo(v, source interface{}, others ...interface{}) error { - return MapToWithMapper(v, nil, source, others...) -} diff --git a/Godeps/_workspace/src/gopkg.in/ini.v1/struct_test.go b/Godeps/_workspace/src/gopkg.in/ini.v1/struct_test.go deleted file mode 100644 index f6fad196ae0..00000000000 --- a/Godeps/_workspace/src/gopkg.in/ini.v1/struct_test.go +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2014 Unknwon -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package ini - -import ( - "strings" - "testing" - "time" - - . "github.com/smartystreets/goconvey/convey" -) - -type testNested struct { - Cities []string `delim:"|"` - Visits []time.Time - Note string - Unused int `ini:"-"` -} - -type testEmbeded struct { - GPA float64 -} - -type testStruct struct { - Name string `ini:"NAME"` - Age int - Male bool - Money float64 - Born time.Time - Others testNested - *testEmbeded `ini:"grade"` - Unused int `ini:"-"` -} - -const _CONF_DATA_STRUCT = ` -NAME = Unknwon -Age = 21 -Male = true -Money = 1.25 -Born = 1993-10-07T20:17:05Z - -[Others] -Cities = HangZhou|Boston -Visits = 1993-10-07T20:17:05Z, 1993-10-07T20:17:05Z -Note = Hello world! - -[grade] -GPA = 2.8 -` - -type unsupport struct { - Byte byte -} - -type unsupport2 struct { - Others struct { - Cities byte - } -} - -type unsupport3 struct { - Cities byte -} - -type unsupport4 struct { - *unsupport3 `ini:"Others"` -} - -type defaultValue struct { - Name string - Age int - Male bool - Money float64 - Born time.Time - Cities []string -} - -const _INVALID_DATA_CONF_STRUCT = ` -Name = -Age = age -Male = 123 -Money = money -Born = nil -Cities = -` - -func Test_Struct(t *testing.T) { - Convey("Map file to struct", t, func() { - ts := new(testStruct) - So(MapTo(ts, []byte(_CONF_DATA_STRUCT)), ShouldBeNil) - - So(ts.Name, ShouldEqual, "Unknwon") - So(ts.Age, ShouldEqual, 21) - So(ts.Male, ShouldBeTrue) - So(ts.Money, ShouldEqual, 1.25) - - t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z") - So(err, ShouldBeNil) - So(ts.Born.String(), ShouldEqual, t.String()) - - So(strings.Join(ts.Others.Cities, ","), ShouldEqual, "HangZhou,Boston") - So(ts.Others.Visits[0].String(), ShouldEqual, t.String()) - So(ts.Others.Note, ShouldEqual, "Hello world!") - So(ts.testEmbeded.GPA, ShouldEqual, 2.8) - }) - - Convey("Map to non-pointer struct", t, func() { - cfg, err := Load([]byte(_CONF_DATA_STRUCT)) - So(err, ShouldBeNil) - So(cfg, ShouldNotBeNil) - - So(cfg.MapTo(testStruct{}), ShouldNotBeNil) - }) - - Convey("Map to unsupported type", t, func() { - cfg, err := Load([]byte(_CONF_DATA_STRUCT)) - So(err, ShouldBeNil) - So(cfg, ShouldNotBeNil) - - cfg.NameMapper = func(raw string) string { - if raw == "Byte" { - return "NAME" - } - return raw - } - So(cfg.MapTo(&unsupport{}), ShouldNotBeNil) - So(cfg.MapTo(&unsupport2{}), ShouldNotBeNil) - So(cfg.MapTo(&unsupport4{}), ShouldNotBeNil) - }) - - Convey("Map from invalid data source", t, func() { - So(MapTo(&testStruct{}, "hi"), ShouldNotBeNil) - }) - - Convey("Map to wrong types and gain default values", t, func() { - cfg, err := Load([]byte(_INVALID_DATA_CONF_STRUCT)) - So(err, ShouldBeNil) - - t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z") - So(err, ShouldBeNil) - dv := &defaultValue{"Joe", 10, true, 1.25, t, []string{"HangZhou", "Boston"}} - So(cfg.MapTo(dv), ShouldBeNil) - So(dv.Name, ShouldEqual, "Joe") - So(dv.Age, ShouldEqual, 10) - So(dv.Male, ShouldBeTrue) - So(dv.Money, ShouldEqual, 1.25) - So(dv.Born.String(), ShouldEqual, t.String()) - So(strings.Join(dv.Cities, ","), ShouldEqual, "HangZhou,Boston") - }) -} - -type testMapper struct { - PackageName string -} - -func Test_NameGetter(t *testing.T) { - Convey("Test name mappers", t, func() { - So(MapToWithMapper(&testMapper{}, TitleUnderscore, []byte("packag_name=ini")), ShouldBeNil) - - cfg, err := Load([]byte("PACKAGE_NAME=ini")) - So(err, ShouldBeNil) - So(cfg, ShouldNotBeNil) - - cfg.NameMapper = AllCapsUnderscore - tg := new(testMapper) - So(cfg.MapTo(tg), ShouldBeNil) - So(tg.PackageName, ShouldEqual, "ini") - }) -} diff --git a/Godeps/_workspace/src/gopkg.in/ini.v1/testdata/conf.ini b/Godeps/_workspace/src/gopkg.in/ini.v1/testdata/conf.ini deleted file mode 100644 index 2ed0ac1d3ac..00000000000 --- a/Godeps/_workspace/src/gopkg.in/ini.v1/testdata/conf.ini +++ /dev/null @@ -1,2 +0,0 @@ -[author] -E-MAIL = u@gogs.io \ No newline at end of file diff --git a/Godeps/_workspace/src/gopkg.in/macaron.v1/macaronlogo.png b/Godeps/_workspace/src/gopkg.in/macaron.v1/macaronlogo.png deleted file mode 100644 index 399759769a8..00000000000 Binary files a/Godeps/_workspace/src/gopkg.in/macaron.v1/macaronlogo.png and /dev/null differ diff --git a/Gruntfile.js b/Gruntfile.js index 9a0c69b96f9..50ac332d894 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -9,14 +9,21 @@ module.exports = function (grunt) { genDir: 'public_gen', destDir: 'dist', tempDir: 'tmp', - arch: os.arch(), platform: process.platform.replace('win32', 'windows'), }; - if (process.platform.match(/^win/)) { - config.arch = process.env.hasOwnProperty('ProgramFiles(x86)') ? 'x64' : 'x86'; + if (grunt.option('arch')) { + config.arch = grunt.option('arch'); + } else { + config.arch = os.arch(); + + if (process.platform.match(/^win/)) { + config.arch = process.env.hasOwnProperty('ProgramFiles(x86)') ? 'x64' : 'x86'; + } } + config.phjs = grunt.option('phjsToRelease'); + config.pkg.version = grunt.option('pkgVer') || config.pkg.version; console.log('Version', config.pkg.version); diff --git a/Makefile b/Makefile new file mode 100644 index 00000000000..16a1e3cf3dc --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +all: deps build + +deps-go: + go run build.go setup + +deps-js: + yarn install + +deps: deps-go deps-js + +build-go: + go run build.go build + +build-js: + npm run build + +build: build-go build-js + +test-go: + go test -v ./pkg/... + +test-js: + npm test + +test: test-go test-js + +run: + ./bin/grafana-server diff --git a/README.md b/README.md index a3336e0373b..af83c63c41b 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,24 @@ -[Grafana](http://grafana.org) [![Circle CI](https://circleci.com/gh/grafana/grafana.svg?style=svg)](https://circleci.com/gh/grafana/grafana) [![Coverage Status](https://coveralls.io/repos/grafana/grafana/badge.png)](https://coveralls.io/r/grafana/grafana) [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/grafana/grafana?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[Grafana](http://grafana.org) [![Circle CI](https://circleci.com/gh/grafana/grafana.svg?style=svg)](https://circleci.com/gh/grafana/grafana) [![Coverage Status](https://coveralls.io/repos/grafana/grafana/badge.png)](https://coveralls.io/r/grafana/grafana) ================ [Website](http://grafana.org) | [Twitter](https://twitter.com/grafana) | [IRC](https://webchat.freenode.net/?channels=grafana) | +[![Slack](https://brandfolder.com/api/favicon/icon?size=16&domain=www.slack.com)](http://slack.raintank.io) +[Slack](http://slack.raintank.io) | [Email](mailto:contact@grafana.org) Grafana is an open source, feature rich metrics dashboard and graph editor for Graphite, Elasticsearch, OpenTSDB, Prometheus and InfluxDB. -![](http://grafana.org/assets/img/start_page_bg.png) +![](http://grafana.org/assets/img/features/dashboard_ex1.png) - [Install instructions](http://docs.grafana.org/installation/) - [What's New in Grafana 2.0](http://docs.grafana.org/guides/whats-new-in-v2/) - [What's New in Grafana 2.1](http://docs.grafana.org/guides/whats-new-in-v2-1/) - [What's New in Grafana 2.5](http://docs.grafana.org/guides/whats-new-in-v2-5/) +- [What's New in Grafana 3.0](http://docs.grafana.org/guides/whats-new-in-v3/) +- [What's New in Grafana 4.0](http://docs.grafana.org/guides/whats-new-in-v4/) +- [What's New in Grafana 4.1 beta](http://docs.grafana.org/guides/whats-new-in-v4-1/) ## Features ### Graphite Target Editor @@ -71,12 +76,12 @@ Be sure to read the [getting started guide](http://docs.grafana.org/guides/getti ## Run from master If you want to build a package yourself, or contribute. Here is a guide for how to do that. You can always find -the latest master builds [here](http://grafana.org/download/builds) +the latest master builds [here](http://grafana.org/builds) ### Dependencies -- Go 1.5 -- NodeJS +- Go 1.7.3 +- NodeJS v4+ ### Get Code @@ -84,28 +89,45 @@ the latest master builds [here](http://grafana.org/download/builds) go get github.com/grafana/grafana ``` +Since imports of dependencies use the absolute path `github.com/grafana/grafana` within the `$GOPATH`, +you will need to put your version of the code in `$GOPATH/src/github.com/grafana/grafana` to be able +to develop and build grafana on a cloned repository. To do so, you can clone your forked repository +directly to `$GOPATH/src/github.com/grafana` or you can create a symbolic link from your version +of the code to `$GOPATH/src/github.com/grafana/grafana`. The last options makes it possible to change +easily the grafana repository you want to build. +```bash +go get github.com/*your_account*/grafana +mkdir $GOPATH/src/github.com/grafana +ln -s $GOPATH/src/github.com/*your_account*/grafana $GOPATH/src/github.com/grafana/grafana +``` + ### Building the backend -Replace X.Y.Z by actual version number. ```bash cd $GOPATH/src/github.com/grafana/grafana -go run build.go setup (only needed once to install godep) -godep restore (will pull down all golang lib dependencies in your current GOPATH) +go run build.go setup go run build.go build ``` ### Building frontend assets -To build less to css for the frontend you will need a recent version of of node (v0.12.0), +To build less to css for the frontend you will need a recent version of **node (v4+)**, npm (v2.5.0) and grunt (v0.4.5). Run the following: ```bash -npm install -npm install -g grunt-cli -grunt +npm install -g yarn +yarn install +npm run build +``` + +To build the frontend assets only on changes: + +```bash +sudo npm install -g grunt-cli # to do only once to install grunt command line interface +grunt watch ``` ### Recompile backend on source change -To rebuild on source change (requires that you executed godep restore) +To rebuild on source change. ```bash go get github.com/Unknwon/bra bra run @@ -116,7 +138,7 @@ bra run ./bin/grafana-server ``` -Open grafana in your browser (default http://localhost:3000) and login with admin user (default user/pass = admin/admin). +Open grafana in your browser (default: `http://localhost:3000`) and login with admin user (default: `user/pass = admin/admin`). ### Dev config @@ -128,18 +150,13 @@ You only need to add the options you want to override. Config files are applied 3. custom.ini ## Create a pull request -Before or after you create a pull request, sign the [contributor license agreement](http://grafana.org/docs/contributing/cla.html). +Before or after you create a pull request, sign the [contributor license agreement](http://docs.grafana.org/project/cla/). ## Contribute If you have any idea for an improvement or found a bug do not hesitate to open an issue. And if you have time clone this repo and submit a pull request and help me make Grafana the kickass metrics & devops dashboard we all dream about! -Before creating a pull request be sure that "grunt test" runs without any style or unit test errors, also -please [sign the CLA](http://docs.grafana.org/project/cla/) - ## License - Grafana is distributed under Apache 2.0 License. Work in progress Grafana 2.0 (with included Grafana backend) - diff --git a/appveyor.yml b/appveyor.yml index 83506312912..09674ca3502 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,16 +5,17 @@ os: Windows Server 2012 R2 clone_folder: c:\gopath\src\github.com\grafana\grafana environment: - nodejs_version: "4" + nodejs_version: "5" GOPATH: c:\gopath install: # install nodejs and npm - ps: Install-Product node $env:nodejs_version - - npm install + - npm install -g yarn + - yarn install - npm install -g grunt-cli # install gcc (needed for sqlite3) - - choco install -y mingw + - choco install -y --limit-output mingw - set PATH=C:\tools\mingw64\bin;%PATH% - echo %PATH% - echo %GOPATH% @@ -25,7 +26,13 @@ install: build_script: - go run build.go build - grunt release + - go run build.go sha1-dist + - cp dist/* . artifacts: - - path: dist/* + - path: grafana-*windows-*.* name: binzip + +deploy: + - provider: Environment + name: GrafanaBuildsS3 diff --git a/bower.json b/bower.json index 557ee9c9f8f..c71b0b7dea0 100644 --- a/bower.json +++ b/bower.json @@ -13,11 +13,13 @@ "tests" ], "dependencies": { - "jquery": "~2.1.4", - "angular": "~1.5.3", - "angular-route": "~1.5.3", - "angular-mocks": "~1.5.3", - "angular-sanitize": "~1.5.3", - "angular-bindonce": "~0.3.3" + "jquery": "3.1.0", + "lodash": "4.15.0", + "angular": "1.5.8", + "angular-route": "1.5.8", + "angular-mocks": "1.5.8", + "angular-sanitize": "1.5.8", + "angular-native-dragdrop": "1.2.2", + "angular-bindonce": "0.3.3" } } diff --git a/build.go b/build.go index 93b9e6db087..faa014d7619 100644 --- a/build.go +++ b/build.go @@ -5,6 +5,7 @@ package main import ( "bytes" "crypto/md5" + "crypto/sha1" "encoding/json" "flag" "fmt" @@ -25,16 +26,21 @@ var ( versionRe = regexp.MustCompile(`-[0-9]{1,3}-g[0-9a-f]{5,10}`) goarch string goos string + gocc string + gocxx string + cgo string + pkgArch string version string = "v1" // deb & rpm does not support semver so have to handle their version a little differently linuxPackageVersion string = "v1" linuxPackageIteration string = "" race bool + phjsToRelease string workingDir string binaries []string = []string{"grafana-server", "grafana-cli"} ) -const minGoVersion = 1.3 +const minGoVersion = 1.7 func main() { log.SetOutput(os.Stdout) @@ -47,6 +53,11 @@ func main() { flag.StringVar(&goarch, "goarch", runtime.GOARCH, "GOARCH") flag.StringVar(&goos, "goos", runtime.GOOS, "GOOS") + flag.StringVar(&gocc, "cc", "", "CC") + flag.StringVar(&gocxx, "cxx", "", "CXX") + flag.StringVar(&cgo, "cgo-enabled", "", "CGO_ENABLED") + flag.StringVar(&pkgArch, "pkg-arch", "", "PKG ARCH") + flag.StringVar(&phjsToRelease, "phjs", "", "PhantomJS binary") flag.BoolVar(&race, "race", race, "Use race detector") flag.Parse() @@ -62,6 +73,10 @@ func main() { case "setup": setup() + case "build-cli": + clean() + build("grafana-cli", "./pkg/cmd/grafana-cli", []string{}) + case "build": clean() for _, binary := range binaries { @@ -73,19 +88,26 @@ func main() { grunt("test") case "package": - grunt("release", fmt.Sprintf("--pkgVer=%v-%v", linuxPackageVersion, linuxPackageIteration)) + grunt(gruntBuildArg("release")...) createLinuxPackages() + sha1FilesInDist() case "pkg-rpm": - grunt("release") + grunt(gruntBuildArg("release")...) createRpmPackages() + sha1FilesInDist() case "pkg-deb": - grunt("release") + grunt(gruntBuildArg("release")...) createDebPackages() + sha1FilesInDist() + + case "sha1-dist": + sha1FilesInDist() case "latest": makeLatestDistCopies() + sha1FilesInDist() case "clean": clean() @@ -132,12 +154,10 @@ func readVersionFromPackageJson() { if len(parts) > 1 { linuxPackageVersion = parts[0] linuxPackageIteration = parts[1] - if linuxPackageIteration != "" { - // add timestamp to iteration - linuxPackageIteration = fmt.Sprintf("%s%v", linuxPackageIteration, time.Now().Unix()) - } - log.Println(fmt.Sprintf("teration %v", linuxPackageIteration)) } + + // add timestamp to iteration + linuxPackageIteration = fmt.Sprintf("%d%s", time.Now().Unix(), linuxPackageIteration) } type linuxPackageOptions struct { @@ -260,6 +280,10 @@ func createPackage(options linuxPackageOptions) { "-p", "./dist", } + if pkgArch != "" { + args = append(args, "-a", pkgArch) + } + if linuxPackageIteration != "" { args = append(args, "--iteration", linuxPackageIteration) } @@ -306,14 +330,23 @@ func ChangeWorkingDir(dir string) { } func grunt(params ...string) { - runPrint("./node_modules/grunt-cli/bin/grunt", params...) + runPrint("./node_modules/.bin/grunt", params...) +} + +func gruntBuildArg(task string) []string { + args := []string{task, fmt.Sprintf("--pkgVer=%v-%v", linuxPackageVersion, linuxPackageIteration)} + if pkgArch != "" { + args = append(args, fmt.Sprintf("--arch=%v", pkgArch)) + } + if phjsToRelease != "" { + args = append(args, fmt.Sprintf("--phjsToRelease=%v", phjsToRelease)) + } + return args } func setup() { - runPrint("go", "get", "-v", "github.com/tools/godep") - runPrint("go", "get", "-v", "github.com/blang/semver") - runPrint("go", "get", "-v", "github.com/mattn/go-sqlite3") - runPrint("go", "install", "-v", "github.com/mattn/go-sqlite3") + runPrint("go", "get", "-v", "github.com/kardianos/govendor") + runPrint("go", "install", "-v", "./pkg/cmd/grafana-server") } func test(pkg string) { @@ -368,7 +401,6 @@ func rmr(paths ...string) { } func clean() { - rmr("bin", "Godeps/_workspace/pkg", "Godeps/_workspace/bin") rmr("dist") rmr("tmp") rmr(filepath.Join(os.Getenv("GOPATH"), fmt.Sprintf("pkg/%s_%s/github.com/grafana", goos, goarch))) @@ -385,13 +417,15 @@ func setBuildEnv() { if goarch == "386" { os.Setenv("GO386", "387") } - wd, err := os.Getwd() - if err != nil { - log.Println("Warning: can't determine current dir:", err) - log.Println("Build might not work as expected") + if cgo != "" { + os.Setenv("CGO_ENABLED", cgo) + } + if gocc != "" { + os.Setenv("CC", gocc) + } + if gocxx != "" { + os.Setenv("CXX", gocxx) } - os.Setenv("GOPATH", fmt.Sprintf("%s%c%s", filepath.Join(wd, "Godeps", "_workspace"), os.PathListSeparator, os.Getenv("GOPATH"))) - log.Println("GOPATH=" + os.Getenv("GOPATH")) } func getGitSha() string { @@ -479,3 +513,38 @@ func md5File(file string) error { return out.Close() } + +func sha1FilesInDist() { + filepath.Walk("./dist", func(path string, f os.FileInfo, err error) error { + if strings.Contains(path, ".sha1") == false { + sha1File(path) + } + return nil + }) +} + +func sha1File(file string) error { + fd, err := os.Open(file) + if err != nil { + return err + } + defer fd.Close() + + h := sha1.New() + _, err = io.Copy(h, fd) + if err != nil { + return err + } + + out, err := os.Create(file + ".sha1") + if err != nil { + return err + } + + _, err = fmt.Fprintf(out, "%x\n", h.Sum(nil)) + if err != nil { + return err + } + + return out.Close() +} diff --git a/circle.yml b/circle.yml index 22dab8ab893..7930ab1b875 100644 --- a/circle.yml +++ b/circle.yml @@ -1,36 +1,31 @@ machine: node: - version: 4.0 + version: 6.9.2 environment: GOPATH: "/home/ubuntu/.go_workspace" ORG_PATH: "github.com/grafana" REPO_PATH: "${ORG_PATH}/grafana" + GODIST: "go1.7.4.linux-amd64.tar.gz" + post: + - mkdir -p download + - test -e download/$GODIST || curl -o download/$GODIST https://storage.googleapis.com/golang/$GODIST + - sudo rm -rf /usr/local/go + - sudo tar -C /usr/local -xzf download/$GODIST dependencies: override: - rm -rf ${GOPATH}/src/${REPO_PATH} - mkdir -p ${GOPATH}/src/${ORG_PATH} - - ln -s ~/grafana ${GOPATH}/src/${ORG_PATH} - - go get github.com/tools/godep - - rm -rf node_modules - - npm install -g npm - - npm install + - cp -r ~/grafana ${GOPATH}/src/${ORG_PATH} test: override: - # FMT - - test -z "$(gofmt -s -l . | grep -v Godeps/_workspace/src/ | tee /dev/stderr)" - # GO VET - - go vet ./pkg/... - # Go test - - godep go test -v ./pkg/... - # js tests - - ./node_modules/grunt-cli/bin/grunt test - - npm run coveralls + - bash scripts/circle-test.sh -deployment: - master: - branch: master - owner: grafana - commands: - - ./trigger_grafana_packer.sh ${TRIGGER_GRAFANA_PACKER_CIRCLECI_TOKEN} +# deployment: +# master: +# branch: master +# owner: grafana +# commands: +# - ./scripts/trigger_grafana_packer.sh ${TRIGGER_GRAFANA_PACKER_CIRCLECI_TOKEN} +# - ./scripts/trigger_windows_build.sh ${APPVEYOR_TOKEN} diff --git a/conf/defaults.ini b/conf/defaults.ini index 851c88efc7c..81d6c8d8050 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -6,7 +6,10 @@ # possible values : production, development app_mode = production -#################################### Paths #################################### +# instance name, defaults to HOSTNAME environment variable value or hostname if HOSTNAME var is empty +instance_name = ${HOSTNAME} + +#################################### Paths ############################### [paths] # Path to where grafana can store temp files, sessions, and the sqlite3 db (if that is used) # @@ -20,7 +23,7 @@ logs = data/log # plugins = data/plugins -#################################### Server #################################### +#################################### Server ############################## [server] # Protocol (http or https) protocol = http @@ -54,14 +57,21 @@ enable_gzip = false cert_file = cert_key = -#################################### Database #################################### +#################################### Database ############################ [database] +# You can configure the database connection by specifying type, host, name, user and password +# as seperate properties or as on string using the url propertie. + # Either "mysql", "postgres" or "sqlite3", it's your choice type = sqlite3 host = 127.0.0.1:3306 name = grafana user = root +# If the password contains # or ; you have to wrap it with trippel quotes. Ex """#password;""" password = +# Use either URL or the previous fields to configure the database +# Example: mysql://user:secret@host:port/database +url = # For "postgres", use either "disable", "require" or "verify-full" # For "mysql", use either "true", "false", or "skip-verify". @@ -75,7 +85,7 @@ server_cert_name = # For "sqlite3" only, path relative to data_path setting path = grafana.db -#################################### Session #################################### +#################################### Session ############################# [session] # Either "memory", "file", "redis", "mysql", "postgres", "memcache", default is "file" provider = file @@ -103,7 +113,7 @@ cookie_secure = false session_life_time = 86400 gc_interval_time = 86400 -#################################### Analytics #################################### +#################################### Analytics ########################### [analytics] # Server reporting, sends usage counters to stats.grafana.org every 24 hours. # No ip addresses are being tracked, only simple counters to track @@ -111,13 +121,20 @@ gc_interval_time = 86400 # Change this option to false to disable reporting. reporting_enabled = true +# Set to false to disable all checks to https://grafana.net +# for new vesions (grafana itself and plugins), check is used +# in some UI views to notify that grafana or plugin update exists +# This option does not cause any auto updates, nor send any information +# only a GET request to http://grafana.net to get latest versions +check_for_updates = true + # Google Analytics universal tracking code, only enabled if you specify an id here google_analytics_ua_id = # Google Tag Manager ID, only enabled if you specify an id here google_tag_manager_id = -#################################### Security #################################### +#################################### Security ############################ [security] # default admin user, created on startup admin_user = admin @@ -136,7 +153,7 @@ cookie_remember_name = grafana_remember # disable gravatar profile images disable_gravatar = false -# data source proxy whitelist (ip_or_domain:port seperated by spaces) +# data source proxy whitelist (ip_or_domain:port separated by spaces) data_source_proxy_whitelist = [snapshots] @@ -145,6 +162,12 @@ external_enabled = true external_snapshot_url = https://snapshots-origin.raintank.io external_snapshot_name = Publish to snapshot.raintank.io +# remove expired snapshot +snapshot_remove_expired = true + +# remove snapshots after 90 days +snapshot_TTL_days = 90 + #################################### Users #################################### [users] # disable user signup / registration @@ -165,7 +188,14 @@ verify_email_enabled = false # Background text for the user field on the login page login_hint = email or username -#################################### Anonymous Auth ########################## +# Default UI theme ("dark" or "light") +default_theme = dark + +[auth] +# Set to true to disable (hide) the login form, useful if you use OAuth +disable_login_form = false + +#################################### Anonymous Auth ###################### [auth.anonymous] # enable anonymous access enabled = false @@ -176,10 +206,10 @@ org_name = Main Org. # specify role for unauthenticated users org_role = Viewer -#################################### Github Auth ########################## +#################################### Github Auth ######################### [auth.github] enabled = false -allow_sign_up = false +allow_sign_up = true client_id = some_id client_secret = some_secret scopes = user:email @@ -189,10 +219,10 @@ api_url = https://api.github.com/user team_ids = allowed_organizations = -#################################### Google Auth ########################## +#################################### Google Auth ######################### [auth.google] enabled = false -allow_sign_up = false +allow_sign_up = true client_id = some_client_id client_secret = some_client_secret scopes = https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email @@ -200,6 +230,30 @@ auth_url = https://accounts.google.com/o/oauth2/auth token_url = https://accounts.google.com/o/oauth2/token api_url = https://www.googleapis.com/oauth2/v1/userinfo allowed_domains = +hosted_domain = + +#################################### Grafana.net Auth #################### +[auth.grafananet] +enabled = false +allow_sign_up = true +client_id = some_id +client_secret = some_secret +scopes = user:email +allowed_organizations = + +#################################### Generic OAuth ####################### +[auth.generic_oauth] +name = OAuth +enabled = false +allow_sign_up = true +client_id = some_id +client_secret = some_secret +scopes = user:email +auth_url = +token_url = +api_url = +team_ids = +allowed_organizations = #################################### Basic Auth ########################## [auth.basic] @@ -211,13 +265,16 @@ enabled = false header_name = X-WEBAUTH-USER header_property = username auto_sign_up = true +ldap_sync_ttl = 60 +whitelist = -#################################### Auth LDAP ########################## +#################################### Auth LDAP ########################### [auth.ldap] enabled = false config_file = /etc/grafana/ldap.toml +allow_sign_up = true -#################################### SMTP / Emailing ########################## +#################################### SMTP / Emailing ##################### [smtp] enabled = false host = localhost:25 @@ -234,25 +291,30 @@ templates_pattern = emails/*.html #################################### Logging ########################## [log] -# Either "console", "file", default is "console" -# Use comma to separate multiple modes, e.g. "console, file" -mode = console, file +# Either "console", "file", "syslog". Default is console and file +# Use space to separate multiple modes, e.g. "console file" +mode = console file -# Buffer length of channel, keep it as it is if you don't know what it is. -buffer_len = 10000 +# Either "debug", "info", "warn", "error", "critical", default is "info" +level = info -# Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Trace" -level = Info +# optional settings to set different levels for specific loggers. Ex filters = sqlstore:debug +filters = # For "console" mode only [log.console] level = -# Set formatting to "false" to disable color formatting of console logs -formatting = false + +# log line format, valid options are text, console and json +format = console # For "file" mode only [log.file] level = + +# log line format, valid options are text, console and json +format = text + # This enables automated log rotate(switch of following options), default is true log_rotate = true @@ -260,7 +322,7 @@ log_rotate = true max_lines = 1000000 # Max size shift of single file, default is 28 means 1 << 28, 256MB -max_lines_shift = 28 +max_size_shift = 28 # Segment log daily, default is true daily_rotate = true @@ -270,6 +332,10 @@ max_days = 7 [log.syslog] level = + +# log line format, valid options are text, console and json +format = text + # Syslog network type and address. This can be udp, tcp, or unix. If left blank, the default unix endpoints will be used. network = address = @@ -280,18 +346,19 @@ facility = # Syslog tag. By default, the process' argv[0] is used. tag = -#################################### AMPQ Event Publisher ########################## + +#################################### AMQP Event Publisher ################ [event_publisher] enabled = false rabbitmq_url = amqp://localhost/ exchange = grafana_events -#################################### Dashboard JSON files ########################## +#################################### Dashboard JSON files ################ [dashboards.json] enabled = false path = /var/lib/grafana/dashboards -#################################### Usage Quotas ########################## +#################################### Usage Quotas ######################## [quota] enabled = false @@ -325,3 +392,38 @@ global_api_key = -1 # global limit on number of logged in users. global_session = -1 + +#################################### Alerting ############################ +[alerting] +# Makes it possible to turn off alert rule execution. +execute_alerts = true + +#################################### Internal Grafana Metrics ############ +# Metrics available at HTTP API Url /api/metrics +[metrics] +enabled = true +interval_seconds = 10 + +# Send internal Grafana metrics to graphite +[metrics.graphite] +# Enable by setting the address setting (ex localhost:2003) +address = +prefix = prod.grafana.%(instance_name)s. + +[grafana_net] +url = https://grafana.net + +#################################### External Image Storage ############## +[external_image_storage] +# You can choose between (s3, webdav) +provider = + +[external_image_storage.s3] +bucket_url = +access_key = +secret_key = + +[external_image_storage.webdav] +url = +username = +password = diff --git a/conf/ldap.toml b/conf/ldap.toml index 395179e219f..305929b80d7 100644 --- a/conf/ldap.toml +++ b/conf/ldap.toml @@ -1,5 +1,6 @@ -# Set to true to log user information returned from LDAP -verbose_logging = false +# To troubleshoot and get more log info enable ldap debug logging in grafana.ini +# [log] +# filters = ldap:debug [[servers]] # Ldap server host (specify multiple hosts space separated) @@ -8,6 +9,8 @@ host = "127.0.0.1" port = 389 # Set to true if ldap server supports TLS use_ssl = false +# Set to true if connect ldap server with STARTTLS pattern (create connection in insecure, then upgrade to secure connection with TLS) +start_tls = false # set to true if you want to skip ssl cert validation ssl_skip_verify = false # set to the path to your root CA certificate or leave unset to use system defaults @@ -16,6 +19,7 @@ ssl_skip_verify = false # Search user bind dn bind_dn = "cn=admin,dc=grafana,dc=org" # Search user bind password +# If the password contains # or ; you have to wrap it with trippel quotes. Ex """#password;""" bind_password = 'grafana' # User search filter, for example "(cn=%s)" or "(sAMAccountName=%s)" or "(uid=%s)" diff --git a/conf/sample.ini b/conf/sample.ini index b875cbda093..6a8aa623f85 100644 --- a/conf/sample.ini +++ b/conf/sample.ini @@ -6,6 +6,9 @@ # possible values : production, development ; app_mode = production +# instance name, defaults to HOSTNAME environment variable value or hostname if HOSTNAME var is empty +; instance_name = ${HOSTNAME} + #################################### Paths #################################### [paths] # Path to where grafana can store temp files, sessions, and the sqlite3 db (if that is used) @@ -39,8 +42,9 @@ # Prevents DNS rebinding attacks ;enforce_domain = false -# The full public facing url -;root_url = %(protocol)s://%(domain)s:%(http_port)s/ +# The full public facing url you use in browser, used for redirects and emails +# If you use reverse proxy and sub path specify full url (with sub path) +;root_url = http://localhost:3000 # Log web requests ;router_logging = false @@ -57,13 +61,21 @@ #################################### Database #################################### [database] +# You can configure the database connection by specifying type, host, name, user and password +# as seperate properties or as on string using the url propertie. + # Either "mysql", "postgres" or "sqlite3", it's your choice ;type = sqlite3 ;host = 127.0.0.1:3306 ;name = grafana ;user = root +# If the password contains # or ; you have to wrap it with trippel quotes. Ex """#password;""" ;password = +# Use either URL or the previous fields to configure the database +# Example: mysql://user:secret@host:port/database +;url = + # For "postgres" only, either "disable", "require" or "verify-full" ;ssl_mode = disable @@ -100,6 +112,13 @@ # Change this option to false to disable reporting. ;reporting_enabled = true +# Set to false to disable all checks to https://grafana.net +# for new vesions (grafana itself and plugins), check is used +# in some UI views to notify that grafana or plugin update exists +# This option does not cause any auto updates, nor send any information +# only a GET request to http://grafana.net to get latest versions +;check_for_updates = true + # Google Analytics universal tracking code, only enabled if you specify an id here ;google_analytics_ua_id = @@ -122,7 +141,7 @@ # disable gravatar profile images ;disable_gravatar = false -# data source proxy whitelist (ip_or_domain:port seperated by spaces) +# data source proxy whitelist (ip_or_domain:port separated by spaces) ;data_source_proxy_whitelist = [snapshots] @@ -131,6 +150,12 @@ ;external_snapshot_url = https://snapshots-origin.raintank.io ;external_snapshot_name = Publish to snapshot.raintank.io +# remove expired snapshot +;snapshot_remove_expired = true + +# remove snapshots after 90 days +;snapshot_TTL_days = 90 + #################################### Users #################################### [users] # disable user signup / registration @@ -148,6 +173,13 @@ # Background text for the user field on the login page ;login_hint = email or username +# Default UI theme ("dark" or "light") +;default_theme = dark + +[auth] +# Set to true to disable (hide) the login form, useful if you use OAuth, defaults to false +;disable_login_form = false + #################################### Anonymous Auth ########################## [auth.anonymous] # enable anonymous access @@ -162,7 +194,7 @@ #################################### Github Auth ########################## [auth.github] ;enabled = false -;allow_sign_up = false +;allow_sign_up = true ;client_id = some_id ;client_secret = some_secret ;scopes = user:email,read:org @@ -175,7 +207,7 @@ #################################### Google Auth ########################## [auth.google] ;enabled = false -;allow_sign_up = false +;allow_sign_up = true ;client_id = some_client_id ;client_secret = some_client_secret ;scopes = https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email @@ -184,12 +216,37 @@ ;api_url = https://www.googleapis.com/oauth2/v1/userinfo ;allowed_domains = +#################################### Generic OAuth ########################## +[auth.generic_oauth] +;enabled = false +;name = OAuth +;allow_sign_up = true +;client_id = some_id +;client_secret = some_secret +;scopes = user:email,read:org +;auth_url = https://foo.bar/login/oauth/authorize +;token_url = https://foo.bar/login/oauth/access_token +;api_url = https://foo.bar/user +;team_ids = +;allowed_organizations = + +#################################### Grafana.net Auth #################### +[auth.grafananet] +;enabled = false +;allow_sign_up = true +;client_id = some_id +;client_secret = some_secret +;scopes = user:email +;allowed_organizations = + #################################### Auth Proxy ########################## [auth.proxy] ;enabled = false ;header_name = X-WEBAUTH-USER ;header_property = username ;auto_sign_up = true +;ldap_sync_ttl = 60 +;whitelist = 192.168.1.1, 192.168.2.1 #################################### Basic Auth ########################## [auth.basic] @@ -199,6 +256,7 @@ [auth.ldap] ;enabled = false ;config_file = /etc/grafana/ldap.toml +;allow_sign_up = true #################################### SMTP / Emailing ########################## [smtp] @@ -216,23 +274,31 @@ #################################### Logging ########################## [log] -# Either "console", "file", default is "console" -# Use comma to separate multiple modes, e.g. "console, file" -;mode = console, file +# Either "console", "file", "syslog". Default is console and file +# Use space to separate multiple modes, e.g. "console file" +;mode = console file -# Buffer length of channel, keep it as it is if you don't know what it is. -;buffer_len = 10000 +# Either "trace", "debug", "info", "warn", "error", "critical", default is "info" +;level = info + +# optional settings to set different levels for specific loggers. Ex filters = sqlstore:debug +;filters = -# Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Trace" -;level = Info # For "console" mode only [log.console] ;level = +# log line format, valid options are text, console and json +;format = console + # For "file" mode only [log.file] ;level = + +# log line format, valid options are text, console and json +;format = text + # This enables automated log rotate(switch of following options), default is true ;log_rotate = true @@ -240,7 +306,7 @@ ;max_lines = 1000000 # Max size shift of single file, default is 28 means 1 << 28, 256MB -;max_lines_shift = 28 +;max_size_shift = 28 # Segment log daily, default is true ;daily_rotate = true @@ -248,7 +314,24 @@ # Expired days of log file(delete after max days), default is 7 ;max_days = 7 -#################################### AMPQ Event Publisher ########################## +[log.syslog] +;level = + +# log line format, valid options are text, console and json +;format = text + +# Syslog network type and address. This can be udp, tcp, or unix. If left blank, the default unix endpoints will be used. +;network = +;address = + +# Syslog facility. user, daemon and local0 through local7 are valid. +;facility = + +# Syslog tag. By default, the process' argv[0] is used. +;tag = + + +#################################### AMQP Event Publisher ########################## [event_publisher] ;enabled = false ;rabbitmq_url = amqp://localhost/ @@ -259,5 +342,43 @@ ;enabled = false ;path = /var/lib/grafana/dashboards +#################################### Alerting ###################################### +[alerting] +# Makes it possible to turn off alert rule execution. +;execute_alerts = true +#################################### Internal Grafana Metrics ########################## +# Metrics available at HTTP API Url /api/metrics +[metrics] +# Disable / Enable internal metrics +;enabled = true +# Publish interval +;interval_seconds = 10 + +# Send internal metrics to Graphite +[metrics.graphite] +# Enable by setting the address setting (ex localhost:2003) +;address = +;prefix = prod.grafana.%(instance_name)s. + +#################################### Internal Grafana Metrics ########################## +# Url used to to import dashboards directly from Grafana.net +[grafana_net] +;url = https://grafana.net + +#################################### External image storage ########################## +[external_image_storage] +# Used for uploading images to public servers so they can be included in slack/email messages. +# you can choose between (s3, webdav) +;provider = + +[external_image_storage.s3] +;bucket_url = +;access_key = +;secret_key = + +[external_image_storage.webdav] +;url = +;username = +;password = diff --git a/docker/blocks/collectd/Dockerfile b/docker/blocks/collectd/Dockerfile new file mode 100644 index 00000000000..a08b1f9c1b2 --- /dev/null +++ b/docker/blocks/collectd/Dockerfile @@ -0,0 +1,16 @@ +FROM ubuntu:xenial + +ENV DEBIAN_FRONTEND noninteractive + +RUN apt-get -y update +RUN apt-get -y install collectd curl python-pip + +# add a fake mtab for host disk stats +ADD etc_mtab /etc/mtab + +ADD collectd.conf.tpl /etc/collectd/collectd.conf.tpl + +RUN pip install envtpl +ADD start_container /usr/bin/start_container +RUN chmod +x /usr/bin/start_container +CMD start_container diff --git a/docker/blocks/collectd/README.md b/docker/blocks/collectd/README.md new file mode 100644 index 00000000000..2c1a8cb79fc --- /dev/null +++ b/docker/blocks/collectd/README.md @@ -0,0 +1,37 @@ +collectd-write-graphite +======================= + +Basic collectd-based server monitoring. Sends stats to Graphite. + +Collectd metrics: + +* CPU used/free/idle/etc +* Free disk (via mounting hosts '/' into container, eg: -v /:/hostfs:ro) +* Disk performance +* Load average +* Memory used/free/etc +* Uptime +* Network interface +* Swap + +Environment variables +--------------------- + +* `HOST_NAME` + - Will be sent to Graphite + - Required +* `GRAPHITE_HOST` + - Graphite IP or hostname + - Required +* `GRAPHITE_PORT` + - Graphite port + - Optional, defaults to 2003 +* `GRAPHITE_PREFIX` + - Graphite prefix + - Optional, defaults to collectd. +* `REPORT_BY_CPU` + - Report per-CPU metrics if true, global sum of CPU metrics if false (details: [collectd.conf man page](https://collectd.org/documentation/manpages/collectd.conf.5.shtml#plugin_cpu)) + - Optional, defaults to false. +* `COLLECT_INTERVAL` + - Collection interval and thus resolution of metrics + - Optional, defaults to 10 diff --git a/docker/blocks/collectd/collectd.conf.tpl b/docker/blocks/collectd/collectd.conf.tpl new file mode 100644 index 00000000000..69b019007fb --- /dev/null +++ b/docker/blocks/collectd/collectd.conf.tpl @@ -0,0 +1,106 @@ +Hostname "{{ HOST_NAME }}" + +FQDNLookup false +Interval {{ COLLECT_INTERVAL | default("10") }} +Timeout 2 +ReadThreads 5 + +LoadPlugin cpu +LoadPlugin df +LoadPlugin load +LoadPlugin memory +LoadPlugin disk +LoadPlugin interface +LoadPlugin uptime +LoadPlugin swap +LoadPlugin write_graphite +LoadPlugin processes +LoadPlugin aggregation +LoadPlugin match_regex +# LoadPlugin memcached + + + # expose host's mounts into container using -v /:/host:ro (location inside container does not matter much) + # ignore rootfs; else, the root file-system would appear twice, causing + # one of the updates to fail and spam the log + FSType rootfs + # ignore the usual virtual / temporary file-systems + FSType sysfs + FSType proc + FSType devtmpfs + FSType devpts + FSType tmpfs + FSType fusectl + FSType cgroup + FSType overlay + FSType debugfs + FSType pstore + FSType securityfs + FSType hugetlbfs + FSType squashfs + FSType mqueue + MountPoint "/etc/resolv.conf" + MountPoint "/etc/hostname" + MountPoint "/etc/hosts" + IgnoreSelected true + ReportByDevice false + ReportReserved true + ReportInodes true + ValuesAbsolute true + ValuesPercentage true + ReportInodes true + + + + Disk "/^[hs]d[a-z]/" + IgnoreSelected false + + + + + Plugin "cpu" + Type "cpu" + GroupBy "Host" + GroupBy "TypeInstance" + CalculateAverage true + + + + + Interface "lo" + Interface "/^veth.*/" + Interface "/^docker.*/" + IgnoreSelected true + + +# +# Host "memcached" +# Port "11211" +# + + + + + Plugin "^cpu$" + PluginInstance "^[0-9]+$" + + + Plugin "aggregation" + + Target stop + + Target "write" + + + + + Host "{{ GRAPHITE_HOST }}" + Port "{{ GRAPHITE_PORT | default("2003") }}" + Prefix "{{ GRAPHITE_PREFIX | default("collectd.") }}" + EscapeCharacter "_" + SeparateInstances true + StoreRates true + AlwaysAppendDS false + + + diff --git a/docker/blocks/collectd/etc_mtab b/docker/blocks/collectd/etc_mtab new file mode 100644 index 00000000000..749f9789482 --- /dev/null +++ b/docker/blocks/collectd/etc_mtab @@ -0,0 +1 @@ +hostfs /.dockerinit ext4 ro,relatime,user_xattr,barrier=1,data=ordered 0 0 diff --git a/docker/blocks/collectd/fig b/docker/blocks/collectd/fig new file mode 100644 index 00000000000..99f45a66d12 --- /dev/null +++ b/docker/blocks/collectd/fig @@ -0,0 +1,11 @@ +collectd: + build: blocks/collectd + environment: + HOST_NAME: myserver + GRAPHITE_HOST: graphite + GRAPHITE_PORT: 2003 + GRAPHITE_PREFIX: collectd. + REPORT_BY_CPU: 'false' + COLLECT_INTERVAL: 10 + links: + - graphite diff --git a/docker/blocks/collectd/start_container b/docker/blocks/collectd/start_container new file mode 100644 index 00000000000..b01cd0d5ff2 --- /dev/null +++ b/docker/blocks/collectd/start_container @@ -0,0 +1,5 @@ +#!/bin/bash + +envtpl /etc/collectd/collectd.conf.tpl + +collectd -f diff --git a/docker/blocks/elastic/fig b/docker/blocks/elastic/fig index 357352cabaa..fa79a9af59c 100644 --- a/docker/blocks/elastic/fig +++ b/docker/blocks/elastic/fig @@ -1,5 +1,5 @@ elasticsearch: - image: elasticsearch:latest + image: elasticsearch:2.4.1 command: elasticsearch -Des.network.host=0.0.0.0 ports: - "9200:9200" diff --git a/docker/blocks/elastic1/elasticsearch.yml b/docker/blocks/elastic1/elasticsearch.yml new file mode 100644 index 00000000000..c57b2c12908 --- /dev/null +++ b/docker/blocks/elastic1/elasticsearch.yml @@ -0,0 +1,2 @@ +script.inline: on +script.indexed: on diff --git a/docker/blocks/elastic1/fig b/docker/blocks/elastic1/fig new file mode 100644 index 00000000000..c33e51f16a2 --- /dev/null +++ b/docker/blocks/elastic1/fig @@ -0,0 +1,8 @@ +elasticsearch1: + image: elasticsearch:1.7.6 + command: elasticsearch -Des.network.host=0.0.0.0 + ports: + - "11200:9200" + - "11300:9300" + volumes: + - ./blocks/elastic/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml diff --git a/docker/blocks/elastic5/elasticsearch.yml b/docker/blocks/elastic5/elasticsearch.yml new file mode 100644 index 00000000000..c57b2c12908 --- /dev/null +++ b/docker/blocks/elastic5/elasticsearch.yml @@ -0,0 +1,2 @@ +script.inline: on +script.indexed: on diff --git a/docker/blocks/elastic5/fig b/docker/blocks/elastic5/fig new file mode 100644 index 00000000000..6e5cd89ab3d --- /dev/null +++ b/docker/blocks/elastic5/fig @@ -0,0 +1,8 @@ +# You need to run 'sysctl -w vm.max_map_count=262144' on the host machine + +elasticsearch5: + image: elasticsearch:5 + command: elasticsearch + ports: + - "10200:9200" + - "10300:9300" diff --git a/docker/blocks/graphite/fig b/docker/blocks/graphite/fig index 84da45341e1..60acb8c1131 100644 --- a/docker/blocks/graphite/fig +++ b/docker/blocks/graphite/fig @@ -8,3 +8,10 @@ graphite: - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro +fake-graphite-data: + image: grafana/fake-data-gen + net: bridge + environment: + FD_DATASOURCE: graphite + FD_PORT: 2003 + diff --git a/docker/blocks/influxdb/config.toml b/docker/blocks/influxdb/config.toml deleted file mode 100644 index 23834b22e3d..00000000000 --- a/docker/blocks/influxdb/config.toml +++ /dev/null @@ -1,75 +0,0 @@ -bind-address = "0.0.0.0" - -[logging] -level = "debug" -file = "/opt/influxdb/shared/data/influxdb.log" # stdout to log to standard out - -[admin] -port = 8083 # binding is disabled if the port isn't set -assets = "/opt/influxdb/current/admin" - -[api] -port = 8086 # binding is disabled if the port isn't set - -read-timeout = "5s" - -[input_plugins] - - [input_plugins.graphite] - enabled = true - port = 2004 - database = "graphite" # store graphite data in this database - - -[raft] -port = 8090 -dir = "/opt/influxdb/shared/data/raft" - -[storage] -dir = "/opt/influxdb/shared/data/db" -# How many requests to potentially buffer in memory. If the buffer gets filled then writes -# will still be logged and once the local storage has caught up (or compacted) the writes -# will be replayed from the WAL -write-buffer-size = 10000 -default-engine = "rocksdb" -max-open-shards = 0 -point-batch-size = 100 -write-batch-size = 5000000 -retention-sweep-period = "10m" - -[storage.engines.rocksdb] -max-open-files = 1000 -lru-cache-size = "200m" - -[storage.engines.leveldb] -max-open-files = 1000 -lru-cache-size = "200m" - -[cluster] -protobuf_port = 8099 -protobuf_timeout = "2s" # the write timeout on the protobuf conn any duration parseable by time.ParseDuration -protobuf_heartbeat = "200ms" # the heartbeat interval between the servers. must be parseable by time.ParseDuration -protobuf_min_backoff = "1s" # the minimum backoff after a failed heartbeat attempt -protobuf_max_backoff = "10s" # the maxmimum backoff after a failed heartbeat attempt -write-buffer-size = 10000 -ax-response-buffer-size = 100000 -oncurrent-shard-query-limit = 10 - -[sharding] - replication-factor = 1 - - [sharding.short-term] - duration = "7d" - split = 1 - - [sharding.long-term] - duration = "30d" - split = 1 - # split-random = "/^Hf.*/" - -[wal] -dir = "/opt/influxdb/shared/data/wal" -flush-after = 1000 # the number of writes after which wal will be flushed, 0 for flushing on every write -bookmark-after = 1000 # the number of writes after which a bookmark will be created -index-after = 1000 -requests-per-logfile = 10000 diff --git a/docker/blocks/influxdb/fig b/docker/blocks/influxdb/fig index 931f8a2640a..8821c010a98 100644 --- a/docker/blocks/influxdb/fig +++ b/docker/blocks/influxdb/fig @@ -1,6 +1,17 @@ influxdb: - image: tutum/influxdb:latest + image: influxdb:latest + container_name: influxdb ports: - "2004:2004" - "8083:8083" - "8086:8086" + volumes: + - ./blocks/influxdb/influxdb.conf:/etc/influxdb/influxdb.conf + +fake-influxdb-data: + image: grafana/fake-data-gen + net: bridge + environment: + FD_DATASOURCE: influxdb + FD_PORT: 8086 + diff --git a/docker/blocks/influxdb/influxdb.conf b/docker/blocks/influxdb/influxdb.conf new file mode 100644 index 00000000000..c0331ce7449 --- /dev/null +++ b/docker/blocks/influxdb/influxdb.conf @@ -0,0 +1,92 @@ +reporting-disabled = false + +[meta] + # Where the metadata/raft database is stored + dir = "/var/lib/influxdb/meta" + + retention-autocreate = true + + # If log messages are printed for the meta service + logging-enabled = true + pprof-enabled = false + + # The default duration for leases. + lease-duration = "1m0s" + +[data] + # Controls if this node holds time series data shards in the cluster + enabled = true + + dir = "/var/lib/influxdb/data" + + # These are the WAL settings for the storage engine >= 0.9.3 + wal-dir = "/var/lib/influxdb/wal" + wal-logging-enabled = true + + +[coordinator] + write-timeout = "10s" + max-concurrent-queries = 0 + query-timeout = "0" + log-queries-after = "0" + max-select-point = 0 + max-select-series = 0 + max-select-buckets = 0 + +[retention] + enabled = true + check-interval = "30m" + +[shard-precreation] + enabled = true + check-interval = "10m" + advance-period = "30m" + +[monitor] + store-enabled = true # Whether to record statistics internally. + store-database = "_internal" # The destination database for recorded statistics + store-interval = "10s" # The interval at which to record statistics + +[admin] + enabled = true + bind-address = ":8083" + https-enabled = false + https-certificate = "/etc/ssl/influxdb.pem" + +[http] + enabled = true + bind-address = ":8086" + auth-enabled = true + log-enabled = true + write-tracing = false + pprof-enabled = false + https-enabled = false + https-certificate = "/etc/ssl/influxdb.pem" + ### Use a separate private key location. + # https-private-key = "" + max-row-limit = 10000 + realm = "InfluxDB" + + unix-socket-enabled = false # enable http service over unix domain socket + # bind-socket = "/var/run/influxdb.sock" + +[subscriber] + enabled = true + +[[graphite]] + enabled = false + +[[collectd]] + enabled = false + +[[opentsdb]] + enabled = false + +[[udp]] + enabled = false + +[continuous_queries] + log-enabled = true + enabled = true + # run-interval = "1s" # interval for how often continuous queries will be checked if they need to run + diff --git a/docker/blocks/memcached/fig b/docker/blocks/memcached/fig new file mode 100644 index 00000000000..a0da9df2bc2 --- /dev/null +++ b/docker/blocks/memcached/fig @@ -0,0 +1,5 @@ +memcached: + image: memcached:latest + ports: + - "11211:11211" + diff --git a/docker/blocks/opentsdb/fig b/docker/blocks/opentsdb/fig index 34bbf4b854c..c346475e9a3 100644 --- a/docker/blocks/opentsdb/fig +++ b/docker/blocks/opentsdb/fig @@ -2,4 +2,10 @@ opentsdb: image: opower/opentsdb:latest ports: - "4242:4242" - + +fake-opentsdb-data: + image: grafana/fake-data-gen + net: bridge + environment: + FD_DATASOURCE: opentsdb + diff --git a/docker/blocks/postgres/fig b/docker/blocks/postgres/fig index c7458cbe400..33499688810 100644 --- a/docker/blocks/postgres/fig +++ b/docker/blocks/postgres/fig @@ -3,5 +3,6 @@ postgrestest: environment: POSTGRES_USER: grafana POSTGRES_PASSWORD: password + POSTGRES_DATABASE: grafana ports: - "5432:5432" diff --git a/docker/blocks/prometheus/fig b/docker/blocks/prometheus/fig index 0880902c9fd..ec4dd8e4b16 100644 --- a/docker/blocks/prometheus/fig +++ b/docker/blocks/prometheus/fig @@ -1,6 +1,22 @@ prometheus: build: blocks/prometheus + net: host ports: - "9090:9090" volumes: - /var/docker/prometheus:/prometheus-data + +node_exporter: + image: prom/node-exporter + net: host + ports: + - "9100:9100" + +fake-prometheus-data: + image: grafana/fake-data-gen + net: host + ports: + - "9091:9091" + environment: + FD_DATASOURCE: prom + diff --git a/docker/blocks/prometheus/prometheus.yml b/docker/blocks/prometheus/prometheus.yml index 5c853622af3..35be33b80a7 100644 --- a/docker/blocks/prometheus/prometheus.yml +++ b/docker/blocks/prometheus/prometheus.yml @@ -22,5 +22,6 @@ scrape_configs: # metrics_path defaults to '/metrics' # scheme defaults to 'http'. - target_groups: - - targets: ['localhost:9090', '172.17.0.1:9091'] + static_configs: + #- targets: ['localhost:9090', '172.17.0.1:9091', '172.17.0.1:9100', '172.17.0.1:9150'] + - targets: ['localhost:9090', '127.0.0.1:9091', '127.0.0.1:9100', '127.0.0.1:9150'] diff --git a/docker/production/Dockerfile b/docker/production/Dockerfile deleted file mode 100644 index 5017c2c1a36..00000000000 --- a/docker/production/Dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -FROM debian:jessie - -RUN apt-get -y update -RUN apt-get -y install libfontconfig - -RUN mkdir -p /opt/grafana - -ADD tmp/ /opt/grafana/ - -EXPOSE 3000 - -VOLUME ["/opt/grafana/data"] -VOLUME ["/opt/grafana/conf"] - -WORKDIR /opt/grafana/ -ENTRYPOINT ["./grafana", "web"] diff --git a/docker/production/README.md b/docker/production/README.md deleted file mode 100644 index 9b0e23baf75..00000000000 --- a/docker/production/README.md +++ /dev/null @@ -1,31 +0,0 @@ - -# Grafana docker image - -This container currently only contains the in development alpha of Grafana 2.0 (ie non production use). The -`#develop` tag is constantly updated as we make progress towards a beta release. - - -## Running your Grafana image --------------------------- - -Start your image binding the external port `3000`. - - docker run -i -p 3000:3000 grafana/grafana - -Try it out, default admin user is admin/admin. - - -## Configuring your Grafana container - -All options defined in conf/grafana.ini can be overridden using environment variables, for example: - - -``` -docker run -i -p 3000:3000 \ - -e "GF_SERVER_ROOT_URL=http://grafana.server.name" \ - -e "GF_SECURITY_ADMIN_PASSWORD=secret \ - grafana/grafana:develop -``` - - - diff --git a/docker/production/build.sh b/docker/production/build.sh deleted file mode 100755 index d97b29de934..00000000000 --- a/docker/production/build.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -cp Dockerfile ../../ -cd ../../ - -go run build.go build - -grunt release - -docker build --tag "grafana/grafana:develop" . - -rm Dockerfile -cd docker/production - - diff --git a/docker/production/test_container.sh b/docker/production/test_container.sh deleted file mode 100755 index aa8fdba4cbf..00000000000 --- a/docker/production/test_container.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -docker run -i -p 3001:3000 \ - -e "GF_SERVER_ROOT_URL=http://grafana.server.name" \ - grafana/grafana:develop diff --git a/docs/Dockerfile b/docs/Dockerfile index 765ca86dbb7..7652cbd3e3f 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,25 +1,12 @@ FROM grafana/docs-base:latest -# TODO: need the full repo source to get the git version info -COPY . /src +# to get the git info for this repo +# COPY config.toml /site -# Reset the /docs dir so we can replace the theme meta with the new repo's git info -RUN git reset --hard +RUN rm -rf /site/content/* -# Then copy the desired docs into the /docs/sources/ dir -COPY ./sources/ /docs/sources +COPY ./sources /site/content/ -COPY ./VERSION /docs/VERSION +COPY awsconfig /site -COPY ./changed-files /docs/changed-files - -# adding the image spec will require Docker 1.5 and `docker build -f docs/Dockerfile .` -#COPY ./image/spec/v1.md /docs/sources/reference/image-spec-v1.md - -# TODO: don't do this - look at merging the yml file in build.sh -COPY ./mkdocs.yml /docs/mkdocs.yml - -COPY ./s3_website.json /docs/s3_website.json - -# Then build everything together, ready for mkdocs -RUN /docs/build.sh +VOLUME ["/site/content"] diff --git a/docs/Makefile b/docs/Makefile index b1a72adc3f8..718c4b52be7 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -1,28 +1,21 @@ -.PHONY: all binary build cross default docs docs-build docs-shell shell test test-unit test-integration test-integration-cli test-docker-py validate - -# env vars passed through directly to Docker's build scripts -# to allow things like `make DOCKER_CLIENTONLY=1 binary` easily -# `docs/sources/contributing/devenvironment.md ` and `project/PACKAGERS.md` have some limited documentation of some of these -DOCKER_ENVS := \ - -e BUILDFLAGS \ - -e DOCKER_CLIENTONLY \ - -e DOCKER_EXECDRIVER \ - -e DOCKER_GRAPHDRIVER \ - -e TESTDIRS \ - -e TESTFLAGS \ - -e TIMEOUT -# note: we _cannot_ add "-e DOCKER_BUILDTAGS" here because even if it's unset in the shell, that would shadow the "ENV DOCKER_BUILDTAGS" set in our Dockerfile, which is very important for our official builds - -# to allow `make DOCSDIR=docs docs-shell` (to create a bind mount in docs) -DOCS_MOUNT := $(if $(DOCSDIR),-v $(CURDIR)/$(DOCSDIR):/$(DOCSDIR)) +.PHONY: all default docs docs-build docs-shell shell test +# to allow `make DOCSDIR=1 docs-shell` (to create a bind mount in docs) +DOCS_MOUNT := $(if $(DOCSDIR),-v $(CURDIR):/docs/content/grafana/) # to allow `make DOCSPORT=9000 docs` -DOCSPORT := 8180 +DOCSPORT := 3004 + +# Get the IP ADDRESS +DOCKER_IP=$(shell python -c "import urlparse ; print urlparse.urlparse('$(DOCKER_HOST)').hostname or ''") +HUGO_BASE_URL=$(shell test -z "$(DOCKER_IP)" && echo localhost || echo "$(DOCKER_IP)") +HUGO_BIND_IP=0.0.0.0 GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null) -DOCKER_DOCS_IMAGE := grafana-docs-base$(if $(GIT_BRANCH),:$(GIT_BRANCH)) +GIT_BRANCH_CLEAN := $(shell echo $(GIT_BRANCH) | sed -e "s/[^[:alnum:]]/-/g") +DOCKER_DOCS_IMAGE := grafana/grafana-docs DOCKER_RUN_DOCS := docker run --rm -it $(DOCS_MOUNT) -e AWS_S3_BUCKET -e NOCACHE +SOURCES_HOST_DIR := "$(shell pwd)/sources" # for some docs workarounds (see below in "docs-build" target) GITCOMMIT := $(shell git rev-parse --short HEAD 2>/dev/null) @@ -30,21 +23,28 @@ GITCOMMIT := $(shell git rev-parse --short HEAD 2>/dev/null) default: docs docs: docs-build - $(DOCKER_RUN_DOCS) -p $(if $(DOCSPORT),$(DOCSPORT):)8000 "$(DOCKER_DOCS_IMAGE)" mkdocs serve + $(DOCKER_RUN_DOCS) -p 3004:3004 -p 3005:3005 -e DOCKERHOST "$(DOCKER_DOCS_IMAGE)" /bin/bash -c "grunt && grunt connect --port=3004" + +docs-watch: docs-build + $(DOCKER_RUN_DOCS) -p 3004:3004 -p 3005:3005 -v $(SOURCES_HOST_DIR):/site/content -e DOCKERHOST "$(DOCKER_DOCS_IMAGE)" /bin/bash -c "grunt --env=dev-docs && grunt connect --port=3004 & grunt watch --port=3004 --env=dev-docs" + +docs-watch-mac: docs-build + $(DOCKER_RUN_DOCS) -p 3004:3004 -p 3005:3005 -v $(SOURCES_HOST_DIR):/site/content -e DOCKERHOST "$(DOCKER_DOCS_IMAGE)" /bin/bash -c "grunt --env=dev-docs-mac && grunt connect --port=3004 & grunt watch --port=3004 --env=dev-docs-mac" + +publish: docs-build + $(DOCKER_RUN_DOCS) "$(DOCKER_DOCS_IMAGE)" /bin/bash -c "./publish.sh staging-docs v3.1" + +publish-prod: docs-build + $(DOCKER_RUN_DOCS) "$(DOCKER_DOCS_IMAGE)" /bin/bash -c "./publish.sh prod-docs root" + +docs-draft: docs-build + $(DOCKER_RUN_DOCS) -p $(if $(DOCSPORT),$(DOCSPORT):)8000 -e DOCKERHOST "$(DOCKER_DOCS_IMAGE)" hugo server --buildDrafts="true" --port=$(DOCSPORT) --baseUrl=$(HUGO_BASE_URL) --bind=$(HUGO_BIND_IP) docs-shell: docs-build $(DOCKER_RUN_DOCS) -p $(if $(DOCSPORT),$(DOCSPORT):)8000 "$(DOCKER_DOCS_IMAGE)" bash -docs-release: docs-build - $(DOCKER_RUN_DOCS) -e OPTIONS -e BUILD_ROOT -e DISTRIBUTION_ID \ - -v $(CURDIR)/awsconfig:/docs/awsconfig \ - "$(DOCKER_DOCS_IMAGE)" ./release.sh - -docs-test: docs-build - $(DOCKER_RUN_DOCS) "$(DOCKER_DOCS_IMAGE)" ./test.sh +test: docs-build + $(DOCKER_RUN_DOCS) -p $(if $(DOCSPORT),$(DOCSPORT):)8000 "$(DOCKER_DOCS_IMAGE)" docs-build: - git fetch https://github.com/grafana/grafana.git docs-2.6 && git diff --name-status FETCH_HEAD...HEAD -- . > changed-files - echo "$(GIT_BRANCH)" > GIT_BRANCH - echo "$(GITCOMMIT)" > GITCOMMIT docker build -t "$(DOCKER_DOCS_IMAGE)" . diff --git a/docs/README.md b/docs/README.md index 36c636fcc72..65bd5714615 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,7 +1,15 @@ -To build the docs locally, you need to have docker installed. The docs are built using a custom [docker](https://www.docker.com/) -image and [mkdocs](http://www.mkdocs.org/). +# Building The Docs -Build the `grafana/docs-base:latest` image: +To build the docs locally, you need to have docker installed. The +docs are built using a custom [docker](https://www.docker.com/) image +and the [mkdocs](http://www.mkdocs.org/) tool. + +**Prepare the Docker Image**: + +Build the `grafana/docs-base:latest` image. Run these commands in the +same directory this file is in. **Note** that you may require ``sudo`` +when running ``make docs-build`` depending on how your system's docker +service is configured): ``` $ git clone https://github.com/grafana/docs-base @@ -9,10 +17,45 @@ $ cd docs-base $ make docs-build ``` -To build the docs: +**Build the Documentation**: + +Now that the docker image has been prepared we can build the +docs. Switch your working directory back to the directory this file +(README.md) is in and run (possibly with ``sudo``): + ``` -$ cd docs $ make docs ``` +This command will not return control of the shell to the user. Instead +the command is now running a new docker container built from the image +we created in the previous step. + Open [localhost:8180](http://localhost:8180) to view the docs. + +**Note** that after running ``make docs`` you may notice a message +like this in the console output + +> Running at: http://0.0.0.0:8000/ + +This is misleading. That is **not** the port the documentation is +served from. You must browse to port **8180** to view the new +documentation. + + +# Adding a New Page + +Adding a new page requires updating the ``mkdocs.yml`` file which is +located in this directory. + +For example, if you are adding documentation for a new HTTP API called +``preferences`` you would: + +1. Create the file ``docs/sources/http_api/preferences.md`` +1. Add a reference to it in ``docs/sources/http_api/overview.md`` +1. Update the list under the **pages** key in the ``docs/mkdocs.yml`` file with a reference to your new page: + + +```yaml +- ['http_api/preferences.md', 'API', 'Preferences API'] +``` diff --git a/docs/VERSION b/docs/VERSION index fcdb2e109f6..fd2a01863fd 100644 --- a/docs/VERSION +++ b/docs/VERSION @@ -1 +1 @@ -4.0.0 +3.1.0 diff --git a/docs/config.toml b/docs/config.toml new file mode 100644 index 00000000000..c8d093a81d7 --- /dev/null +++ b/docs/config.toml @@ -0,0 +1,70 @@ +baseurl = "http://localhost:3002/" +languageCode = "en-us" +title = "Grafana Docs" +canonifyurls = false +relativeURLs = false +verbose = true +enableRobotsTXT = true +disableSitemap = false +disableRSS = true + +[[menu.top]] + name = "Docs" + url = "" + weight = 1 + +[[menu.top]] + name = "Community" + url = "/community" + weight = 2 + +[[menu.top]] + name = "Support" + url = "/support" + weight = 3 + +[[menu.top]] + name = "Plugins" + url = "https://grafana.net/plugins" + weight = 4 + +[[menu.top]] + name = "Dashboards" + url = "https://grafana.net/dashboards" + weight = 5 + +[[menu.top]] + name = "Hosting" + url = "/hosting" + weight = 6 + +[[menu.top]] + name = "Github" + url = "https://github.com/grafana/grafana" + weight = 7 + +## Main +[[menu.main]] + name = "Feature Gallery" + url = "/features" + weight = 1 + +[[menu.main]] + name = "Live Demo" + url = "http://play.grafana.org" + weight = 2 + +[[menu.main]] + name = "Download" + url = "/download" + weight = 3 + +[[menu.main]] + name = "Blog" + url = "/blog" + weight = 4 + + + + + diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml deleted file mode 100644 index 46b0b964b59..00000000000 --- a/docs/mkdocs.yml +++ /dev/null @@ -1,99 +0,0 @@ -site_name: Grafana Documentation -#site_url: http://docs.grafana.com/ -site_url: / -site_description: Documentation for Grafana, The Graphite and Influxdb dashboard and graph composer -site_favicon: img/fav32.png - -dev_addr: '0.0.0.0:8000' - -repo_url: https://github.com/grafana/grafana/ - -docs_dir: sources - -include_search: true - -use_absolute_urls: true - -# theme: docker -theme_dir: ./theme/mkdocs/ -theme_center_lead: false - -copyright: Copyright © 2014-2015, Coding Instinct AB. -google_analytics: ['UA-47280256-1', 'grafana.org'] - - -pages: - -# Introduction: -# - ['index.md', 'Project', 'About Grafana'] -# - ['project/cla.md', 'Project', 'Contributor License Agreement'] - -- ['index.md', '**HIDDEN**'] -- ['installation/index.md', 'Installation', 'Installation'] -- ['installation/debian.md', 'Installation', 'Installing on Debian / Ubuntu'] -- ['installation/rpm.md', 'Installation', 'Installing on RPM-based Linux'] -- ['installation/mac.md', 'Installation', 'Installing on Mac OS X'] -- ['installation/windows.md', 'Installation', 'Installing on Windows'] -- ['installation/docker.md', 'Installation', 'Installing on Docker'] -- ['project/building_from_source.md', 'Installation', 'Building from Source'] - -- ['installation/configuration.md', 'Installation', 'Configuration'] -- ['installation/ldap.md', 'Installation', 'LDAP Integration'] -- ['installation/provisioning.md', 'Installation', 'Provisioning'] -- ['installation/performance.md', 'Installation', 'Performance Tips'] -- ['installation/troubleshooting.md', 'Installation', 'Troubleshooting'] -- ['installation/migrating_to2.md', 'Installation', 'Migrating from v1.x to v2.x'] - -- ['guides/basic_concepts.md', 'User Guides', 'Basic Concepts'] -- ['guides/gettingstarted.md', 'User Guides', 'Getting Started'] -- ['guides/whats-new-in-v2-6.md', 'User Guides', "What's New in Grafana v2.6"] -- ['guides/whats-new-in-v2-5.md', 'User Guides', "What's New in Grafana v2.5"] -- ['guides/whats-new-in-v2-1.md', 'User Guides', "What's New in Grafana v2.1"] -- ['guides/whats-new-in-v2.md', 'User Guides', "What's New in Grafana v2.0"] -- ['guides/screencasts.md', 'User Guides', 'Screencasts'] - -- ['reference/graph.md', 'Reference', 'Graph Panel'] -- ['reference/singlestat.md', 'Reference', 'Singlestat Panel'] -- ['reference/table_panel.md', 'Reference', 'Table Panel'] -- ['reference/dashlist.md', 'Reference', 'Dashboard List Panel'] -- ['reference/sharing.md', 'Reference', 'Sharing'] -- ['reference/annotations.md', 'Reference', 'Annotations'] -- ['reference/timerange.md', 'Reference', 'Time Range'] -- ['reference/search.md', 'Reference', 'Search'] -- ['reference/templating.md', 'Reference', 'Templating'] -- ['reference/scripting.md', 'Reference', 'Scripting'] -- ['reference/playlist.md', 'Reference', 'Playlist'] -- ['reference/export_import.md', 'Reference', 'Import & Export'] -- ['reference/admin.md', 'Reference', 'Administration'] -- ['reference/keyboard_shortcuts.md', 'Reference', 'Keyboard Shortcuts'] - -- ['datasources/overview.md', 'Data Sources', 'Overview'] -- ['datasources/graphite.md', 'Data Sources', 'Graphite'] -- ['datasources/elasticsearch.md', 'Data Sources', 'Elasticsearch'] -- ['datasources/cloudwatch.md', 'Data Sources', 'CloudWatch'] -- ['datasources/influxdb.md', 'Data Sources', 'InfluxDB'] -- ['datasources/opentsdb.md', 'Data Sources', 'OpenTSDB'] -- ['datasources/kairosdb.md', 'Data Sources', 'KairosDB'] -- ['datasources/prometheus.md', 'Data Sources', 'Prometheus'] - -- ['http_api/overview.md', 'API', 'Overview'] -- ['http_api/auth.md', 'API', 'Authentication API'] -- ['http_api/dashboard.md', 'API', 'Dashboard API'] -- ['http_api/data_source.md', 'API', 'Data Source API'] -- ['http_api/org.md', 'API', 'Organisation API'] -- ['http_api/user.md', 'API', 'User API'] -- ['http_api/admin.md', 'API', 'Admin API'] -- ['http_api/snapshot.md', 'API', 'Snapshot API'] -- ['http_api/other.md', 'API', 'Other API'] - -- ['plugins/index.md', 'Plugins', 'Overview'] -- ['plugins/installation.md', 'Plugins', 'Installation'] -- ['plugins/development.md', 'Plugins', 'Development'] -- ['plugins/apps.md', 'Plugins', 'Apps'] -- ['plugins/datasources.md', 'Plugins', 'Datasources'] -- ['plugins/panels.md', 'Plugins', 'Panels'] - -- ['tutorials/index.md', 'Tutorials', 'Tutorials'] -- ['tutorials/hubot_howto.md', 'Tutorials', 'How To integrate Hubot and Grafana'] - -- ['jsearch.md', '**HIDDEN**'] diff --git a/docs/sources/administration/index.md b/docs/sources/administration/index.md new file mode 100644 index 00000000000..334285db08b --- /dev/null +++ b/docs/sources/administration/index.md @@ -0,0 +1,11 @@ ++++ +title = "Administration" +description = "Administration" +type = "docs" +[menu.docs] +name = "Administration" +identifier = "admin" +weight = 2 ++++ + + diff --git a/docs/sources/alerting/index.md b/docs/sources/alerting/index.md new file mode 100644 index 00000000000..1317048a499 --- /dev/null +++ b/docs/sources/alerting/index.md @@ -0,0 +1,9 @@ ++++ +title = "Alerting" +type = "docs" +[menu.docs] +identifier = "alerting" +parent = "features" +weight = 6 ++++ + diff --git a/docs/sources/alerting/metrics.md b/docs/sources/alerting/metrics.md new file mode 100644 index 00000000000..b0bf5c9f4fc --- /dev/null +++ b/docs/sources/alerting/metrics.md @@ -0,0 +1,23 @@ ++++ +title = "Alerting Metrics" +description = "Alerting Metrics Guide" +keywords = ["Grafana", "alerting", "guide", "metrics"] +type = "docs" +[menu.docs] +name = "Metrics" +parent = "alerting" +weight = 2 ++++ + +# Metrics from the alert engine + +> Alerting is only available in Grafana v4.0 and above. + +The alert engine publish some internal metrics about itself. You can read more about how Grafana published [interal metrics](/installation/configuration/#metrics) + +Description | Type | Metric name +---------- | ----------- | ---------- +Total number of alerts | counter | `alerting.active_alerts` +Alert execution result | counter | `alerting.result` +Notifications sent counter | counter | `alerting.notifications_sent` +Alert execution timer | timer | `alerting.execution_time` diff --git a/docs/sources/alerting/notifications.md b/docs/sources/alerting/notifications.md new file mode 100644 index 00000000000..9f8d3c36120 --- /dev/null +++ b/docs/sources/alerting/notifications.md @@ -0,0 +1,104 @@ ++++ +title = "Alerting Notifications" +description = "Alerting Notifications Guide" +keywords = ["Grafana", "alerting", "guide", "notifications"] +type = "docs" +[menu.docs] +name = "Notifications" +parent = "alerting" +weight = 2 ++++ + + +# Alert Notifications + +{{< imgbox max-width="40%" img="/img/docs/v4/alert_notifications_menu.png" caption="Alerting notifications" >}} + +> Alerting is only available in Grafana v4.0 and above. + +When an alert changes state it sends out notifications. Each alert rule can have +multiple notifications. But in order to add a notification to an alert rule you first need +to add and configure a `notification` object. This is done from the Alerting/Notifications page. + +## Notification Setup + +On the notifications list page hit the `New Notification` button to go the the page where you +can configure and setup a new notification. + +You specify name and type, and type specific options. You can also test the notification to make +sure it's working and setup correctly. + +### Send on all alerts + +When checked this option will make this notification used for all alert rules, existing and new. + +## Supported notification types + +Grafana ships with a set of notification types. More will be added in future releases. + +### Email + +To enable email notification you have to setup [SMTP settings](/installation/configuration/#smtp) +in the Grafana config. Email notification will upload an image of the alert graph to an +external image destination if available or fallback on attaching the image in the email. + +### Slack + +{{< imgbox max-width="40%" img="/img/docs/v4/slack_notification.png" caption="Alerting Slack Notification" >}} + +To set up slack you need to configure an incoming webhook url at slack. You can follow their guide for how +to do that https://api.slack.com/incoming-webhooks If you want to include screenshots of the firing alerts +in the slack messages you have to configure the [external image destination](#external-image-store) in Grafana. + +Setting | Description +---------- | ----------- +Recipient | allows you to override the slack recipient. +Mention | make it possible to include a mention in the slack notification sent by Grafana. Ex @here or @channel + +### Webhook + +The webhook notification is a simple way to send information about an state change over HTTP to a custom endpoint. +Using this notification you could integrated Grafana into any system you choose, by yourself. + +Example json body: +```json +{ + "title": "My alert", + "ruleId": 1, + "ruleName": "Load peaking!", + "ruleUrl": "http://url.to.grafana/db/dashboard/my_dashboard?panelId=2", + "state": "Alerting", + "imageUrl": "http://s3.image.url", + "message": "Load is peaking. Make sure the traffic is real and spin up more webfronts", + "evalMatches": [ + { + "metric": "requests", + "tags": {}, + "value": 122 + } + ] +} +``` + +### PagerDuty + +To set up PagerDuty, all you have to do is to provide an api key. + +Setting | Description +---------- | ----------- +Integration Key | Integration key for pagerduty. +Auto resolve incidents | Resolve incidents in pagerduty once the alert goes back to ok + + +# Enable images in notifications {#external-image-store} + +Grafana can render the panel associated with the alert rule and include that in the notification. Some types +of notifications require that this image be publicly accessable (Slack for example). In order to support +images in notifications like Slack Grafana can upload the image to an image store. It currently supports +Amazon S3 for this and Webdav. So to set that up you need to configure the +[external image uploader](/installation/configuration/#external-image-storage) in your grafana-server ini +config file. + +This is an optional requirement, you can get slack and email notifications without setting this up. + + diff --git a/docs/sources/alerting/rules.md b/docs/sources/alerting/rules.md new file mode 100644 index 00000000000..af3cfecfdb8 --- /dev/null +++ b/docs/sources/alerting/rules.md @@ -0,0 +1,152 @@ ++++ +title = "Alerting Engine & Rules Guide" +description = "Configuring Alert Rules" +keywords = ["grafana", "alerting", "guide", "rules"] +type = "docs" +[menu.docs] +name = "Engine & Rules" +parent = "alerting" +weight = 1 ++++ + +# Alerting Engine & Rules Guide + +> Alerting is only available in Grafana v4.0 and above. + +## Introduction + +{{< imgbox max-width="40%" img="/img/docs/v4/drag_handles_gif.gif" caption="Alerting overview" >}} + +Alerting in Grafana allows you to attach rules to your dashboard panels. When you save the dashboard +Grafana will extract the alert rules into a separate alert rule storage and schedule them for evaluation. + +In the alert tab of the graph panel you can configure how often the alert rule should be evaluated +and the conditions that need to be met for the alert to change state and trigger its +[notifications]({{< relref "notifications.md" >}}). + +## Execution + +The alert rules are evaluated in the Grafana backend in a scheduler and query execution engine that is part +of core Grafana. Only some data soures are supported right now. They include `Graphite`, `Prometheus`, +`InfluxDB` and `OpenTSDB`. + +### Clustering + +We have not implemented clustering yet. So if you run multiple instances of grafana-server +you have to make sure [execute_alerts]({{< relref "/installation/configuration.md#alerting" >}}) +is true on only one instance or otherwise you will get duplicated notifications. + +
+ +## Rule Config + +{{< imgbox max-width="40%" img="/img/docs/v4/alerting_conditions.png" caption="Alerting Conditions" >}} + +Currently only the graph panel supports alert rules but this will be added to the **Singlestat** and **Table** +panels as well in a future release. + +### Name & Evaluation interval + +Here you can specify the name of the alert rule and how often the scheduler should evaluate the alert rule. + +### Conditions + +Currently the only condition type that exists is a `Query` condition that allows you to +specify a query letter, time range and an aggregation function. The letter refers to +a query you already have added in the **Metrics** tab. The result from the query and the aggregation function is +a single value that is then used in the threshold check. The query used in an alert rule cannot +contain any template variables. Currently we only support `AND` and `OR` operators between conditions and they are executed serially. +For example, we have 3 conditions in the following order: +`condition:A(evaluates to: TRUE) OR condition:B(evaluates to: FALSE) AND condition:C(evaluates to: TRUE)` +so the result will be calculated as ((TRUE OR FALSE) AND TRUE) = TRUE. + +We plan to add other condition types in the future, like `Other Alert`, where you can include the state +of another alert in your conditions, and `Time Of Day`. + +#### Multiple Series + +If a query returns multiple series then the aggregation function and threshold check will be evaluated for each series. +What Grafana does not do currently is track alert rule state **per series**. This has implications that is exemplified +in the scenario below. + +- Alert condition with query that returns 2 series: **server1** and **server2** +- **server1** series cause the alert rule to fire and switch to state `Alerting` +- Notifications are sent out with message: _load peaking (server1)_ +- In a subsequence evaluation of the same alert rule the **server2** series also cause the alert rule to fire +- No new notifications are sent as the alert rule is already in state `Alerting`. + +So as you can see from the above scenario Grafana will not send out notifications when other series cause the alert +to fire if the rule already is in state `Alerting`. To improve support for queries that return multiple series +we plan to track state **per series** in a future release. + +### No Data / Null values + +Below you condition you can configure how the rule evaluation engine should handle queries that return no data or only null valued +data. + +No Data Option | Description +------------ | ------------- +NoData | Set alert rule state to `NoData` +Alerting | Set alert rule state to `Alerting` +Keep Last State | Keep the current alert rule state, what ever it is. + +### Execution errors or timeouts + +The last option is how to handle execution or timeout errors. + +Error or timeout option | Description +------------ | ------------- +Alerting | Set alert rule state to `Alerting` +Keep Last State | Keep the current alert rule state, what ever it is. + +If you an unreliable time series store that where queries sometime timeout or fail randomly you can set this option +t `Keep Last State` to basically ignore them. + +## Notifications + +In alert tab you can also specify alert rule notifications along with a detailed messsage about the alert rule. +The message can contain anything, information about how you might solve the issue, link to runbook etc. + +The actual notifications are configured and shared between multiple alerts. Read the +[Notifications]({{< relref "notifications.md" >}}) guide for how to configure and setup notifications. + +## Alert State History & Annotations + +Alert state changes are recorded in the internal annotation table in Grafana's database. The state changes +are visualized as annotations in the alert rule's graph panel. You can also go into the `State history` +submenu in the alert tab to view & clear state history. + +## Troubleshooting + +{{< imgbox max-width="40%" img="/img/docs/v4/alert_test_rule.png" caption="Test Rule" >}} + +First level of troubleshooting you can do is hit the **Test Rule** button. You will get result back that you can expand +to the point where you can see the raw data that was returned form your query. + +Further troubleshooting can also be done by inspecting the grafana-server log. If it's not an error or for some reason +the log does not say anything you can enable debug logging for some relevant components. This is done +in Grafana's ini config file. + +Example showing loggers that could be relevant when troubleshooting alerting. + +```ini +[log] +filters = alerting.scheduler:debug \ + alerting.engine:debug \ + alerting.resultHandler:debug \ + alerting.evalHandler:debug \ + alerting.evalContext:debug \ + alerting.extractor:debug \ + alerting.notifier:debug \ + alerting.notifier.slack:debug \ + alerting.notifier.pagerduty:debug \ + alerting.notifier.email:debug \ + alerting.notifier.webhook:debug \ + tsdb.graphite:debug \ + tsdb.prometheus:debug \ + tsdb.opentsdb:debug \ + tsdb.influxdb:debug \ +``` + +If you want to log raw query sent to your TSDB and raw response in log you also have to set grafana.ini option `app_mode` to +`development`. diff --git a/docs/sources/archive.md b/docs/sources/archive.md new file mode 100644 index 00000000000..af4ab5e7a8f --- /dev/null +++ b/docs/sources/archive.md @@ -0,0 +1,21 @@ ++++ +title = "Docs Archive" +keywords = ["grafana", "archive", "documentation", "guide"] +type = "docs" +[menu.docs] +name = "Docs Archive" +weight = 200 ++++ + +# Docs Archive + +Here you can find links to older versions of the documentation that might be better suited for your version +of Grafana. + +- [Latest](/) +- [Version 3.1](/v3.1) +- [Version 3.0](/v3.0) +- [Version 2.6](/v2.6) +- [Version 2.5](/v2.5) +- [Version 2.1](/v2.1) +- [Version 2.0](/v2.0) diff --git a/docs/sources/datasources/cloudwatch.md b/docs/sources/datasources/cloudwatch.md index c69d3579784..b4ad0b3288e 100644 --- a/docs/sources/datasources/cloudwatch.md +++ b/docs/sources/datasources/cloudwatch.md @@ -1,16 +1,22 @@ ----- -page_title: Cloudwatch -page_description: Cloudwatch grafana datasource documentation -page_keywords: Cloudwatch, grafana, documentation, datasource, docs ---- ++++ +title = "AWS CloudWatch" +description = "Guide for using CloudWatch in Grafana" +keywords = ["grafana", "cloudwatch", "guide"] +type = "docs" +[menu.docs] +name = "AWS Cloudwatch" +identifier = "cloudwatch" +parent = "datasources" +weight = 10 ++++ -# CloudWatch +# Using AWS CloudWatch in Grafana Grafana ships with built in support for CloudWatch. You just have to add it as a data source and you will be ready to build dashboards for you CloudWatch metrics. ## Adding the data source -![](/img/cloudwatch/cloudwatch_add.png) +![](/img/docs/cloudwatch/cloudwatch_add.png) 1. Open the side menu by clicking the the Grafana icon in the top header. 2. In the side menu under the `Dashboards` link you should find a link named `Data Sources`. @@ -19,6 +25,7 @@ be ready to build dashboards for you CloudWatch metrics. 3. Click the `Add new` link in the top header. 4. Select `CloudWatch` from the dropdown. + > NOTE: If at any moment you have issues with getting this datasource to work and grafana is giving you undescriptive errors then dont forget to check your log file (try looking in /var/log/grafana/). Name | Description ------------ | ------------- @@ -26,6 +33,8 @@ Name | The data source name, important that this is the same as in Grafana v1.x Default | Default data source means that it will be pre-selected for new panels. Credentials profile name | Specify the name of the profile to use (if you use `~/aws/credentials` file), leave blank for default. This option was introduced in Grafana 2.5.1 Default Region | Used in query editor to set region (can be changed on per query basis) +Custom Metrics namespace | Specify the CloudWatch namespace of Custom metrics +Assume Role Arn | Specify the ARN of the role to assume ## Authentication @@ -39,6 +48,7 @@ Checkout AWS docs on [IAM Roles](http://docs.aws.amazon.com/AWSEC2/latest/UserGu ### AWS credentials file Create a file at `~/.aws/credentials`. That is the `HOME` path for user running grafana-server. + > NOTE: If you think you have the credentials file in the right place but it is still not working then you might try moving your .aws file to '/usr/share/grafana/' and make sure your credentials file has at most 0644 permissions. Example content: @@ -50,7 +60,7 @@ Example content: ## Metric Query Editor -![](/img/cloudwatch/query_editor.png) +![](/img/docs/cloudwatch/query_editor.png) You need to specify a namespace, metric, at least one stat, and at least one dimension. @@ -61,7 +71,7 @@ Name | Description ------- | -------- `regions()` | Returns a list of regions AWS provides their service. `namespaces()` | Returns a list of namespaces CloudWatch support. -`metrics(namespace)` | Returns a list of metrics in the namespace. +`metrics(namespace, [region])` | Returns a list of metrics in the namespace. (specify region for custom metrics) `dimension_keys(namespace)` | Returns a list of dimension keys in the namespace. `dimension_values(region, namespace, metric, dimension_key)` | Returns a list of dimension values matching the specified `region`, `namespace`, `metric` and `dimension_key`. `ebs_volume_ids(region, instance_id)` | Returns a list of volume id matching the specified `region`, `instance_id`. @@ -75,7 +85,7 @@ Example dimension queries which will return list of resources for individual AWS Service | Query ------- | ----- -EBS | `dimension_values(us-east-1,AWS/ELB,RequestCount,LoadBalancerName)` +ELB | `dimension_values(us-east-1,AWS/ELB,RequestCount,LoadBalancerName)` ElastiCache | `dimension_values(us-east-1,AWS/ElastiCache,CPUUtilization,CacheClusterId)` RedShift | `dimension_values(us-east-1,AWS/Redshift,CPUUtilization,ClusterIdentifier)` RDS | `dimension_values(us-east-1,AWS/RDS,CPUUtilization,DBInstanceIdentifier)` @@ -91,12 +101,12 @@ Example `ec2_instance_attribute()` query ec2_instance_attribute(us-east-1, InstanceId, { "tag:Environment": [ "production" ] }) -![](/img/v2/cloudwatch_templating.png) +![](/img/docs/v2/cloudwatch_templating.png) ## Cost -It's worth to mention that Amazon will charge you for CloudWatch API usage. CloudWatch costs -$0.01 per 1,000 GetMetricStatistics or ListMetrics requests. For each query Grafana will +Amazon provides 1 million CloudWatch API requests each month at no additional charge. Past this, +it costs $0.01 per 1,000 GetMetricStatistics or ListMetrics requests. For each query Grafana will issue a GetMetricStatistics request and every time you pick a dimension in the query editor Grafana will issue a ListMetrics request. diff --git a/docs/sources/datasources/elasticsearch.md b/docs/sources/datasources/elasticsearch.md index 314a0f4870b..345f68a9220 100644 --- a/docs/sources/datasources/elasticsearch.md +++ b/docs/sources/datasources/elasticsearch.md @@ -1,17 +1,23 @@ ----- -page_title: Elasticsearch -page_description: Elasticsearch grafana datasource documentation -page_keywords: Elasticsearch, grafana, kibana, documentation, datasource, docs ---- ++++ +title = "Using Elasticsearch in Grafana" +description = "Guide for using Elasticsearch in Grafana" +keywords = ["grafana", "elasticsearch", "guide"] +type = "docs" +[menu.docs] +name = "Elasticsearch" +parent = "datasources" +weight = 3 ++++ -# Elasticsearch +# Using Elasticsearch in Grafana Grafana ships with advanced support for Elasticsearch. You can do many types of simple or complex elasticsearch queries to visualize logs or metrics stored in elasticsearch. You can also annotate your graphs with log events stored in elasticsearch. ## Adding the data source -![](/img/v2/add_Graphite.jpg) + +![](/img/docs/v2/add_Graphite.jpg) 1. Open the side menu by clicking the the Grafana icon in the top header. 2. In the side menu under the `Dashboards` link you should find a link named `Data Sources`. @@ -26,7 +32,7 @@ Name | Description Name | The data source name, important that this is the same as in Grafana v1.x if you plan to import old dashboards. Default | Default data source means that it will be pre-selected for new panels. Url | The http protocol, ip and port of you elasticsearch server. -Access | Proxy = access via Grafana backend, Direct = access directory from browser. +Access | Proxy = access via Grafana backend, Direct = access directly from browser. Proxy access means that the Grafana backend will proxy all requests from the browser, and send them on to the Data Source. This is useful because it can eliminate CORS (Cross Origin Site Resource) issues, as well as eliminate the need to disseminate authentication details to the Data Source to the browser. @@ -41,14 +47,14 @@ Elasticsearch from the browser. You do this by specifying these to options in yo ### Index settings -![](/img/elasticsearch/elasticsearch_ds_details.png) +![](/img/docs/elasticsearch/elasticsearch_ds_details.png) Here you can specify a default for the `time field` and specify the name of your elasticsearch index. You can use a time pattern for the index name or a wildcard. ## Metric Query editor -![](/img/elasticsearch/query_editor.png) +![](/img/docs/elasticsearch/query_editor.png) The Elasticsearch query editor allows you to select multiple metrics and group by multiple terms or filters. Use the plus and minus icons to the right to add / remove metrics or group bys. Some metrics and group by have options, click the option text to expand the the row to view and edit metric or group by options. @@ -60,7 +66,7 @@ If you have Elasticsearch 2.x and Grafana 2.6 or above then you can use pipeline to hide metrics from appearing in the graph. This is useful for metrics you only have in the query to be used in a pipeline metric. -![](/img/elasticsearch/pipeline_metrics_editor.png) +![](/img/docs/elasticsearch/pipeline_metrics_editor.png) ## Templating @@ -86,7 +92,3 @@ The Elasticsearch datasource supports two types of queries you can use to fill t Use lucene format. - -## Annotations -TODO - diff --git a/docs/sources/datasources/graphite.md b/docs/sources/datasources/graphite.md index af53d0bf60c..44a4dff3761 100644 --- a/docs/sources/datasources/graphite.md +++ b/docs/sources/datasources/graphite.md @@ -1,17 +1,23 @@ ----- -page_title: Graphite query guide -page_description: Graphite query guide -page_keywords: grafana, graphite, metrics, query, documentation ---- ++++ +title = "Using Graphite in Grafana" +description = "Guide for using graphite in Grafana" +keywords = ["grafana", "graphite", "guide"] +type = "docs" +[menu.docs] +name = "Graphite" +identifier = "graphite" +parent = "datasources" +weight = 1 ++++ -# Graphite +# Using Graphite in Grafana Grafana has an advanced Graphite query editor that lets you quickly navigate the metric space, add functions, change function parameters and much more. The editor can handle all types of graphite queries. It can even handle complex nested queries through the use of query references. ## Adding the data source -![](/img/v2/add_Graphite.jpg) +![](/img/docs/v2/add_Graphite.jpg) 1. Open the side menu by clicking the the Grafana icon in the top header. 2. In the side menu under the `Dashboards` link you should find a link named `Data Sources`. @@ -26,7 +32,7 @@ Name | Description Name | The data source name, important that this is the same as in Grafana v1.x if you plan to import old dashboards. Default | Default data source means that it will be pre-selected for new panels. Url | The http protocol, ip and port of your graphite-web or graphite-api install. -Access | Proxy = access via Grafana backend, Direct = access directory from browser. +Access | Proxy = access via Grafana backend, Direct = access directly from browser. Proxy access means that the Grafana backend will proxy all requests from the browser, and send them on to the Data Source. This is useful because it can eliminate CORS (Cross Origin Site Resource) issues, as well as eliminate the need to disseminate authentication details to the Data Source to the browser. @@ -40,7 +46,7 @@ Direct access is still supported because in some cases it may be useful to acces Click the ``Select metric`` link to start navigating the metric space. One you start you can continue using the mouse or keyboard arrow keys. You can select a wildcard and still continue. -![](/img/animated_gifs/graphite_query1.gif) +![](/img/docs/animated_gifs/graphite_query1.gif) ### Functions Click the plus icon to the right to add a function. You can search for the function or select it from the menu. Once @@ -48,13 +54,13 @@ a function is selected it will be added and your focus will be in the text box o a parameter just click on it and it will turn into a text box. To delete a function click the function name followed by the x icon. -![](/img/animated_gifs/graphite_query2.gif) +![](/img/docs/animated_gifs/graphite_query2.gif) ### Optional parameters Some functions like aliasByNode support an optional second argument. To add this parameter specify for example 3,-2 as the first parameter and the function editor will adapt and move the -2 to a second parameter. To remove the second optional parameter just click on it and leave it blank and the editor will remove it. -![](/img/animated_gifs/func_editor_optional_params.gif) +![](/img/docs/animated_gifs/func_editor_optional_params.gif) ## Point consolidation @@ -74,7 +80,7 @@ values that exists in the wildcard position. You can also create nested variables that use other variables in their definition. For example `apps.$app.servers.*` uses the variable `$app` in its query definition. -![](/img/v2/templated_variable_parameter.png) +![](/img/docs/v2/templated_variable_parameter.png) ## Query Reference diff --git a/docs/sources/datasources/index.md b/docs/sources/datasources/index.md new file mode 100644 index 00000000000..af0062ddc51 --- /dev/null +++ b/docs/sources/datasources/index.md @@ -0,0 +1,31 @@ ++++ +title = "Data Sources" +type = "docs" +[menu.docs] +name = "Data Sources" +identifier = "datasources" +parent = "features" +weight = 5 ++++ + +# Data Source Overview +Grafana supports many different storage backends for your time series data (Data Source). Each Data Source has a specific Query Editor that is customized for the features and capabilities that the particular Data Source exposes. + + +## Querying +The query language and capabilities of each Data Source are obviously very different. You can combine data from multiple Data Sources onto a single Dashboard, but each Panel is tied to a specific Data Source that belongs to a particular Organization. + +## Supported Data Sources +The following datasources are officially supported: + +* [Graphite]({{< relref "graphite.md" >}}) +* [Elasticsearch]({{< relref "elasticsearch.md" >}}) +* [CloudWatch]({{< relref "cloudwatch.md" >}}) +* [InfluxDB]({{< relref "influxdb.md" >}}) +* [OpenTSDB]({{< relref "opentsdb.md" >}}) +* [Prometheus]({{< relref "prometheus.md" >}}) + +## Data source plugins + +Since grafana 3.0 you can install data sources as plugins. Checkout [Grafana.net](https://grafana.net/plugins) for more data sources. + diff --git a/docs/sources/datasources/influxdb.md b/docs/sources/datasources/influxdb.md index da8ca08f549..c6afdfdc8d4 100644 --- a/docs/sources/datasources/influxdb.md +++ b/docs/sources/datasources/influxdb.md @@ -1,19 +1,20 @@ ----- -page_title: InfluxDB query guide -page_description: InfluxDB query guide -page_keywords: grafana, influxdb, metrics, query, documentation ---- ++++ +title = "Using InfluxDB in Grafana" +description = "Guide for using InfluxDB in Grafana" +keywords = ["grafana", "influxdb", "guide"] +type = "docs" +[menu.docs] +name = "InfluxDB" +parent = "datasources" +weight = 3 ++++ -# InfluxDB +# Using InfluxDB in Grafana -There are currently two separate datasources for InfluxDB in Grafana: InfluxDB 0.8.x and InfluxDB 0.9.x. -The API and capabilities of InfluxDB 0.9.x are completely different from InfluxDB 0.8.x which is why Grafana handles -them as different data sources. - -InfluxDB 0.9 is rapidly evolving and we continue to track its API. InfluxDB 0.8 is no longer maintained by InfluxDB Inc, but we provide support as a convenience to existing users. +Grafana ships with very feature rich data source plugin for InfluxDB. Supporting a feature rich query editor, annotation and templating queries. ## Adding the data source -![](/img/v2/add_Influx.jpg) +![](/img/docs/v2/add_Influx.jpg) 1. Open the side menu by clicking the the Grafana icon in the top header. 2. In the side menu under the `Dashboards` link you should find a link named `Data Sources`. @@ -40,7 +41,7 @@ Password | Database user's password ## Query Editor -![](/img/influxdb/editor_v3.png) +![](/assets/img/blog/v2.6/influxdb_editor_v3.gif) You find the InfluxDB editor in the metrics tab in Graph or Singlestat panel's edit mode. You enter edit mode by clicking the panel title, then edit. The editor allows you to select metrics and tags. @@ -59,7 +60,7 @@ In the `SELECT` row you can specify what fields and functions you want to use. I group by time you need an aggregation function. Some functions like derivative require an aggregation function. The editor tries simplify and unify this part of the query. For example: -![](/img/influxdb/select_editor.png) +![](/img/docs/influxdb/select_editor.png) The above will generate the following InfluxDB `SELECT` clause: @@ -92,7 +93,7 @@ You can switch to raw query mode by clicking hamburger icon and then `Switch edi ### Table query / raw data -![](/img/influxdb/raw_data.png) +![](/assets/img/blog/v2.6/table_influxdb_logs.png) You can remove the group by time by clicking on the `time` part and then the `x` icon. You can change the option `Format As` to `Table` if you want to show raw data in the `Table` panel. @@ -115,9 +116,9 @@ the hosts variable only show hosts from the current selected region with a query SHOW TAG VALUES WITH KEY = "hostname" WHERE region =~ /$region/ ``` -> Always you `regex values` or `regex wildcard` for All format or multi select format. +> Always use `regex values` or `regex wildcard` for All format or multi select format. -![](/img/influxdb/templating_simple_ex1.png) +![](/img/docs/influxdb/templating_simple_ex1.png) ## Annotations Annotations allows you to overlay rich event information on top of graphs. diff --git a/docs/sources/datasources/kairosdb.md b/docs/sources/datasources/kairosdb.md index fc9b5682515..d27105d0ee1 100644 --- a/docs/sources/datasources/kairosdb.md +++ b/docs/sources/datasources/kairosdb.md @@ -10,8 +10,8 @@ Grafana v2.1 brings initial support for KairosDB Datasources. While the process ## Adding the data source to Grafana ![](/img/v2/add_KairosDB.jpg) -1. Open the side menu by clicking the the Grafana icon in the top header. -2. In the side menu under the `Dashboards` link you should find a link named `Data Sources`. +1. Open the side menu by clicking the the Grafana icon in the top header. +2. In the side menu under the `Dashboards` link you should find a link named `Data Sources`. > NOTE: If this link is missing in the side menu it means that your current user does not have the `Admin` role for the current organization. @@ -25,12 +25,12 @@ Name | Description Name | The data source name, important that this is the same as in Grafana v1.x if you plan to import old dashboards. Default | Default data source means that it will be pre-selected for new panels. Url | The http protocol, ip and port of your kairosdb server (default port is usually 8080) -Access | Proxy = access via Grafana backend, Direct = access directory from browser. +Access | Proxy = access via Grafana backend, Direct = access directly from browser. ## Query editor Open a graph in edit mode by click the title. -![](/img/v2/kairos_query_editor.png) +![](/img/v2/kairos_query_editor.jpg) For details on KairosDB metric queries checkout the official. - [Query Metrics - KairosDB 0.9.4 documentation](http://kairosdb.github.io/kairosdocs/restapi/QueryMetrics.html). diff --git a/docs/sources/datasources/opentsdb.md b/docs/sources/datasources/opentsdb.md index 28d90c19b00..7e81ebe1483 100644 --- a/docs/sources/datasources/opentsdb.md +++ b/docs/sources/datasources/opentsdb.md @@ -1,16 +1,22 @@ ---- -page_title: OpenTSDB Guide -page_description: OpenTSDB guide for Grafana -page_keywords: grafana, opentsdb, documentation ---- ++++ +title = "Using OpenTSDB in Grafana" +description = "Guide for using OpenTSDB in Grafana" +keywords = ["grafana", "opentsdb", "guide"] +type = "docs" +[menu.docs] +name = "OpenTSDB" +parent = "datasources" +weight = 5 ++++ + +# Using OpenTSDB in Grafana + +{{< docs-imagebox img="/img/docs/v2/add_OpenTSDB.png" max-width="14rem" >}} -# OpenTSDB Guide The newest release of Grafana adds additional functionality when using an OpenTSDB Data source. -![](/img/v2/add_OpenTSDB.jpg) - -1. Open the side menu by clicking the the Grafana icon in the top header. -2. In the side menu under the `Dashboards` link you should find a link named `Data Sources`. +1. Open the side menu by clicking the the Grafana icon in the top header. +2. In the side menu under the `Dashboards` link you should find a link named `Data Sources`. > NOTE: If this link is missing in the side menu it means that your current user does not have the `Admin` role for the current organization. @@ -22,7 +28,7 @@ Name | Description Name | The data source name, important that this is the same as in Grafana v1.x if you plan to import old dashboards. Default | Default data source means that it will be pre-selected for new panels. Url | The http protocol, ip and port of you opentsdb server (default port is usually 4242) -Access | Proxy = access via Grafana backend, Direct = access directory from browser. +Access | Proxy = access via Grafana backend, Direct = access directly from browser. Version | Version = opentsdb version, either <=2.1 or 2.2 Resolution | Metrics from opentsdb may have datapoints with either second or millisecond resolution. @@ -31,7 +37,7 @@ Open a graph in edit mode by click the title. Query editor will differ if the da > Note: While using Opentsdb 2.2 datasource, make sure you use either Filters or Tags as they are mutually exclusive. If used together, might give you weird results. -![](/img/v2/opentsdb_query_editor.png) +![](/img/docs/v2/opentsdb_query_editor.png) ### Auto complete suggestions As soon as you start typing metric names, tag names and tag values , you should see highlighted auto complete suggestions for them. @@ -51,6 +57,13 @@ When using OpenTSDB with a template variable of `query` type you can use followi If you do not see template variables being populated in `Preview of values` section, you need to enable `tsd.core.meta.enable_realtime_ts` in the OpenTSDB server settings. Also, to populate metadata of the existing time series data in OpenTSDB, you need to run `tsdb uid metasync` on the OpenTSDB server. +### Nested Templating + +One template variable can be used to filter tag values for another template varible. Very importantly, the order of the parameters matter in tag_values function. First parameter is the metric name, second parameter is the tag key for which you need to find tag values, and after that all other dependent template variables. Some examples are mentioned below to make nested template queries work successfully. + + tag_values(cpu, hostname, env=$env) // return tag values for cpu metric, selected env tag value and tag key hostname + tag_values(cpu, hostanme, env=$env, region=$region) // return tag values for cpu metric, selected env tag value, selected region tag value and tag key hostname + > Note: This is required for the OpenTSDB `lookup` api to work. For details on opentsdb metric queries checkout the official [OpenTSDB documentation](http://opentsdb.net/docs/build/html/index.html) diff --git a/docs/sources/datasources/overview.md b/docs/sources/datasources/overview.md deleted file mode 100644 index 8fe6538dcd3..00000000000 --- a/docs/sources/datasources/overview.md +++ /dev/null @@ -1,25 +0,0 @@ ----- -page_title: Data Source Overview -page_description: Data Source Overview -page_keywords: grafana, graphite, influxDB, KairosDB, OpenTSDB, Prometheus, documentation ---- - -# Data Source Overview -Grafana supports many different storage backends for your time series data (Data Source). Each Data Source has a specific Query Editor that is customized for the features and capabilities that the particular Data Source exposes. - - -## Querying -The query language and capabilities of each Data Source are obviously very different. You can combine data from multiple Data Sources onto a single Dashboard, but each Panel is tied to a specific Data Source that belongs to a particular Organization. - -## Supported Data Sources -The following datasources are officially supported: - -* [Graphite](/datasources/graphite/) -* [Elasticsearch](/datasources/elasticsearch/) -* [CloudWatch](/datasources/cloudwatch/) -* [InfluxDB](/datasources/influxdb/) -* [OpenTSDB](/datasources/opentsdb/) -* [KairosDB](/datasources/kairosdb) -* [Prometheus](/datasources/prometheus) - -Grafana can query any Elasticsearch index for annotation events, but at this time, it's not supported for metric queries. Learn more about [annotations](/reference/annotations/#elasticsearch-annotations) diff --git a/docs/sources/datasources/plugin_api.md b/docs/sources/datasources/plugin_api.md index cdcaca29460..2e2121ed21a 100644 --- a/docs/sources/datasources/plugin_api.md +++ b/docs/sources/datasources/plugin_api.md @@ -30,11 +30,5 @@ Even though the data source type name is with lowercase `g`, the directive uses that is how angular directives needs to be named in order to match an element with name ``. You also specify the query controller here instead of in the query.editor.html partial like before. -### query.editor.html - -This partial needs to be updated, remove the `np-repeat` this is done in the outer partial now,m the query.editor.html -should only render a single query. Take a look at the Graphite or InfluxDB partials for `query.editor.html` for reference. -You should also add a `tight-form-item` with `{{target.refId}}`, all queries needs to be assigned a letter (`refId`). -These query reference letters are going to be utilized in a later feature. diff --git a/docs/sources/datasources/prometheus.md b/docs/sources/datasources/prometheus.md index 9ad435270c4..fd14d0539e7 100644 --- a/docs/sources/datasources/prometheus.md +++ b/docs/sources/datasources/prometheus.md @@ -1,17 +1,24 @@ ----- -page_title: Prometheus query guide -page_description: Prometheus query guide -page_keywords: grafana, prometheus, metrics, query, documentation ---- ++++ +title = "Using Prometheus in Grafana" +description = "Guide for using Prometheus in Grafana" +keywords = ["grafana", "prometheus", "guide"] +type = "docs" +[menu.docs] +name = "Prometheus" +parent = "datasources" +weight = 2 ++++ + + +# Using Prometheus in Grafana -# Prometheus Grafana includes support for Prometheus Datasources. While the process of adding the datasource is similar to adding a Graphite or OpenTSDB datasource type, Prometheus does have a few different options for building queries. ## Adding the data source to Grafana ![](/img/v2/add_Prometheus.png) -1. Open the side menu by clicking the the Grafana icon in the top header. -2. In the side menu under the `Dashboards` link you should find a link named `Data Sources`. +1. Open the side menu by clicking the the Grafana icon in the top header. +2. In the side menu under the `Dashboards` link you should find a link named `Data Sources`. > NOTE: If this link is missing in the side menu it means that your current user does not have the `Admin` role for the current organization. @@ -23,7 +30,7 @@ Name | Description Name | The data source name, important that this is the same as in Grafana v1.x if you plan to import old dashboards. Default | Default data source means that it will be pre-selected for new panels. Url | The http protocol, ip and port of you Prometheus server (default port is usually 9090) -Access | Proxy = access via Grafana backend, Direct = access directory from browser. +Access | Proxy = access via Grafana backend, Direct = access directly from browser. Basic Auth | Enable basic authentication to the Prometheus datasource. User | Name of your Prometheus user Password | Database user's password diff --git a/docs/sources/features/dashboard/index.md b/docs/sources/features/dashboard/index.md new file mode 100644 index 00000000000..86e15ac3390 --- /dev/null +++ b/docs/sources/features/dashboard/index.md @@ -0,0 +1,8 @@ ++++ +title = "Dashboard Features" +type = "docs" +[menu.docs] +identifier = "dashboard_features" +parent = "features" +weight = 4 ++++ diff --git a/docs/sources/features/index.md b/docs/sources/features/index.md new file mode 100644 index 00000000000..1352e9f0576 --- /dev/null +++ b/docs/sources/features/index.md @@ -0,0 +1,11 @@ ++++ +title = "Beginner Guides" +description = "Beginner guides" +type = "docs" +[menu.docs] +name = "Features" +identifier = "features" +weight = 3 ++++ + + diff --git a/docs/sources/features/panels/index.md b/docs/sources/features/panels/index.md new file mode 100644 index 00000000000..7e50d3592d0 --- /dev/null +++ b/docs/sources/features/panels/index.md @@ -0,0 +1,8 @@ ++++ +title = "Panels" +type = "docs" +[menu.docs] +parent = "features" +identifier = "panels" +weight = 3 ++++ diff --git a/docs/sources/features/shortcuts.md b/docs/sources/features/shortcuts.md new file mode 100644 index 00000000000..ec7250b7a5a --- /dev/null +++ b/docs/sources/features/shortcuts.md @@ -0,0 +1,53 @@ ++++ +title = "Keyboard Shortcuts" +type = "docs" +[menu.docs] +parent = "features" +weight = 7 ++++ + +# Keyboard shortcuts + +{{< docs-imagebox img="/img/docs/v4/shortcuts.png" max-width="20rem" >}} + +Grafana v4 introduces a number of really powerful keyboard shortcuts. You can now focus a panel +by hovering over it with your mouse. With a panel focused you can simple hit `e` to toggle panel +edit mode, or `v` to toggle fullscreen mode. `p` `r` removes the panel. `p` `s` opens share +modal. + +Hit `?` on your keyboard to open the shortcuts help modal. + +### Global + +- `g` `h` Go to Home Dashboard +- `g` `p` Go to Profile +- `s` `o` Open search +- `s` `s` Open search with starred filter +- `s` `t` Open search in tags view +- `esc` Exit edit/setting views + +### Dashboard + +- `mod+s` Save dashboard +- `mod+h` Hide row controls +- `d` `r` Refresh all panels +- `d` `s` Dashboard settings +- `d` `v` Toggle in-active / view mode +- `d` `k` Toggle kiosk mode (hides top nav) +- `mod+o` Toggle shared graph crosshair + +### Focused Panel +- `e` Toggle panel edit view +- `v` Toggle panel fullscreen view +- `p` `s` Open Panel Share Modal +- `p` `r` Remove Panel + +### Focused Row +- `r` `c` Collapse Row +- `r` `r` Remove Row + +### Time Range +- `t` `z` Zoom out time range +- `t` Move time range back +- `t` Move time range forward + diff --git a/docs/sources/features/whatsnew/index.md b/docs/sources/features/whatsnew/index.md new file mode 100644 index 00000000000..30357af4668 --- /dev/null +++ b/docs/sources/features/whatsnew/index.md @@ -0,0 +1,9 @@ ++++ +title = "What's New in Grafana" +[menu.docs] +name = "What's New In Grafana" +identifier = "whatsnew" +weight = 2 ++++ + + diff --git a/docs/sources/guides/basic_concepts.md b/docs/sources/guides/basic_concepts.md index b654554fa48..bbb1cb53728 100644 --- a/docs/sources/guides/basic_concepts.md +++ b/docs/sources/guides/basic_concepts.md @@ -1,48 +1,52 @@ ----- -page_title: Graphite query guide -page_description: Graphite query guide -page_keywords: grafana, graphite, metrics, query, documentation ---- ++++ +title = "Basic Concepts" +description = "Grafana intro and concept guide" +keywords = ["grafana", "intro", "guide", "concepts"] +type = "docs" +[menu.docs] +name = "Basic Concepts" +identifier = "basic_concepts" +parent = "guides" ++++ # Basic Concepts This document is a “bottom up” introduction to basic concepts in Grafana, and can be used as a starting point to get familiar with core features. +### Data Source +Grafana supports many different storage backends for your time series data (Data Source). Each Data Source has a specific Query Editor that is customized for the features and capabilities that the particular Data Source exposes. -### ** Data Source ** -Grafana supports many different storage backends for your time series data (Data Source). Each Data Source has a specific Query Editor that is customized for the features and capabilities that the particular Data Source exposes. - -The following datasources are officially supported: [Graphite](/datasources/graphite/), [InfluxDB](/datasources/influxdb/), [OpenTSDB](/datasources/opentsdb/), and [KairosDB](/datasources/kairosdb) +The following datasources are officially supported: [Graphite](/datasources/graphite/), [InfluxDB](/datasources/influxdb/), [OpenTSDB](/datasources/opentsdb/), [Prometheus](/datasources/prometheus/), [Elasticsearch](/datasources/elasticsearch/), [CloudWatch](/datasources/cloudwatch/), and [KairosDB](/datasources/kairosdb) The query language and capabilities of each Data Source are obviously very different. You can combine data from multiple Data Sources onto a single Dashboard, but each Panel is tied to a specific Data Source that belongs to a particular Organization. -### ** Organization ** +### Organization Grafana supports multiple organizations in order to support a wide variety of deployment models, including using a single Grafana instance to provide service to multiple potentially untrusted Organizations. In many cases, Grafana will be deployed with a single Organization. -Each Organization can have one or more Data Sources. +Each Organization can have one or more Data Sources. All Dashboards are owned by a particular Organization. - > Note: It is important to remember that most metric databases to not provide any sort of per-user series authentication. Therefore, in Grafana, Data Sources and Dashboards are available to all Users in a particular Organization. + > Note: It is important to remember that most metric databases do not provide any sort of per-user series authentication. Therefore, in Grafana, Data Sources and Dashboards are available to all Users in a particular Organization. For more details on the user model for Grafana, please refer to [Admin](/reference/admin/) -### ** User ** -A User is a named account in Grafana. A user can belong to one or more Organizations, and can be assigned different levels of privileges through roles. +### User +A User is a named account in Grafana. A user can belong to one or more Organizations, and can be assigned different levels of privileges through roles. -Grafana supports a wide variety of internal and external ways for Users to authenticate themselves. These include from its own integrated database, from an external SQL server, or from an external LDAP server. +Grafana supports a wide variety of internal and external ways for Users to authenticate themselves. These include from its own integrated database, from an external SQL server, or from an external LDAP server. For more details please refer to [User Auth](/reference/http_api/#users) -### ** Row ** +### Row A Row is a logical divider within a Dashboard, and is used to group Panels together. Rows are always 12 “units” wide. These units are automatically scaled dependent on the horizontal resolution of your browser. You can control the relative width of Panels within a row by setting their own width. -We utilize a unit abstraction so that Grafana looks great on all screens both small and huge. +We utilize a unit abstraction so that Grafana looks great on all screens both small and huge. > Note: With MaxDataPoint functionality, Grafana can show you the perfect amount of datapoints no matter your resolution or time-range. @@ -50,7 +54,7 @@ Utilize the [Repeating Row functionality](/reference/templating/#utilizing-templ Rows can be collapsed by clicking on the Row Title. If you save a Dashboard with a Row collapsed, it will save in that state and will not preload those graphs until the row is expanded. -### ** Panel ** +### Panel The Panel is the basic visualization building block in Grafana. Each Panel provides a Query Editor (dependent on the Data Source selected in the panel) that allows you to extract the perfect visualization to display on the Panel by utilizing the Query Editor @@ -58,7 +62,7 @@ There are a wide variety of styling and formatting options that each Panel expos Panels can be dragged and dropped and rearranged on the Dashboard. They can also be resized. -There are currently four Panel types: [Graph](/reference/graph/), [Singlestat](/reference/singlestat/), [Dashlist](/reference/dashlist/), and [Text](/reference/text/). +There are currently four Panel types: [Graph](/reference/graph/), [Singlestat](/reference/singlestat/), [Dashlist](/reference/dashlist/), [Table](/reference/table_panel/),and [Text](/reference/text/). Panels like the [Graph](/reference/graph/) panel allow you to graph as many metrics and series as you want. Other panels like [Singlestat](/reference/singlestat/) require a reduction of a single query into a single number. [Dashlist](/reference/dashlist/) and [Text](/reference/text/) are special panels that do not connect to any Data Source. @@ -66,14 +70,14 @@ Panels can be made more dynamic by utilizing [Dashboard Templating](/reference/t Utilize the [Repeating Panel](/reference/templating/#utilizing-template-variables-with-repeating-panels-and-repeating-rows) functionality to dynamically create or remove Panels based on the [Templating Variables](/reference/templating/#utilizing-template-variables-with-repeating-panels-and-repeating-rows) selected. -The time range on Panels is normally what is set in the [Dashboard time picker](/reference/timerange/) but this can be overridden by utilizes [Panel specific time overrides](/reference/timerange/#panel-time-override). +The time range on Panels is normally what is set in the [Dashboard time picker](/reference/timerange/) but this can be overridden by utilizes [Panel specific time overrides](/reference/timerange/#panel-time-overrides-timeshift). Panels (or an entire Dashboard) can be [Shared](/reference/sharing/) easily in a variety of ways. You can send a link to someone who has a login to your Grafana. You can use the [Snapshot](/reference/sharing/#snapshots) feature to encode all the data currently being viewed into a static and interactive JSON document; it's so much better than emailing a screenshot! -### ** Query Editor ** +### Query Editor -The Query Editor exposes capabilities of your Data Source and allows you to query the metrics that it contains. +The Query Editor exposes capabilities of your Data Source and allows you to query the metrics that it contains. Use the Query Editor to build one or more queries (for one or more series) in your time series database. The panel will instantly update allowing you to effectively explore your data in real time and build a perfect query for that particular Panel. @@ -81,13 +85,13 @@ You can utilize [Template variables](/reference/templating/) in the Query Editor Grafana allows you to reference queries in the Query Editor by the row that they’re on. If you add a second query to graph, you can reference the first query simply by typing in #A. This provides an easy and convenient way to build compounded queries. -### ** Dashboard ** +### Dashboard The Dashboard is where it all comes together. Dashboards can be thought of as of a set of one or more Panels organized and arranged into one or more Rows. The time period for the Dashboard can be controlled by the [Dashboard time picker](/reference/timerange/) in the upper right of the Dashboard. -Dashboards can utilize [Templating](/reference/templating/) to make them more dynamic and interactive. +Dashboards can utilize [Templating](/reference/templating/) to make them more dynamic and interactive. Dashboards can utilize [Annotations](/reference/annotations/) to display event data across Panels. This can help correlate the time series data in the Panel with other events. diff --git a/docs/sources/guides/gettingstarted.md b/docs/sources/guides/getting_started.md similarity index 85% rename from docs/sources/guides/gettingstarted.md rename to docs/sources/guides/getting_started.md index c92f30098ab..3f039f97ae4 100644 --- a/docs/sources/guides/gettingstarted.md +++ b/docs/sources/guides/getting_started.md @@ -1,23 +1,28 @@ ---- -page_title: Getting started -page_description: Getting started -page_keywords: grafana, guide, documentation ---- ++++ +title = "Getting Started" +description = "Getting started with Grafana guide" +keywords = ["grafana", "intro", "guide", "started"] +type = "docs" +[menu.docs] +name = "Getting Started" +identifier = "getting_started_guide" +parent = "guides" ++++ # Getting started -This guide will help you get started and acquainted with Grafana. It assumes you have a working Grafana 2.x instance, and have added at least one [Data Source](/datasources/overview). +This guide will help you get started and acquainted with Grafana. It assumes you have a working Grafana server up and running and have added at least one [Data Source](/datasources/overview). ## Beginner guides Watch the 10min [beginners guide to building dashboards](https://www.youtube.com/watch?v=sKNZMtoSHN4&index=7&list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2) to get a quick intro to setting up Dashboards and Panels. -##Basic Concepts +## Basic Concepts Read the [Basic Concepts](/guides/basic_concepts) document to get a crash course in key Grafana concepts. ### Top header Let's start with creating a new Dashboard. You can find the new Dashboard link at the bottom of the Dashboard picker. You now have a blank Dashboard. - + The image above shows you the top header for a Dashboard. @@ -29,12 +34,12 @@ The image above shows you the top header for a Dashboard. 6. Settings: Manage Dashboard settings and features such as Templating and Annotations. ## Dashboards, Panels, Rows, the building blocks of Grafana... -Dashboards are at the core of what Grafana is all about. Dashboards are composed of individual Panels arranged on a number of Rows. Grafana ships with a variety of Panels. Grafana makes it easy to construct the right queries, and customize the display properties so that you can create the perfect Dashboard for your need. Each Panel can interact with data from any configured Grafana Data Source (currently InfluxDB, Graphite, OpenTSDB, and KairosDB). The [Core Concepts](/guides/basic_concepts) guide explores these key ideas in detail. +Dashboards are at the core of what Grafana is all about. Dashboards are composed of individual Panels arranged on a number of Rows. Grafana ships with a variety of Panels. Grafana makes it easy to construct the right queries, and customize the display properties so that you can create the perfect Dashboard for your need. Each Panel can interact with data from any configured Grafana Data Source (currently InfluxDB, Graphite, OpenTSDB, and KairosDB). The [Basic Concepts](/guides/basic_concepts) guide explores these key ideas in detail. ## Adding & Editing Graphs and Panels -![](/img/v2/graph_metrics_tab_graphite.png) +![](/img/docs/v2/graph_metrics_tab_graphite.png) 1. You add panels via row menu. The row menu is the green icon to the left of each row. 2. To edit the graph you click on the graph title to open the panel menu, then `Edit`. @@ -43,8 +48,7 @@ Dashboards are at the core of what Grafana is all about. Dashboards are composed When you click the `Metrics` tab, you are presented with a Query Editor that is specific to the Panel Data Source. Use the Query Editor to build your queries and Grafana will visualize them in real time. - - + 1. Zoom out time range 2. Time picker dropdown. Here you can access relative time range options, auto refresh options and set custom absolute time ranges. @@ -57,7 +61,7 @@ When you click the `Metrics` tab, you are presented with a Query Editor that is You can Drag-and-Drop Panels within and between Rows. Click and hold the Panel title, and drag it to its new location. You can also easily resize panels by clicking the (-) and (+) icons. -![](/img/animated_gifs/drag_drop.gif) +![](/img/docs/animated_gifs/drag_drop.gif) ## Tips and shortcuts @@ -75,15 +79,3 @@ You can Drag-and-Drop Panels within and between Rows. Click and hold the Panel t * Ctrl+H Hides all controls (good for tv displays) * Hit Escape to exit graph when in fullscreen or edit mode - - - - - - - - - - - - diff --git a/docs/sources/guides/index.md b/docs/sources/guides/index.md new file mode 100644 index 00000000000..c80dd624624 --- /dev/null +++ b/docs/sources/guides/index.md @@ -0,0 +1,9 @@ ++++ +title = "Guides" +type = "docs" +[menu.docs] +name = "Getting Started" +identifier = "guides" +weight = 2 ++++ + diff --git a/docs/sources/guides/screencasts.md b/docs/sources/guides/screencasts.md deleted file mode 100644 index 500ca9f9b6a..00000000000 --- a/docs/sources/guides/screencasts.md +++ /dev/null @@ -1,69 +0,0 @@ -page_title: Screencasts -page_description: Grafana screencasts -page_keywords: grafana, screencasts, documentation, guides -no_toc: true - -# Screencasts - -
-
-

Episode 1 - Building Graphite Queries

- Learn how the Graphite Query Editor works, and how to use different graphing functions. There's also an introduction to graph display settings. -
- -
-
-
-

Episode 2 - Templated Graphite Queries

- The screencast focuses on Templating with the Graphite Data Source. Learn how to make dynamic and adaptable Dashboards for your Graphite metrics. -
- -
-
-
-
-
-
-

Episode 3 - Whats New In Grafana 2.0

- This screencast highlights many of the great new features that were included in the Grafana 2.0 release. -
- -
-
-
-

Episode 4 - Installation & Configuration on Ubuntu / Debian

- Learn how to easily install the dependencies and packages to get Grafana 2.0 up and running on Ubuntu or Debian in just a few minutes. -
- -
-
-
-
-
-
-

Episode 5 - Installation & Configuration on Red Hat / CentOS

- This screencasts shows how to get Grafana 2.0 installed and configured quickly on RPM-based Linux operating systems. -
- -
-
-
-

Episode 6 - Adding data sources, users & organizations

- Now that Grafana has been installed, learn about adding data sources and get a closer look at adding and managing Users and Organizations. -
- -
-
-
-
-
-
-

Episode 7 - Beginners guide to building dashboards

- For newer users of Grafana, this screencast will familiarize you with the general UI and teach you how to build your first Dashboard. -
- -
-
-
-
-
diff --git a/docs/sources/guides/whats-new-in-v2-1.md b/docs/sources/guides/whats-new-in-v2-1.md index 10519cb0422..68da4f60226 100644 --- a/docs/sources/guides/whats-new-in-v2-1.md +++ b/docs/sources/guides/whats-new-in-v2-1.md @@ -1,8 +1,14 @@ ---- -page_title: What's New in Grafana v2.1 -page_description: What's new in Grafana v2.1 -page_keywords: grafana, new, changes, features, documentation ---- ++++ +title = "What's New in Grafana v2.1" +description = "Feature & improvement highlights for Grafana v2.1" +keywords = ["grafana", "new", "documentation", "2.1"] +type = "docs" +[menu.docs] +name = "Version 2.1" +identifier = "v2.1" +parent = "whatsnew" +weight = 10 ++++ # What's new in Grafana v2.1 Grafana 2.1 brings improvements in three core areas: dashboarding, authentication, and data sources. @@ -17,7 +23,7 @@ A template variable with Multi-Value enabled allows for the selection of multipl These variables can then be used in any Panel to make them more dynamic, and to give you the perfect view of your data. Multi-Value variables is also enabling the new `row repeat` and `panel repeat` feature described below. -![Multi-Value Select](/img/v2/multi-select.gif "Multi-Value Select") +![Multi-Value Select](/img/docs/v2/multi-select.gif "Multi-Value Select")

### Repeating Rows and Panels @@ -25,7 +31,7 @@ It’s now possible to create a dashboard that automatically adds (or removes) b on selected variable values. Any row or any panel can be configured to repeat (duplicate itself) based on a multi-value template variable.

-![Repeating Rows and Panels](/img/v2/panel-row-repeat.gif "Repeating Rows and Panels") +![Repeating Rows and Panels](/img/docs/v2/panel-row-repeat.gif "Repeating Rows and Panels")

### Dashboard Links & Navigation @@ -33,7 +39,7 @@ To support better navigation between dashboards, it's now possible to create cus panels to appropriate Dashboards. You also have the ability to create flexible top-level links on any given dashboard thanks to the new dashboard navigation bar feature. -![Dashboard Links](/img/v2/dash_links.png "Dashboard Links") +![Dashboard Links](/img/docs/v2/dash_links.png "Dashboard Links") Dashboard links can be added under dashboard settings. Either defined as static URLs with a custom icon or as dynamic dashboard links or dropdowns based on custom dashboard search query. These links appear in the same @@ -82,7 +88,7 @@ The Viewer role has been modified in Grafana 2.1 so that users assigned this rol Grafana 2.1 now comes with full support for InfluxDB 0.9. There is a new query editor designed from scratch for the new features InfluxDB 0.9 enables. -![InfluxDB Editor](/img/v2/influx_09_editor_anim.gif "InfluxDB Editor") +![InfluxDB Editor](/img/docs/v2/influx_09_editor_anim.gif "InfluxDB Editor")
@@ -110,15 +116,15 @@ Define series color using regex rule. This is useful when you have templated gra that change depending selected template variables. Using a regex style override rule you could for example make all series that contain the word **CPU** `red` and assigned to the second y axis. -![Define series color using regex rule](/img/v2/regex_color_override.png "Define series color using regex rule") +![Define series color using regex rule](/img/docs/v2/regex_color_override.png "Define series color using regex rule") New series style override, negative-y transform and stack groups. Negative y transform is very useful if you want to plot a series on the negative y scale without affecting the legend values like min or max or the values shown in the hover tooltip. -![Negative-y Transform](/img/v2/negative-y.png "Negative-y Transform") +![Negative-y Transform](/img/docs/v2/negative-y.png "Negative-y Transform") -![Negative-y Transform](/img/v2/negative-y-form.png "Negative-y Transform") +![Negative-y Transform](/img/docs/v2/negative-y-form.png "Negative-y Transform") ### Singlestat Panel Now support string values. Useful for time series database like InfluxDB that supports diff --git a/docs/sources/guides/whats-new-in-v2-5.md b/docs/sources/guides/whats-new-in-v2-5.md index f02d0d43fd0..93cdd59cb50 100644 --- a/docs/sources/guides/whats-new-in-v2-5.md +++ b/docs/sources/guides/whats-new-in-v2-5.md @@ -1,8 +1,14 @@ ---- -page_title: What's New in Grafana v2.5 -page_description: What's new in Grafana v2.5 -page_keywords: grafana, new, changes, features, documentation ---- ++++ +title = "What's New in Grafana v2.5" +description = "Feature & improvement highlights for Grafana v2.5" +keywords = ["grafana", "new", "documentation", "2.5"] +type = "docs" +[menu.docs] +name = "Version 2.5" +identifier = "v2.5" +parent = "whatsnew" +weight = 9 ++++ # What's new in Grafana v2.5 @@ -12,7 +18,7 @@ fixes and enhancements to all areas of Grafana, like new Data Sources, a new and resize handles and improved InfluxDB and OpenTSDB support. ### New time range controls -New Time picker +New Time picker A new timepicker with room for more quick ranges as well as new types of relative ranges, like `Today`, `The day so far` and `This day last week`. Also an improved time & calendar picker that now works @@ -20,7 +26,7 @@ correctly in UTC mode. ### Elasticsearch -Elasticsearch example +Elasticsearch example
This release brings a fully featured query editor for Elasticsearch. You will now be able to visualize @@ -40,7 +46,7 @@ Try the new Elasticsearch query editor on the [play.grafana.org](http://play.gra ### CloudWatch -Cloudwatch editor +Cloudwatch editor Grafana 2.5 ships with a new CloudWatch datasource that will allow you to query and visualize CloudWatch metrics directly from Grafana. @@ -51,14 +57,14 @@ metrics directly from Grafana. ### Prometheus -Prometheus editor +Prometheus editor Grafana 2.5 ships with a new Prometheus datasource that will allow you to query and visualize data stored in Prometheus. ### Mix different data sources -Mix data sources in the same dashboard or in the same graph! +Mix data sources in the same dashboard or in the same graph! In previous releases you have been able to mix different data sources on the same dashboard. In v2.5 you will be able to mix then on the same graph! You can enable this by selecting the built in `-- Mixed --` data source. @@ -67,12 +73,12 @@ to plot metrics from different Graphite servers on the same Graph or plot data f data from Prometheus. Mixing different data sources on the same graph works for any data source, even custom ones. ### Panel Resize handles - + This release adds resize handles to the the bottom right corners of panels making is easy to resize both width and height. ### User invites - + This version also brings some new features for user management. diff --git a/docs/sources/guides/whats-new-in-v2-6.md b/docs/sources/guides/whats-new-in-v2-6.md index ac644ad44af..0b1e6688e60 100644 --- a/docs/sources/guides/whats-new-in-v2-6.md +++ b/docs/sources/guides/whats-new-in-v2-6.md @@ -1,8 +1,14 @@ ---- -page_title: What's New in Grafana v2.6 -page_description: What's new in Grafana v2.6 -page_keywords: grafana, new, changes, features, documentation, table ---- ++++ +title = "What's New in Grafana v2.6" +description = "Feature & improvement highlights for Grafana v2.6" +keywords = ["grafana", "new", "documentation", "2.6"] +type = "docs" +[menu.docs] +name = "Version 2.6" +identifier = "v2.6" +parent = "whatsnew" +weight = 7 ++++ # What's new in Grafana v2.6 @@ -11,7 +17,7 @@ The release includes a new Table panel, a new InfluxDB query editor, support for support for multiple Cloudwatch credentials. ## Table Panel - + The new table panel is very flexible, supporting both multiple modes for time series as well as for table, annotation and raw JSON data. It also provides date formating and value formating and coloring options. @@ -21,7 +27,7 @@ table, annotation and raw JSON data. It also provides date formating and value f In the most simple mode you can turn time series to rows. This means you get a `Time`, `Metric` and a `Value` column. Where `Metric` is the name of the time series. - + ### Table Transform Above you see the options tab for the **Table Panel**. The most important option is the `To Table Transform`. @@ -34,7 +40,7 @@ The column styles allow you control how dates and numbers are formatted. This transform allows you to take multiple time series and group them by time. Which will result in a `Time` column and a column for each time series. - + In the screenshot above you can see how the same time series query as in the previous example can be transformed into a different table by changing the `To Table Transform` to `Time series to columns`. @@ -43,7 +49,7 @@ a different table by changing the `To Table Transform` to `Time series to colum This transform works very similar to the legend values in the Graph panel. Each series gets its own row. In the Options tab you can select which aggregations you want using the plus button the Columns section. - + You have to think about how accurate the aggregations will be. It depends on what aggregation is used in the time series query, how many data points are fetched, etc. The time series aggregations are calculated by Grafana after aggregation is performed @@ -53,38 +59,39 @@ by the time series database. If you want to show documents from Elasticsearch pick `Raw Document` as the first metric. - + This in combination with the `JSON Data` table transform will allow you to pick which fields in the document you want to show in the table. - + ### Elasticsearch aggregations You can also make Elasticsearch aggregation queries without a `Date Histogram`. This allows you to use Elasticsearch metric aggregations to get accurate aggregations for the selected time range. - + ### Annotations The table can also show any annotations you have enabled in the dashboard. - + ## The New InfluxDB Editor The new InfluxDB editor is a lot more flexible and powerful. It supports nested functions, like `derivative`. It also uses the same technique as the Graphite query editor in that it presents nested functions as chain of function transformations. It tries to simplify and unify the complicated nature of InfluxDB's query language. - + In the `SELECT` row you can specify what fields and functions you want to use. If you have a group by time you need an aggregation function. Some functions like derivative require an aggregation function. The editor tries simplify and unify this part of the query. For example: -![](/img/influxdb/select_editor.png) + +![](/img/docs/influxdb/select_editor.png) The above will generate the following InfluxDB `SELECT` clause: @@ -103,7 +110,7 @@ You can remove the group by by clicking on the `tag` and then click on the x ico The new editor also allows you to remove group by time and select `raw` table data. Which is very useful in combination with the new Table panel to show raw log data stored in InfluxDB. - + ## Pipeline metrics @@ -111,7 +118,7 @@ If you have Elasticsearch 2.x and Grafana 2.6 or above then you can use pipeline **Moving Average** and **Derivative**. Elasticsearch pipeline metrics require another metric to be based on. Use the eye icon next to the metric to hide metrics from appearing in the graph. -![](/img/elasticsearch/pipeline_metrics_editor.png) +![](/img/docs/elasticsearch/pipeline_metrics_editor.png) ## Changelog For a detailed list and link to github issues for everything included in the 2.6 release please diff --git a/docs/sources/guides/whats-new-in-v2.md b/docs/sources/guides/whats-new-in-v2.md index 9e87ab55e6e..bd92128a12e 100644 --- a/docs/sources/guides/whats-new-in-v2.md +++ b/docs/sources/guides/whats-new-in-v2.md @@ -1,8 +1,14 @@ ---- -page_title: What's New in Grafana v2.0 -page_description: What's new in Grafana v2.0 -page_keywords: grafana, new, changes, features, documentation ---- ++++ +title = "What's New in Grafana v2.0" +description = "Feature & improvement highlights for Grafana v2.0" +keywords = ["grafana", "new", "documentation", "2.0"] +type = "docs" +[menu.docs] +name = "Version 2.0" +identifier = "v2.0" +parent = "whatsnew" +weight = 11 ++++ # What's New in Grafana v2.0 @@ -49,7 +55,7 @@ even zoom in). Also they are fast to load as they aren't actually connected to a They're a great way to communicate about a particular incident with specific people who aren't Users of your Grafana instance. You can also use them to show off your dashboards over the Internet. -![](/img/v2/dashboard_snapshot_dialog.png) +![](/img/docs/v2/dashboard_snapshot_dialog.png) ### Publish snapshots @@ -61,11 +67,11 @@ Either way, anyone with the link (and access to your Grafana instance for local In Grafana v2.x you can now override the relative time range for individual panels, causing them to be different than what is selected in the Dashboard time picker in the upper right. You can also add a time shift to individual panels. This allows you to show metrics from different time periods or days at the same time. -![](/img/v2/panel_time_override.jpg) +![](/img/docs/v2/panel_time_override.jpg) You control these overrides in panel editor mode and the new tab `Time Range`. -![](/img/v2/time_range_tab.jpg) +![](/img/docs/v2/time_range_tab.jpg) When you zoom or change the Dashboard time to a custom absolute time range, all panel overrides will be disabled. The panel relative time override is only active when the dashboard time is also relative. The panel timeshift override however is always active, even when the dashboard time is absolute. @@ -90,7 +96,7 @@ This feature makes it easy to include interactive visualizations from your Grafa The top header has gotten a major streamlining in Grafana V2.0. - + 1. `Side menubar toggle` Toggle the side menubar on or off. This allows you to focus on the data presented on the Dashboard. The side menubar provides access to features unrelated to a Dashboard such as Users, Organizations, and Data Sources. 2. `Dashboard dropdown` The main dropdown shows you which Dashboard you are currently viewing, and allows you to easily switch to a new Dashboard. From here you can also create a new Dashboard, Import existing Dashboards, and manage the Playlist. @@ -115,7 +121,7 @@ You can easily collapse or re-open the side menubar at any time by clicking the ## New search view & starring dashboards -![](/img/v2/dashboard_search.jpg) +![](/img/docs/v2/dashboard_search.jpg) The dashboard search view has gotten a big overhaul. You can now see and filter by which dashboard you have personally starred. @@ -124,11 +130,11 @@ The dashboard search view has gotten a big overhaul. You can now see and filter The Graph panel now supports 3 logarithmic scales, `log base 10`, `log base 32`, `log base 1024`. Logarithmic y-axis scales are very useful when rendering many series of different order of magnitude on the same scale (eg. latency, network traffic, and storage) -![](/img/v2/graph_logbase10_ms.png) +![](/img/docs/v2/graph_logbase10_ms.png) ## Dashlist panel -![](/img/v2/dashlist_starred.png) +![](/img/docs/v2/dashlist_starred.png) The dashlist is a new panel in Grafana v2.0. It allows you to show your personal starred dashboards, as well as do custom searches based on search strings or tags. @@ -147,7 +153,7 @@ In addition, connections to Data Sources can be better controlled and secured, a A commonly reported problem has been graphs dipping to zero at the the end, because metric data for the last interval has yet to be written to the Data Source. These graphs then "self correct" once the data comes in, but can look deceiving or alarming at times. You can avoid this problem by adding a `now delay` in `Dashboard Settings` > `Time Picker` tab. This new feature will cause Grafana to ignore the most recent data up to the set delay. -![](/img/v2/timepicker_now_delay.jpg) +![](/img/docs/v2/timepicker_now_delay.jpg) The delay that may be necessary depends on how much latency you have in your collection pipeline. @@ -155,7 +161,7 @@ The delay that may be necessary depends on how much latency you have in your col Grafana v2.0 protects Users from accidentally overwriting each others Dashboard changes. Similar protections are in place if you try to create a new Dashboard with the same name as an existing one. -![](/img/v2/overwrite_protection.jpg) +![](/img/docs/v2/overwrite_protection.jpg) These protections are only the first step; we will be building out additional capabilities around dashboard versioning and management in future versions of Grafana. @@ -171,6 +177,6 @@ Grafana now supports server-side PNG rendering. From the Panel share dialog you > **Note** This requires that your Data Source is accessible from your Grafana instance. -![](/img/v2/share_dialog_image_highlight.jpg) +![](/img/docs/v2/share_dialog_image_highlight.jpg) diff --git a/docs/sources/guides/whats-new-in-v3-1.md b/docs/sources/guides/whats-new-in-v3-1.md new file mode 100644 index 00000000000..236e77ea266 --- /dev/null +++ b/docs/sources/guides/whats-new-in-v3-1.md @@ -0,0 +1,73 @@ ++++ +title = "What's New in Grafana v3.1" +description = "Feature & improvement highlights for Grafana v3.1" +keywords = ["grafana", "new", "documentation", "3.1"] +type = "docs" +[menu.docs] +name = "Version 3.1" +identifier = "v3.1" +parent = "whatsnew" +weight = 1 ++++ + +# What's New in Grafana v3.1 + +## Dashboard Export & Import + +The export feature is now accessed from the share menu. + + + +Dashboards exported from Grafana 3.1 are now more portable and easier for others to import than before. +The export process extracts information data source types used by panels and adds these to a new `inputs` +section in the dashboard json. So when you or another person tries to import the dashboard they will be asked to +select data source and optional metrix prefix options. + + + +The above screenshot shows the new import modal that gives you 3 options for how to import a dashboard. +One notable new addition here is the ability to import directly from Dashboards shared on [Grafana.net](https://grafana.net). + +The next step in the import process: + + + +Here you can change the name of the dashboard and also pick what data sources you want the dashboard to use. The above screenshot +shows a CollectD dashboard for Graphite that requires a metric prefix be specified. + +## Discover Dashboards + +On [Grafana.net](https://grafana.net) you can now browse & search for dashboards. We have already added a few but +more are being uploaded every day. To import a dashboard just copy the dashboard url and head back to Grafana, +then Dashboard Search -> Import -> Paste Grafana.net Dashboard URL. + + + +## Constant template variables + +We added a new template variable named constant that makes it easier to share and export dashboard that have custom prefixes. + +## Dashboard Urls +Having current time range and template variable value always sync with the URL makes it possible to always copy your current +Grafana url to share with a colleague without having to use the Share modal. + +## Internal metrics + +Do you want metrics about viewing metrics? Ofc you do! In this release we added support for sending metrics about Grafana to graphite. +You can configure interval and server in the config file. + +## Logging + +Switched logging framework to log15 to enable key value per logging and filtering based on different log levels. +Its now possible to configure different log levels for different modules. + +### Breaking changes +- **Logging** format have been changed to improve log filtering. +- **Graphite PNG** Graphite PNG support dropped from Graph panel (use Grafana native PNG instead). +- **Migration** No longer possible to migrate dashboards from 1.x (Stored in ES or Influx 0.8). + +## CHANGELOG + +For a detailed list and link to github issues for everything included +in the 3.1 release please view the [CHANGELOG.md](https://github.com/grafana/grafana/blob/master/CHANGELOG.md) +file. diff --git a/docs/sources/guides/whats-new-in-v3.md b/docs/sources/guides/whats-new-in-v3.md new file mode 100644 index 00000000000..32912754fe9 --- /dev/null +++ b/docs/sources/guides/whats-new-in-v3.md @@ -0,0 +1,229 @@ ++++ +title = "What's New in Grafana v3.0" +description = "Feature & improvement highlights for Grafana v3.0" +keywords = ["grafana", "new", "documentation", "3.0"] +type = "docs" +[menu.docs] +name = "Version 3.0" +identifier = "v3.0" +parent = "whatsnew" +weight = 2 ++++ + +# What's New in Grafana v3.0 + +## Commercial Support + +Commercial Support subscriptions for Grafana are now [generally available](https://grafana.net/support/plans/). + +Raintank is committed to a 100% open-source strategy for Grafana. We +do not want to go down the “open core” route. If your organization +finds Grafana valuable, please consider purchasing a subscription. Get +direct support, bug fixes, and training from the core Grafana team. + +## Plugins + +With the popularity of Grafana continuing to accelerate, it has been +challenging to keep up with all the requests for new features, new +panels, new data sources, and new functionality. Saying “no” so often +has been frustrating, especially for an open source project with such +a vibrant community. + +The team felt that it was time to dramatically improve extensibility +through plugin support. Grafana 3.0 comes with a completely revamped +plugin SDK / API. + +We’ve refactored our **Data Source** plugin architecture and added +two new plugin types: + +* **Panel** plugins let you add new panel types for your Dashboards. +* **App** plugins bundle **Panels** plugins, **Data Sources** plugins, +Dashboards, and Grafana **Pages**. Apps are a great way to provide an +entire experience right within Grafana. + +## Grafana.net + + + +[Grafana.net](https://grafana.net) offers a central repository where the community can come together to discover, create and +share plugins (data sources, panels, apps) and dashboards. + +We are also working on a hosted Graphite-compatible data source that will be optimized for use with Grafana. +It’ll be easy to combine your existing data source(s) with this OpenSaaS option. Finally, Grafana.net can +also be a hub to manage all your Grafana instances. You’ll be able to monitor their health and availability, +perform dashboard backups, and more. + +We are also working on a hosted Graphite-compatible Data Source that +will be optimized for use with Grafana. It’ll be easy to combine your +existing Data Source(s) with this OpenSaaS option. + +Finally, Grafana.net will also be a hub to manage all your Grafana +instances. You’ll be able to monitor their health and availability, +perform Dashboard backups, and more. + +Grafana.net will officially launch along with the stable version of +Grafana 3.0, but check out the preview +and sign up for an account in the meantime. + + +## grafana-cli + +Grafana 3.0 comes with a new command line tool called grafana-cli. You +can easily install plugins from Grafana.net with it. For +example: + +``` +grafana-cli install grafana-pie-chart-panel +``` + +## Personalization & Preferences + +The home dashboard, timezone and theme can now be customized on Organization +and user Profile level. Grafana can also track recently viewed dashboards, which +can then be displayed in the dashboard list panel. + +## Improved Playlists + +You can now save Playlists, and start them by using a Playlist URL. If +you update a running Playlist, it will update after its next cycle. + +This is powerful as it allows you to remote control Grafana. If you +have a big TV display showing Grafana in your company lobby, create a +playlist named Lobby, and start it on the computer connected to the +Lobby TV. + +You can now change the Lobby playlist and have the dashboards shown in +the Lobby update accordingly, automatically. + +The playlist does not even have to contain multiple Dashboards; you +can use this feature to reload the whole Dashboard (and Grafana) +periodically and remotely. + +You can also make Playlists dynamic by using Dashboard **tags** to +define the Playlist. + + + +## Improved UI + +We’ve always tried to focus on a good looking, usable, and responsive +UI. We’ve continued to pay a lot of attention to these areas in this +release. + +Grafana 3.0 has a dramatically updated UI that not only looks better +but also has a number of usability improvements. The side menu now +works as a dropdown that you can pin to the side. The Organization / +Profile / Sign out side menu links have been combined into an on hover +slide out menu. + +In addition, all the forms and the layouts of all pages have been +updated to look and flow better, and be much more consistent. There +are literally hundreds of UI improvements and refinements. + +Here’s the new side menu in action: + + + +And here's the new look for Dashboard settings: + + + +Check out the Play +Site to get a feel for some of the UI changes. + +## Improved Annotations + +It is now possible to define a link in each annotation. You can hover +over the link and click the annotation text. This feature is very +useful for linking to particular commits or tickets where more +detailed information can be presented to the user. + + + +## Data source variables + +This has been a top requested feature for very long we are exited to finally provide +this feature. You can now add a new `Data source` type variable. That will +automatically be filled with instance names of your data sources. + + + +You can then use this variable as the panel data source: + + + +This will allow you to quickly change data source server and reuse the +same dashboard for different instances of your metrics backend. For example +you might have Graphite running in multiple data centers or environments. + +## Prometheus, InfluxDB, and OpenTSDB improvements + +All three of these popular included Data Sources have seen a variety +of improvements in this release. Here are some highlights: + +### Prometheus + +The Prometheus Data Source now supports annotations. + +### InfluxDB + +You can now select the InfluxDB policy from the query editor. + + +Grafana 3.0 also comes with support for InfluxDB 0.11 and InfluxDB 0.12. + +### OpenTSDB + +OpenTSDB 2.2 is better supported and now supports millisecond precision. + +## Breaking changes + +Dashboards from v2.6 are compatible; no manual updates should be necessary. There could +be some edge case scenarios where dashboards using templating could stop working. +If that is the case just enter the edit view for the template variable and hit Update button. +This is due to a simplification of the variable format system where template variables are +now stored without any formatting (glob/regex/etc), this is done on the fly when the +variable is interpolated. + +* Plugin API: The plugin API has changed so if you are using a custom +data source (or panel) they need to be updated as well. + +* InfluxDB 0.8: This data source is no longer included in releases, +you can still install manually from [Grafana.net](http://grafana.net) + +* KairosDB: This data source has also no longer shipped with Grafana, +you can install it manually from [Grafana.net](http://grafana.net) + +## Plugin showcase + +Discovering and installing plugins is very quick and easy with Grafana 3.0 and [Grafana.net](https://grafana.net). Here +are a couple that I incurage you try! + +#### [Clock Panel](https://grafana.net/plugins/grafana-clock-panel) +Support's both current time and count down mode. + + +#### [Pie Chart Panel](https://grafana.net/plugins/grafana-piechart-panel) +A simple pie chart panel is now available as an external plugin. + + +#### [WorldPing App](https://grafana.net/plugins/raintank-worldping-app) +This is full blown Grafana App that adds new panels, data sources and pages to give +feature rich global performance monitoring directly from your on-prem Grafana. + + + +#### [Zabbix App](https://grafana.net/plugins/alexanderzobnin-zabbix-app) +This app contains the already very pouplar Zabbix data source plugin, 2 dashboards and a triggers panel. It is +created and maintained by [Alexander Zobnin](https://github.com/alexanderzobnin/grafana-zabbix). + + + +Checkout the full list of plugins on [Grafana.net](https://grafana.net/plugins) + +## CHANGELOG + +For a detailed list and link to github issues for everything included +in the 3.0 release please view the +[CHANGELOG.md](https://github.com/grafana/grafana/blob/master/CHANGELOG.md) +file. diff --git a/docs/sources/guides/whats-new-in-v4-1.md b/docs/sources/guides/whats-new-in-v4-1.md new file mode 100644 index 00000000000..b4e3b9f904c --- /dev/null +++ b/docs/sources/guides/whats-new-in-v4-1.md @@ -0,0 +1,70 @@ ++++ +title = "What's New in Grafana v4.1 beta" +description = "Feature & improvement highlights for Grafana v4.1 beta" +keywords = ["grafana", "new", "documentation", "4.1.0-beta1"] +type = "docs" +[menu.docs] +name = "Version 4.1 beta" +identifier = "v4.1" +parent = "whatsnew" +weight = -1 ++++ + + +## Whats new in Grafana v4.1 beta +- **Graph**: Support for shared tooltip on all graphs as you hover over one graph. [#1578](https://github.com/grafana/grafana/pull/1578), [#6274](https://github.com/grafana/grafana/pull/6274) +- **Victorops**: Add VictorOps notification integration [#6411](https://github.com/grafana/grafana/issues/6411), thx [@ichekrygin](https://github.com/ichekrygin) +- **Opsgenie**: Add OpsGenie notification integratiion [#6687](https://github.com/grafana/grafana/issues/6687), thx [@kylemcc](https://github.com/kylemcc) +- **Cloudwatch**: Make it possible to specify access and secret key on the data source config page [#6697](https://github.com/grafana/grafana/issues/6697) +- **Elasticsearch**: Added support for Elasticsearch 5.x [#5740](https://github.com/grafana/grafana/issues/5740), thx [@lpic10](https://github.com/lpic10) +- **Panel**: Added help text for panels. [#4079](https://github.com/grafana/grafana/issues/4079), thx [@utkarshcmu](https://github.com/utkarshcmu) +- [Full changelog](https://github.com/grafana/grafana/blob/master/CHANGELOG.md) + +### Shared tooltip + +{{< imgbox max-width="60%" img="/img/docs/v41/shared_tooltip.gif" caption="Shared tooltip" >}} + +Showing the tooltip on all panels at the same time has been a long standing request in Grafana and we are really happy to finally be able to release it. +You can enable/disable the shared tooltip from the dashboard settings menu or cycle between default, shared tooltip and shared crosshair by pressing `CTRL + O` or `CMD + O`. + +
+ +### Help text for panel + +{{< imgbox max-width="60%" img="/img/docs/v41/helptext_for_panel_settings.png" caption="Hovering help text" >}} + +You can set a help text in the general tab on any panel. The help text is using Markdown to enable better formating and linking to other sites that can provide more information. + +
+ +{{< imgbox max-width="60%" img="/img/docs/v41/helptext_hover.png" caption="Hovering help text" >}} + +Panels with a help text available have a little indicator in the top left corner. You can show the help text by hovering the icon. +
+ + +### Easier Cloudwatch configuration + +{{< imgbox max-width="60%" img="/img/docs/v41/cloudwatch_settings.png" caption="Cloudwatch configuration" >}} + +In Grafana 4.1.0 you can configure your Cloudwatch data source with `access key` and `secret key` directly in the data source configuration page. +This enables people to use the Cloudwatch data source without having access to the filesystem where Grafana is running. + +Once the `access key` and `secret key` have been saved the user will no longer be able to view them. +
+ +## Upgrade & Breaking changes + +Elasticsearch 1.x is no longer supported. Please upgrade to Elasticsearch 2.x or 5.x. Otherwise Grafana 4.1.0-beta1 contains no breaking changes. + +## Changelog + +Checkout the [CHANGELOG.md](https://github.com/grafana/grafana/blob/master/CHANGELOG.md) file for a complete list +of new features, changes, and bug fixes. + +## Download + +Head to [v4.1 download page](/download/4_1_0/) for download links & instructions. + +## Thanks +A big thanks to all the Grafana users who contribute by submitting PRs, bug reports & feedback! diff --git a/docs/sources/guides/whats-new-in-v4.md b/docs/sources/guides/whats-new-in-v4.md new file mode 100644 index 00000000000..71a5c0251da --- /dev/null +++ b/docs/sources/guides/whats-new-in-v4.md @@ -0,0 +1,180 @@ ++++ +title = "What's New in Grafana v4.0" +description = "Feature & improvement highlights for Grafana v4.0" +keywords = ["grafana", "new", "documentation", "4.0"] +type = "docs" +[menu.docs] +name = "Version 4.0 (Latest)" +identifier = "v4.0" +parent = "whatsnew" +weight = -1 ++++ + +# What's New in Grafana v4.0 + +As usual this release contains a ton of minor new features, fixes and improved UX. But on top of the usual new goodies +is a core new feature: Alerting! Read on below for a detailed description of what's new in v4.0. + +## Alerting + +{{< imgbox max-width="40%" img="/img/docs/v4/drag_handles_gif.gif" caption="Alerting overview" >}} + +Alerting is a really revolutionary feature for Grafana. It transforms Grafana from a +visualization tool into a truly mission critical monitoring tool. The alert rules are very easy to +configure using your existing graph panels and threshold levels can be set simply by dragging handles to +the right side of the graph. The rules will continually be evaluated by grafana-server and +notifications will be sent out when the rule conditions are met. + +This feature has been worked on for over a year with many iterations and rewrites +just to make sure the foundations are really solid. We are really proud to finally release it! +Since the alerting execution is processed in the backend all data source plugins are not supported. +Right now Graphite, Prometheus, InfluxDB and OpenTSDB are supported. Elasticsearch is being worked +on but will be not ready for v4 release. + +
+ +### Rules + +{{< imgbox max-width="40%" img="/img/docs/v4/alerting_conditions.png" caption="Alerting Conditions" >}} + +The rule config allows you to specify a name, how often the rule should be evaluated and a series +of conditions that all need to be true for the alert to fire. + +Currently the only condition type that exists is a `Query` condition that allows you to +specify a query letter, time range and an aggregation function. The letter refers to +a query you already have added in the **Metrics** tab. The result from the +query and the aggregation function is a single value that is then used in the threshold check. + +We plan to add other condition types in the future, like `Other Alert`, where you can include the state +of another alert in your conditions, and `Time Of Day`. + +### Notifications + +{{< imgbox max-width="40%" img="/img/docs/v4/slack_notification.png" caption="Alerting Slack Notification" >}} + +Alerting would not be very useful if there was no way to send notifications when rules trigger and change state. You +can setup notifications of different types. We currently have `Slack`, `PagerDuty`, `Email` and `Webhook` with more in the +pipe that will be added during beta period. The notifications can then be added to your alert rules. +If you have configured an external image store in the grafana.ini config file (s3 and webdav options available) +you can get very rich notifications with an image of the graph and the metric +values all included in the notification. + +### Annotations + +Alert state changes are recorded in a new annotation store that is built into Grafana. This store +currently only supports storing annotations in Grafana's own internal database (mysql, postgres or sqlite). +The Grafana annotation storage is currently only used for alert state changes but we hope to add the ability for users +to add graph comments in the form of annotations directly from within Grafana in a future release. + +### Alert List Panel + +{{< imgbox max-width="30%" img="/img/docs/v4/alert_list_panel.png" caption="Alert List Panel" >}} + +This new panel allows you to show alert rules or a history of alert rule state changes. You can filter based on states your +interested in. Very useful panel for overview style dashboards. + +
+ +## Ad-hoc filter variable + +{{< imgbox max-width="30%" img="/img/docs/v4/adhoc_filters.gif" caption="Ad-hoc filters variable" >}} + +This is a new and very different type of template variable. It will allow you to create new key/value filters on the fly. +With autocomplete for both key and values. The filter condition will be automatically applied to all +queries that use that data source. This feature opens up more exploratory dashboards. In the gif animation to the right +you have a dashboard for Elasticsearch log data. It uses one query variable that allow you to quickly change how the data +is grouped, and an interval variable for controlling the granularity of the time buckets. What was missing +was a way to dynamically apply filters to the log query. With the `Ad-Hoc Filters` variable you can +dynamically add filters to any log property! + +## UX Improvements + +We always try to bring some UX/UI refinements & polish in every release. + +### TV-mode & Kiosk mode + + +
+
+

+ Grafana is so often used on wall mounted TVs that we figured a clean TV mode would be + really nice. In TV mode the top navbar, row & panel controls will all fade to transparent. +

+ +

+ This happens automatically after one minute of user inactivity but can also be toggled manually + with the d v sequence shortcut. Any mouse movement or keyboard action will + restore navbar & controls. +

+ +

+ Another feature is the kiosk mode. This can be enabled with d k + shortcut or by adding &kiosk to the URL when you load a dashboard. + In kiosk mode the navbar is completely hidden/removed from view. +

+
+
+ {{< lightboxhelper max-width="100%" img="/img/docs/v4/tvmode.png" caption="TV mode" >}} + +
+
+ +### New row menu & add panel experience + +{{< imgbox max-width="50%" img="/img/docs/v4/add_panel.gif" caption="Add Panel flow" >}} + +We spent a lot of time improving the dashboard building experience. Trying to make it both +more efficient and easier for beginners. After many good but not great experiments +with a `build mode` we eventually decided to just improve the green row menu and +continue work on a `build mode` for a future release. + +The new row menu automatically slides out when you mouse over the edge of the row. You no longer need +to hover over the small green icon and the click it to expand the row menu. + +There is some minor improvements to drag and drop behaviour. Now when dragging a panel from one row +to another you will insert the panel and Grafana will automatically make room for it. +When you drag a panel within a row you will simply reorder the panels. + +If you look at the animation to the right you can see that you can drag and drop a new panel. This is not +required, you can also just click the panel type and it will be inserted at the end of the row +automatically. Dragging a new panel has an advantage in that you can insert a new panel where ever you want +not just at the end of the row. + +We plan to further improve dashboard building in the future with a more rich grid & layout system. + +### Keyboard shortcuts + +{{< imgbox max-width="40%" img="/img/docs/v4/shortcuts.png" caption="Shortcuts" >}} + +Grafana v4 introduces a number of really powerful keyboard shortcuts. You can now focus a panel +by hovering over it with your mouse. With a panel focused you can simple hit `e` to toggle panel +edit mode, or `v` to toggle fullscreen mode. `p r` removes the panel. `p s` opens share +modal. + +Some nice navigation shortcuts are: + +- `g h` for go to home dashboard +- `s s` open search with starred pre-selected +- `s t` open search in tags list view + +
+ +## Upgrade & Breaking changes + +There are no breaking changes. Old dashboards and features should work the same. Grafana-server will automatically upgrade it's db +schema on restart. It's advisable to do a backup of Grafana's database before updating. + +If your are using plugins make sure to update your plugins as some might not work perfectly v4. + +You can update plugins using grafana-cli + + grafana-cli plugins update-all + +## Changelog + +Checkout the [CHANGELOG.md](https://github.com/grafana/grafana/blob/master/CHANGELOG.md) file for a complete list +of new features, changes, and bug fixes. + diff --git a/docs/sources/http_api/admin.md b/docs/sources/http_api/admin.md index ba1a0923861..2d15b19454c 100644 --- a/docs/sources/http_api/admin.md +++ b/docs/sources/http_api/admin.md @@ -1,11 +1,20 @@ ----- -page_title: Admin APIs -page_description: Grafana Admin API Reference -page_keywords: grafana, admin, http, api, documentation ---- ++++ +title = "Admin HTTP API " +description = "Grafana Admin HTTP API" +keywords = ["grafana", "http", "documentation", "api", "admin"] +aliases = ["/http_api/admin/"] +type = "docs" +[menu.docs] +name = "Admin" +parent = "http_api" ++++ # Admin API +The admin http API does not currently work with an api token. Api Token's are currently only linked to an organization and organization role. They cannot given +the permission of server admin, only user's can be given that permission. So in order to use these API calls you will have to use basic auth and Grafana user +with Grafana admin permission. + ## Settings `GET /api/admin/settings` @@ -15,7 +24,6 @@ page_keywords: grafana, admin, http, api, documentation GET /api/admin/settings Accept: application/json Content-Type: application/json - Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk **Example Response**: @@ -171,7 +179,6 @@ page_keywords: grafana, admin, http, api, documentation GET /api/admin/stats Accept: application/json Content-Type: application/json - Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk **Example Response**: @@ -201,7 +208,6 @@ Create new user POST /api/admin/users HTTP/1.1 Accept: application/json Content-Type: application/json - Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk { "name":"User", @@ -228,7 +234,6 @@ Change password for specific user PUT /api/admin/users/2/password HTTP/1.1 Accept: application/json Content-Type: application/json - Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk **Example Response**: @@ -246,7 +251,6 @@ Change password for specific user PUT /api/admin/users/2/permissions HTTP/1.1 Accept: application/json Content-Type: application/json - Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk **Example Response**: @@ -264,7 +268,6 @@ Change password for specific user DELETE /api/admin/users/2 HTTP/1.1 Accept: application/json Content-Type: application/json - Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk **Example Response**: diff --git a/docs/sources/http_api/alerting.md b/docs/sources/http_api/alerting.md new file mode 100644 index 00000000000..037176f39bf --- /dev/null +++ b/docs/sources/http_api/alerting.md @@ -0,0 +1,216 @@ ++++ +title = "Alerting HTTP API " +description = "Grafana Alerting HTTP API" +keywords = ["grafana", "http", "documentation", "api", "alerting"] +aliases = ["/http_api/alerting/"] +type = "docs" +[menu.docs] +name = "Alerting" +parent = "http_api" ++++ + + +# Alerting API + +You can use the Alerting API to get information about alerts and their states but this API cannot be used to modify the alert. +To create new alerts or modify them you need to update the dashboard json that contains the alerts. + +This API can also be used to create, update and delete alert notifications. + +## Get alerts + +`GET /api/alerts/` + +**Example Request**: + + GET /api/org HTTP/1.1 + Accept: application/json + Content-Type: application/json + Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk + +**Example Response**: + + HTTP/1.1 200 + Content-Type: application/json + [ + { + "id": 1, + "dashboardId": 1, + "panelId": 1, + "name": "fire place sensor", + "message": "Someone is trying to break in through the fire place", + "state": "alerting", + "newStateDate": "2016-12-25", + "executionError": "", + "dashboardUri": "http://grafana.com/dashboard/db/sensors" + } + ] + +## Get one alert + +`GET /api/alerts/:id` + +**Example Request**: + + GET /api/org HTTP/1.1 + Accept: application/json + Content-Type: application/json + Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk + +**Example Response**: + + HTTP/1.1 200 + Content-Type: application/json + { + "id": 1, + "dashboardId": 1, + "panelId": 1, + "name": "fire place sensor", + "message": "Someone is trying to break in through the fire place", + "state": "alerting", + "newStateDate": "2016-12-25", + "executionError": "", + "dashboardUri": "http://grafana.com/dashboard/db/sensors" + } + + +## Pause alert + +`POST /api/alerts/:id/pause` + +**Example Request**: + + GET /api/org HTTP/1.1 + Accept: application/json + Content-Type: application/json + Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk + + { + "alertId": 1, + "paused: true + } + +**Example Response**: + + HTTP/1.1 200 + Content-Type: application/json + { + "alertId": 1, + "state": "Paused", + "message": "alert paused" + } + +## Get alert notifications + +`GET /api/alert-notifications` + +**Example Request**: + + GET /api/org HTTP/1.1 + Accept: application/json + Content-Type: application/json + Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk + +**Example Response**: + + HTTP/1.1 200 + Content-Type: application/json + + { + "id": 1, + "name": "Team A", + "type": "email", + "isDefault": true, + "created": "2017-01-01 12:45", + "updated": "2017-01-01 12:45" + } + +## Create alert notification + +`POST /api/alerts-notifications` + +**Example Request**: + + GET /api/org HTTP/1.1 + Accept: application/json + Content-Type: application/json + Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk + + { + "name": "new alert notification", //Required + "type": "email", //Required + "isDefault": false, + "settings": { + "addresses: "carl@grafana.com;dev@grafana.com" + } + } + + +**Example Response**: + + HTTP/1.1 200 + Content-Type: application/json + { + "id": 1, + "name": "new alert notification", + "type": "email", + "isDefault": false, + "settings": { addresses: "carl@grafana.com;dev@grafana.com"} } + "created": "2017-01-01 12:34", + "updated": "2017-01-01 12:34" + } + +## Update alert notification + +`PUT /api/alerts-notifications/1` + +**Example Request**: + + GET /api/org HTTP/1.1 + Accept: application/json + Content-Type: application/json + Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk + + { + "id": 1, + "name": "new alert notification", //Required + "type": "email", //Required + "isDefault": false, + "settings": { + "addresses: "carl@grafana.com;dev@grafana.com" + } + } + + +**Example Response**: + + HTTP/1.1 200 + Content-Type: application/json + { + "id": 1, + "name": "new alert notification", + "type": "email", + "isDefault": false, + "settings": { addresses: "carl@grafana.com;dev@grafana.com"} } + "created": "2017-01-01 12:34", + "updated": "2017-01-01 12:34" + } + +## Delete alert notification + +`DELETE /api/alerts-notifications/1` + +**Example Request**: + + GET /api/org HTTP/1.1 + Accept: application/json + Content-Type: application/json + Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk + +**Example Response**: + + HTTP/1.1 200 + Content-Type: application/json + { + "message": "Notification deleted" + } diff --git a/docs/sources/http_api/auth.md b/docs/sources/http_api/auth.md index df874d1653e..aaeda1105b1 100644 --- a/docs/sources/http_api/auth.md +++ b/docs/sources/http_api/auth.md @@ -1,8 +1,13 @@ ----- -page_title: Authentication API -page_description: Grafana HTTP API Reference -page_keywords: grafana, admin, http, api, documentation ---- ++++ +title = "Authentication HTTP API " +description = "Grafana Authentication HTTP API" +keywords = ["grafana", "http", "documentation", "api", "authentication"] +aliases = ["/http_api/authentication/"] +type = "docs" +[menu.docs] +name = "Authentication" +parent = "http_api" ++++ # Authentication API @@ -13,7 +18,7 @@ Currently you can authenticate via an `API Token` or via a `Session cookie` (acq ## Basic Auth If basic auth is enabled (it is enabled by default) you can authenticate your HTTP request via -standard basic auth. +standard basic auth. Basic auth will also authenticate LDAP users. curl example: ``` diff --git a/docs/sources/http_api/dashboard.md b/docs/sources/http_api/dashboard.md index 68f6ab022cc..5e9891e0a89 100644 --- a/docs/sources/http_api/dashboard.md +++ b/docs/sources/http_api/dashboard.md @@ -1,8 +1,13 @@ ----- -page_title: Dashboard API -page_description: Grafana Dashboard API Reference -page_keywords: grafana, admin, http, api, documentation, dashboard ---- ++++ +title = "Dashboard HTTP API " +description = "Grafana Dashboard HTTP API" +keywords = ["grafana", "http", "documentation", "api", "dashboard"] +aliases = ["/http_api/dashboard/"] +type = "docs" +[menu.docs] +name = "Dashboard" +parent = "http_api" ++++ # Dashboard API @@ -96,7 +101,7 @@ Will return the dashboard given the dashboard slug. Slug is the url friendly ver "isStarred": false, "slug": "production-overview" }, - "model": { + "dashboard": { "id": null, "title": "Production Overview", "tags": [ "templated" ], @@ -191,7 +196,7 @@ Will return the home dashboard. `GET /api/dashboards/tags` -Get all tabs of dashboards +Get all tags of dashboards **Example Request**: diff --git a/docs/sources/http_api/data_source.md b/docs/sources/http_api/data_source.md index 2a3c20e9af8..dd8cbc9aa74 100644 --- a/docs/sources/http_api/data_source.md +++ b/docs/sources/http_api/data_source.md @@ -1,8 +1,14 @@ ----- -page_title: Data source API -page_description: Grafana Data source API Reference -page_keywords: grafana, admin, http, api, documentation, datasource ---- ++++ +title = "Data source HTTP API " +description = "Grafana Data source HTTP API" +keywords = ["grafana", "http", "documentation", "api", "data source"] +aliases = ["/http_api/datasource/"] +type = "docs" +[menu.docs] +name = "Data source" +parent = "http_api" ++++ + # Data source API @@ -152,7 +158,7 @@ page_keywords: grafana, admin, http, api, documentation, datasource HTTP/1.1 200 Content-Type: application/json - {"id":1,"message":"Datasource added"} + {"id":1,"message":"Datasource added", "name": "test_datasource"} ## Update an existing data source @@ -187,7 +193,7 @@ page_keywords: grafana, admin, http, api, documentation, datasource HTTP/1.1 200 Content-Type: application/json - {"message":"Datasource updated"} + {"message":"Datasource updated", "id": 1, "name": "test_datasource"} ## Delete an existing data source @@ -207,35 +213,6 @@ page_keywords: grafana, admin, http, api, documentation, datasource {"message":"Data source deleted"} -## Available data source types - -`GET /api/datasources/plugins` - -**Example Request**: - - GET /api/datasources/plugins HTTP/1.1 - Accept: application/json - Content-Type: application/json - Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk - -**Example Response**: - - HTTP/1.1 200 - Content-Type: application/json - - { - "grafana":{ - "metrics":true,"module":"plugins/datasource/grafana/datasource", - "name":"Grafana (for testing)", - "partials":{ - "query":"app/plugins/datasource/grafana/partials/query.editor.html" - }, - "pluginType":"datasource", - "serviceName":"GrafanaDatasource", - "type":"grafana" - } - } - ## Data source proxy calls `GET /api/datasources/proxy/:datasourceId/*` diff --git a/docs/sources/http_api/index.md b/docs/sources/http_api/index.md new file mode 100644 index 00000000000..9c5d0e7d49a --- /dev/null +++ b/docs/sources/http_api/index.md @@ -0,0 +1,29 @@ ++++ +title = "HTTP API" +description = "Grafana HTTP API" +keywords = ["grafana", "http", "documentation", "api", "overview"] +type = "docs" +[menu.docs] +name = "HTTP API" +identifier = "http_api" +weight = 9 ++++ + + +# HTTP API Reference + +The Grafana backend exposes an HTTP API, the same API is used by the frontend to do everything from saving +dashboards, creating users and updating data sources. + +## Supported HTTP APIs: + + +* [Authentication API]({{< relref "auth.md" >}}) +* [Dashboard API]({{< relref "dashboard.md" >}}) +* [Data Source API]({{< relref "data_source.md" >}}) +* [Organisation API]({{< relref "org.md" >}}) +* [User API]({{< relref "user.md" >}}) +* [Admin API]({{< relref "admin.md" >}}) +* [Snapshot API]({{< relref "snapshot.md" >}}) +* [Preferences API]({{< relref "preferences.md" >}}) +* [Other API]({{< relref "other.md" >}}) diff --git a/docs/sources/http_api/org.md b/docs/sources/http_api/org.md index adb5d5cd31e..72c995adedf 100644 --- a/docs/sources/http_api/org.md +++ b/docs/sources/http_api/org.md @@ -1,8 +1,14 @@ ----- -page_title: Organisation API -page_description: Grafana Organisation API Reference -page_keywords: grafana, admin, http, api, documentation, orgs, organisation ---- ++++ +title = "Organisation HTTP API " +description = "Grafana Organisation HTTP API" +keywords = ["grafana", "http", "documentation", "api", "organisation"] +aliases = ["/http_api/organisation/"] +type = "docs" +[menu.docs] +name = "Organisation" +parent = "http_api" ++++ + # Organisation API @@ -85,6 +91,34 @@ page_keywords: grafana, admin, http, api, documentation, orgs, organisation } } +## Create Organisation + +`POST /api/orgs` + +**Example Request**: + + POST /api/orgs HTTP/1.1 + Accept: application/json + Content-Type: application/json + Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk + + { + "name":"New Org." + } + + +**Example Response**: + + HTTP/1.1 200 + Content-Type: application/json + + { + "orgId":"1", + "message":"Organization created" + } + + + ## Update current Organisation `PUT /api/org` diff --git a/docs/sources/http_api/other.md b/docs/sources/http_api/other.md index 8852b6ccb38..65d18f94ea4 100644 --- a/docs/sources/http_api/other.md +++ b/docs/sources/http_api/other.md @@ -1,8 +1,14 @@ ----- -page_title: Other APIs -page_description: Grafana Other API Reference -page_keywords: grafana, admin, http, api, documentation, dashboards ---- ++++ +title = "Other HTTP API " +description = "Grafana Other HTTP API" +keywords = ["grafana", "http", "documentation", "api", "other"] +aliases = ["/http_api/other/"] +type = "docs" +[menu.docs] +name = "Other" +parent = "http_api" ++++ + # Frontend Settings API diff --git a/docs/sources/http_api/overview.md b/docs/sources/http_api/overview.md deleted file mode 100644 index 8e7e2d60ad3..00000000000 --- a/docs/sources/http_api/overview.md +++ /dev/null @@ -1,21 +0,0 @@ ----- -page_title: HTTP API -page_description: Grafana HTTP API Reference -page_keywords: grafana, admin, http, api, documentation ---- - -# HTTP API Reference - -The Grafana backend exposes an HTTP API, the same API is used by the frontend to do everything from saving -dashboards, creating users and updating data sources. - -###Supported HTTP APIs: - -* [Authentication API](/http_api/auth/) -* [Dashboard API](/http_api/dashboard/) -* [Data Source API](/http_api/data_source/) -* [Organisation API](/http_api/org/) -* [User API](/http_api/user/) -* [Admin API](/http_api/admin/) -* [Snapshot API](/http_api/snapshot/) -* [Other API](/http_api/other/) diff --git a/docs/sources/http_api/preferences.md b/docs/sources/http_api/preferences.md new file mode 100644 index 00000000000..a4b953cdaed --- /dev/null +++ b/docs/sources/http_api/preferences.md @@ -0,0 +1,105 @@ ++++ +title = "HTTP Preferences API " +description = "Grafana HTTP API" +keywords = ["grafana", "http", "documentation", "api", "preferences"] +aliases = ["/http_api/preferences/"] +type = "docs" +[menu.docs] +name = "Preferences" +parent = "http_api" ++++ + +# User and Org Preferences API + +Keys: + +- **theme** - One of: ``light``, ``dark``, or an empty string for the default theme +- **homeDashboardId** - The numerical ``:id`` of a favorited dashboard, default: ``0`` +- **timezone** - One of: ``utc``, ``browser``, or an empty string for the default + +Omitting a key will cause the current value to be replaced with the +system default value. + +## Get Current User Prefs + +`GET /api/user/preferences` + +**Example Request**: + + GET /api/user/preferences HTTP/1.1 + Accept: application/json + Content-Type: application/json + Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk + +**Example Response**: + + HTTP/1.1 200 + Content-Type: application/json + + {"theme":"","homeDashboardId":0,"timezone":""} + +## Update Current User Prefs + +`PUT /api/user/preferences` + +**Example Request**: + + PUT /api/user/preferences HTTP/1.1 + Accept: application/json + Content-Type: application/json + Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk + + { + "theme": "", + "homeDashboardId":0, + "timezone":"utc" + } + +**Example Response**: + + HTTP/1.1 200 + Content-Type: text/plain; charset=utf-8 + + {"message":"Preferences updated"} + +## Get Current Org Prefs + +`GET /api/org/preferences` + +**Example Request**: + + GET /api/org/preferences HTTP/1.1 + Accept: application/json + Content-Type: application/json + Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk + +**Example Response**: + + HTTP/1.1 200 + Content-Type: application/json + + {"theme":"","homeDashboardId":0,"timezone":""} + +## Update Current Org Prefs + +`PUT /api/org/preferences` + +**Example Request**: + + PUT /api/org/preferences HTTP/1.1 + Accept: application/json + Content-Type: application/json + Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk + + { + "theme": "", + "homeDashboardId":0, + "timezone":"utc" + } + +**Example Response**: + + HTTP/1.1 200 + Content-Type: text/plain; charset=utf-8 + + {"message":"Preferences updated"} diff --git a/docs/sources/http_api/snapshot.md b/docs/sources/http_api/snapshot.md index 8f18c6ed81f..f0b8304cd24 100644 --- a/docs/sources/http_api/snapshot.md +++ b/docs/sources/http_api/snapshot.md @@ -1,8 +1,13 @@ ----- -page_title: Snapshot API -page_description: Grafana Snapshot API Reference -page_keywords: grafana, admin, http, api, documentation, snapshot, dashboard ---- ++++ +title = "HTTP Snapshot API " +description = "Grafana HTTP API" +keywords = ["grafana", "http", "documentation", "api", "snapshot"] +aliases = ["/http_api/snapshot/"] +type = "docs" +[menu.docs] +name = "Snapshot" +parent = "http_api" ++++ # Snapshot API diff --git a/docs/sources/http_api/user.md b/docs/sources/http_api/user.md index aa870031ca2..734fbb4f934 100644 --- a/docs/sources/http_api/user.md +++ b/docs/sources/http_api/user.md @@ -1,10 +1,15 @@ ----- -page_title: User API -page_description: Grafana User API Reference -page_keywords: grafana, admin, http, api, documentation, user ---- ++++ +title = "User HTTP API " +description = "Grafana User HTTP API" +keywords = ["grafana", "http", "documentation", "api", "user"] +aliases = ["/http_api/user/"] +type = "docs" +[menu.docs] +name = "Users" +parent = "http_api" ++++ -# User API +# User HTTP resources / actions ## Search Users diff --git a/docs/sources/index.md b/docs/sources/index.md index 83b7f44dd5b..0324bf888ad 100644 --- a/docs/sources/index.md +++ b/docs/sources/index.md @@ -1,37 +1,50 @@ ---- -page_title: Grafana Installation -page_description: Install guide for Grafana. -page_keywords: grafana, installation, documentation ---- ++++ +title = "Grafana Documentation Site" +description = "Install guide for Grafana" +keywords = ["grafana", "installation", "documentation"] +type = "docs" +[menu.docs] +name = "Welcome to the Docs" +identifier = "root" +weight = -1 ++++ -# Installation +# Welcome to the Grafana Documentation -Grafana is easily installed via a Debian/Ubuntu package (.deb), via -Redhat/Centos package (.rpm) or manually via a tarball that contains all -required files and binaries. If you can't find a package or binary for -your platform, you might be able to build one yourself. Read the [build -from source](../project/building_from_source) instructions for more -information. +Grafana is an open source metric analytics & visualization suite. It is most commonly used for +visualizing time series data for infrastructure and application analytics but many use it in +other domains including industrial sensors, home automation, weather, and process control. -## Platforms -- [Installing on Debian / Ubuntu](installation/debian.md) -- [Installing on RPM-based Linux (CentOS, Fedora, OpenSuse, RedHat)](installation/rpm.md) -- [Installing on Mac OS X](installation/mac.md) -- [Installing on Windows](installation/windows.md) -- [Installing on Docker](installation/docker.md) -- [Installing using Provisioning (Chef, Puppet, Salt, Ansible, etc)](installation/provisioning.md) -- [Nightly Builds](http://grafana.org/download/builds.html) +## Installing Grafana +- [Installing on Debian / Ubuntu](installation/debian) +- [Installing on RPM-based Linux (CentOS, Fedora, OpenSuse, RedHat)](installation/rpm) +- [Installing on Mac OS X](installation/mac) +- [Installing on Windows](installation/windows) +- [Installing on Docker](installation/docker) +- [Installing using Provisioning (Chef, Puppet, Salt, Ansible, etc)](installation/provisioning) +- [Nightly Builds](http://grafana.org/builds) -## Configuration +For other platforms Read the [build from source]({{< relref "project/building_from_source.md" >}}) +instructions for more information. + +## Configuring Grafana The back-end web server has a number of configuration options. Go the [Configuration](/installation/configuration) page for details on all those options. + +## Getting started + +- [Getting Started](guides/getting_started) +- [Basic Concepts](guides/basic_concepts) +- [Screencasts](tutorials/screencasts) + ## Data sources guides -- [Graphite](datasources/graphite.md) -- [Elasticsearch](datasources/elasticsearch.md) -- [InfluxDB](datasources/influxdb.md) -- [OpenTSDB](datasources/opentsdb.md) +- [Graphite](datasources/graphite) +- [Elasticsearch](datasources/elasticsearch) +- [InfluxDB](datasources/influxdb) +- [OpenTSDB](datasources/opentsdb) + diff --git a/docs/sources/installation/behind_proxy.md b/docs/sources/installation/behind_proxy.md new file mode 100644 index 00000000000..46b70b5dc85 --- /dev/null +++ b/docs/sources/installation/behind_proxy.md @@ -0,0 +1,70 @@ ++++ +title = "Running Grafana behind a reverse proxy" +description = "Guide for running Grafana behind a reverse proxy" +keywords = ["grafana", "nginx", "documentation", "haproxy", "reverse"] +type = "docs" +[menu.docs] +name = "Running Grafana behind a reverse proxy" +parent = "tutorials" +weight = 1 ++++ + + +# Running Grafana behind a reverse proxy + +It should be straight forward to get Grafana up and running behind a reverse proxy. But here are some things that you might run into. + +Links and redirects will not be rendered correctly unless you set the server.domain setting. +``` +[server] +domain = foo.bar +``` + +To use sub *path* ex `http://foo.bar/grafana` make sure to include `/grafana` in the end of root_url. +Otherwise Grafana will not behave correctly. See example below. + +# Examples +Here are some example configurations for running Grafana behind a reverse proxy. + +## Grafana configuration (ex http://foo.bar.com) +``` +[server] +domain = foo.bar +``` + +## Nginx configuration +``` +server { + listen 80; + root /usr/share/nginx/www; + index index.html index.htm; + + location / { + proxy_pass http://localhost:3000/; + } +} +``` + +# Examples with **sub path** (ex http://foo.bar.com/grafana) + +## Grafana configuration with sub path +``` +[server] +domain = foo.bar +root_url = %(protocol)s://%(domain)s:/grafana +``` + +## Nginx configuration with sub path +``` +server { + listen 80; + root /usr/share/nginx/www; + index index.html index.htm; + + location /grafana/ { + proxy_pass http://localhost:3000/; + } +} +``` + + diff --git a/docs/sources/installation/configuration.md b/docs/sources/installation/configuration.md index cdc24dc7c59..157915e8950 100644 --- a/docs/sources/installation/configuration.md +++ b/docs/sources/installation/configuration.md @@ -1,8 +1,14 @@ ---- -page_title: Configuration -page_description: Configuration guide for Grafana. -page_keywords: grafana, configuration, documentation ---- ++++ +title = "Configuration" +description = "Configuration Docs" +keywords = ["grafana", "configuration", "documentation"] +type = "docs" +[menu.docs] +name = "Configuration" +identifier = "config" +parent = "admin" +weight = 1 ++++ # Configuration @@ -30,6 +36,9 @@ using environment variables using the syntax: Where the section name is the text within the brackets. Everything should be upper case, `.` should be replaced by `_`. For example, given these configuration settings: + # default section + instance_name = ${HOSTNAME} + [security] admin_user = admin @@ -39,11 +48,18 @@ should be upper case, `.` should be replaced by `_`. For example, given these co Then you can override them using: + export GF_DEFAULT_INSTANCE_NAME=my-instance export GF_SECURITY_ADMIN_USER=true export GF_AUTH_GOOGLE_CLIENT_SECRET=newS3cretKey
+## instance_name +Set the name of the grafana-server instance. Used in logging and internal metrics and in +clustering info. Defaults to: `${HOSTNAME}`, which will be replaced with +environment variable `HOSTNAME`, if that is empty or does not exist Grafana will try to use +system calls to get the machine name. + ## [paths] ### data @@ -70,7 +86,7 @@ The IP address to bind to. If empty will bind to all interfaces The port to bind to, defaults to `3000`. To use port 80 you need to either give the Grafana binary permission for example: - $ sudo setcap 'cap_net_bind_service=+ep' /opt/grafana/current/grafana + $ sudo setcap 'cap_net_bind_service=+ep' /usr/sbin/grafana-server Or redirect port 80 to the Grafana port using: @@ -82,6 +98,8 @@ Another way is put a webserver like Nginx or Apache in front of Grafana and have `http` or `https` +> **Note** Grafana versions earlier than 3.0 are vulnerable to [POODLE](https://en.wikipedia.org/wiki/POODLE). So we strongly recommend to upgrade to 3.x or use a reverse proxy for ssl termination. + ### domain This setting is only used in as a part of the `root_url` setting (see below). Important if you @@ -126,6 +144,10 @@ Grafana needs a database to store users and dashboards (and other things). By default it is configured to use `sqlite3` which is an embedded database (included in the main Grafana binary). +### url +Use either URL or or the other fields below to configure the database +Example: `mysql://user:secret@host:port/database` + ### type Either `mysql`, `postgres` or `sqlite3`, it's your choice. @@ -152,7 +174,7 @@ The database user (not applicable for `sqlite3`). ### password -The database user's password (not applicable for `sqlite3`). +The database user's password (not applicable for `sqlite3`). If the password contains `#` or `;` you have to wrap it with trippel quotes. Ex `"""#password;"""` ### ssl_mode @@ -186,7 +208,7 @@ Defaults to `admin`. ### admin_password -The password of the default Grafana admin. Defaults to `admin`. +The password of the default Grafana admin. Set once on first-run. Defaults to `admin`. ### login_remember_days @@ -226,7 +248,18 @@ organization to be created for that new user. The role new users will be assigned for the main organization (if the above setting is set to true). Defaults to `Viewer`, other valid -options are `Admin` and `Editor`. +options are `Admin` and `Editor` and `Read Only Editor`. e.g. : + +`auto_assign_org_role = Read Only Editor` + + +
+ +## [auth] + +### disable_login_form + +Set to true to disable (hide) the login form, useful if you use OAuth, defaults to false.
@@ -263,14 +296,16 @@ example: [auth.github] enabled = true + allow_sign_up = true client_id = YOUR_GITHUB_APP_CLIENT_ID client_secret = YOUR_GITHUB_APP_CLIENT_SECRET scopes = user:email auth_url = https://github.com/login/oauth/authorize token_url = https://github.com/login/oauth/access_token - api_url = https://api.github.com + api_url = https://api.github.com/user allow_sign_up = false team_ids = + allowed_organizations = Restart the Grafana back-end. You should now see a GitHub login button on the login page. You can now login or sign up with your GitHub @@ -296,7 +331,25 @@ Grafana instance. For example: team_ids = 150,300 auth_url = https://github.com/login/oauth/authorize token_url = https://github.com/login/oauth/access_token - allow_sign_up = false + allow_sign_up = true + +### allowed_organizations + +Require an active organization membership for at least one of the given +organizations on GitHub. If the authenticated user isn't a member of at least +one of the organizations they will not be able to register or authenticate with +your Grafana instance. For example + + [auth.github] + enabled = true + client_id = YOUR_GITHUB_APP_CLIENT_ID + client_secret = YOUR_GITHUB_APP_CLIENT_SECRET + scopes = user:email,read:org + auth_url = https://github.com/login/oauth/authorize + token_url = https://github.com/login/oauth/access_token + allow_sign_up = true + # space-delimited organization names + allowed_organizations = github google
@@ -322,7 +375,7 @@ Secret. Specify these in the Grafana configuration file. For example: auth_url = https://accounts.google.com/o/oauth2/auth token_url = https://accounts.google.com/o/oauth2/token allowed_domains = mycompany.com mycompany.org - allow_sign_up = false + allow_sign_up = true Restart the Grafana back-end. You should now see a Google login button on the login page. You can now login or sign up with your Google @@ -333,6 +386,26 @@ You may allow users to sign-up via Google authentication by setting the user successfully authenticating via Google authentication will be automatically signed up. +## [auth.generic_oauth] + +This option could be used if have your own oauth service. + +This callback URL must match the full HTTP address that you use in your +browser to access Grafana, but with the prefix path of `/login/generic_oauth`. + + [auth.generic_oauth] + enabled = true + client_id = YOUR_APP_CLIENT_ID + client_secret = YOUR_APP_CLIENT_SECRET + scopes = + auth_url = + token_url = + api_url = + allowed_domains = mycompany.com mycompany.org + allow_sign_up = true + +Set api_url to the resource that returns basic user info. +
## [auth.basic] @@ -348,7 +421,7 @@ Set to `true` to enable LDAP integration (default: `false`) ### config_file Path to the LDAP specific configuration file (default: `/etc/grafana/ldap.toml`) -> For details on LDAP Configuration, go to the [LDAP Integration](ldap.md) page. +> For details on LDAP Configuration, go to the [LDAP Integration]({{< relref "ldap.md" >}}) page.
@@ -384,7 +457,7 @@ session provider you have configured. - **mysql:** go-sql-driver/mysql dsn config string, e.g. `user:password@tcp(127.0.0.1:3306)/database_name` - **postgres:** ex: user=a password=b host=localhost port=5432 dbname=c sslmode=disable - **memcache:** ex: 127.0.0.1:11211 -- **redis:** ex: `addr=127.0.0.1:6379,pool_size=100,db=grafana` +- **redis:** ex: `addr=127.0.0.1:6379,pool_size=100,prefix=grafana` If you use MySQL or Postgres as the session store you need to create the session table manually. @@ -439,3 +512,112 @@ Grafana backend index those json dashboards which will make them appear in regul ### path The full path to a directory containing your json dashboards. + +## [smtp] +Email server settings. + +### enabled +defaults to false + +### host +defaults to localhost:25 + +### user +In case of SMTP auth, defaults to `empty` + +### password +In case of SMTP auth, defaults to `empty` + +### cert_file +File path to a cert file, defaults to `empty` + +### key_file +File path to a key file, defaults to `empty` + +### skip_verify +Verify SSL for smtp server? defaults to `false` + +### from_address +Address used when sending out emails, defaults to `admin@grafana.localhost` + +## [log] + +### mode +Either "console", "file", "syslog". Default is console and file +Use space to separate multiple modes, e.g. "console file" + +### level +Either "debug", "info", "warn", "error", "critical", default is "info" + +### filters +optional settings to set different levels for specific loggers. +Ex `filters = sqlstore:debug` + +## [metrics] + +### enabled +Enable metrics reporting. defaults true. Available via HTTP API `/api/metrics`. + +### interval_seconds + +Flush/Write interval when sending metrics to external TSDB. Defaults to 10s. + +## [metrics.graphite] +Include this section if you want to send internal Grafana metrics to Graphite. + +### address +Format ``:port + +### prefix +Graphite metric prefix. Defaults to `prod.grafana.%(instance_name)s.` + +## [snapshots] + +### external_enabled +Set to false to disable external snapshot publish endpoint (default true) + +### external_snapshot_url +Set root url to a Grafana instance where you want to publish external snapshots (defaults to https://snapshots-origin.raintank.io) + +### external_snapshot_name +Set name for external snapshot button. Defaults to `Publish to snapshot.raintank.io` + +### remove expired snapshot +Enabled to automatically remove expired snapshots + +### remove snapshots after 90 days +Time to live for snapshots. + +## [external_image_storage] +These options control how images should be made public so they can be shared on services like slack. + +### provider +You can choose between (s3, webdav). If left empty Grafana will ignore the upload action. + +## [external_image_storage.s3] + +### bucket_url +bucket url for s3. ex http://grafana.s3.amazonaws.com/ + +### access_key +access key. ex AAAAAAAAAAAAAAAAAAAA + +### secret_key +secret key. ex AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + +## [external_image_storage.webdav] + +### url +Url to where Grafana will send PUT request with images + +### username +basic auth username + +### password +basic auth password + +## [alerting] + +### execute_alerts = true + +Makes it possible to turn off alert rule execution. diff --git a/docs/sources/installation/debian.md b/docs/sources/installation/debian.md index b5c72f3182c..da2358d14cd 100644 --- a/docs/sources/installation/debian.md +++ b/docs/sources/installation/debian.md @@ -1,34 +1,50 @@ ---- -page_title: Installing on Debian / Ubuntu -page_description: Grafana Installation guide for Debian / Ubuntu. -page_keywords: grafana, installation, debian, ubuntu, guide ---- ++++ +title = "Installing on Debian / Ubuntu" +description = "Install guide for Grafana" +keywords = ["grafana", "installation", "documentation"] +type = "docs" +aliases = ["/installation/installation/debian"] +[menu.docs] +name = "Installing on Ubuntu / Debian" +identifier = "debian" +parent = "installation" +weight = 1 ++++ # Installing on Debian / Ubuntu -## Download - Description | Download ------------ | ------------- -.deb for Debian-based Linux | [grafana_2.6.0_amd64.deb](https://grafanarel.s3.amazonaws.com/builds/grafana_2.6.0_amd64.deb) +Stable for Debian-based Linux | [4.0.2 (x86-64 deb)](https://grafanarel.s3.amazonaws.com/builds/grafana_4.0.2-1481203731_amd64.deb) +Latest beta for Debian-based Linux | [4.1.0-beta1 (x86-64 deb)](https://grafanarel.s3.amazonaws.com/builds/grafana_4.1.0-1482230757beta1_amd64.deb) -## Install +## Install Stable - $ wget https://grafanarel.s3.amazonaws.com/builds/grafana_2.6.0_amd64.deb - $ sudo apt-get install -y adduser libfontconfig - $ sudo dpkg -i grafana_2.6.0_amd64.deb +``` +$ wget https://grafanarel.s3.amazonaws.com/builds/grafana_4.0.2-1481203731_amd64.deb +$ sudo apt-get install -y adduser libfontconfig +$ sudo dpkg -i grafana_4.0.2-1481203731_amd64.deb +``` + +## Install Latest Beta + +``` +$ wget https://grafanarel.s3.amazonaws.com/builds/grafana_4.1.0-1482230757beta1_amd64.deb +$ sudo apt-get install -y adduser libfontconfig +$ sudo dpkg -i grafana_4.1.0-1482230757beta1_amd64.deb +``` ## APT Repository Add the following line to your `/etc/apt/sources.list` file. - deb https://packagecloud.io/grafana/stable/debian/ wheezy main + deb https://packagecloud.io/grafana/stable/debian/ jessie main Use the above line even if you are on Ubuntu or another Debian version. There is also a testing repository if you want beta or release candidates. - deb https://packagecloud.io/grafana/testing/debian/ wheezy main + deb https://packagecloud.io/grafana/testing/debian/ jessie main Then add the [Package Cloud](https://packagecloud.io/grafana) key. This allows you to install signed packages. @@ -68,7 +84,7 @@ is `3000` and default user and group is `admin`. To configure the Grafana server to start at boot time: - $ sudo update-rc.d grafana-server defaults 95 10 + $ sudo update-rc.d grafana-server defaults ## Start the server (via systemd) @@ -97,23 +113,24 @@ By default Grafana will log to `/var/log/grafana` The default configuration specifies a sqlite3 database located at `/var/lib/grafana/grafana.db`. Please backup this database before -upgrades. You can also use MySQL or Postgres as the Grafana database, as detailed on [the configuration page](configuration.md#database). +upgrades. You can also use MySQL or Postgres as the Grafana database, as detailed on [the configuration page]({{< relref "configuration.md#database" >}}). ## Configuration The configuration file is located at `/etc/grafana/grafana.ini`. Go the -[Configuration](/installation/configuration) page for details on all +[Configuration]({{< relref "configuration.md" >}}) page for details on all those options. ### Adding data sources -- [Graphite](../datasources/graphite.md) -- [InfluxDB](../datasources/influxdb.md) -- [OpenTSDB](../datasources/opentsdb.md) +- [Graphite]({{< relref "datasources/graphite.md" >}}) +- [InfluxDB]({{< relref "datasources/influxdb.md" >}}) +- [OpenTSDB]({{< relref "datasources/opentsdb.md" >}}) +- [Prometheus]({{< relref "datasources/prometheus.md" >}}) ## Installing from binary tar file -Download [the latest `.tar.gz` file](http://grafana.org/download/builds) and +Download [the latest `.tar.gz` file](http://grafana.org/download) and extract it. This will extract into a folder named after the version you downloaded. This folder contains all files required to run Grafana. There are no init scripts or install scripts in this package. @@ -125,5 +142,3 @@ To configure Grafana add a configuration file named `custom.ini` to the Start Grafana by executing `./bin/grafana-server web`. The `grafana-server` binary needs the working directory to be the root install directory (where the binary and the `public` folder is located). - - diff --git a/docs/sources/installation/docker.md b/docs/sources/installation/docker.md index 18dcf964450..85349dc58fb 100644 --- a/docs/sources/installation/docker.md +++ b/docs/sources/installation/docker.md @@ -1,17 +1,18 @@ ---- -page_title: Installing using Docker -page_description: Grafana Installation guide using Docker container -page_keywords: grafana, installation, docker, container, guide ---- ++++ +title = "Installing using Docker" +description = "Installing Grafana using Docker guide" +keywords = ["grafana", "configuration", "documentation", "docker"] +type = "docs" +[menu.docs] +name = "Installing using Docker" +identifier = "docker" +parent = "installation" +weight = 4 ++++ # Installing using Docker -> **2.0.2 -> 2.1.0 Upgrade NOTICE!** -> The data and log paths were not correct in the previous image. The grafana database was placed by default in /usr/share/grafana/data instead of the correct path /var/lib/grafana. This means it was not in a dir that was marked as a volume. So if you remove the container it will remove the grafana database. So before updating make sure you copy the /usr/share/grafana/data path from inside the container to the host. - -## Install from official docker image - -Grafana has an official Docker container. +Grafana is very easy to install and run using the offical docker container. $ docker run -i -p 3000:3000 grafana/grafana @@ -28,7 +29,7 @@ container: $ docker run -d -p 3000:3000 \ -v /var/lib/grafana:/var/lib/grafana \ -e "GF_SECURITY_ADMIN_PASSWORD=secret" \ - grafana/grafana:develop + grafana/grafana In the above example I map the data folder and sets a configuration option via an `ENV` instruction. @@ -36,6 +37,6 @@ an `ENV` instruction. ## Configuration The back-end web server has a number of configuration options. Go the -[Configuration](../installation/configuration.md) page for details on all +[Configuration]({{< relref "configuration.md" >}}) page for details on all those options. diff --git a/docs/sources/installation/index.md b/docs/sources/installation/index.md index 395c101a8e8..dc7fd9597a2 100644 --- a/docs/sources/installation/index.md +++ b/docs/sources/installation/index.md @@ -1,37 +1,22 @@ ---- -page_title: Grafana Installation -page_description: Install guide for Grafana. -page_keywords: grafana, installation, documentation ---- ++++ +title = "Installation" +description = "Install guide for Grafana" +keywords = ["grafana", "installation", "documentation"] +type = "docs" +aliases = ["installation/installation/"] +[menu.docs] +name = "Installation" +identifier = "installation" ++++ -# Installation +## Installing Grafana -Grafana is easily installed via a Debian/Ubuntu package (.deb), via -Redhat/Centos package (.rpm) or manually via a tarball that contains all -required files and binaries. If you can't find a package or binary for -your platform, you might be able to build one yourself. Read the [build -from source](../project/building_from_source) instructions for more -information. - -## Platforms -- [Installing on Debian / Ubuntu](debian.md) -- [Installing on RPM-based Linux (CentOS, Fedora, OpenSuse, RedHat)](rpm.md) -- [Installing on Mac OS X](mac.md) -- [Installing on Windows](windows.md) -- [Installing on Docker](docker.md) -- [Installing using Provisioning (Chef, Puppet, Salt, Ansible, etc)](provisioning.md) -- [Nightly Builds](http://grafana.org/download/builds.html) - -## Configuration - -The back-end web server has a number of configuration options. Go the -[Configuration](/installation/configuration) page for details on all -those options. - -## Adding data sources - -- [Graphite](../datasources/graphite.md) -- [InfluxDB](../datasources/influxdb.md) -- [OpenTSDB](../datasources/opentsdb.md) +- [Installing on Debian / Ubuntu](debian) +- [Installing on RPM-based Linux (CentOS, Fedora, OpenSuse, RedHat)](rpm) +- [Installing on Mac OS X](mac) +- [Installing on Windows](windows) +- [Installing on Docker](docker) +- [Installing using Provisioning (Chef, Puppet, Salt, Ansible, etc)](provisioning) +- [Nightly Builds](http://grafana.org/builds) diff --git a/docs/sources/installation/ldap.md b/docs/sources/installation/ldap.md index a5311fb4fa5..d8538182b68 100644 --- a/docs/sources/installation/ldap.md +++ b/docs/sources/installation/ldap.md @@ -1,17 +1,23 @@ ---- -page_title: LDAP Integration -page_description: LDAP Integration guide for Grafana. -page_keywords: grafana, ldap, configuration, documentation, integration ---- ++++ +title = "LDAP Authentication" +description = "Grafana LDAP Authentication Guide " +keywords = ["grafana", "configuration", "documentation", "ldap"] +type = "docs" +[menu.docs] +name = "LDAP Authentication" +identifier = "ldap" +parent = "admin" +weight = 2 ++++ -# LDAP Integration +# LDAP Authentication Grafana (2.1 and newer) ships with a strong LDAP integration feature. The LDAP integration in Grafana allows your Grafana users to login with their LDAP credentials. You can also specify mappings between LDAP group memberships and Grafana Organization user roles. ## Configuration -You turn on LDAP in the [main config file](../configuration/#authldap) as well as specify the path to the LDAP +You turn on LDAP in the [main config file]({{< relref "configuration.md#auth-ldap" >}}) as well as specify the path to the LDAP specific configuration file (default: `/etc/grafana/ldap.toml`). ### Example config @@ -27,6 +33,8 @@ host = "127.0.0.1" port = 389 # Set to true if ldap server supports TLS use_ssl = false +# Set to true if connect ldap server with STARTTLS pattern (create connection in insecure, then upgrade to secure connection with TLS) +start_tls = false # set to true if you want to skip ssl cert validation ssl_skip_verify = false # set to the path to your root CA certificate or leave unset to use system defaults @@ -35,6 +43,7 @@ ssl_skip_verify = false # Search user bind dn bind_dn = "cn=admin,dc=grafana,dc=org" # Search user bind password +# If the password contains # or ; you have to wrap it with trippel quotes. Ex """#password;""" bind_password = 'grafana' # User search filter, for example "(cn=%s)" or "(sAMAccountName=%s)" or "(uid=%s)" diff --git a/docs/sources/installation/mac.md b/docs/sources/installation/mac.md index 7246033b640..912a16c66e8 100644 --- a/docs/sources/installation/mac.md +++ b/docs/sources/installation/mac.md @@ -1,13 +1,45 @@ ---- -page_title: Installing on Mac OS X -page_description: Grafana Installation guide for Mac OS X -page_keywords: grafana, installation, mac, osx, guide ---- ++++ +title = "Installing on Mac" +description = "Installing Grafana on Mac" +keywords = ["grafana", "configuration", "documentation", "mac", "homebrew", "osx"] +type = "docs" +[menu.docs] +parent = "installation" +weight = 4 ++++ + # Installing on Mac -There is currently no binary build for Mac, but Grafana will happily build on Mac. Read the [build from -source](/project/building_from_source) page for instructions on how to -build it yourself. +Installation can be done using [homebrew](http://brew.sh/) + +Install latest stable: + +``` +brew update +brew install grafana +``` + +To start grafana look at the command printed after the homebrew install completes. + +To upgrade use the reinstall command + +``` +brew update +brew reinstall grafana +``` + +------------- + +You can also install the latest unstable grafana from git: +``` +brew install --HEAD grafana/grafana/grafana +``` + +To upgrade grafana if you've installed from HEAD: + +``` +brew reinstall --HEAD grafana/grafana/grafana +``` diff --git a/docs/sources/installation/migrating_to2.md b/docs/sources/installation/migrating_to2.md index 32e9c3371f3..e7e2e96b6ad 100644 --- a/docs/sources/installation/migrating_to2.md +++ b/docs/sources/installation/migrating_to2.md @@ -1,8 +1,17 @@ ---- -page_title: Migrating from v1.x to 2.x -page_description: Migration guide for Grafana v1.x to v2.x -page_keywords: grafana, installation, migration, documentation ---- ++++ +title = "Migrating from older versions" +description = "Upgrading & Migrating Grafana from older versions" +keywords = ["grafana", "configuration", "documentation", "migration"] +type = "docs" +[menu.docs] +parent = "installation" +weight = 10 ++++ + +# Migrating from older versions + +Normally new versions of Grafana are backward compatible. Any changes to database or dashboard schema will +be automatically migrated when Grafana-server start up without any user action required. # Migrating from v1.x to v2.x @@ -20,8 +29,7 @@ migrate to Grafana 2.0. ## Adding Data sources The `config.js` file has been deprecated. Data sources are now managed via -the UI or [HTTP API](../http_api/overview.md). Manage your -organizations data sources by clicking on the `Data Sources` menu on the +the UI or HTTP API. Manage your organizations data sources by clicking on the `Data Sources` menu on the side menu (which can be toggled via the Grafana icon in the upper left of your browser). @@ -53,7 +61,7 @@ sure your Elasticsearch data source is added. Specify the Elasticsearch index name where your existing Grafana v1.x dashboards are stored (the default is `grafana-dash`). -![](/img/v2/datasource_edit_elastic.jpg) +![](/img/docs/v2/datasource_edit_elastic.jpg) ### Importing dashboards from InfluxDB @@ -66,7 +74,7 @@ your Grafana v1.x dashboards are stored, the default is `grafana`. Go to the `Dashboards` view and click on the dashboards search drop down. Click the `Import` button at the bottom of the search drop down. -![](/img/v2/dashboard_import.jpg) +![](/img/docs/v2/dashboard_import.jpg) ### Import view @@ -74,7 +82,7 @@ In the Import view you find the section `Migrate dashboards`. Pick the data source you added (from Elasticsearch or InfluxDB), and click the `Import` button. -![](/img/v2/migrate_dashboards.jpg) +![](/img/docs/v2/migrate_dashboards.jpg) Your dashboards should be automatically imported into the Grafana 2.0 back-end. diff --git a/docs/sources/installation/performance.md b/docs/sources/installation/performance.md deleted file mode 100644 index f09686687ca..00000000000 --- a/docs/sources/installation/performance.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -page_title: Performance Tips -page_description: Grafana performance tips -page_keywords: grafana, performance, documentation ---- - -# Performance tips - -## Graphite - -Graphite 0.9.14 adds a much needed feature to the JSON rendering API -that is very important for Grafana. If you are experiencing slow load & -rendering times for large time ranges then it is most likely caused by -running Graphite 0.9.12 or lower. - -The latest version of Graphite adds a `maxDataPoints` parameter to the -JSON render API. Without this feature Graphite can return hundreds of -thousands of data points per graph, which can hang your browser. Be sure -to upgrade to -[0.9.14](http://graphite.readthedocs.org/en/latest/releases/0_9_14.html). - - diff --git a/docs/sources/installation/provisioning.md b/docs/sources/installation/provisioning.md index 2ec79d54741..513b469d4f9 100644 --- a/docs/sources/installation/provisioning.md +++ b/docs/sources/installation/provisioning.md @@ -1,20 +1,23 @@ ---- -page_title: Provisioning -page_description: Grafana provisioning -page_keywords: grafana, provisioning, documentation ---- ++++ +title = "Installing via provisioning tools" +description = "Guide to install Grafana via provisioning tools like puppet & chef" +keywords = ["grafana", "provisioning", "documentation", "puppet", "chef", "ansible"] +type = "docs" +[menu.docs] +parent = "installation" +weight = 8 ++++ -# Provisioning + +# Installing via provisioning tools Here are links for how to install Grafana (and some include Graphite or InfluxDB as well) via a provisioning system. These are not maintained by any core Grafana team member and might be out of date. -Some of the linked cookbooks/manifests/etc. will install and configure Grafana 2.x, while some will only install the older Grafana 1.x versions. They've been broken apart below for your convenience. - ### Puppet -* [forge.puppetlabs.com/bfraser/grafana](https://forge.puppetlabs.com/bfraser/grafana) **Note:** The current version works with Grafana 2.x. To install older versions of Grafana use the 1.x series of releases. +* [forge.puppetlabs.com/bfraser/grafana](https://forge.puppetlabs.com/bfraser/grafana) ### Ansible @@ -25,6 +28,6 @@ Some of the linked cookbooks/manifests/etc. will install and configure Grafana 2 ### Chef -* [github.com/JonathanTron/chef-grafana](https://github.com/JonathanTron/chef-grafana) **Note:** The current version works with Grafana 2.x. To install older versions of Grafana use the 1.x series of releases. +* [github.com/JonathanTron/chef-grafana](https://github.com/JonathanTron/chef-grafana) * [github.com/Nordstrom/grafana2-cookbook](https://github.com/Nordstrom/grafana2-cookbook) diff --git a/docs/sources/installation/rpm.md b/docs/sources/installation/rpm.md index ec4f648e44b..ac182585a5d 100644 --- a/docs/sources/installation/rpm.md +++ b/docs/sources/installation/rpm.md @@ -1,33 +1,54 @@ ---- -page_title: Installing on RPM-based Linux -page_description: Grafana Installation guide for Centos, Fedora, OpenSuse, Redhat. -page_keywords: grafana, installation, centos, fedora, opensuse, redhat, guide ---- ++++ +title = "Installing on RPM-based Linux" +description = "Grafana Installation guide for Centos, Fedora, OpenSuse, Redhat." +keywords = ["grafana", "installation", "documentation", "centos", "fedora", "opensuse", "redhat"] +aliases = ["installation/installation/rpm"] +type = "docs" +[menu.docs] +name = "Installing on Centos / Redhat" +identifier = "rpm" +parent = "installation" +weight = 2 ++++ # Installing on RPM-based Linux (CentOS, Fedora, OpenSuse, RedHat) -## Download - Description | Download ------------ | ------------- -.RPM for CentOS / Fedora / OpenSuse / Redhat Linux | [grafana-2.6.0-1.x86_64.rpm](https://grafanarel.s3.amazonaws.com/builds/grafana-2.6.0-1.x86_64.rpm) +Stable for CentOS / Fedora / OpenSuse / Redhat Linux | [4.0.2 (x86-64 rpm)](https://grafanarel.s3.amazonaws.com/builds/grafana-4.0.2-1481203731.x86_64.rpm) +Latest beta for CentOS / Fedora / OpenSuse / Redhat Linux | [4.1.0-beta1 (x86-64 rpm)](https://grafanarel.s3.amazonaws.com/builds/grafana-4.1.0-1482230757beta1.x86_64.rpm) -## Install from package file +## Install Stable You can install Grafana using Yum directly. - $ sudo yum install https://grafanarel.s3.amazonaws.com/builds/grafana-2.6.0-1.x86_64.rpm + $ sudo yum install https://grafanarel.s3.amazonaws.com/builds/grafana-4.0.2-1481203731.x86_64.rpm Or install manually using `rpm`. #### On CentOS / Fedora / Redhat: $ sudo yum install initscripts fontconfig - $ sudo rpm -Uvh grafana-2.6.0-1.x86_64.rpm + $ sudo rpm -Uvh grafana-4.0.2-1481203731.x86_64.rpm #### On OpenSuse: - $ sudo rpm -i --nodeps grafana-2.6.0-1.x86_64.rpm + $ sudo rpm -i --nodeps grafana-4.0.2-1481203731.x86_64.rpm + +## Or Install Latest Beta + + $ sudo yum install https://grafanarel.s3.amazonaws.com/builds/grafana-4.1.0-1482230757beta1.x86_64.rpm + +Or install manually using `rpm`. + +#### On CentOS / Fedora / Redhat: + + $ sudo yum install initscripts fontconfig + $ sudo rpm -Uvh grafana-4.1.0-1482230757beta1.x86_64.rpm + +#### On OpenSuse: + + $ sudo rpm -i --nodeps grafana-4.1.0-1482230757beta1.x86_64.rpm ## Install via YUM Repository @@ -106,18 +127,46 @@ By default Grafana will log to `/var/log/grafana` The default configuration specifies a sqlite3 database located at `/var/lib/grafana/grafana.db`. Please backup this database before -upgrades. You can also use MySQL or Postgres as the Grafana database, as detailed on [the configuration page](configuration.md#database). +upgrades. You can also use MySQL or Postgres as the Grafana database, as detailed on [the configuration page]({{< relref "configuration.md#database" >}}). ## Configuration The configuration file is located at `/etc/grafana/grafana.ini`. Go the -[Configuration](/installation/configuration) page for details on all +[Configuration]({{< relref "configuration.md" >}}) page for details on all those options. ### Adding data sources -- [Graphite](../datasources/graphite.md) -- [InfluxDB](../datasources/influxdb.md) -- [OpenTSDB](../datasources/opentsdb.md) +- [Graphite]({{< relref "datasources/graphite.md" >}}) +- [InfluxDB]({{< relref "datasources/influxdb.md" >}}) +- [OpenTSDB]({{< relref "datasources/opentsdb.md" >}}) +- [Prometheus]({{< relref "datasources/prometheus.md" >}}) +### Server side image rendering + +Server side image (png) rendering is a feature that is optional but very useful when sharing visualizations, +for example in alert notifications. + +If the image is missing text make sure you have font packages installed. + +``` +yum install fontconfig +yum install freetype* +yum install urw-fonts +``` + +## Installing from binary tar file + +Download [the latest `.tar.gz` file](http://grafana.org/download) and +extract it. This will extract into a folder named after the version you +downloaded. This folder contains all files required to run Grafana. There are +no init scripts or install scripts in this package. + +To configure Grafana add a configuration file named `custom.ini` to the +`conf` folder and override any of the settings defined in +`conf/defaults.ini`. + +Start Grafana by executing `./bin/grafana-server web`. The `grafana-server` +binary needs the working directory to be the root install directory (where the +binary and the `public` folder is located). diff --git a/docs/sources/installation/troubleshooting.md b/docs/sources/installation/troubleshooting.md index 7a6865b9da1..6da8c4f64f8 100644 --- a/docs/sources/installation/troubleshooting.md +++ b/docs/sources/installation/troubleshooting.md @@ -1,6 +1,13 @@ -page_title: Troubleshooting -page_description: Troubleshooting -page_keywords: grafana, support, documentation ++++ +title = "Troubleshooting" +description = "Guide to troubleshooting Grafana problems" +keywords = ["grafana", "troubleshooting", "documentation", "guide"] +type = "docs" +[menu.docs] +parent = "admin" +weight = 8 ++++ + # Troubleshooting @@ -16,7 +23,7 @@ with Grafana being unable to query Graphite, OpenTSDB or InfluxDB. You might not be able to get metric name completion or the graph might show an error like this: -![](/img/v1/graph_timestore_error.png) +![](/img/docs/v1/graph_timestore_error.png) For some types of errors, the `View details` link will show you error details. For many types of HTTP connection errors, however, there is very @@ -24,7 +31,7 @@ little information. The best way to troubleshoot these issues is use the [Chrome developer tools](https://developer.chrome.com/devtools/index). By pressing `F12` you can bring up the chrome dev tools. -![](/img/v1/toubleshooting_chrome_dev_tools.png) +![](/img/docs/v1/toubleshooting_chrome_dev_tools.png) There are two important tabs in the Chrome developer tools: `Network` and `Console`. The `Console` tab will show you Javascript errors and @@ -42,32 +49,10 @@ chrome console error, request and response information from the ### Inspecting Grafana metric requests -![](/img/v1/toubleshooting_chrome_dev_tools_network.png) +![](/img/docs/v1/toubleshooting_chrome_dev_tools_network.png) After opening the Chrome developer tools for the first time the `Network` tab is empty. You will need to refresh the page to get requests to show. For some type of errors, especially CORS-related, there might not be a response at all. -## Graphite connection issues - -If your Graphite web server is on another domain or IP address from your -Grafana web server you will need to [setup -CORS](../install/#graphite-server-config) (Cross Origin Resource -Sharing). - -You know if you are having CORS-related issues if you get an error like -this in the Chrome developer tools: - -![](/img/v1/toubleshooting_graphite_cors_error.png) - -If the request failed on method `OPTIONS` then you need to review your -Graphite web server configuration. - -## Only blank white page - -When you load Grafana and all you get is a blank white page then you -probably have a Javascript syntax error in `config.js`. In the Chrome -developer tools console you will quickly identify the line of the syntax -error. - diff --git a/docs/sources/installation/windows.md b/docs/sources/installation/windows.md index 1bc2b5a2b92..639fb12155f 100644 --- a/docs/sources/installation/windows.md +++ b/docs/sources/installation/windows.md @@ -1,16 +1,20 @@ ---- -page_title: Installing on Windows -page_description: Grafana Installation guide for Windows -page_keywords: grafana, installation, windows guide ---- ++++ +title = "Installing on Windows" +description = "Installing Grafana on Windows" +keywords = ["grafana", "configuration", "documentation", "windows"] +type = "docs" +[menu.docs] +parent = "installation" +weight = 3 ++++ + # Installing on Windows -## Download - Description | Download ------------ | ------------- -Zip package for Windows | [grafana.2.5.0.windows-x64.zip](https://grafanarel.s3.amazonaws.com/winbuilds/dist/grafana-2.5.0.windows-x64.zip) +Latest stable package for Windows | [grafana.4.0.2.windows-x64.zip](https://grafanarel.s3.amazonaws.com/builds/grafana-4.0.2.windows-x64.zip) +Latest beta package for Windows | [grafana.4.1.0-beta1.windows-x64.zip](https://grafanarel.s3.amazonaws.com/builds/grafana-4.1.0-beta1.windows-x64.zip) ## Configure @@ -29,7 +33,7 @@ command line. If you want to run Grafana as windows service, download [NSSM](https://nssm.cc/). It is very easy add Grafana as a Windows service using that tool. -Read more about the [configuration options](/installation/configuration). +Read more about the [configuration options]({{< relref "configuration.md" >}}). ## Building on Windows diff --git a/docs/sources/plugins/datasources.md b/docs/sources/plugins/datasources.md index 3732948d527..9f04d11cdfc 100644 --- a/docs/sources/plugins/datasources.md +++ b/docs/sources/plugins/datasources.md @@ -1,9 +1,3 @@ ---- -page_title: Plugin datasources -page_description: Datasource plugins for Grafana -page_keywords: grafana, plugins, documentation ---- - # Datasources @@ -43,7 +37,7 @@ The Datasource should contain the following functions. ``` query(options) //used by panels to get data testDatasource() //used by datasource configuration page to make sure the connection is working -annotationsQuery(options) // used dashboards to get annotations +annotationsQuery(options) // used by dashboards to get annotations metricFindQuery(options) // used by query editor to get metric suggestions. ``` diff --git a/docs/sources/plugins/development.md b/docs/sources/plugins/development.md index e8b5c620732..9b2a3fb8668 100644 --- a/docs/sources/plugins/development.md +++ b/docs/sources/plugins/development.md @@ -1,16 +1,20 @@ ---- -page_title: Plugin development guide -page_description: Plugin development for Grafana -page_keywords: grafana, plugins, documentation, development ---- ++++ +title = "Developer Guide" +type = "docs" +aliases = ["/plugins/datasources/", "/plugins/apps/", "/plugins/panels/"] +[menu.docs] +name = "Developer Guide" +parent = "plugins" +weight = 5 ++++ -# Plugin development +# Developer Guide From grafana 3.0 it's very easy to develop your own plugins and share them with other grafana users. ## Short version -1. [Setup grafana](https://github.com/grafana/grafana/blob/master/DEVELOPMENT.md) +1. [Setup grafana](http://docs.grafana.org/project/building_from_source/) 2. Clone an example plugin into ```/var/lib/grafana/plugins``` or `data/plugins` (relative to grafana git repo if your running development version from source dir) 3. Code away! @@ -32,9 +36,10 @@ will be expected to export different things. You can find what's expected for [d and [apps](./apps.md) plugins in the documentation. ## Start developing your plugin -There are two ways that you can start developing a Grafana plugin. -1. Setup a Grafana development environment. [(described here)](https://github.com/grafana/grafana/blob/master/DEVELOPMENT.md) and place your plugin in the ```data/plugins``` folder. +There are three ways that you can start developing a Grafana plugin. + +1. Setup a Grafana development environment. [(described here)](http://docs.grafana.org/project/building_from_source/) and place your plugin in the ```data/plugins``` folder. 2. Install Grafana and place your plugin in the plugins directory which is set in your [config file](../installation/configuration.md). By default this is `/var/lib/grafana/plugins` on Linux systems. 3. Place your plugin directory anywhere you like and specify it grafana.ini. @@ -45,8 +50,11 @@ the folder contains a subfolder named dist. In that case grafana will mount the This makes it possible to have both built and src content in the same plugin git repo. ## Examples + We currently have three different examples that you can fork/download to get started developing your grafana plugin. - [simple-json-datasource](https://github.com/grafana/simple-json-datasource) (small datasource plugin for querying json data from backends) - - [piechart-panel](https://github.com/grafana/piechart-panel) - [example-app](https://github.com/grafana/example-app) + - [clock-panel](https://github.com/grafana/clock-panel) + - [singlestat-panel](https://github.com/grafana/grafana/blob/master/public/app/plugins/panel/singlestat/module.ts) + - [piechart-panel](https://github.com/grafana/piechart-panel) diff --git a/docs/sources/plugins/index.md b/docs/sources/plugins/index.md index 156262a4ec1..217a01f9160 100644 --- a/docs/sources/plugins/index.md +++ b/docs/sources/plugins/index.md @@ -1,21 +1,24 @@ ---- -page_title: Plugin overview -page_description: Plugins for Grafana -page_keywords: grafana, plugins, documentation ---- ++++ +title = "Plugins" +[menu.docs] +name = "Plugins" +identifier = "plugins" +weight = 8 ++++ + # Plugins From Grafana 3.0 not only datasource plugins are supported but also panel plugins and apps. Having panels as plugins make it easy to create and add any kind of panel, to show your data or improve your favorite dashboards. Apps is something new in Grafana that enables -bundling of datasources, panels, dashboards and Grafana pages into a cohesive experiance. +bundling of datasources, panels, dashboards and Grafana pages into a cohesive experience. Grafana already have a strong community of contributors and plugin developers. By making it easier to develop and install plugins we hope that the community can grow even stronger and develop new plugins that we would never think about. -You can discover available plugins on [Grafana.net](http://grafana.net) +You can discover available plugins on [Grafana.net](https://grafana.net) diff --git a/docs/sources/plugins/installation.md b/docs/sources/plugins/installation.md index 0dada8b69a7..5880d18c0e3 100644 --- a/docs/sources/plugins/installation.md +++ b/docs/sources/plugins/installation.md @@ -1,15 +1,31 @@ ---- -page_title: Plugin installation -page_description: Plugin installation for Grafana -page_keywords: grafana, plugins, documentation ---- ++++ +title = "Installing Plugins" +type = "docs" +[menu.docs] +parent = "plugins" +weight = 1 ++++ + +# Grafana Plugins + +From Grafana 3.0+ not only are datasource plugins supported but also panel plugins and apps. +Having panels as plugins make it easy to create and add any kind of panel, to show your data +or improve your favorite dashboards. Apps is something new in Grafana that enables +bundling of datasources, panels, dashboards and Grafana pages into a cohesive experience. + +Grafana already have a strong community of contributors and plugin developers. +By making it easier to develop and install plugins we hope that the community +can grow even stronger and develop new plugins that we would never think about. + +To discover plugins checkout the official [Plugin Repository](https://grafana.net/plugins). # Installing plugins The easiest way to install plugins is by using the CLI tool grafana-cli which is bundled with grafana. Before any modification take place after modifying plugins, grafana-server needs to be restarted. ### Grafana plugin directory -On Linux systems the grafana-cli will assume that the grafana plugin directory is `/var/lib/grafana/plugins`. It's possible to override the directory which grafana-cli will operate on by specifying the --path flag. On Windows systems this parameter have to be specified for every call. + +On Linux systems the grafana-cli will assume that the grafana plugin directory is `/var/lib/grafana/plugins`. It's possible to override the directory which grafana-cli will operate on by specifying the --pluginsDir flag. On Windows systems this parameter have to be specified for every call. ### Grafana-cli commands @@ -18,24 +34,29 @@ List available plugins grafana-cli plugins list-remote ``` -Install a plugin type +Install the latest version of a plugin ``` grafana-cli plugins install ``` +Install a specific version of a plugin +``` +grafana-cli plugins install +``` + List installed plugins ``` grafana-cli plugins ls ``` -Upgrade all installed plugins +Update all installed plugins ``` -grafana-cli plugins upgrade-all +grafana-cli plugins update-all ``` -Upgrade one plugin +Update one plugin ``` -grafana-cli plugins upgrade +grafana-cli plugins update ``` Remove one plugin diff --git a/docs/sources/plugins/panels.md b/docs/sources/plugins/panels.md index 7182c3182a3..168d1320ca5 100644 --- a/docs/sources/plugins/panels.md +++ b/docs/sources/plugins/panels.md @@ -5,9 +5,18 @@ page_keywords: grafana, plugins, documentation --- ++++ +title = "Installing Plugins" +type = "docs" +[menu.docs] +parent = "plugins" +weight = 1 ++++ + + # Panels -Panels are the main bulding block of dashboards. +Panels are the main building blocks of dashboards. ## Panel development diff --git a/docs/sources/project/building_from_source.md b/docs/sources/project/building_from_source.md index e4f35f0a49b..11ca2d5b719 100644 --- a/docs/sources/project/building_from_source.md +++ b/docs/sources/project/building_from_source.md @@ -1,8 +1,10 @@ ---- -page_title: Building from source -page_description: Building from source Grafana. -page_keywords: grafana, build, contribute, documentation ---- ++++ +title = "Building from source" +type = "docs" +[menu.docs] +parent = "installation" +weight = 5 ++++ # Building Grafana from source @@ -11,7 +13,7 @@ dev environment. Grafana ships with its own required backend server; also comple ## Dependencies -- [Go 1.5](https://golang.org/dl/) +- [Go 1.7.3](https://golang.org/dl/) - [NodeJS](https://nodejs.org/download/) ## Get Code @@ -24,9 +26,8 @@ go get github.com/grafana/grafana ## Building the backend ``` cd $GOPATH/src/github.com/grafana/grafana -go run build.go setup # (only needed once to install godep) -$GOPATH/bin/godep restore # (will pull down all golang lib dependencies in your current GOPATH) -go run build.go build # (or 'go build .') +go run build.go setup +go run build.go build # (or 'go build ./pkg/cmd/grafana-server') ``` #### Building on Windows @@ -39,13 +40,14 @@ To build less to css for the frontend you will need a recent version of node (v0 npm (v2.5.0) and grunt (v0.4.5). Run the following: ``` -npm install +npm install -g yarn +yarn install npm install -g grunt-cli grunt ``` ## Recompile backend on source change -To rebuild on source change (requires that you executed godep restore) +To rebuild on source change ``` go get github.com/Unknwon/bra bra run @@ -63,9 +65,10 @@ If you built it with `go build .`, run `./grafana` Open grafana in your browser (default [http://localhost:3000](http://localhost:3000)) and login with admin user (default user/pass = admin/admin). ## Developing for Grafana -To add features, customize your config, etc, you'll need to rebuild on source change (requires that you executed [godep restore](#build-the-backend), as outlined above). +To add features, customize your config, etc, you'll need to rebuild on source change. ``` go get github.com/Unknwon/bra + bra run ``` You'll also need to run `grunt watch` to watch for changes to the front-end. @@ -89,6 +92,3 @@ Learn more about Grafana config options in the [Configuration section](/installa ## Create a pull requests Please contribute to the Grafana project and submit a pull request! Build new features, write or update documentation, fix bugs and generally make Grafana even more awesome. - -Before or after you create a pull request, sign the [contributor license agreement](/project/cla.html). -Together we can build amazing software faster. diff --git a/docs/sources/reference/admin.md b/docs/sources/reference/admin.md index 266fc998092..df396fed212 100644 --- a/docs/sources/reference/admin.md +++ b/docs/sources/reference/admin.md @@ -1,8 +1,13 @@ ----- -page_title: Administration -page_description: Grafana Administration -page_keywords: grafana, admin, administration, documentation ---- ++++ +title = "Admin Roles" +description = "Users & Organization permission and administration" +keywords = ["grafana", "configuration", "documentation", "admin", "users", "permissions"] +type = "docs" +[menu.docs] +name = "Admin Roles" +parent = "admin" +weight = 3 ++++ # Administration @@ -22,7 +27,7 @@ modify Organization details and options. ## Grafana Administrators - + As a Grafana Administrator, you have complete access to any Organization or User in that instance of Grafana. When performing actions as a Grafana admin, the sidebar will change it's appearance as below to indicate you are performing global server administration. @@ -32,6 +37,6 @@ From the Grafana Server Admin page, you can access the System Info page which su Organizations in Grafana are best suited for a **multi-tenant deployment**. In a multi-tenant deployment, Organizations can be used to provide a full Grafana experience to different sets of users from a single Grafana instance, -at the convenience of the Grafana Administrator. +at the convenience of the Grafana Administrator. -In most cases, a Grafana installation will only have **one** Organization. Since dashboards, data sources and other configuration items are not shared between organizations, there's no need to create multiple Organizations if you want all your users to have access to the same set of dashboards and data. +In most cases, a Grafana installation will only have **one** Organization. Since dashboards, data sources and other configuration items are not shared between organizations, there's no need to create multiple Organizations if you want all your users to have access to the same set of dashboards and data. diff --git a/docs/sources/reference/annotations.md b/docs/sources/reference/annotations.md index 51852abcdf2..8f2170ba145 100644 --- a/docs/sources/reference/annotations.md +++ b/docs/sources/reference/annotations.md @@ -1,15 +1,19 @@ ----- -page_title: Annotations -page_description: Annotations user guide -page_keywords: grafana, annotations, guide, documentation ---- ++++ +title = "Annotations" +keywords = ["grafana", "annotations", "documentation", "guide"] +type = "docs" +[menu.docs] +name = "Annotations" +parent = "dashboard_features" +weight = 2 ++++ # Annotations Annotations provide a way to mark points on the graph with rich events. When you hover over an annotation you can get title, tags, and text information for the event. -![](/img/v1/annotated_graph1.png) +![](/img/docs/v1/annotated_graph1.png) To add an annotation query click dashboard settings icon in top menu and select `Annotations` from the dropdown. This will open the `Annotations` edit view. Click the `Add` tab to add a new annotation query. @@ -24,7 +28,7 @@ Graphite supports two ways to query annotations. - Graphite events query, use the `Graphite event tags` text input, specify an tag or wildcard (leave empty should also work) ## Elasticsearch annotations -![](/img/v2/annotations_es.png) +![](/img/docs/v2/annotations_es.png) Grafana can query any Elasticsearch index for annotation events. The index name can be the name of an alias or an index wildcard pattern. You can leave the search query blank or specify a lucene query. @@ -35,8 +39,16 @@ as the name for the fields that should be used for the annotation title, tags an > **Note** The annotation timestamp field in elasticsearch need to be in UTC format. ## InfluxDB Annotations -![](/img/v2/annotations_influxdb.png) +![](/img/docs/v2/annotations_influxdb.png) For InfluxDB you need to enter a query like in the above screenshot. You need to have the ```where $timeFilter``` part. If you only select one column you will not need to enter anything in the column mapping fields. +## Prometheus Annotations + +![](/img/docs/v3/annotations_prom.png) + +Prometheus supports two ways to query annotations. + +- A regular metric query +- A Prometheus query for pending and firing alerts (for details see [Inspecting alerts during runtime](https://prometheus.io/docs/alerting/rules/#inspecting-alerts-during-runtime)) diff --git a/docs/sources/reference/dashboard.md b/docs/sources/reference/dashboard.md index 93adf5cd789..c1c574ce917 100644 --- a/docs/sources/reference/dashboard.md +++ b/docs/sources/reference/dashboard.md @@ -1,13 +1,15 @@ ----- -page_title: Dashboard JSON -page_description: Dashboard JSON Reference -page_keywords: grafana, dashboard, json, documentation ---- ++++ +title = "JSON Model" +keywords = ["grafana", "dashboard", "documentation", "json", "model"] +type = "docs" +[menu.docs] +name = "JSON Model" +parent = "dashboard_features" +weight = 100 ++++ # Dashboard JSON -## Overview - A dashboard in Grafana is represented by a JSON object, which stores metadata of its dashboard. Dashboard metadata includes dashboard properties, metadata from rows, panels, template variables, panel queries, etc. To view the JSON of a dashboard, follow the steps mentioned below: @@ -26,13 +28,12 @@ When a user creates a new dashboard, a new dashboard JSON object is initialized { "id": null, "title": "New dashboard", - "originalTitle": "New dashboard", "tags": [], "style": "dark", "timezone": "browser", "editable": true, "hideControls": false, - "sharedCrosshair": false, + "graphTooltip": 1, "rows": [], "time": { "from": "now-6h", @@ -59,13 +60,12 @@ Each field in the dashboard JSON is explained below with its usage: | ---- | ----- | | **id** | unique dashboard id, an integer | | **title** | current title of dashboard | -| **originalTitle** | title of dashboard when saved for the first time | | **tags** | tags associated with dashboard, an array of strings | | **style** | theme of dashboard, i.e. `dark` or `light` | | **timezone** | timezone of dashboard, i.e. `utc` or `browser` | | **editable** | whether a dashboard is editable or not | | **hideControls** | whether row controls on the left in green are hidden or not | -| **sharedCrosshair** | TODO | +| **graphTooltip** | TODO | | **rows** | row metadata, see [rows section](/docs/sources/reference/dashboard.md/#rows) for details | | **time** | time range for dashboard, i.e. last 6 hours, last 7 days, etc | | **timepicker** | timepicker metadata, see [timepicker section](/docs/sources/reference/dashboard.md/#timepicker) for details | diff --git a/docs/sources/reference/dashlist.md b/docs/sources/reference/dashlist.md index ea098541da2..5377c7c1941 100644 --- a/docs/sources/reference/dashlist.md +++ b/docs/sources/reference/dashlist.md @@ -1,29 +1,32 @@ ----- -page_title: Dashlist Panel -page_description: Dashlist Panel Reference -page_keywords: grafana, dashlist, panel, documentation ---- ++++ +title = "Dashboard List" +keywords = ["grafana", "dashboard list", "documentation", "panel", "dashlist"] +type = "docs" +[menu.docs] +name = "Dashboard list" +parent = "panels" +weight = 4 ++++ -# Dashlist Panel -## Overview +# Dashboard List Panel -The dashboard list panel allows you to display dynamic links to other dashboards. The list can be configured to use starred dashboards, a search query and/or dashboard tags. +The dashboard list panel allows you to display dynamic links to other dashboards. The list can be configured to use starred dashboards, a search query and/or dashboard tags. - + > On each dashboard load, the dashlist panel will re-query the dashboard list, always providing the most up to date results. ## Mode: Starred Dashboards -The `starred` dashboard selection displays starred dashboards, up to the number specified in the `Limit Number to` field, in alphabetical order. On dashboard load, the dashlist panel will re-query the favorites to appear in dashboard list panel, always providing the most up to date results. +The `starred` dashboard selection displays starred dashboards, up to the number specified in the `Limit Number to` field, in alphabetical order. On dashboard load, the dashlist panel will re-query the favorites to appear in dashboard list panel, always providing the most up to date results. - + ## Mode: Search Dashboards -The panel may be configured to search by either string query or tag(s). On dashboard load, the dashlist panel will re-query the dashboard list, always providing the most up to date results. +The panel may be configured to search by either string query or tag(s). On dashboard load, the dashlist panel will re-query the dashboard list, always providing the most up to date results. To configure dashboard list in this manner, select `search` from the Mode select box. When selected, the Search Options section will appear. @@ -38,14 +41,14 @@ Limit number to | Specify the maximum number of dashboards ### Search by string -To search by a string, enter a search query in the `Search Options: Query` field. Queries are case-insensitive, and partial values are accepted. - +To search by a string, enter a search query in the `Search Options: Query` field. Queries are case-insensitive, and partial values are accepted. + ### Search by tag -To search by one or more tags, enter your selection in the `Search Options: Tags:` field. Note that existing tags will not appear as you type, and *are* case sensitive. To see a list of existing tags, you can always return to the dashboard, open the Dashboard Picker at the top and click `tags` link in the search bar. - +To search by one or more tags, enter your selection in the `Search Options: Tags:` field. Note that existing tags will not appear as you type, and *are* case sensitive. To see a list of existing tags, you can always return to the dashboard, open the Dashboard Picker at the top and click `tags` link in the search bar. + -> When multiple tags and strings appear, the dashboard list will display those matching ALL conditions. +> When multiple tags and strings appear, the dashboard list will display those matching ALL conditions. diff --git a/docs/sources/reference/export_import.md b/docs/sources/reference/export_import.md index e83c68401d4..bc05795c030 100644 --- a/docs/sources/reference/export_import.md +++ b/docs/sources/reference/export_import.md @@ -1,85 +1,109 @@ ---- -page_title: Export & Import Guide -page_description: Export & Import Guide for Grafana -page_keywords: grafana, export, import, documentation ---- ++++ +title = "Export & Import" +keywords = ["grafana", "dashboard", "documentation", "export", "import"] +type = "docs" +[menu.docs] +parent = "dashboard_features" +weight = 8 ++++ # Export and Import +Grafana Dashboards can easily be exported and imported, either from the UI or from the HTTP API. + ## Exporting a dashboard -Dashboards are exported in Grafana JSON format, and contain everything you need (layout, variables, styles, data sources, queries, etc)to import the dashboard at a later time. +Dashboards are exported in Grafana JSON format, and contain everything you need (layout, variables, styles, data sources, queries, etc)to import the dashboard at a later time. -#### Export to file +The export feature is accessed from the share menu. -To export a dashboard, locate the settings menu within the desired dashboard and click the gear icon. The export option will always be available, and will open a browser save-as dialog window. + - +### Making a dashboard portable -#### Copy JSON +If you want to export a dashboard for others to use then it could be a good idea to +add template variables for things like a metric prefix (use constant variable) and server name. -The raw JSON may be accessed directly from within the interface and copy/pasted into an editor of your choice to be saved later. To view this JSON, locate the settings menu within the desired dashboard and click the gear icon. The View JSON option will always be available, and will open the raw JSON in a text area. To copy the entire JSON file, click into the text area, the select all `CTRL`+`A` (PC, Linux) or `⌘`+`A` (Mac). - - +A template variable of the type `Constant` will automatically be hidden in +the dashboard, and will also be added as an required input when the dashboard is imported. ## Importing a dashboard -Grafana 2.0 now has integrated dashboard storage engine that can be configured to use an internal sqlite3 database, MySQL, or Postgres. This eliminates the need to use Elasticsearch for dashboard storage for Graphite users. Grafana 2.0 does not support storing dashboards in InfluxDB. +To import a dashboard open dashboard search and then hit the import button. -The import view can be found at the Dashboard Picker dropdown, next to the New Dashboard and Playlist buttons. + - +From here you can upload a dashboard json file, paste a [Grafana.net](https://grafana.net) dashboard +url or paste dashboard json text directly into the text area. + -#### Import from a file +In step 2 of the import process Grafana will let you change the name of the dashboard, pick what +data source you want the dashboard to use and specify any metric prefixes (if the dashboard use any). -To import a dashboard through a local JSON file, click the 'Choose file' button in the Import from File section. Note that JSON is not linted or validated prior during upload, so we recommend validating locally if you're editing. In a pinch, you can use http://jsonlint.com/, and if you are editing dashboard JSON frequently, there are linter plugins for popular text editors. +## Discover dashboards on Grafana.net +Find dashboards for common server applications at [Grafana.net/dashboards](https://grafana.net/dashboards). -#### Importing dashboards from Elasticsearch + -Start by going to the `Data Sources` view (via the side menu), and make sure your Elasticsearch data source is added. Specify the Elasticsearch index name where your existing Grafana v1.x dashboards are stored (the default is `grafana-dash`). +## Import & Sharing with Grafana 2.x or 3.0 -![](/img/v2/datasource_edit_elastic.jpg) +Dashboards on Grafana.net use a new feature in Grafana 3.1 that allows the import process +to update each panel so that they are using a data source of your choosing. If you are running a +Grafana version older than 3.1 then you might need to do some manual steps either +before or after import in order for the dashboard to work properly. -#### Importing dashboards from InfluxDB +Dashboards exported from Grafana 3.1+ have a new json section `__inputs` +that define what data sources and metric prefixes the dashboard uses. -Start by going to the `Data Sources` view (via the side menu), and make sure your InfluxDB data source is added. Specify the database name where your Grafana v1.x dashboards are stored, the default is `grafana`. +Example: +```json +{ + "__inputs": [ + { + "name": "DS_GRAPHITE", + "label": "graphite", + "description": "", + "type": "datasource", + "pluginId": "graphite", + "pluginName": "Graphite" + }, + { + "name": "VAR_PREFIX", + "type": "constant", + "label": "prefix", + "value": "collectd", + "description": "" + } + ], +} -### Import view +``` -In the Import view you find the section `Migrate dashboards`. Pick the data source you added (from Elasticsearch or InfluxDB), and click the `Import` button. +These are then referenced in the dashboard panels like this: -![](/img/v2/migrate_dashboards.jpg) +```json +{ + "rows": [ + { + "panels": [ + { + "type": "graph", + "datasource": "${DS_GRAPHITE}", + } + ] + } + ] +} +``` -Your dashboards should be automatically imported into the Grafana 2.0 back-end. Dashboards will no longer be stored in your previous Elasticsearch or InfluxDB databases. +These inputs and their usage in data source properties are automatically added during export in Grafana 3.1. +If you run an older version of Grafana and want to share a dashboard on Grafana.net you need to manually +add the inputs and templatize the datasource properties like above. +If you want to import a dashboard from Grafana.net into an older version of Grafana then you can either import +it as usual and then update the data source option in the metrics tab so that the panel is using the correct +data source. Another alternative is to open the json file in a a text editor and update the data source properties +to value that matches a name of your data source. -## Troubleshooting - -### Template variables could not be initialized. - -When importing a dashboard, keep an eye out for template variables in your JSON that may not exist in your instance of Grafana. For example, - - "templating": { - "list": [ - { - "allFormat": "glob", - "current": { - "tags": [], - "text": "google_com + monkey_id_au", - "value": [ - "google_com", - "monkey_id_au" - ] - }, - "datasource": null, - -To resolve this, remove any unnecessary JSON that may be specific to the instance you are exporting from. In this case, we can remove the entire "current" section entirely, and Grafana will populate default. - - "templating": { - "list": [ - { - "allFormat": "glob", - "datasource": null, - \ No newline at end of file diff --git a/docs/sources/reference/graph.md b/docs/sources/reference/graph.md index 9c2ab63fbaa..7fbebcfeb97 100644 --- a/docs/sources/reference/graph.md +++ b/docs/sources/reference/graph.md @@ -1,20 +1,24 @@ ----- -page_title: Graph Panel -page_description: Graph Panel Reference -page_keywords: grafana, graph, panel, documentation ---- ++++ +title = "Graph Panel" +keywords = ["grafana", "graph panel", "documentation", "guide", "graph"] +type = "docs" +[menu.docs] +name = "Graph" +parent = "panels" +weight = 1 ++++ # Graph Panel The main panel in Grafana is simply named Graph. It provides a very rich set of graphing options. - + Clicking the title for a panel exposes a menu. The `edit` option opens additional configuration options for the panel. ## General -![](/img/v2/graph_general.png) +![](/img/docs/v2/graph_general.png) The general tab allows customization of a panel's appearance and menu options. @@ -44,15 +48,9 @@ populate the template variable to a desired value from the link. The metrics tab defines what series data and sources to render. Each datasource provides different options. -### Graphite - -### InfluxDB - -### OpenTSDB - ## Axes & Grid -![](/img/v2/graph_axes_grid_options.png) +![](/img/docs/v2/graph_axes_grid_options.png) The Axes & Grid tab controls the display of axes, grids and legend. @@ -67,9 +65,6 @@ The ``Left Y`` and ``Right Y`` can be customized using: Axes can also be hidden by unchecking the appropriate box from `Show Axis`. -Thresholds allow you to add arbitrary lines or sections to the graph to make it easier to see when -the graph crosses a particular threshold. - ### Legend The legend hand be hidden by checking the ``Show`` checkbox. If it's shown, it can be @@ -91,14 +86,20 @@ The legend values are calculated client side by Grafana and depend on what type aggregation or point consolidation you metric query is using. All the above legend values cannot be correct at the same time. For example if you plot a rate like requests/second, this is probably using average as aggregator, then the Total in the legend will not represent the total number of requests. -It is just the sum of all data data points received by Grafana. +It is just the sum of all data points received by Grafana. ## Display styles -![](/img/v2/graph_display_styles.png) +![](/img/docs/v2/graph_display_styles.png) Display styles controls properties of the graph. +### Thresholds + +Thresholds allow you to add arbitrary lines or sections to the graph to make it easier to see when +the graph crosses a particular threshold. + + ### Chart Options - ``Bar`` - Display values as a bar chart @@ -140,4 +141,4 @@ a thicker line width to make it standout. ## Time range -![](/img/v2/graph_time_range.png) +![](/img/docs/v2/graph_time_range.png) diff --git a/docs/sources/reference/keyboard_shortcuts.md b/docs/sources/reference/keyboard_shortcuts.md index 9947418ae5a..edd2e85f43b 100644 --- a/docs/sources/reference/keyboard_shortcuts.md +++ b/docs/sources/reference/keyboard_shortcuts.md @@ -1,7 +1,11 @@ -page_title: Keyboard Shortcuts -page_description: Keyboard Shortcuts for Grafana -page_keywords: grafana, export, import, documentation ---- ++++ +title = "Keyboard shortcuts" +keywords = ["grafana", "dashboard", "documentation", "shortcuts"] +type = "docs" +[menu.docs] +parent = "dashboard_features" +weight = 8 ++++ # Keyboard Shortcuts @@ -11,7 +15,7 @@ No mouse? No problem. Grafana has extensive keyboard shortcuts to allow you to n Press `Shift`+`?` to open the keyboard shortcut dialog from anywhere within the dashboard views. - + |Shortcut|Action| diff --git a/docs/sources/reference/playlist.md b/docs/sources/reference/playlist.md index 5d546b1a3df..359a5d8f3bd 100644 --- a/docs/sources/reference/playlist.md +++ b/docs/sources/reference/playlist.md @@ -1,8 +1,12 @@ ---- -page_title: Playlist Guide -page_description: Playlist guide for Grafana -page_keywords: grafana, playlist, documentation ---- ++++ +title = "Playlist" +keywords = ["grafana", "dashboard", "documentation", "playlist"] +type = "docs" +[menu.docs] +parent = "dashboard_features" +weight = 4 ++++ + # Playlist @@ -12,9 +16,9 @@ Since Grafana automatically scales Dashboards to any resolution they're perfect ## Creating a Playlist -The Playlist feature can be accessed from Grafana's sidemenu. Click the 'Playlist' button from the sidemenu to access the Playlist functionality. When 'Playlist' button is clicked, playlist view will open up showing saved playlists and an option to create new playlists. +{{< docs-imagebox img="img/docs/v3/playlist.png" max-width="25rem" >}} - +The Playlist feature can be accessed from Grafana's sidemenu, in the Dashboard submenu. Click on "New Playlist" button to create a new playlist. Firstly, name your playlist and configure a time interval for Grafana to wait on a particular Dashboard before advancing to the next one on the Playlist. diff --git a/docs/sources/reference/scripting.md b/docs/sources/reference/scripting.md index d896a2c7650..551805b567a 100644 --- a/docs/sources/reference/scripting.md +++ b/docs/sources/reference/scripting.md @@ -1,8 +1,12 @@ ----- -page_title: Scripted dashboards -page_description: Scripted dashboards -page_keywords: grafana, scripted, guide, documentation ---- ++++ +title = "Scripted Dashboards" +keywords = ["grafana", "dashboard", "documentation", "scripted"] +type = "docs" +[menu.docs] +parent = "dashboard_features" +weight = 9 ++++ + # Scripted Dashboards diff --git a/docs/sources/reference/search.md b/docs/sources/reference/search.md index e2d6647229c..9fc4d47893c 100644 --- a/docs/sources/reference/search.md +++ b/docs/sources/reference/search.md @@ -1,54 +1,58 @@ ----- -page_title: Dashboard Search -page_description: Dashboard Search in Grafana -page_keywords: grafana, search, guide, documentation ---- ++++ +title = "Search" +keywords = ["grafana", "dashboard", "documentation", "search"] +type = "docs" +[menu.docs] +parent = "dashboard_features" +weight = 5 ++++ + # Dashboard Search Dashboards can be searched by the dashboard name, filtered by one (or many) tags or filtered by starred status. The dashboard search is accessed through the dashboard picker, available in the dashboard top nav area. - + 1. `Dashboard Picker`: The Dashboard Picker is your primary navigation tool to move between dashboards. It is present on all dashboards, and open the Dashboard Search. The dashboard picker also doubles as the title of the current dashboard. 2. `Search Bar`: The search bar allows you to enter any string and search both database and file based dashboards in real-time. -3. `Starred`: The starred link allows you to filter the list to display only starred dashboards. -4. `Tags`: The tags filter allows you to filter the list by dashboard tags. +3. `Starred`: The starred link allows you to filter the list to display only starred dashboards. +4. `Tags`: The tags filter allows you to filter the list by dashboard tags. When using only a keyboard, you can use your keyboard arrow keys to navigate the results, hit enter to open the selected dashboard. ## Find by dashboard name - + -To search and load dashboards click the open folder icon in the header or use the shortcut `CTRL`+`F`. Begin typing any part of the desired dashboard names. Search will return results for for any partial string match in real-time, as you type. +To search and load dashboards click the open folder icon in the header or use the shortcut `CTRL`+`F`. Begin typing any part of the desired dashboard names. Search will return results for for any partial string match in real-time, as you type. Dashboard search is: - Real-time - *Not* case sensitive -- Functional across stored *and* file based dashboards. +- Functional across stored *and* file based dashboards. ## Filter by Tag(s) Tags are a great way to organize your dashboards, especially as the number of dashboards grow. Tags can be added and managed in the dashboard `Settings`. -To filter the dashboard list by tag, click on any tag appearing in the right column. The list may be further filtered by clicking on additional tags: +To filter the dashboard list by tag, click on any tag appearing in the right column. The list may be further filtered by clicking on additional tags: - + Alternately, to see a list of all available tags, click the tags link in the search bar. All tags will be shown, and when a tag is selected, the dashboard search will be instantly filtered: - + When using only a keyboard: `tab` to focus on the *tags* link, `▼` down arrow key to find a tag and select with the `Enter` key. -**Note**: When multiple tags are selected, Grafana will show dashboards that include **all**. +**Note**: When multiple tags are selected, Grafana will show dashboards that include **all**. ## Filter by Starred Starring is a great way to organize and find commonly used dashboards. To show only starred dashboards in the list, click the *starred* link in the search bar: - + -When using only a keyboard: `tab` to focus on the *stars* link, `▼` down arrow key to find a tag and select with the `Enter` key. \ No newline at end of file +When using only a keyboard: `tab` to focus on the *stars* link, `▼` down arrow key to find a tag and select with the `Enter` key. diff --git a/docs/sources/reference/sharing.md b/docs/sources/reference/sharing.md index c20f4e5f67c..5210b2811df 100644 --- a/docs/sources/reference/sharing.md +++ b/docs/sources/reference/sharing.md @@ -1,8 +1,11 @@ ----- -page_title: Sharing -page_description: Sharing -page_keywords: grafana, sharing, guide, documentation ---- ++++ +title = "Sharing" +keywords = ["grafana", "dashboard", "documentation", "sharing"] +type = "docs" +[menu.docs] +parent = "dashboard_features" +weight = 6 ++++ # Sharing features Grafana provides a number of ways to share a dashboard or a specific panel to other users within your @@ -19,7 +22,7 @@ A dashboard snapshot is an instant way to share an interactive dashboard publicl (metric, template and annotation) and panel links, leaving only the visible metric data and series names embedded into your dashboard. Dashboard snapshots can be accessed by anyone who has the link and can reach the URL. -![](/img/v2/dashboard_snapshot_dialog.png) +![](/img/docs/v2/dashboard_snapshot_dialog.png) ### Publish snapshots You can publish snapshots to you local instance or to [snapshot.raintank.io](http://snapshot.raintank.io). The later is a free service diff --git a/docs/sources/reference/singlestat.md b/docs/sources/reference/singlestat.md index 954bfeed8b7..ed0a956b7eb 100644 --- a/docs/sources/reference/singlestat.md +++ b/docs/sources/reference/singlestat.md @@ -1,12 +1,17 @@ ----- -page_title: Singlestat Panel -page_description: Singlestat Panel Reference -page_keywords: grafana, singlestat, panel, documentation ---- ++++ +title = "Singlestat Panel" +keywords = ["grafana", "dashboard", "documentation", "panels", "singlestat"] +type = "docs" +[menu.docs] +name = "Singlestat" +parent = "panels" +weight = 2 ++++ + # Singlestat Panel -![](/img/v1/singlestat_panel2.png) +![](/img/docs/v1/singlestat_panel2.png) The Singlestat Panel allows you to show the one main summary stat of a SINGLE series. It reduces the series into a single number (by looking at the max, min, average, or sum of values in the series). Singlestat also provides thresholds to color the stat or the Panel background. It can also translate the single number into a text value, and show a sparkline summary of the series. @@ -14,11 +19,19 @@ The Singlestat Panel allows you to show the one main summary stat of a SINGLE se The singlestat panel has a normal query editor to allow you define your exact metric queries like many other Panels. Through the Options tab, you can access the Singlestat-specific functionality. - + 1. `Big Value`: Big Value refers to how we display the main stat for the Singlestat Panel. This is always a single value that is displayed in the Panel in between two strings, `Prefix` and `Suffix`. The single number is calculated by choosing a function (min,max,average,current,total) of your metric query. This functions reduces your query into a single numeric value. 2. `Font Size`: You can use this section to select the font size of the different texts in the Singlestat Panel, i.e. prefix, value and postfix. -3. `Values`: The Value fields let you set the function (min, max, average, current, total) that your entire query is reduced into a single value with. You can also set the font size of the Value field and font-size (as a %) of the metric query that the Panel is configured with. This reduces the entire query into a single summary value that is displayed. +3. `Values`: The Value fields let you set the function (min, max, average, current, total, first, delta, range) that your entire query is reduced into a single value with. You can also set the font size of the Value field and font-size (as a %) of the metric query that the Panel is configured with. This reduces the entire query into a single summary value that is displayed. + * `min` - The smallest value in the series + * `max` - The largest value in the series + * `average` - The average of all the non-null values in the series + * `current` - The last value in the series. If the series ends on null the previous value will be used. + * `total` - The sum of all the non-null values in the series + * `first` - The first value in the series + * `delta` - The total incremental increase (of a counter) in the series. An attempt is made to account for counter resets, but this will only be accurate for single instance metrics. Used to show total counter increase in time series. + * `range` - The difference between 'min' and 'max'. Useful the show the range of change for a gauge. 4. `Postfixes`: The Postfix fields let you define a custom label and font-size (as a %) to appear *after* the value 5. `Units`: Units are appended to the the Singlestat within the panel, and will respect the color and threshold settings for the value. 6. `Decimals`: The Decimal field allows you to override the automatic decimal precision, and set it explicitly. @@ -27,19 +40,19 @@ The singlestat panel has a normal query editor to allow you define your exact me The coloring options of the Singlestat Panel config allow you to dynamically change the colors based on the Singlestat value. - + 1. `Background`: This checkbox applies the configured thresholds and colors to the entirety of the Singlestat Panel background. 2. `Value`: This checkbox applies the configured thresholds and colors to the summary stat. 3. `Thresholds`: Change the background and value colors dynamically within the panel, depending on the Singlestat value. The threshold field accepts **2 comma-separated** values which represent 3 ranges that correspond to the three colors directly to the right. For example: if the thresholds are 70, 90 then the first color represents < 70, the second color represents between 70 and 90 and the third color represents > 90. 4. `Colors`: Select a color and opacity -5. `Invert order`: This link toggles the threshold color order.
For example: Green, Orange, Red () will become Red, Orange, Green (). +5. `Invert order`: This link toggles the threshold color order.
For example: Green, Orange, Red () will become Red, Orange, Green (). ### Spark Lines Sparklines are a great way of seeing the historical data related to the summary stat, providing valuable context at a glance. Sparklines act differently than traditional Graph Panels and do not include x or y axis, coordinates, a legend, or ability to interact with the graph. - + 1. `Show`: The show checkbox will toggle whether the spark line is shown in the Panel. When unselected, only the Singlestat value will appear. 2. `Background`: Check if you want the sparklines to take up the full panel width, or uncheck if they should be below the main Singlestat value. @@ -52,13 +65,13 @@ Sparklines are a great way of seeing the historical data related to the summary Value to text mapping allows you to translate the value of the summary stat into explicit text. The text will respect all styling, thresholds and customization defined for the value. This can be useful to translate the number of the main Singlestat value into a context-specific human-readable word or message. - + ## Troubleshooting ### Multiple Series Error - + Grafana 2.5 introduced stricter checking for multiple-series on singlestat panels. In previous versions, the panel logic did not verify that only a single series was used, and instead, displayed the first series encountered. Depending on your data source, this could have lead to inconsistent data being shown and/or a general confusion about which metric was being displayed. diff --git a/docs/sources/reference/table_panel.md b/docs/sources/reference/table_panel.md index a857be38357..249886e1f57 100644 --- a/docs/sources/reference/table_panel.md +++ b/docs/sources/reference/table_panel.md @@ -1,12 +1,17 @@ ----- -page_title: Table Panel -page_description: Table Panel Reference -page_keywords: grafana, table, panel, documentation ---- ++++ +title = "Table Panel" +keywords = ["grafana", "dashboard", "documentation", "panels", "table panel"] +type = "docs" +[menu.docs] +name = "Table" +parent = "panels" +weight = 2 ++++ + # Table Panel - + The new table panel is very flexible, supporting both multiple modes for time series as well as for table, annotation and raw JSON data. It also provides date formatting and value formatting and coloring options. @@ -17,7 +22,7 @@ To view table panels in action and test different configurations with sample dat The table panel has many ways to manipulate your data for optimal presentation. - + 1. `Data`: Control how your query is transformed into a table. 2. `Table Display`: Table display options. @@ -25,7 +30,7 @@ The table panel has many ways to manipulate your data for optimal presentation. ## Data to Table - + The data section contains the **To Table Transform (1)**. This is the primary option for how your data/metric query should be transformed into a table format. The **Columns (2)** option allows you to select what columns @@ -33,38 +38,38 @@ you want in the table. Only applicable for some transforms. ### Time series to rows - + In the most simple mode you can turn time series to rows. This means you get a `Time`, `Metric` and a `Value` column. Where `Metric` is the name of the time series. ### Time series to columns -![](/img/v2/table_ts_to_columns2.png) +![](/img/docs/v2/table_ts_to_columns2.png) This transform allows you to take multiple time series and group them by time. Which will result in the primary column being `Time` and a column for each time series. ### Time series aggregations -![](/img/v2/table_ts_to_aggregations2.png) +![](/img/docs/v2/table_ts_to_aggregations2.png) This table transformation will lay out your table into rows by metric, allowing columns of `Avg`, `Min`, `Max`, `Total`, `Current` and `Count`. More than one column can be added. ### Annotations -![](/img/v2/table_annotations.png) +![](/img/docs/v2/table_annotations.png) If you have annotations enabled in the dashboard you can have the table show them. If you configure this mode then any queries you have in the metrics tab will be ignored. ### JSON Data -![](/img/v2/table_json_data.png) +![](/img/docs/v2/table_json_data.png) If you have an Elasticsearch **Raw Document** query or an Elasticsearch query without a `date histogram` use this transform mode and pick the columns using the **Columns** section. -![](/img/v2/elastic_raw_doc.png) +![](/img/docs/v2/elastic_raw_doc.png) ## Table Display - + 1. `Pagination (Page Size)`: The table display fields allow you to control The `Pagination` (page size) is the threshold at which the table rows will be broken into pages. For example, if your table had 95 records with a pagination value of 10, your table would be split across 9 pages. 2. `Scroll`: The `scroll bar` checkbox toggles the ability to scroll within the panel, when unchecked, the panel height will grow to display all rows. @@ -75,7 +80,7 @@ transform mode and pick the columns using the **Columns** section. The column styles allow you control how dates and numbers are formatted. - + 1. `Name or regex`: The Name or Regex field controls what columns the rule should be applied to. The regex or name filter will be matched against the column name not against column values. 2. `Type`: The three supported types of types are `Number`, `String` and `Date`. diff --git a/docs/sources/reference/templating.md b/docs/sources/reference/templating.md index e605af845ea..636cc62a0c8 100644 --- a/docs/sources/reference/templating.md +++ b/docs/sources/reference/templating.md @@ -1,15 +1,18 @@ ----- -page_title: Dashboard Templating -page_description: Dashboard Templating -page_keywords: grafana, templating, variables, guide, documentation ---- ++++ +title = "Templating" +keywords = ["grafana", "templating", "documentation", "guide"] +type = "docs" +[menu.docs] +name = "Templating" +parent = "dashboard_features" +weight = 1 ++++ -# Dashboard Templating -![](/img/v2/templating_var_list.png) +# Templating -## Overview + -Dashboard Templating allows you to make your Dashboards more interactive and dynamic. +Dashboard Templating allows you to make your Dashboards more interactive and dynamic. They’re one of the most powerful and most used features of Grafana, and they’ve recently gotten even more attention in Grafana 2.0 and Grafana 2.1. @@ -40,13 +43,13 @@ You can utilize the special ** All ** value to allow the Dashboard user to query #### Multi-select As of Grafana 2.1, it is now possible to select a subset of Query Template variables (previously it was possible to select an individual value or 'All', not multiple values that were less than All). This is accomplished via the Multi-Select option. If enabled, the Dashboard user will be able to enable and disable individual variables. -The Multi-Select functionality is taken a step further with the introduction of Multi-Select Tagging. This functionality allows you to group individual Template variables together under a Tag or Group name. +The Multi-Select functionality is taken a step further with the introduction of Multi-Select Tagging. This functionality allows you to group individual Template variables together under a Tag or Group name. -For example, if you were using Templating to list all 20 of your applications, you could use Multi-Select Tagging to group your applications by function or region or criticality, etc. +For example, if you were using Templating to list all 20 of your applications, you could use Multi-Select Tagging to group your applications by function or region or criticality, etc. > Note: Multi-Select Tagging functionality is currently experimental but is part of Grafana 2.1. To enable this feature click the enable icon when editing Template options for a particular variable. - + Grafana gets the list of tags and the list of values in each tag by performing two queries on your metric namespace. @@ -58,20 +61,19 @@ Note: a proof of concept shim that translates the metric query into a SQL call i Once configured, Multi-Select Tagging provides a convenient way to group and your template variables, and slice your data in the exact way you want. The Tags can be seen on the right side of the template pull-down. -![](/img/v2/multi-select.gif) - +![](/img/docs/v2/multi-select.gif) ### Interval Use the `Interval` type to create Template variables around time ranges (eg. `1m`,`1h`, `1d`). There is also a special `auto` option that will change depending on the current time range, you can specify how many times the current time range should be divided to calculate the current `auto` range. -![](/img/v2/templated_variable_parameter.png) +![](/img/docs/v2/templated_variable_parameter.png) ### Custom -Use the `Custom` type to manually create Template variables around explicit values that are hard-coded into the Dashboard, and not dependent on any Data Source. You can specify multiple Custom Template values by separating them with a comma. +Use the `Custom` type to manually create Template variables around explicit values that are hard-coded into the Dashboard, and not dependent on any Data Source. You can specify multiple Custom Template values by separating them with a comma. -## Utilizing Template Variables with Repeating Panels and Repeating Rows +## Repeating Panels and Repeating Rows Template Variables can be very useful to dynamically change what you're visualizing on a given panel. Sometimes, you might want to create entire new Panels (or Rows) based on what Template Variables have been selected. This is now possible in Grafana 2.1. diff --git a/docs/sources/reference/timerange.md b/docs/sources/reference/timerange.md index 2ab428622bc..a4d6fc62336 100644 --- a/docs/sources/reference/timerange.md +++ b/docs/sources/reference/timerange.md @@ -1,32 +1,37 @@ ----- -page_title: Time Range options -page_description: Time range user guide -page_keywords: grafana, time range, guide, documentation ---- ++++ +title = "Time Range" +keywords = ["grafana", "dashboard", "documentation", "time range"] +type = "docs" +[menu.docs] +name = "Time Range" +parent = "dashboard_features" +weight = 7 ++++ + # Time Range Controls Grafana provides numerous ways to manage the time ranges of the data being visualized, both at the Dashboard-level and the Panel-level. - + In the top right, you have the master Dashboard time picker (it's in between the 'Zoom out' and the 'Refresh' links). -1. `Current time range & refresh interval`: This shows the current dashboard time and refresh interval. It also acts as the menu button to toggle the time range controls. -2. `Quick ranges`: Quick ranges are preset values to choose a relative time. At this time, quick ranges are not configurable, and will appear on every dashboard. +1. `Current time range & refresh interval`: This shows the current dashboard time and refresh interval. It also acts as the menu button to toggle the time range controls. +2. `Quick ranges`: Quick ranges are preset values to choose a relative time. At this time, quick ranges are not configurable, and will appear on every dashboard. 3. `Time range`: The time range section allows you to mix both explicit and relative ranges. The explicit time range format is `YYYY-MM-DD HH:MM:SS` -4. `Refreshing every:` When enabled, auto-refresh will reload the dashboard at the specified time range. Auto-refresh is most commonly used with relative time ranges ending in `now`, so new data will appear when the dashboard refreshes. +4. `Refreshing every:` When enabled, auto-refresh will reload the dashboard at the specified time range. Auto-refresh is most commonly used with relative time ranges ending in `now`, so new data will appear when the dashboard refreshes. These settings apply to all Panels in the Dashboard (except those with Panel Time Overrides enabled) ## Time Units -The following time units are supported: `s (seconds)`, `m (minutes)`, `h (hours)`, `d (days)`, `w (weeks)`, `M (months)`, `y (years)`. The minus operator allows you to step back in time, relative to now. If you wish to display the full period of the unit (day, week, month, etc...), append `/$unit` to the end. +The following time units are supported: `s (seconds)`, `m (minutes)`, `h (hours)`, `d (days)`, `w (weeks)`, `M (months)`, `y (years)`. The minus operator allows you to step back in time, relative to now. If you wish to display the full period of the unit (day, week, month, etc...), append `/$unit` to the end. Take a look at some examples to seen these concepts in practice: -Example Relative Range | From: | To: --------------- | ----- | --- +Example Relative Range | From: | To: +-------------- | ----- | --- Last 5 minutes | `now-5m` | `now` The day so far | `now/d` | `now` This week | `now/w` | `now/w` @@ -38,7 +43,7 @@ Previous Month | `now-1M/M` | `now-1M/M` There are two settings available from the Dashboard Settings area, allowing customization of the auto-refresh intervals and the definition of `now`. - + ### Auto-Refresh Options @@ -54,15 +59,15 @@ Users often ask, [when will then be now](https://www.youtube.com/watch?v=VeZ9HhH You can override the relative time range for individual panels, causing them to be different than what is selected in the Dashboard time picker in the upper right. This allows you to show metrics from different time periods or days at the same time. - + You control these overrides in panel editor mode and the tab `Time Range`. - + When you zoom or change the Dashboard time to a custom absolute time range, all panel overrides will be disabled. The panel relative time override is only active when the dashboard time is also relative. The panel timeshift override is always active, even when the dashboard time is absolute. The `Hide time override info` option allows you to hide the override info text that is by default shown in the upper right of a panel when overridden time range options. -Note: You can only override the dashboard time with relative time ranges. Absolute time ranges are not available. +Note: You can only override the dashboard time with relative time ranges. Absolute time ranges are not available. diff --git a/docs/sources/tutorials/hubot_howto.md b/docs/sources/tutorials/hubot_howto.md index 85ebb3e7c85..17658fbaecd 100644 --- a/docs/sources/tutorials/hubot_howto.md +++ b/docs/sources/tutorials/hubot_howto.md @@ -1,9 +1,11 @@ ---- -page_title: How To integrate Hubot and Grafana -page_description: Hubot Grafana install guide -page_keywords: grafana, tutorials, hubot, slack, hipchat, setup, install, config -author: Torkel Ödegaard ---- ++++ +title = "How To integrate Hubot and Grafana" +type = "docs" +keywords = ["grafana", "tutorials", "hubot", "slack", "hipchat", "setup", "install", "config"] +[menu.docs] +parent = "tutorials" +weight = 10 ++++ # How to integrate Hubot with Grafana diff --git a/docs/sources/tutorials/index.md b/docs/sources/tutorials/index.md index fd064ba5b15..cb11940c6dd 100644 --- a/docs/sources/tutorials/index.md +++ b/docs/sources/tutorials/index.md @@ -1,8 +1,9 @@ ---- -page_title: Grafana Tutorials -page_description: Tutorials -page_keywords: grafana, tutorials ---- ++++ +title = "Tutorials" +[menu.docs] +identifier = "tutorials" +weight = 6 ++++ # Tutorials diff --git a/docs/sources/tutorials/screencasts.md b/docs/sources/tutorials/screencasts.md new file mode 100644 index 00000000000..f92ead64d49 --- /dev/null +++ b/docs/sources/tutorials/screencasts.md @@ -0,0 +1,66 @@ ++++ +title = "Screencasts" +type = "docs" +[menu.docs] +identifier = "screencasts" +parent = "guides" +weight = 10 ++++ + +# Screencasts + + +{{< screencast src="https://www.youtube.com/embed/sKNZMtoSHN4?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" >}} + +### Episode 7 - Beginners guide to building dashboards + +For newer users of Grafana, this screencast will familiarize you with the general UI and teach you how to build your first Dashboard. + +
+ +{{< screencast src="https://www.youtube.com/embed/9ZCMVNxUf6s?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" >}} + +### Episode 6 - Adding data sources, users & organizations + +Now that Grafana has been installed, learn about adding data sources and get a closer look at adding and managing Users and Organizations. + +
+ +{{< screencast src="https://www.youtube.com/embed/E-gMFv85FE8?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" >}} + +### Episode 5 - Installation & Configuration on Red Hat / CentOS + +This screencasts shows how to get Grafana 2.0 installed and configured quickly on RPM-based Linux operating systems. + +
+{{< screencast src="https://www.youtube.com/embed/JY22EBOR9hQ?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" >}} + +### Episode 4 - Installation & Configuration on Ubuntu / Debian + +Learn how to easily install the dependencies and packages to get Grafana 2.0 up and running on Ubuntu or Debian in just a few minutes. + +
+ +{{< screencast src="https://www.youtube.com/embed/FC13uhFRsVw?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" >}} + +### Episode 3 - Whats New In Grafana 2.0 + +This screencast highlights many of the great new features that were included in the Grafana 2.0 release. + +
+ +{{< screencast src="//www.youtube.com/embed/FhNUrueWwOk?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" >}} +### Episode 2 - Templated Graphite Queries + +The screencast focuses on Templating with the Graphite Data Source. Learn how to make dynamic and adaptable Dashboards for your Graphite metrics. + +
+ +{{< screencast src="//www.youtube.com/embed/mgcJPREl3CU?list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2" >}} +### Episode 1 - Building Graphite Queries + +Learn how the Graphite Query Editor works, and how to use different graphing functions. There's also an introduction to graph display settings. + +
+ + diff --git a/docs/sources/versions.html_fragment b/docs/sources/versions.html_fragment index 0d62ee1e461..df6dbd4db7f 100644 --- a/docs/sources/versions.html_fragment +++ b/docs/sources/versions.html_fragment @@ -1,3 +1,4 @@ +
  • Version v3.1
  • Version v3.0
  • Version v2.6
  • Version v2.5
  • diff --git a/emails/assets/css/ink.css b/emails/assets/css/ink.css index e65aed19194..f4c1a291cb3 100644 --- a/emails/assets/css/ink.css +++ b/emails/assets/css/ink.css @@ -17,6 +17,8 @@ body{ padding:0; } + + .ExternalClass { width:100%; } @@ -42,7 +44,6 @@ img { text-decoration:none; -ms-interpolation-mode: bicubic; width: auto; - max-width: 100%; float: left; clear: both; display: block; @@ -581,8 +582,7 @@ body.outlook p { @media only screen and (max-width: 600px) { table[class="body"] img { - width: auto !important; - height: auto !important; + } table[class="body"] center { diff --git a/emails/assets/css/style.css b/emails/assets/css/style.css index f138a0c1296..83f8d2c67a6 100644 --- a/emails/assets/css/style.css +++ b/emails/assets/css/style.css @@ -9,7 +9,8 @@ h1 {font-size: 40px;} h2 {font-size: 36px;} h3 { font-size: 22px; - margin-top: 20px; + margin-top: 10px; + margin-bottom: 10px; } h4 {font-size: 20px;} h5 {font-size: 18px;} @@ -79,10 +80,17 @@ table.google-plus:hover td { } .header { - background: #333; +margin-top:25px; +margin-bottom: 25px; +} + +.data { + font-size: 16px; } .footer { + background-color: #2e2e2e; + color: #999999; margin-top: 20px; } @@ -94,6 +102,10 @@ table.google-plus:hover td { table[class="body"] .left-text-pad { padding-right: 10px !important; } + + .logo { + margin-left: 10px; + } } table.better-button { @@ -134,6 +146,45 @@ table.columns td.better-button { color: #FFFFFF !important; } +table.better-button-alt { + margin-top: 10px; + margin-bottom: 20px; +} + +table.columns td.better-button-alt { + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; + padding-bottom: 0px; +} + +.better-button-alt a { + text-decoration: none; + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; + + padding: 12px 25px; + border: 1px solid #ff8f2b; + background-color: #EFEFEF; + display: inline-block; + color: #ff8f2b; +} + +.better-button-alt:hover a { + color: #ff8f2b !important; + background-color: #DDDDDD; + border: 1px solid #F2821E; +} + +.better-button-alt:visited a { + color: #ff8f2b !important; +} + +.better-button-alt:active a { + color: #ff8f2b !important; +} + .verification-code { background-color: #EEEEEE; padding: 3px; diff --git a/emails/templates/alert_notification.html b/emails/templates/alert_notification.html new file mode 100644 index 00000000000..d0d69faa106 --- /dev/null +++ b/emails/templates/alert_notification.html @@ -0,0 +1,111 @@ +[[Subject .Subject "[[.Title]]"]] + + + + + +
    + + + + +
    +

    [[.Title]]

    +
    +
    + + + + + +
    + + + + +
    +

    [[.Message]]

    +
    +
    + +[[if ne .State "ok" ]] + + + + +
    +
    + + + + + + [[range .EvalMatches]] + + + + + [[end]] +
    +
    Metric name
    +
    +
    Value
    +
    +
    [[.Metric]]
    +
    +
    [[.Value]]
    +
    +
    +
    +[[end]] + + + + + +
    + + + + +
    + [[if ne .ImageLink "" ]] + Alerting Panel + [[end]] + [[if ne .EmbededImage "" ]] + Alerting Panel + [[end]] +
    +
    + + + + + + +
    + + + + + +
    + + + + +
    + View your Alert rule +
    +
    + + + + +
    + Go to the Alerts page +
    +
    +
    + + diff --git a/emails/templates/invited_to_org.html b/emails/templates/invited_to_org.html index 59e76cd5a77..681830604b9 100644 --- a/emails/templates/invited_to_org.html +++ b/emails/templates/invited_to_org.html @@ -9,7 +9,7 @@ @@ -25,7 +25,7 @@
    -

    You have been added to [[.OrgName]]

    +

    You have been added to [[.OrgName]]

    diff --git a/emails/templates/layouts/default.html b/emails/templates/layouts/default.html index 0fd5b35ea48..f6d729054cd 100644 --- a/emails/templates/layouts/default.html +++ b/emails/templates/layouts/default.html @@ -3,77 +3,160 @@ - - - - + + + + - -
    -

    [[.InvitedBy]] has added you to the [[.OrgName]] organization in Grafana. +

    [[.InvitedBy]] has added you to the [[.OrgName]] organization in Grafana.

    Once logged in, [[.OrgName]] will be available in the left side menu, in the dropdown below your username.

    + + +
    -
    -
    +
    - - - - -
    -
    - - - - - -
    - - - - - - -
    - -
    - -
    - -
    -
    - - +
    - + +
    - {{> body }} - - - - - - + +
    + + + + +
    + + + + + + +
    + +
    + +
    + +
    +
    + + + + + + + - +
    + {{> body }}
    + + + + +
    diff --git a/emails/templates/new_user_invite.html b/emails/templates/new_user_invite.html index 86948a665f6..6e75a203953 100644 --- a/emails/templates/new_user_invite.html +++ b/emails/templates/new_user_invite.html @@ -9,7 +9,7 @@ @@ -25,7 +25,7 @@
    -

    You're invited to join [[.OrgName]]

    +

    You're invited to join [[.OrgName]]

    diff --git a/emails/templates/reset_password.html b/emails/templates/reset_password.html index f3aca5da95e..e9d1527116c 100644 --- a/emails/templates/reset_password.html +++ b/emails/templates/reset_password.html @@ -7,7 +7,7 @@
    -

    You've been invited to join the [[.OrgName]] organization by [[.InvitedBy]]. To accept your invitation and join the team, please click the link below:

    +

    You've been invited to join the [[.OrgName]] organization by [[.InvitedBy]]. To accept your invitation and join the team, please click the link below:

    @@ -24,7 +24,7 @@ @@ -29,6 +34,13 @@ + + +
    -

    Hi [[.Name]]

    +

    Hi [[.Name]],

    - Please click the following link to reset your password within [[.EmailCodeValidHours]] hours. + Please click the following link to reset your password within [[.EmailCodeValidHours]] hours.

    [[.AppUrl]]user/password/reset?code=[[.Code]] diff --git a/emails/templates/signup_started.html b/emails/templates/signup_started.html index 39b369a1f7c..15689a0e62c 100644 --- a/emails/templates/signup_started.html +++ b/emails/templates/signup_started.html @@ -7,7 +7,7 @@ diff --git a/emails/templates/welcome_on_signup.html b/emails/templates/welcome_on_signup.html index b93c56b77b1..0e0e4dbe3bc 100644 --- a/emails/templates/welcome_on_signup.html +++ b/emails/templates/welcome_on_signup.html @@ -7,10 +7,15 @@
    -

    Complete the signup

    +

    Complete the signup

    + + +
    -

    Hi [[.Name]]

    +

    Hi [[.Name]],

    + Welcome! Ready to start building some beautiful metric and analytic dashboards? +

    + Thank you for joining our community. +
    +

    The Grafana Team

    +
    diff --git a/examples/README.md b/examples/README.md index 64341a7fdbc..75f1f9a9a86 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,4 +1,5 @@ ## Example plugin implementations datasource:[simple-json-datasource](https://github.com/grafana/simple-json-datasource) -app: [example-app](https://github.com/grafana/example-app) \ No newline at end of file +app: [example-app](https://github.com/grafana/example-app) +panel: [grafana-piechart-panel](https://github.com/grafana/piechart-panel) diff --git a/examples/alerting-dashboard.json b/examples/alerting-dashboard.json new file mode 100644 index 00000000000..744460d7847 --- /dev/null +++ b/examples/alerting-dashboard.json @@ -0,0 +1,800 @@ +{ + "__inputs": [ + { + "name": "DS_GRAPHITE", + "label": "graphite", + "description": "", + "type": "datasource", + "pluginId": "graphite", + "pluginName": "Graphite" + } + ], + "__requires": [ + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "3.1.0" + }, + { + "type": "datasource", + "id": "graphite", + "name": "Graphite", + "version": "1.0.0" + } + ], + "id": null, + "title": "Alerting example", + "tags": [], + "style": "dark", + "timezone": "browser", + "editable": true, + "hideControls": false, + "sharedCrosshair": false, + "rows": [ + { + "collapse": false, + "editable": true, + "height": "250px", + "panels": [ + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 355 + ], + "type": "gt" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "enabled": true, + "frequency": "60s", + "handler": 1, + "name": "Critical alert panel", + "notifications": [], + "severity": "critical" + }, + "alerting": {}, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "id": 1, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + }, + { + "refId": "B", + "target": "aliasByNode(scale(statsd.$apa.counters.session_start.*.count, 10), 4)" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 355 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Critical panel", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 20 + ], + "type": "gt" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "enabled": true, + "frequency": "60s", + "handler": 1, + "name": "Warning panel alert", + "notifications": [], + "severity": "warning" + }, + "alerting": {}, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "id": 2, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + } + ], + "thresholds": [ + { + "colorMode": "warning", + "fill": true, + "fillColor": "rgba(235, 138, 14, 0.12)", + "line": true, + "lineColor": "rgba(247, 149, 32, 0.60)", + "op": "gt", + "value": 20 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Warning panel", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "lt" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "count" + }, + "type": "query" + } + ], + "enabled": true, + "frequency": "60s", + "handler": 1, + "name": "No datapoints", + "notifications": [], + "severity": "critical" + }, + "alerting": {}, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "id": 20, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + } + ], + "thresholds": [ + { + "value": 1, + "op": "lt", + "fill": true, + "line": true, + "colorMode": "critical" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Count datapoints", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "title": "Row" + }, + { + "collapse": false, + "editable": true, + "height": "250px", + "panels": [ + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 20 + ], + "type": "lt" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "enabled": true, + "frequency": "60s", + "handler": 1, + "name": "Alert below value", + "notifications": [], + "severity": "critical" + }, + "alerting": {}, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "id": 17, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "fillColor": "rgba(234, 112, 112, 0.12)", + "line": true, + "lineColor": "rgba(237, 46, 24, 0.60)", + "op": "lt", + "value": 20 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Alert below value", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 10, + 80 + ], + "type": "outside_range" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "enabled": true, + "frequency": "10s", + "handler": 1, + "name": "Alert is outside range", + "notifications": [], + "severity": "critical" + }, + "alerting": {}, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "id": 18, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "fillColor": "rgba(234, 112, 112, 0.12)", + "line": true, + "lineColor": "rgba(237, 46, 24, 0.60)", + "op": "lt", + "value": 10 + }, + { + "colorMode": "critical", + "fill": true, + "fillColor": "rgba(234, 112, 112, 0.12)", + "line": true, + "lineColor": "rgba(237, 46, 24, 0.60)", + "op": "gt", + "value": 80 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Alert is outside range", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 60, + 80 + ], + "type": "within_range" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "enabled": true, + "frequency": "10s", + "handler": 1, + "name": "Alert is within range", + "notifications": [], + "severity": "critical" + }, + "alerting": {}, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "id": 19, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "fillColor": "rgba(234, 112, 112, 0.12)", + "line": true, + "lineColor": "rgba(237, 46, 24, 0.60)", + "op": "gt", + "value": 60 + }, + { + "colorMode": "critical", + "fill": true, + "fillColor": "rgba(234, 112, 112, 0.12)", + "line": true, + "lineColor": "rgba(237, 46, 24, 0.60)", + "op": "lt", + "value": 80 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Alert is within range", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "title": "New row" + } + ], + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "templating": { + "list": [ + { + "current": { + "text": "fakesite", + "value": "fakesite" + }, + "datasource": null, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "apa", + "options": [ + { + "selected": true, + "text": "fakesite", + "value": "fakesite" + } + ], + "query": "fakesite", + "refresh": 0, + "type": "custom" + } + ] + }, + "annotations": { + "list": [] + }, + "schemaVersion": 13, + "version": 15, + "links": [], + "gnetId": null +} \ No newline at end of file diff --git a/examples/alerting-multiple-alerts.json b/examples/alerting-multiple-alerts.json new file mode 100644 index 00000000000..e6e729ecc06 --- /dev/null +++ b/examples/alerting-multiple-alerts.json @@ -0,0 +1,2216 @@ +{ + "__inputs": [ + { + "name": "DS_GRAPHITE", + "label": "graphite", + "description": "", + "type": "datasource", + "pluginId": "graphite", + "pluginName": "Graphite" + } + ], + "__requires": [ + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "3.1.0" + }, + { + "type": "datasource", + "id": "graphite", + "name": "Graphite", + "version": "1.0.0" + } + ], + "id": null, + "title": "Dashboard with many alerts", + "tags": [], + "style": "dark", + "timezone": "browser", + "editable": true, + "hideControls": false, + "sharedCrosshair": false, + "rows": [ + { + "collapse": false, + "editable": true, + "height": "250px", + "panels": [ + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 30 + ], + "type": "gt" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "sum" + }, + "type": "query" + } + ], + "enabled": true, + "frequency": "60s", + "handler": 1, + "name": "Critical alert panel", + "notifications": [], + "severity": "critical" + }, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "id": 1, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "fillColor": "rgba(234, 112, 112, 0.12)", + "line": true, + "lineColor": "rgba(237, 46, 24, 0.60)", + "op": "gt", + "value": 30 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Critical panel", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 30 + ], + "type": "gt" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "sum" + }, + "type": "query" + } + ], + "enabled": true, + "frequency": "60s", + "handler": 1, + "name": "Critical alert panel", + "notifications": [], + "severity": "critical" + }, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "id": 5, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "fillColor": "rgba(234, 112, 112, 0.12)", + "line": true, + "lineColor": "rgba(237, 46, 24, 0.60)", + "op": "gt", + "value": 30 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Critical panel", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 30 + ], + "type": "gt" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "sum" + }, + "type": "query" + } + ], + "enabled": true, + "frequency": "60s", + "handler": 1, + "name": "Critical alert panel", + "notifications": [], + "severity": "critical" + }, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "id": 6, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "fillColor": "rgba(234, 112, 112, 0.12)", + "line": true, + "lineColor": "rgba(237, 46, 24, 0.60)", + "op": "gt", + "value": 30 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Critical panel", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 30 + ], + "type": "gt" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "sum" + }, + "type": "query" + } + ], + "enabled": true, + "frequency": "60s", + "handler": 1, + "name": "Critical alert panel", + "notifications": [], + "severity": "critical" + }, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "id": 8, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "fillColor": "rgba(234, 112, 112, 0.12)", + "line": true, + "lineColor": "rgba(237, 46, 24, 0.60)", + "op": "gt", + "value": 30 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Critical panel", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "title": "Row" + }, + { + "collapse": false, + "editable": true, + "height": "250px", + "panels": [ + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 20 + ], + "type": "gt" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "enabled": true, + "frequency": "60s", + "handler": 1, + "name": "Warning panel alert", + "notifications": [], + "severity": "warning" + }, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "id": 2, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + } + ], + "thresholds": [ + { + "colorMode": "warning", + "fill": true, + "fillColor": "rgba(235, 138, 14, 0.12)", + "line": true, + "lineColor": "rgba(247, 149, 32, 0.60)", + "op": "gt", + "value": 20 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Warning panel", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 20 + ], + "type": "gt" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "enabled": true, + "frequency": "60s", + "handler": 1, + "name": "Warning panel alert", + "notifications": [], + "severity": "warning" + }, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "id": 3, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + } + ], + "thresholds": [ + { + "colorMode": "warning", + "fill": true, + "fillColor": "rgba(235, 138, 14, 0.12)", + "line": true, + "lineColor": "rgba(247, 149, 32, 0.60)", + "op": "gt", + "value": 20 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Warning panel", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 20 + ], + "type": "gt" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "enabled": true, + "frequency": "60s", + "handler": 1, + "name": "Warning panel alert", + "notifications": [], + "severity": "warning" + }, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "id": 4, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + } + ], + "thresholds": [ + { + "colorMode": "warning", + "fill": true, + "fillColor": "rgba(235, 138, 14, 0.12)", + "line": true, + "lineColor": "rgba(247, 149, 32, 0.60)", + "op": "gt", + "value": 20 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Warning panel", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 20 + ], + "type": "gt" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "enabled": true, + "frequency": "60s", + "handler": 1, + "name": "Warning panel alert", + "notifications": [], + "severity": "warning" + }, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "id": 7, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + } + ], + "thresholds": [ + { + "colorMode": "warning", + "fill": true, + "fillColor": "rgba(235, 138, 14, 0.12)", + "line": true, + "lineColor": "rgba(247, 149, 32, 0.60)", + "op": "gt", + "value": 20 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Warning panel", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "title": "New row" + }, + { + "collapse": false, + "editable": true, + "height": "250px", + "panels": [ + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 50 + ], + "type": "gt" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "enabled": true, + "frequency": "10s", + "handler": 1, + "name": "Fast Critical panel alert", + "notifications": [], + "severity": "critical" + }, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "id": 9, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "fillColor": "rgba(234, 112, 112, 0.12)", + "line": true, + "lineColor": "rgba(237, 46, 24, 0.60)", + "op": "gt", + "value": 50 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Fast Critical panel", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 50 + ], + "type": "gt" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "enabled": true, + "frequency": "10s", + "handler": 1, + "name": "Fast Critical panel alert", + "notifications": [], + "severity": "critical" + }, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "id": 10, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "fillColor": "rgba(234, 112, 112, 0.12)", + "line": true, + "lineColor": "rgba(237, 46, 24, 0.60)", + "op": "gt", + "value": 50 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Fast Critical panel", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 50 + ], + "type": "gt" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "enabled": true, + "frequency": "10s", + "handler": 1, + "name": "Fast Critical panel alert", + "notifications": [], + "severity": "critical" + }, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "id": 11, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "fillColor": "rgba(234, 112, 112, 0.12)", + "line": true, + "lineColor": "rgba(237, 46, 24, 0.60)", + "op": "gt", + "value": 50 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Fast Critical panel", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 50 + ], + "type": "gt" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "enabled": true, + "frequency": "10s", + "handler": 1, + "name": "Fast Critical panel alert", + "notifications": [], + "severity": "critical" + }, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "id": 12, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "fillColor": "rgba(234, 112, 112, 0.12)", + "line": true, + "lineColor": "rgba(237, 46, 24, 0.60)", + "op": "gt", + "value": 50 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Fast Critical panel", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "title": "New row" + }, + { + "collapse": false, + "editable": true, + "height": "250px", + "panels": [ + { + "alert": { + "enabled": true, + "conditions": [ + { + "type": "query", + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "type": "avg", + "params": [] + }, + "evaluator": { + "type": "gt", + "params": [ + 10 + ] + } + } + ], + "severity": "warning", + "frequency": "1s", + "handler": 1, + "notifications": [], + "name": "Fast Warning panel alert" + }, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "id": 13, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + } + ], + "thresholds": [ + { + "value": 10, + "op": "gt", + "fill": true, + "line": true, + "colorMode": "warning", + "fillColor": "rgba(235, 138, 14, 0.12)", + "lineColor": "rgba(247, 149, 32, 0.60)" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Fast Warning panel", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "alert": { + "enabled": true, + "conditions": [ + { + "type": "query", + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "type": "avg", + "params": [] + }, + "evaluator": { + "type": "gt", + "params": [ + 10 + ] + } + } + ], + "severity": "warning", + "frequency": "1s", + "handler": 1, + "notifications": [], + "name": "Fast Warning panel alert" + }, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "id": 14, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + } + ], + "thresholds": [ + { + "value": 10, + "op": "gt", + "fill": true, + "line": true, + "colorMode": "warning", + "fillColor": "rgba(235, 138, 14, 0.12)", + "lineColor": "rgba(247, 149, 32, 0.60)" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Fast Warning panel", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "alert": { + "enabled": true, + "conditions": [ + { + "type": "query", + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "type": "avg", + "params": [] + }, + "evaluator": { + "type": "gt", + "params": [ + 10 + ] + } + } + ], + "severity": "warning", + "frequency": "1s", + "handler": 1, + "notifications": [], + "name": "Fast Warning panel alert" + }, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "id": 15, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + } + ], + "thresholds": [ + { + "value": 10, + "op": "gt", + "fill": true, + "line": true, + "colorMode": "warning", + "fillColor": "rgba(235, 138, 14, 0.12)", + "lineColor": "rgba(247, 149, 32, 0.60)" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Fast Warning panel", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "alert": { + "enabled": true, + "conditions": [ + { + "type": "query", + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "type": "avg", + "params": [] + }, + "evaluator": { + "type": "gt", + "params": [ + 10 + ] + } + } + ], + "severity": "warning", + "frequency": "1s", + "handler": 1, + "notifications": [], + "name": "Fast Warning panel alert" + }, + "aliasColors": {}, + "bars": false, + "datasource": "${DS_GRAPHITE}", + "editable": true, + "error": false, + "fill": 1, + "id": 16, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)" + } + ], + "thresholds": [ + { + "value": 10, + "op": "gt", + "fill": true, + "line": true, + "colorMode": "warning", + "fillColor": "rgba(235, 138, 14, 0.12)", + "lineColor": "rgba(247, 149, 32, 0.60)" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Fast Warning panel", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "show": true + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "title": "New row" + }, + { + "title": "New row", + "height": "250px", + "editable": true, + "collapse": false, + "panels": [ + { + "title": "Alert below value", + "error": false, + "span": 3, + "editable": true, + "type": "graph", + "isNew": true, + "id": 17, + "targets": [ + { + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)", + "refId": "A" + } + ], + "datasource": "${DS_GRAPHITE}", + "renderer": "flot", + "yaxes": [ + { + "label": null, + "show": true, + "logBase": 1, + "min": null, + "max": null, + "format": "short" + }, + { + "label": null, + "show": true, + "logBase": 1, + "min": null, + "max": null, + "format": "short" + } + ], + "xaxis": { + "show": true + }, + "alert": { + "conditions": [ + { + "type": "query", + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "type": "avg", + "params": [] + }, + "evaluator": { + "type": "lt", + "params": [ + 20 + ] + } + } + ], + "severity": "critical", + "frequency": "60s", + "handler": 1, + "notifications": [], + "name": "Alert below value", + "enabled": true + }, + "lines": true, + "fill": 1, + "linewidth": 2, + "points": false, + "pointradius": 5, + "bars": false, + "stack": false, + "percentage": false, + "legend": { + "show": true, + "values": false, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": false + }, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "shared": true, + "sort": 0, + "msResolution": false + }, + "timeFrom": null, + "timeShift": null, + "aliasColors": {}, + "seriesOverrides": [], + "thresholds": [ + { + "value": 20, + "op": "lt", + "fill": true, + "line": true, + "colorMode": "critical", + "fillColor": "rgba(234, 112, 112, 0.12)", + "lineColor": "rgba(237, 46, 24, 0.60)" + } + ], + "links": [] + }, + { + "title": "Alert is outside range", + "error": false, + "span": 3, + "editable": true, + "type": "graph", + "isNew": true, + "id": 18, + "targets": [ + { + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)", + "refId": "A" + } + ], + "datasource": "${DS_GRAPHITE}", + "renderer": "flot", + "yaxes": [ + { + "label": null, + "show": true, + "logBase": 1, + "min": null, + "max": null, + "format": "short" + }, + { + "label": null, + "show": true, + "logBase": 1, + "min": null, + "max": null, + "format": "short" + } + ], + "xaxis": { + "show": true + }, + "alert": { + "conditions": [ + { + "type": "query", + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "type": "avg", + "params": [] + }, + "evaluator": { + "type": "outside_range", + "params": [ + 10, + 80 + ] + } + } + ], + "severity": "critical", + "frequency": "10s", + "handler": 1, + "notifications": [], + "name": "Alert is outside range", + "enabled": true + }, + "lines": true, + "fill": 1, + "linewidth": 2, + "points": false, + "pointradius": 5, + "bars": false, + "stack": false, + "percentage": false, + "legend": { + "show": true, + "values": false, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": false + }, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "shared": true, + "sort": 0, + "msResolution": false + }, + "timeFrom": null, + "timeShift": null, + "aliasColors": {}, + "seriesOverrides": [], + "thresholds": [ + { + "value": 10, + "op": "lt", + "fill": true, + "line": true, + "colorMode": "critical", + "fillColor": "rgba(234, 112, 112, 0.12)", + "lineColor": "rgba(237, 46, 24, 0.60)" + }, + { + "value": 80, + "op": "gt", + "fill": true, + "line": true, + "colorMode": "critical", + "fillColor": "rgba(234, 112, 112, 0.12)", + "lineColor": "rgba(237, 46, 24, 0.60)" + } + ], + "links": [] + }, + { + "title": "Alert is within range", + "error": false, + "span": 3, + "editable": true, + "type": "graph", + "isNew": true, + "id": 19, + "targets": [ + { + "target": "aliasByNode(statsd.fakesite.counters.session_start.*.count, 4)", + "refId": "A" + } + ], + "datasource": "${DS_GRAPHITE}", + "renderer": "flot", + "yaxes": [ + { + "label": null, + "show": true, + "logBase": 1, + "min": null, + "max": null, + "format": "short" + }, + { + "label": null, + "show": true, + "logBase": 1, + "min": null, + "max": null, + "format": "short" + } + ], + "xaxis": { + "show": true + }, + "alert": { + "conditions": [ + { + "type": "query", + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "type": "avg", + "params": [] + }, + "evaluator": { + "type": "within_range", + "params": [ + 60, + 80 + ] + } + } + ], + "severity": "critical", + "frequency": "10s", + "handler": 1, + "notifications": [], + "name": "Alert is within range", + "enabled": true + }, + "lines": true, + "fill": 1, + "linewidth": 2, + "points": false, + "pointradius": 5, + "bars": false, + "stack": false, + "percentage": false, + "legend": { + "show": true, + "values": false, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": false + }, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "shared": true, + "sort": 0, + "msResolution": false + }, + "timeFrom": null, + "timeShift": null, + "aliasColors": {}, + "seriesOverrides": [], + "thresholds": [ + { + "value": 60, + "op": "gt", + "fill": true, + "line": true, + "colorMode": "critical", + "fillColor": "rgba(234, 112, 112, 0.12)", + "lineColor": "rgba(237, 46, 24, 0.60)" + }, + { + "value": 80, + "op": "lt", + "fill": true, + "line": true, + "colorMode": "critical", + "fillColor": "rgba(234, 112, 112, 0.12)", + "lineColor": "rgba(237, 46, 24, 0.60)" + } + ], + "links": [] + } + ] + } + ], + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "templating": { + "list": [] + }, + "annotations": { + "list": [] + }, + "schemaVersion": 13, + "version": 50, + "links": [], + "gnetId": null +} \ No newline at end of file diff --git a/examples/boilerplate-es5-panel/css/styles.css b/examples/boilerplate-es5-panel/css/styles.css deleted file mode 100644 index b7259cb6cc8..00000000000 --- a/examples/boilerplate-es5-panel/css/styles.css +++ /dev/null @@ -1,3 +0,0 @@ -.panel-boilerplate-values { - text-align: center; -} \ No newline at end of file diff --git a/examples/boilerplate-es5-panel/module.js b/examples/boilerplate-es5-panel/module.js deleted file mode 100644 index ef6b23ea749..00000000000 --- a/examples/boilerplate-es5-panel/module.js +++ /dev/null @@ -1,53 +0,0 @@ -define([ - 'app/plugins/sdk', - 'lodash', - './css/styles.css!' -], function(sdk, _) { - - var BoilerPlatePanelCtrl = (function(_super) { - var self; - - function BoilerPlatePanelCtrl($scope, $injector) { - _super.call(this, $scope, $injector); - - this.results = [] - - self = this; - } - - // you do not need a templateUrl, you can use a inline template here - // BoilerPlatePanelCtrl.template = '

    boilerplate

    '; - - // all panel static assets can be accessed via 'public/plugins// - BoilerPlatePanelCtrl.templateUrl = 'panel.html'; - - BoilerPlatePanelCtrl.prototype = Object.create(_super.prototype); - BoilerPlatePanelCtrl.prototype.constructor = BoilerPlatePanelCtrl; - - BoilerPlatePanelCtrl.prototype.refreshData = function(datasource) { - this.issueQueries(datasource) - .then(function(result) { - self.results = []; - _.each(result.data, function(target) { - var last = _.last(target.datapoints) - self.results.push(last[0]); - }); - - self.render(); - }); - } - - BoilerPlatePanelCtrl.prototype.render = function() { - this.values = this.results.join(','); - } - - return BoilerPlatePanelCtrl; - - })(sdk.MetricsPanelCtrl); - - - return { - PanelCtrl: BoilerPlatePanelCtrl - }; -}); - diff --git a/examples/boilerplate-es5-panel/panel.html b/examples/boilerplate-es5-panel/panel.html deleted file mode 100644 index 4a413c95dfe..00000000000 --- a/examples/boilerplate-es5-panel/panel.html +++ /dev/null @@ -1,7 +0,0 @@ -

    - Basic panel -

    - -

    {{ctrl.values}}

    - - diff --git a/examples/boilerplate-es5-panel/plugin.json b/examples/boilerplate-es5-panel/plugin.json deleted file mode 100644 index b585698c20a..00000000000 --- a/examples/boilerplate-es5-panel/plugin.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "type": "panel", - "name": "Panel Boilerplate", - "id": "panel-boilerplate-es5", - "staticRoot": "." -} diff --git a/karma.conf.js b/karma.conf.js index cbb0abff7c6..cdcea23a90b 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -9,7 +9,6 @@ module.exports = function(config) { // list of files / patterns to load in the browser files: [ 'vendor/npm/es6-shim/es6-shim.js', - 'vendor/npm/es6-promise/dist/es6-promise.js', 'vendor/npm/systemjs/dist/system.src.js', 'test/test-main.js', @@ -25,9 +24,10 @@ module.exports = function(config) { logLevel: config.LOG_INFO, autoWatch: true, browsers: ['PhantomJS'], - captureTimeout: 2000, + captureTimeout: 20000, singleRun: true, autoWatchBatchDelay: 1000, + browserNoActivityTimeout: 60000, }); diff --git a/latest.json b/latest.json index 79eb42a8527..78fd48769e8 100644 --- a/latest.json +++ b/latest.json @@ -1,3 +1,4 @@ { - "version": "2.1.1" + "stable": "4.0.2", + "testing": "4.0.2" } diff --git a/package.json b/package.json index ad4840144dc..5124edff40b 100644 --- a/package.json +++ b/package.json @@ -4,81 +4,83 @@ "company": "Coding Instinct AB" }, "name": "grafana", - "version": "3.0.0-beta1", + "version": "4.2.0-pre1", "repository": { "type": "git", "url": "http://github.com/grafana/grafana.git" }, "devDependencies": { - "angular2": "2.0.0-beta.12", - "zone.js": "^0.6.6", - "autoprefixer": "^6.3.3", + "autoprefixer": "^6.4.0", "es6-promise": "^3.0.2", - "es6-shim": "^0.35.0", + "es6-shim": "^0.35.1", "expect.js": "~0.2.0", - "glob": "~3.2.7", - "grunt": "~0.4.0", - "grunt-angular-templates": "^0.5.5", - "grunt-cli": "~0.1.13", - "grunt-contrib-clean": "~0.7.0", - "grunt-contrib-compress": "~0.14.0", - "grunt-contrib-concat": "^0.5.1", - "grunt-contrib-copy": "~0.8.2", - "grunt-contrib-cssmin": "~0.14.0", - "grunt-contrib-htmlmin": "~0.6.0", - "grunt-contrib-jshint": "~1.0.0", - "grunt-contrib-less": "~0.7.0", - "grunt-contrib-uglify": "~0.11.0", - "grunt-contrib-watch": "^0.6.1", - "grunt-filerev": "^0.2.1", - "grunt-git-describe": "~2.3.2", - "grunt-karma": "~0.12.1", - "grunt-ng-annotate": "^1.0.1", - "grunt-notify": "^0.4.3", + "glob": "~7.0.0", + "grunt": "^0.4.5", + "grunt-angular-templates": "^1.1.0", + "grunt-cli": "~1.2.0", + "grunt-contrib-clean": "~1.0.0", + "grunt-contrib-compress": "^1.3.0", + "grunt-contrib-concat": "^1.0.1", + "grunt-contrib-copy": "~1.0.0", + "grunt-contrib-cssmin": "~1.0.2", + "grunt-contrib-htmlmin": "~2.0.0", + "grunt-contrib-jshint": "~1.1.0", + "grunt-contrib-uglify": "~2.0.0", + "grunt-contrib-watch": "^1.0.0", + "grunt-exec": "^1.0.1", + "grunt-filerev": "^2.3.1", + "grunt-git-describe": "~2.4.2", + "grunt-karma": "~2.0.0", + "grunt-ng-annotate": "^3.0.0", + "grunt-notify": "^0.4.5", "grunt-postcss": "^0.8.0", - "grunt-sass": "^1.1.0", - "grunt-string-replace": "~1.2.1", - "grunt-systemjs-builder": "^0.2.6", - "grunt-tslint": "^3.0.2", - "grunt-typescript": "^0.8.0", - "grunt-usemin": "3.0.0", - "jshint-stylish": "~2.1.0", - "karma": "~0.13.15", - "karma-chrome-launcher": "~0.2.2", - "karma-coverage": "0.5.3", + "grunt-sass": "^1.2.1", + "grunt-string-replace": "~1.3.1", + "grunt-systemjs-builder": "^0.2.7", + "grunt-usemin": "3.1.1", + "jshint-stylish": "~2.2.1", + "karma": "1.3.0", + "karma-chrome-launcher": "~2.0.0", + "karma-coverage": "1.1.1", "karma-coveralls": "1.1.2", - "karma-expect": "~1.1.0", - "karma-mocha": "~0.2.1", - "karma-phantomjs-launcher": "1.0.0", - "load-grunt-tasks": "3.4.0", - "mocha": "2.3.4", - "phantomjs-prebuilt": "^2.1.3", - "reflect-metadata": "0.1.2", - "rxjs": "5.0.0-beta.2", - "sass-lint": "^1.5.0", - "systemjs": "0.19.24" + "karma-expect": "~1.1.3", + "karma-mocha": "~1.3.0", + "karma-phantomjs-launcher": "1.0.2", + "load-grunt-tasks": "3.5.2", + "mocha": "3.2.0", + "phantomjs-prebuilt": "^2.1.14", + "reflect-metadata": "0.1.8", + "rxjs": "^5.0.0-rc.5", + "sass-lint": "^1.10.2", + "systemjs": "0.19.41", + "zone.js": "^0.7.2" }, "engines": { - "node": "0.4.x", + "node": "4.x", "npm": "2.14.x" }, "scripts": { + "build": "grunt", "test": "grunt test", "coveralls": "grunt karma:coveralls && rm -rf ./coverage" }, "license": "Apache-2.0", "dependencies": { - "grunt-jscs": "~1.5.x", - "grunt-sass-lint": "^0.1.0", - "grunt-sync": "^0.4.1", - "karma-sinon": "^1.0.3", - "lodash": "^2.4.1", - "remarkable": "^1.6.2", - "sinon": "1.16.1", - "systemjs-builder": "^0.15.13", - "tether": "^1.2.0", - "tether-drop": "^1.4.2", - "tslint": "^3.4.0", - "typescript": "^1.7.5" + "eventemitter3": "^2.0.2", + "gaze": "^1.1.2", + "grunt-jscs": "3.0.1", + "grunt-sass-lint": "^0.2.2", + "grunt-sync": "^0.6.2", + "karma-sinon": "^1.0.5", + "lodash": "^4.17.2", + "mousetrap": "^1.6.0", + "remarkable": "^1.7.1", + "sinon": "1.17.6", + "systemjs-builder": "^0.15.34", + "tether": "^1.4.0", + "tether-drop": "git://github.com/torkelo/drop", + "tslint": "^4.0.2", + "typescript": "^2.1.4", + "virtual-scroll": "^1.1.1" } } diff --git a/packaging/deb/control/postinst b/packaging/deb/control/postinst index b93c8433490..425a7319e62 100755 --- a/packaging/deb/control/postinst +++ b/packaging/deb/control/postinst @@ -7,12 +7,12 @@ set -e startGrafana() { if [ -x /bin/systemctl ]; then /bin/systemctl daemon-reload - /bin/systemctl start grafana-server + /bin/systemctl restart grafana-server elif [ -x "/etc/init.d/grafana-server" ]; then if [ -x "`which invoke-rc.d 2>/dev/null`" ]; then - invoke-rc.d grafana-server start || true + invoke-rc.d grafana-server restart || true else - /etc/init.d/grafana-server start || true + /etc/init.d/grafana-server restart || true fi fi } diff --git a/packaging/deb/systemd/grafana-server.service b/packaging/deb/systemd/grafana-server.service index e87635bb3de..ea7193c55a6 100644 --- a/packaging/deb/systemd/grafana-server.service +++ b/packaging/deb/systemd/grafana-server.service @@ -1,5 +1,5 @@ [Unit] -Description=Starts and stops a single grafana instance on this system +Description=Grafana instance Documentation=http://docs.grafana.org Wants=network-online.target After=network-online.target diff --git a/packaging/mac/bin/grafana b/packaging/mac/bin/grafana new file mode 100755 index 00000000000..fb33079079e --- /dev/null +++ b/packaging/mac/bin/grafana @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +DAEMON=grafana-server +EXECUTABLE=/usr/local/bin/grafana-server +CONFIG=/usr/local/etc/grafana/grafana.ini +HOMEPATH=/usr/local/share/grafana +LOGPATH=/usr/local/var/log/grafana +DATAPATH=/usr/local/var/lib/grafana +PLUGINPATH=/usr/local/var/lib/grafana/plugins + +case "$1" in +start) + $EXECUTABLE --config=$CONFIG --homepath=$HOMEPATH cfg:default.paths.logs=$LOGPATH cfg:default.paths.data=$DATAPATH cfg:default.paths.plugins=$PLUGINPATH 2> /dev/null & + [ $? -eq 0 ] && echo "$DAEMON started" +;; +stop) + killall $DAEMON + [ $? -eq 0 ] && echo "$DAEMON stopped" +;; +restart) + $0 stop + $0 start +;; +*) + echo "Usage: $0 (start|stop|restart)" +;; +esac diff --git a/packaging/publish/publish.sh b/packaging/publish/publish.sh deleted file mode 100755 index d918f9a89d8..00000000000 --- a/packaging/publish/publish.sh +++ /dev/null @@ -1,22 +0,0 @@ -#! /usr/bin/env bash - -deb_ver=3.0.0-pre1459399258 -rpm_ver=3.0.0-pre1459399258 - -#rpm_ver=3.0.0-1 - -#wget https://grafanarel.s3.amazonaws.com/builds/grafana_${deb_ver}_amd64.deb - -# package_cloud push grafana/stable/debian/jessie grafana_${deb_ver}_amd64.deb -# package_cloud push grafana/stable/debian/wheezy grafana_${deb_ver}_amd64.deb - -package_cloud push grafana/testing/debian/jessie grafana_${deb_ver}_amd64.deb -package_cloud push grafana/testing/debian/wheezy grafana_${deb_ver}_amd64.deb - -wget https://grafanarel.s3.amazonaws.com/builds/grafana-${rpm_ver}.x86_64.rpm - -package_cloud push grafana/testing/el/6 grafana-${rpm_ver}.x86_64.rpm -package_cloud push grafana/testing/el/7 grafana-${rpm_ver}.x86_64.rpm - -# package_cloud push grafana/stable/el/7 grafana-${version}-1.x86_64.rpm -# package_cloud push grafana/stable/el/6 grafana-${version}-1.x86_64.rpm diff --git a/packaging/publish/publish_both.sh b/packaging/publish/publish_both.sh new file mode 100755 index 00000000000..57adcbd3481 --- /dev/null +++ b/packaging/publish/publish_both.sh @@ -0,0 +1,19 @@ +#! /usr/bin/env bash +deb_ver=4.0.2-1481203731 +rpm_ver=4.0.2-1481203731 + +wget https://grafanarel.s3.amazonaws.com/builds/grafana_${deb_ver}_amd64.deb + +package_cloud push grafana/stable/debian/jessie grafana_${deb_ver}_amd64.deb +package_cloud push grafana/stable/debian/wheezy grafana_${deb_ver}_amd64.deb + +package_cloud push grafana/testing/debian/jessie grafana_${deb_ver}_amd64.deb +package_cloud push grafana/testing/debian/wheezy grafana_${deb_ver}_amd64.deb + +wget https://grafanarel.s3.amazonaws.com/builds/grafana-${rpm_ver}.x86_64.rpm + +package_cloud push grafana/testing/el/6 grafana-${rpm_ver}.x86_64.rpm +package_cloud push grafana/testing/el/7 grafana-${rpm_ver}.x86_64.rpm + +package_cloud push grafana/stable/el/7 grafana-${rpm_ver}.x86_64.rpm +package_cloud push grafana/stable/el/6 grafana-${rpm_ver}.x86_64.rpm diff --git a/packaging/publish/publish_testing.sh b/packaging/publish/publish_testing.sh new file mode 100755 index 00000000000..1e39d65b7e5 --- /dev/null +++ b/packaging/publish/publish_testing.sh @@ -0,0 +1,14 @@ +#! /usr/bin/env bash +deb_ver=4.1.0-1482230757beta1 +rpm_ver=4.1.0-1482230757beta1 + +wget https://grafanarel.s3.amazonaws.com/builds/grafana_${deb_ver}_amd64.deb + +package_cloud push grafana/testing/debian/jessie grafana_${deb_ver}_amd64.deb +package_cloud push grafana/testing/debian/wheezy grafana_${deb_ver}_amd64.deb + +wget https://grafanarel.s3.amazonaws.com/builds/grafana-${rpm_ver}.x86_64.rpm + +package_cloud push grafana/testing/el/6 grafana-${rpm_ver}.x86_64.rpm +package_cloud push grafana/testing/el/7 grafana-${rpm_ver}.x86_64.rpm + diff --git a/packaging/release_process.md b/packaging/release_process.md new file mode 100644 index 00000000000..6037a9c499c --- /dev/null +++ b/packaging/release_process.md @@ -0,0 +1,29 @@ +# New Grafana Release Processes + +## Building release packages + +1) Update package.json so that it has the right version. +2) Create a git tag for the release: `git tag -a v3.0.4 -m "3.0.4 release"` +3) Push branch & tag to github! +2) Packages from master a built automatically by circle CI for this repo [grafana/grafana-packer](https://github.com/grafana/grafana-packer) + +### Non master branch + +When building from non master branch create a new branch in repo [grafana/grafana-packer](https://github.com/grafana/grafana-packer) +and configure circle.yml to deploy that branch as well, https://github.com/grafana/grafana-packer/blob/master/circle.yml#L25, +you also need to update https://github.com/grafana/grafana-packer/blob/v3.1.x/deploy.sh#L7. + +### Windows build + +Sign into ci.appveyor.com and the Grafana project's build history page. Builds for windows take a long time (around 20min) +and fail quite often for random reasons so I usually continue with the release process without a windows build already built. + +1) Click on the green build that has the correct version and tag +2) Click on `DEPLOYMENTS` +3) Click on `NEW DEPLOYMENT` +4) Select GrafanaBuildS3 +4) Select the build you want to deploy. + +The deployment should be quick (just uploads the release zip file to S3) + + diff --git a/packaging/rpm/init.d/grafana-server b/packaging/rpm/init.d/grafana-server index c60f4fb6080..cb9bb73de7d 100755 --- a/packaging/rpm/init.d/grafana-server +++ b/packaging/rpm/init.d/grafana-server @@ -72,8 +72,6 @@ function isRunning() { case "$1" in start) - echo -n $"Starting $DESC: .... " - isRunning if [ $? -eq 0 ]; then echo "Already running." @@ -90,7 +88,7 @@ case "$1" in # Start Daemon cd $GRAFANA_HOME - su -s /bin/sh -c "nohup ${DAEMON} ${DAEMON_OPTS} >> /dev/null 3>&1 &" $GRAFANA_USER 2> /dev/null + action $"Starting $DESC: ..." su -s /bin/sh -c "nohup ${DAEMON} ${DAEMON_OPTS} >> /dev/null 3>&1 &" $GRAFANA_USER 2> /dev/null return=$? if [ $return -eq 0 ] then @@ -114,26 +112,25 @@ case "$1" in done fi - echo "OK" exit $return ;; stop) - echo -n "Stopping $DESC ..." + echo -n "Stopping $DESC: ..." if [ -f "$PID_FILE" ]; then killproc -p $PID_FILE -d 20 $NAME if [ $? -eq 1 ]; then - echo -n "$DESC is not running but pid file exists, cleaning up" + echo "$DESC is not running but pid file exists, cleaning up" elif [ $? -eq 3 ]; then PID="`cat $PID_FILE`" - echo -n "Failed to stop $DESC (pid $PID)" + echo "Failed to stop $DESC (pid $PID)" exit 1 fi rm -f "$PID_FILE" - echo "OK" + echo "" exit 0 else - echo -n "(not running)" + echo "(not running)" fi exit 0 ;; diff --git a/packaging/rpm/systemd/grafana-server.service b/packaging/rpm/systemd/grafana-server.service index d79c5987576..ec0ef7e804e 100644 --- a/packaging/rpm/systemd/grafana-server.service +++ b/packaging/rpm/systemd/grafana-server.service @@ -1,5 +1,5 @@ [Unit] -Description=Starts and stops a single grafana instance on this system +Description=Grafana instance Documentation=http://docs.grafana.org Wants=network-online.target After=network-online.target diff --git a/pkg/api/alerting.go b/pkg/api/alerting.go new file mode 100644 index 00000000000..143c72106fe --- /dev/null +++ b/pkg/api/alerting.go @@ -0,0 +1,316 @@ +package api + +import ( + "fmt" + + "github.com/grafana/grafana/pkg/api/dtos" + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/middleware" + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/alerting" +) + +func ValidateOrgAlert(c *middleware.Context) { + id := c.ParamsInt64(":alertId") + query := models.GetAlertByIdQuery{Id: id} + + if err := bus.Dispatch(&query); err != nil { + c.JsonApiErr(404, "Alert not found", nil) + return + } + + if c.OrgId != query.Result.OrgId { + c.JsonApiErr(403, "You are not allowed to edit/view alert", nil) + return + } +} + +func GetAlertStatesForDashboard(c *middleware.Context) Response { + dashboardId := c.QueryInt64("dashboardId") + + if dashboardId == 0 { + return ApiError(400, "Missing query parameter dashboardId", nil) + } + + query := models.GetAlertStatesForDashboardQuery{ + OrgId: c.OrgId, + DashboardId: c.QueryInt64("dashboardId"), + } + + if err := bus.Dispatch(&query); err != nil { + return ApiError(500, "Failed to fetch alert states", err) + } + + return Json(200, query.Result) +} + +// GET /api/alerts +func GetAlerts(c *middleware.Context) Response { + query := models.GetAlertsQuery{ + OrgId: c.OrgId, + DashboardId: c.QueryInt64("dashboardId"), + PanelId: c.QueryInt64("panelId"), + Limit: c.QueryInt64("limit"), + } + + states := c.QueryStrings("state") + if len(states) > 0 { + query.State = states + } + + if err := bus.Dispatch(&query); err != nil { + return ApiError(500, "List alerts failed", err) + } + + dashboardIds := make([]int64, 0) + alertDTOs := make([]*dtos.AlertRule, 0) + for _, alert := range query.Result { + dashboardIds = append(dashboardIds, alert.DashboardId) + alertDTOs = append(alertDTOs, &dtos.AlertRule{ + Id: alert.Id, + DashboardId: alert.DashboardId, + PanelId: alert.PanelId, + Name: alert.Name, + Message: alert.Message, + State: alert.State, + NewStateDate: alert.NewStateDate, + ExecutionError: alert.ExecutionError, + }) + } + + dashboardsQuery := models.GetDashboardsQuery{ + DashboardIds: dashboardIds, + } + + if len(alertDTOs) > 0 { + if err := bus.Dispatch(&dashboardsQuery); err != nil { + return ApiError(500, "List alerts failed", err) + } + } + + //TODO: should be possible to speed this up with lookup table + for _, alert := range alertDTOs { + for _, dash := range dashboardsQuery.Result { + if alert.DashboardId == dash.Id { + alert.DashbboardUri = "db/" + dash.Slug + } + } + } + + return Json(200, alertDTOs) +} + +// POST /api/alerts/test +func AlertTest(c *middleware.Context, dto dtos.AlertTestCommand) Response { + if _, idErr := dto.Dashboard.Get("id").Int64(); idErr != nil { + return ApiError(400, "The dashboard needs to be saved at least once before you can test an alert rule", nil) + } + + backendCmd := alerting.AlertTestCommand{ + OrgId: c.OrgId, + Dashboard: dto.Dashboard, + PanelId: dto.PanelId, + } + + if err := bus.Dispatch(&backendCmd); err != nil { + if validationErr, ok := err.(alerting.ValidationError); ok { + return ApiError(422, validationErr.Error(), nil) + } + return ApiError(500, "Failed to test rule", err) + } + + res := backendCmd.Result + + dtoRes := &dtos.AlertTestResult{ + Firing: res.Firing, + ConditionEvals: res.ConditionEvals, + } + + if res.Error != nil { + dtoRes.Error = res.Error.Error() + } + + for _, log := range res.Logs { + dtoRes.Logs = append(dtoRes.Logs, &dtos.AlertTestResultLog{Message: log.Message, Data: log.Data}) + } + for _, match := range res.EvalMatches { + dtoRes.EvalMatches = append(dtoRes.EvalMatches, &dtos.EvalMatch{Metric: match.Metric, Value: match.Value}) + } + + dtoRes.TimeMs = fmt.Sprintf("%1.3fms", res.GetDurationMs()) + + return Json(200, dtoRes) +} + +// GET /api/alerts/:id +func GetAlert(c *middleware.Context) Response { + id := c.ParamsInt64(":alertId") + query := models.GetAlertByIdQuery{Id: id} + + if err := bus.Dispatch(&query); err != nil { + return ApiError(500, "List alerts failed", err) + } + + return Json(200, &query.Result) +} + +// DEL /api/alerts/:id +func DelAlert(c *middleware.Context) Response { + alertId := c.ParamsInt64(":alertId") + + if alertId == 0 { + return ApiError(401, "Failed to parse alertid", nil) + } + + cmd := models.DeleteAlertCommand{AlertId: alertId} + + if err := bus.Dispatch(&cmd); err != nil { + return ApiError(500, "Failed to delete alert", err) + } + + var resp = map[string]interface{}{"alertId": alertId} + return Json(200, resp) +} + +func GetAlertNotifiers(c *middleware.Context) Response { + return Json(200, alerting.GetNotifiers()) +} + +func GetAlertNotifications(c *middleware.Context) Response { + query := &models.GetAllAlertNotificationsQuery{OrgId: c.OrgId} + + if err := bus.Dispatch(query); err != nil { + return ApiError(500, "Failed to get alert notifications", err) + } + + result := make([]*dtos.AlertNotification, 0) + + for _, notification := range query.Result { + result = append(result, &dtos.AlertNotification{ + Id: notification.Id, + Name: notification.Name, + Type: notification.Type, + IsDefault: notification.IsDefault, + Created: notification.Created, + Updated: notification.Updated, + }) + } + + return Json(200, result) +} + +func GetAlertNotificationById(c *middleware.Context) Response { + query := &models.GetAlertNotificationsQuery{ + OrgId: c.OrgId, + Id: c.ParamsInt64("notificationId"), + } + + if err := bus.Dispatch(query); err != nil { + return ApiError(500, "Failed to get alert notifications", err) + } + + return Json(200, query.Result) +} + +func CreateAlertNotification(c *middleware.Context, cmd models.CreateAlertNotificationCommand) Response { + cmd.OrgId = c.OrgId + + if err := bus.Dispatch(&cmd); err != nil { + return ApiError(500, "Failed to create alert notification", err) + } + + return Json(200, cmd.Result) +} + +func UpdateAlertNotification(c *middleware.Context, cmd models.UpdateAlertNotificationCommand) Response { + cmd.OrgId = c.OrgId + + if err := bus.Dispatch(&cmd); err != nil { + return ApiError(500, "Failed to update alert notification", err) + } + + return Json(200, cmd.Result) +} + +func DeleteAlertNotification(c *middleware.Context) Response { + cmd := models.DeleteAlertNotificationCommand{ + OrgId: c.OrgId, + Id: c.ParamsInt64("notificationId"), + } + + if err := bus.Dispatch(&cmd); err != nil { + return ApiError(500, "Failed to delete alert notification", err) + } + + return ApiSuccess("Notification deleted") +} + +//POST /api/alert-notifications/test +func NotificationTest(c *middleware.Context, dto dtos.NotificationTestCommand) Response { + cmd := &alerting.NotificationTestCommand{ + Name: dto.Name, + Type: dto.Type, + Settings: dto.Settings, + } + + if err := bus.Dispatch(cmd); err != nil { + return ApiError(500, "Failed to send alert notifications", err) + } + + return ApiSuccess("Test notification sent") +} + +//POST /api/alerts/:alertId/pause +func PauseAlert(c *middleware.Context, dto dtos.PauseAlertCommand) Response { + alertId := c.ParamsInt64("alertId") + cmd := models.PauseAlertCommand{ + OrgId: c.OrgId, + AlertIds: []int64{alertId}, + Paused: dto.Paused, + } + + if err := bus.Dispatch(&cmd); err != nil { + return ApiError(500, "", err) + } + + var response models.AlertStateType = models.AlertStatePending + pausedState := "un paused" + if cmd.Paused { + response = models.AlertStatePaused + pausedState = "paused" + } + + result := map[string]interface{}{ + "alertId": alertId, + "state": response, + "message": "alert " + pausedState, + } + + return Json(200, result) +} + +//POST /api/admin/pause-all-alerts +func PauseAllAlerts(c *middleware.Context, dto dtos.PauseAllAlertsCommand) Response { + updateCmd := models.PauseAllAlertCommand{ + Paused: dto.Paused, + } + + if err := bus.Dispatch(&updateCmd); err != nil { + return ApiError(500, "Failed to pause alerts", err) + } + + var response models.AlertStateType = models.AlertStatePending + pausedState := "un paused" + if updateCmd.Paused { + response = models.AlertStatePaused + pausedState = "paused" + } + + result := map[string]interface{}{ + "state": response, + "message": "alerts " + pausedState, + "alertsAffected": updateCmd.ResultCount, + } + + return Json(200, result) +} diff --git a/pkg/api/annotations.go b/pkg/api/annotations.go new file mode 100644 index 00000000000..48bf6c327ad --- /dev/null +++ b/pkg/api/annotations.go @@ -0,0 +1,62 @@ +package api + +import ( + "github.com/grafana/grafana/pkg/api/dtos" + "github.com/grafana/grafana/pkg/middleware" + "github.com/grafana/grafana/pkg/services/annotations" +) + +func GetAnnotations(c *middleware.Context) Response { + + query := &annotations.ItemQuery{ + From: c.QueryInt64("from") / 1000, + To: c.QueryInt64("to") / 1000, + Type: annotations.ItemType(c.Query("type")), + OrgId: c.OrgId, + AlertId: c.QueryInt64("alertId"), + DashboardId: c.QueryInt64("dashboardId"), + PanelId: c.QueryInt64("panelId"), + Limit: c.QueryInt64("limit"), + NewState: c.QueryStrings("newState"), + } + + repo := annotations.GetRepository() + + items, err := repo.Find(query) + if err != nil { + return ApiError(500, "Failed to get annotations", err) + } + + result := make([]dtos.Annotation, 0) + + for _, item := range items { + result = append(result, dtos.Annotation{ + AlertId: item.AlertId, + Time: item.Epoch * 1000, + Data: item.Data, + NewState: item.NewState, + PrevState: item.PrevState, + Text: item.Text, + Metric: item.Metric, + Title: item.Title, + }) + } + + return Json(200, result) +} + +func DeleteAnnotations(c *middleware.Context, cmd dtos.DeleteAnnotationsCmd) Response { + repo := annotations.GetRepository() + + err := repo.Delete(&annotations.DeleteParams{ + AlertId: cmd.PanelId, + DashboardId: cmd.DashboardId, + PanelId: cmd.PanelId, + }) + + if err != nil { + return ApiError(500, "Failed to delete annotations", err) + } + + return ApiSuccess("Annotations deleted") +} diff --git a/pkg/api/api.go b/pkg/api/api.go index 23a65c6a972..ef550838c56 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -19,6 +19,9 @@ func Register(r *macaron.Macaron) { quota := middleware.Quota bind := binding.Bind + // automatically set HEAD for every GET + r.SetAutoHead(true) + // not logged in views r.Get("/", reqSignedIn, Index) r.Get("/logout", Logout) @@ -29,9 +32,12 @@ func Register(r *macaron.Macaron) { // authed views r.Get("/profile/", reqSignedIn, Index) + r.Get("/profile/password", reqSignedIn, Index) + r.Get("/profile/switch-org/:id", reqSignedIn, ChangeActiveOrgAndRedirectToHome) r.Get("/org/", reqSignedIn, Index) r.Get("/org/new", reqSignedIn, Index) r.Get("/datasources/", reqSignedIn, Index) + r.Get("/datasources/new", reqSignedIn, Index) r.Get("/datasources/edit/*", reqSignedIn, Index) r.Get("/org/users/", reqSignedIn, Index) r.Get("/org/apikeys/", reqSignedIn, Index) @@ -52,10 +58,15 @@ func Register(r *macaron.Macaron) { r.Get("/plugins/:id/page/:page", reqSignedIn, Index) r.Get("/dashboard/*", reqSignedIn, Index) + r.Get("/dashboard-solo/snapshot/*", Index) r.Get("/dashboard-solo/*", reqSignedIn, Index) + r.Get("/import/dashboard", reqSignedIn, Index) + r.Get("/dashboards/*", reqSignedIn, Index) r.Get("/playlists/", reqSignedIn, Index) r.Get("/playlists/*", reqSignedIn, Index) + r.Get("/alerting/", reqSignedIn, Index) + r.Get("/alerting/*", reqSignedIn, Index) // sign up r.Get("/signup", Index) @@ -96,10 +107,18 @@ func Register(r *macaron.Macaron) { r.Put("/", bind(m.UpdateUserCommand{}), wrap(UpdateSignedInUser)) r.Post("/using/:id", wrap(UserSetUsingOrg)) r.Get("/orgs", wrap(GetSignedInUserOrgList)) + r.Post("/stars/dashboard/:id", wrap(StarDashboard)) r.Delete("/stars/dashboard/:id", wrap(UnstarDashboard)) + r.Put("/password", bind(m.ChangeUserPasswordCommand{}), wrap(ChangeUserPassword)) r.Get("/quotas", wrap(GetUserQuotas)) + r.Put("/helpflags/:id", wrap(SetHelpFlag)) + // For dev purpose + r.Get("/helpflags/clear", wrap(ClearHelpFlags)) + + r.Get("/preferences", wrap(GetUserPreferences)) + r.Put("/preferences", bind(dtos.UpdatePrefsCmd{}), wrap(UpdateUserPreferences)) }) // users (admin permission required) @@ -108,6 +127,7 @@ func Register(r *macaron.Macaron) { r.Get("/:id", wrap(GetUserById)) r.Get("/:id/orgs", wrap(GetUserOrgList)) r.Put("/:id", bind(m.UpdateUserCommand{}), wrap(UpdateUser)) + r.Post("/:id/using/:orgId", wrap(UpdateUserActiveOrg)) }, reqGrafanaAdmin) // org information available to all users. @@ -130,6 +150,9 @@ func Register(r *macaron.Macaron) { r.Post("/invites", quota("user"), bind(dtos.AddInviteForm{}), wrap(AddOrgInvite)) r.Patch("/invites/:code/revoke", wrap(RevokeInvite)) + // prefs + r.Get("/preferences", wrap(GetOrgPreferences)) + r.Put("/preferences", bind(dtos.UpdatePrefsCmd{}), wrap(UpdateOrgPreferences)) }, reqOrgAdmin) // create new org @@ -164,11 +187,16 @@ func Register(r *macaron.Macaron) { r.Delete("/:id", wrap(DeleteApiKey)) }, reqOrgAdmin) + // Preferences + r.Group("/preferences", func() { + r.Post("/set-home-dash", bind(m.SavePreferencesCommand{}), wrap(SetHomeDashboard)) + }) + // Data sources r.Group("/datasources", func() { r.Get("/", GetDataSources) r.Post("/", quota("data_source"), bind(m.AddDataSourceCommand{}), AddDataSource) - r.Put("/:id", bind(m.UpdateDataSourceCommand{}), UpdateDataSource) + r.Put("/:id", bind(m.UpdateDataSourceCommand{}), wrap(UpdateDataSource)) r.Delete("/:id", DeleteDataSource) r.Get("/:id", wrap(GetDataSourceById)) r.Get("/name/:name", wrap(GetDataSourceByName)) @@ -176,12 +204,12 @@ func Register(r *macaron.Macaron) { r.Get("/datasources/id/:name", wrap(GetDataSourceIdByName), reqSignedIn) - r.Group("/plugins", func() { - r.Get("/", wrap(GetPluginList)) + r.Get("/plugins", wrap(GetPluginList)) + r.Get("/plugins/:pluginId/settings", wrap(GetPluginSettingById)) + r.Get("/plugins/:pluginId/readme", wrap(GetPluginReadme)) - r.Get("/:pluginId/readme", wrap(GetPluginReadme)) + r.Group("/plugins", func() { r.Get("/:pluginId/dashboards/", wrap(GetPluginDashboards)) - r.Get("/:pluginId/settings", wrap(GetPluginSettingById)) r.Post("/:pluginId/settings", bind(m.UpdatePluginSettingCmd{}), wrap(UpdatePluginSetting)) }, reqOrgAdmin) @@ -192,9 +220,9 @@ func Register(r *macaron.Macaron) { // Dashboard r.Group("/dashboards", func() { r.Combo("/db/:slug").Get(GetDashboard).Delete(DeleteDashboard) - r.Post("/db", reqEditorRole, bind(m.SaveDashboardCommand{}), PostDashboard) + r.Post("/db", reqEditorRole, bind(m.SaveDashboardCommand{}), wrap(PostDashboard)) r.Get("/file/:file", GetDashboardFromJsonFile) - r.Get("/home", GetHomeDashboard) + r.Get("/home", wrap(GetHomeDashboard)) r.Get("/tags", GetDashboardTags) r.Post("/import", bind(dtos.ImportDashboardCommand{}), wrap(ImportDashboard)) }) @@ -219,7 +247,36 @@ func Register(r *macaron.Macaron) { r.Get("/search/", Search) // metrics - r.Get("/metrics/test", GetTestMetrics) + r.Post("/tsdb/query", bind(dtos.MetricRequest{}), wrap(QueryMetrics)) + r.Get("/tsdb/testdata/scenarios", wrap(GetTestDataScenarios)) + + // metrics + r.Get("/metrics", wrap(GetInternalMetrics)) + + r.Group("/alerts", func() { + r.Post("/test", bind(dtos.AlertTestCommand{}), wrap(AlertTest)) + r.Post("/:alertId/pause", bind(dtos.PauseAlertCommand{}), wrap(PauseAlert), reqEditorRole) + r.Get("/:alertId", ValidateOrgAlert, wrap(GetAlert)) + r.Get("/", wrap(GetAlerts)) + r.Get("/states-for-dashboard", wrap(GetAlertStatesForDashboard)) + }) + + r.Get("/alert-notifications", wrap(GetAlertNotifications)) + r.Get("/alert-notifiers", wrap(GetAlertNotifiers)) + + r.Group("/alert-notifications", func() { + r.Post("/test", bind(dtos.NotificationTestCommand{}), wrap(NotificationTest)) + r.Post("/", bind(m.CreateAlertNotificationCommand{}), wrap(CreateAlertNotification)) + r.Put("/:notificationId", bind(m.UpdateAlertNotificationCommand{}), wrap(UpdateAlertNotification)) + r.Get("/:notificationId", wrap(GetAlertNotificationById)) + r.Delete("/:notificationId", wrap(DeleteAlertNotification)) + }, reqEditorRole) + + r.Get("/annotations", wrap(GetAnnotations)) + r.Post("/annotations/mass-delete", reqOrgAdmin, bind(dtos.DeleteAnnotationsCmd{}), wrap(DeleteAnnotations)) + + // error test + r.Get("/metrics/error", wrap(GenerateError)) }, reqSignedIn) @@ -233,11 +290,15 @@ func Register(r *macaron.Macaron) { r.Get("/users/:id/quotas", wrap(GetUserQuotas)) r.Put("/users/:id/quotas/:target", bind(m.UpdateUserQuotaCmd{}), wrap(UpdateUserQuota)) r.Get("/stats", AdminGetStats) + r.Post("/pause-all-alerts", bind(dtos.PauseAllAlertsCommand{}), wrap(PauseAllAlerts)) }, reqGrafanaAdmin) // rendering r.Get("/render/*", reqSignedIn, RenderToPng) + // grafana.net proxy + r.Any("/api/gnet/*", reqSignedIn, ProxyGnetRequest) + // Gravatar service. avt := avatar.CacheServer() r.Get("/avatar/:hash", avt.ServeHTTP) @@ -251,4 +312,5 @@ func Register(r *macaron.Macaron) { InitAppPluginRoutes(r) + r.NotFound(NotFoundHandler) } diff --git a/pkg/api/app_routes.go b/pkg/api/app_routes.go index 5796f09bb21..aee67ac8478 100644 --- a/pkg/api/app_routes.go +++ b/pkg/api/app_routes.go @@ -1,6 +1,11 @@ package api import ( + "crypto/tls" + "net" + "net/http" + "time" + "gopkg.in/macaron.v1" "github.com/grafana/grafana/pkg/api/pluginproxy" @@ -11,6 +16,16 @@ import ( "github.com/grafana/grafana/pkg/util" ) +var pluginProxyTransport = &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + Proxy: http.ProxyFromEnvironment, + Dial: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + }).Dial, + TLSHandshakeTimeout: 10 * time.Second, +} + func InitAppPluginRoutes(r *macaron.Macaron) { for _, plugin := range plugins.Apps { for _, route := range plugin.Routes { @@ -30,7 +45,7 @@ func InitAppPluginRoutes(r *macaron.Macaron) { } handlers = append(handlers, AppPluginRoute(route, plugin.Id)) r.Route(url, route.Method, handlers...) - log.Info("Plugins: Adding proxy route %s", url) + log.Debug("Plugins: Adding proxy route %s", url) } } } @@ -40,7 +55,7 @@ func AppPluginRoute(route *plugins.AppPluginRoute, appId string) macaron.Handler path := c.Params("*") proxy := pluginproxy.NewApiPluginProxy(c, path, route, appId) - proxy.Transport = dataProxyTransport + proxy.Transport = pluginProxyTransport proxy.ServeHTTP(c.Resp, c.Req.Request) } } diff --git a/pkg/api/avatar/avatar.go b/pkg/api/avatar/avatar.go index 79aebece349..41ce857db4f 100644 --- a/pkg/api/avatar/avatar.go +++ b/pkg/api/avatar/avatar.go @@ -116,6 +116,7 @@ func (this *service) ServeHTTP(w http.ResponseWriter, r *http.Request) { if avatar.Expired() { if err := avatar.Update(); err != nil { log.Trace("avatar update error: %v", err) + avatar = this.notFound } } diff --git a/pkg/api/cloudwatch/cloudwatch.go b/pkg/api/cloudwatch/cloudwatch.go index 88d22800d65..1b796be874e 100644 --- a/pkg/api/cloudwatch/cloudwatch.go +++ b/pkg/api/cloudwatch/cloudwatch.go @@ -4,6 +4,8 @@ import ( "encoding/json" "errors" "io/ioutil" + "strings" + "sync" "time" "github.com/aws/aws-sdk-go/aws" @@ -14,6 +16,8 @@ import ( "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/cloudwatch" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go/service/sts" + "github.com/grafana/grafana/pkg/metrics" "github.com/grafana/grafana/pkg/middleware" m "github.com/grafana/grafana/pkg/models" ) @@ -29,6 +33,39 @@ type cwRequest struct { DataSource *m.DataSource } +type datasourceInfo struct { + Profile string + Region string + AssumeRoleArn string + Namespace string + + AccessKey string + SecretKey string +} + +func (req *cwRequest) GetDatasourceInfo() *datasourceInfo { + assumeRoleArn := req.DataSource.JsonData.Get("assumeRoleArn").MustString() + accessKey := "" + secretKey := "" + + for key, value := range req.DataSource.SecureJsonData.Decrypt() { + if key == "accessKey" { + accessKey = value + } + if key == "secretKey" { + secretKey = value + } + } + + return &datasourceInfo{ + AssumeRoleArn: assumeRoleArn, + Region: req.Region, + Profile: req.DataSource.Database, + AccessKey: accessKey, + SecretKey: secretKey, + } +} + func init() { actionHandlers = map[string]actionHandler{ "GetMetricStatistics": handleGetMetricStatistics, @@ -44,42 +81,122 @@ func init() { } } -var awsCredentials map[string]*credentials.Credentials = make(map[string]*credentials.Credentials) +type cache struct { + credential *credentials.Credentials + expiration *time.Time +} -func getCredentials(profile string) *credentials.Credentials { - if _, ok := awsCredentials[profile]; ok { - return awsCredentials[profile] +var awsCredentialCache map[string]cache = make(map[string]cache) +var credentialCacheLock sync.RWMutex + +func getCredentials(dsInfo *datasourceInfo) (*credentials.Credentials, error) { + cacheKey := dsInfo.Profile + ":" + dsInfo.AssumeRoleArn + credentialCacheLock.RLock() + if _, ok := awsCredentialCache[cacheKey]; ok { + if awsCredentialCache[cacheKey].expiration != nil && + (*awsCredentialCache[cacheKey].expiration).After(time.Now().UTC()) { + result := awsCredentialCache[cacheKey].credential + credentialCacheLock.RUnlock() + return result, nil + } + } + credentialCacheLock.RUnlock() + + accessKeyId := "" + secretAccessKey := "" + sessionToken := "" + var expiration *time.Time + expiration = nil + if strings.Index(dsInfo.AssumeRoleArn, "arn:aws:iam:") == 0 { + params := &sts.AssumeRoleInput{ + RoleArn: aws.String(dsInfo.AssumeRoleArn), + RoleSessionName: aws.String("GrafanaSession"), + DurationSeconds: aws.Int64(900), + } + + stsSess := session.New() + stsCreds := credentials.NewChainCredentials( + []credentials.Provider{ + &credentials.EnvProvider{}, + &credentials.SharedCredentialsProvider{Filename: "", Profile: dsInfo.Profile}, + &ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(stsSess), ExpiryWindow: 5 * time.Minute}, + }) + stsConfig := &aws.Config{ + Region: aws.String(dsInfo.Region), + Credentials: stsCreds, + } + + svc := sts.New(session.New(stsConfig), stsConfig) + resp, err := svc.AssumeRole(params) + if err != nil { + return nil, err + } + if resp.Credentials != nil { + accessKeyId = *resp.Credentials.AccessKeyId + secretAccessKey = *resp.Credentials.SecretAccessKey + sessionToken = *resp.Credentials.SessionToken + expiration = resp.Credentials.Expiration + } } sess := session.New() creds := credentials.NewChainCredentials( []credentials.Provider{ + &credentials.StaticProvider{Value: credentials.Value{ + AccessKeyID: accessKeyId, + SecretAccessKey: secretAccessKey, + SessionToken: sessionToken, + }}, &credentials.EnvProvider{}, - &credentials.SharedCredentialsProvider{Filename: "", Profile: profile}, + &credentials.StaticProvider{Value: credentials.Value{ + AccessKeyID: dsInfo.AccessKey, + SecretAccessKey: dsInfo.SecretKey, + }}, + &credentials.SharedCredentialsProvider{Filename: "", Profile: dsInfo.Profile}, &ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute}, }) - awsCredentials[profile] = creds - return creds + credentialCacheLock.Lock() + awsCredentialCache[cacheKey] = cache{ + credential: creds, + expiration: expiration, + } + credentialCacheLock.Unlock() + + return creds, nil +} + +func getAwsConfig(req *cwRequest) (*aws.Config, error) { + creds, err := getCredentials(req.GetDatasourceInfo()) + if err != nil { + return nil, err + } + + cfg := &aws.Config{ + Region: aws.String(req.Region), + Credentials: creds, + } + return cfg, nil } func handleGetMetricStatistics(req *cwRequest, c *middleware.Context) { - cfg := &aws.Config{ - Region: aws.String(req.Region), - Credentials: getCredentials(req.DataSource.Database), + cfg, err := getAwsConfig(req) + if err != nil { + c.JsonApiErr(500, "Unable to call AWS API", err) + return } - svc := cloudwatch.New(session.New(cfg), cfg) reqParam := &struct { Parameters struct { - Namespace string `json:"namespace"` - MetricName string `json:"metricName"` - Dimensions []*cloudwatch.Dimension `json:"dimensions"` - Statistics []*string `json:"statistics"` - StartTime int64 `json:"startTime"` - EndTime int64 `json:"endTime"` - Period int64 `json:"period"` + Namespace string `json:"namespace"` + MetricName string `json:"metricName"` + Dimensions []*cloudwatch.Dimension `json:"dimensions"` + Statistics []*string `json:"statistics"` + ExtendedStatistics []*string `json:"extendedStatistics"` + StartTime int64 `json:"startTime"` + EndTime int64 `json:"endTime"` + Period int64 `json:"period"` } `json:"parameters"` }{} json.Unmarshal(req.Body, reqParam) @@ -88,27 +205,33 @@ func handleGetMetricStatistics(req *cwRequest, c *middleware.Context) { Namespace: aws.String(reqParam.Parameters.Namespace), MetricName: aws.String(reqParam.Parameters.MetricName), Dimensions: reqParam.Parameters.Dimensions, - Statistics: reqParam.Parameters.Statistics, StartTime: aws.Time(time.Unix(reqParam.Parameters.StartTime, 0)), EndTime: aws.Time(time.Unix(reqParam.Parameters.EndTime, 0)), Period: aws.Int64(reqParam.Parameters.Period), } + if len(reqParam.Parameters.Statistics) != 0 { + params.Statistics = reqParam.Parameters.Statistics + } + if len(reqParam.Parameters.ExtendedStatistics) != 0 { + params.ExtendedStatistics = reqParam.Parameters.ExtendedStatistics + } resp, err := svc.GetMetricStatistics(params) if err != nil { c.JsonApiErr(500, "Unable to call AWS API", err) return } + metrics.M_Aws_CloudWatch_GetMetricStatistics.Inc(1) c.JSON(200, resp) } func handleListMetrics(req *cwRequest, c *middleware.Context) { - cfg := &aws.Config{ - Region: aws.String(req.Region), - Credentials: getCredentials(req.DataSource.Database), + cfg, err := getAwsConfig(req) + if err != nil { + c.JsonApiErr(500, "Unable to call AWS API", err) + return } - svc := cloudwatch.New(session.New(cfg), cfg) reqParam := &struct { @@ -127,8 +250,9 @@ func handleListMetrics(req *cwRequest, c *middleware.Context) { } var resp cloudwatch.ListMetricsOutput - err := svc.ListMetricsPages(params, + err = svc.ListMetricsPages(params, func(page *cloudwatch.ListMetricsOutput, lastPage bool) bool { + metrics.M_Aws_CloudWatch_ListMetrics.Inc(1) metrics, _ := awsutil.ValuesAtPath(page, "Metrics") for _, metric := range metrics { resp.Metrics = append(resp.Metrics, metric.(*cloudwatch.Metric)) @@ -144,11 +268,11 @@ func handleListMetrics(req *cwRequest, c *middleware.Context) { } func handleDescribeAlarms(req *cwRequest, c *middleware.Context) { - cfg := &aws.Config{ - Region: aws.String(req.Region), - Credentials: getCredentials(req.DataSource.Database), + cfg, err := getAwsConfig(req) + if err != nil { + c.JsonApiErr(500, "Unable to call AWS API", err) + return } - svc := cloudwatch.New(session.New(cfg), cfg) reqParam := &struct { @@ -187,20 +311,21 @@ func handleDescribeAlarms(req *cwRequest, c *middleware.Context) { } func handleDescribeAlarmsForMetric(req *cwRequest, c *middleware.Context) { - cfg := &aws.Config{ - Region: aws.String(req.Region), - Credentials: getCredentials(req.DataSource.Database), + cfg, err := getAwsConfig(req) + if err != nil { + c.JsonApiErr(500, "Unable to call AWS API", err) + return } - svc := cloudwatch.New(session.New(cfg), cfg) reqParam := &struct { Parameters struct { - Namespace string `json:"namespace"` - MetricName string `json:"metricName"` - Dimensions []*cloudwatch.Dimension `json:"dimensions"` - Statistic string `json:"statistic"` - Period int64 `json:"period"` + Namespace string `json:"namespace"` + MetricName string `json:"metricName"` + Dimensions []*cloudwatch.Dimension `json:"dimensions"` + Statistic string `json:"statistic"` + ExtendedStatistic string `json:"extendedStatistic"` + Period int64 `json:"period"` } `json:"parameters"` }{} json.Unmarshal(req.Body, reqParam) @@ -216,6 +341,9 @@ func handleDescribeAlarmsForMetric(req *cwRequest, c *middleware.Context) { if reqParam.Parameters.Statistic != "" { params.Statistic = aws.String(reqParam.Parameters.Statistic) } + if reqParam.Parameters.ExtendedStatistic != "" { + params.ExtendedStatistic = aws.String(reqParam.Parameters.ExtendedStatistic) + } resp, err := svc.DescribeAlarmsForMetric(params) if err != nil { @@ -227,11 +355,11 @@ func handleDescribeAlarmsForMetric(req *cwRequest, c *middleware.Context) { } func handleDescribeAlarmHistory(req *cwRequest, c *middleware.Context) { - cfg := &aws.Config{ - Region: aws.String(req.Region), - Credentials: getCredentials(req.DataSource.Database), + cfg, err := getAwsConfig(req) + if err != nil { + c.JsonApiErr(500, "Unable to call AWS API", err) + return } - svc := cloudwatch.New(session.New(cfg), cfg) reqParam := &struct { @@ -263,11 +391,11 @@ func handleDescribeAlarmHistory(req *cwRequest, c *middleware.Context) { } func handleDescribeInstances(req *cwRequest, c *middleware.Context) { - cfg := &aws.Config{ - Region: aws.String(req.Region), - Credentials: getCredentials(req.DataSource.Database), + cfg, err := getAwsConfig(req) + if err != nil { + c.JsonApiErr(500, "Unable to call AWS API", err) + return } - svc := ec2.New(session.New(cfg), cfg) reqParam := &struct { @@ -287,7 +415,7 @@ func handleDescribeInstances(req *cwRequest, c *middleware.Context) { } var resp ec2.DescribeInstancesOutput - err := svc.DescribeInstancesPages(params, + err = svc.DescribeInstancesPages(params, func(page *ec2.DescribeInstancesOutput, lastPage bool) bool { reservations, _ := awsutil.ValuesAtPath(page, "Reservations") for _, reservation := range reservations { diff --git a/pkg/api/cloudwatch/metrics.go b/pkg/api/cloudwatch/metrics.go index f5e5274a202..26c5c2cc3ec 100644 --- a/pkg/api/cloudwatch/metrics.go +++ b/pkg/api/cloudwatch/metrics.go @@ -11,6 +11,7 @@ import ( "github.com/aws/aws-sdk-go/aws/awsutil" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/cloudwatch" + "github.com/grafana/grafana/pkg/metrics" "github.com/grafana/grafana/pkg/middleware" "github.com/grafana/grafana/pkg/util" ) @@ -28,12 +29,19 @@ var customMetricsDimensionsMap map[string]map[string]map[string]*CustomMetricsCa func init() { metricsMap = map[string][]string{ - "AWS/AutoScaling": {"GroupMinSize", "GroupMaxSize", "GroupDesiredCapacity", "GroupInServiceInstances", "GroupPendingInstances", "GroupStandbyInstances", "GroupTerminatingInstances", "GroupTotalInstances"}, - "AWS/Billing": {"EstimatedCharges"}, - "AWS/CloudFront": {"Requests", "BytesDownloaded", "BytesUploaded", "TotalErrorRate", "4xxErrorRate", "5xxErrorRate"}, - "AWS/CloudSearch": {"SuccessfulRequests", "SearchableDocuments", "IndexUtilization", "Partitions"}, - "AWS/DynamoDB": {"ConditionalCheckFailedRequests", "ConsumedReadCapacityUnits", "ConsumedWriteCapacityUnits", "OnlineIndexConsumedWriteCapacity", "OnlineIndexPercentageProgress", "OnlineIndexThrottleEvents", "ProvisionedReadCapacityUnits", "ProvisionedWriteCapacityUnits", "ReadThrottleEvents", "ReturnedItemCount", "SuccessfulRequestLatency", "SystemErrors", "ThrottledRequests", "UserErrors", "WriteThrottleEvents"}, - "AWS/ECS": {"CPUUtilization", "MemoryUtilization"}, + "AWS/ApiGateway": {"4XXError", "5XXError", "CacheHitCount", "CacheMissCount", "Count", "IntegrationLatency", "Latency"}, + "AWS/ApplicationELB": {"ActiveConnectionCount", "ClientTLSNegotiationErrorCount", "HealthyHostCount", "HTTPCode_ELB_4XX_Count", "HTTPCode_ELB_5XX_Count", "HTTPCode_Target_2XX_Count", "HTTPCode_Target_3XX_Count", "HTTPCode_Target_4XX_Count", "HTTPCode_Target_5XX_Count", "NewConnectionCount", "ProcessedBytes", "RejectedConnectionCount", "RequestCount", "TargetConnectionErrorCount", "TargetResponseTime", "TargetTLSNegotiationErrorCount", "UnHealthyHostCount"}, + "AWS/AutoScaling": {"GroupMinSize", "GroupMaxSize", "GroupDesiredCapacity", "GroupInServiceInstances", "GroupPendingInstances", "GroupStandbyInstances", "GroupTerminatingInstances", "GroupTotalInstances"}, + "AWS/Billing": {"EstimatedCharges"}, + "AWS/CloudFront": {"Requests", "BytesDownloaded", "BytesUploaded", "TotalErrorRate", "4xxErrorRate", "5xxErrorRate"}, + "AWS/CloudSearch": {"SuccessfulRequests", "SearchableDocuments", "IndexUtilization", "Partitions"}, + "AWS/DynamoDB": {"ConditionalCheckFailedRequests", "ConsumedReadCapacityUnits", "ConsumedWriteCapacityUnits", "OnlineIndexConsumedWriteCapacity", "OnlineIndexPercentageProgress", "OnlineIndexThrottleEvents", "ProvisionedReadCapacityUnits", "ProvisionedWriteCapacityUnits", "ReadThrottleEvents", "ReturnedBytes", "ReturnedItemCount", "ReturnedRecordsCount", "SuccessfulRequestLatency", "SystemErrors", "ThrottledRequests", "UserErrors", "WriteThrottleEvents"}, + "AWS/EBS": {"VolumeReadBytes", "VolumeWriteBytes", "VolumeReadOps", "VolumeWriteOps", "VolumeTotalReadTime", "VolumeTotalWriteTime", "VolumeIdleTime", "VolumeQueueLength", "VolumeThroughputPercentage", "VolumeConsumedReadWriteOps", "BurstBalance"}, + "AWS/EC2": {"CPUCreditUsage", "CPUCreditBalance", "CPUUtilization", "DiskReadOps", "DiskWriteOps", "DiskReadBytes", "DiskWriteBytes", "NetworkIn", "NetworkOut", "NetworkPacketsIn", "NetworkPacketsOut", "StatusCheckFailed", "StatusCheckFailed_Instance", "StatusCheckFailed_System"}, + "AWS/EC2Spot": {"AvailableInstancePoolsCount", "BidsSubmittedForCapacity", "EligibleInstancePoolCount", "FulfilledCapacity", "MaxPercentCapacityAllocation", "PendingCapacity", "PercentCapacityAllocation", "TargetCapacity", "TerminatingCapacity"}, + "AWS/ECS": {"CPUReservation", "MemoryReservation", "CPUUtilization", "MemoryUtilization"}, + "AWS/EFS": {"BurstCreditBalance", "ClientConnections", "DataReadIOBytes", "DataWriteIOBytes", "MetadataIOBytes", "TotalIOBytes", "PermittedThroughput", "PercentIOLimit"}, + "AWS/ELB": {"HealthyHostCount", "UnHealthyHostCount", "RequestCount", "Latency", "HTTPCode_ELB_4XX", "HTTPCode_ELB_5XX", "HTTPCode_Backend_2XX", "HTTPCode_Backend_3XX", "HTTPCode_Backend_4XX", "HTTPCode_Backend_5XX", "BackendConnectionErrors", "SurgeQueueLength", "SpilloverCount"}, "AWS/ElastiCache": { "CPUUtilization", "FreeableMemory", "NetworkBytesIn", "NetworkBytesOut", "SwapUsage", "BytesUsedForCacheItems", "BytesReadIntoMemcached", "BytesWrittenOutFromMemcached", "CasBadval", "CasHits", "CasMisses", "CmdFlush", "CmdGet", "CmdSet", "CurrConnections", "CurrItems", "DecrHits", "DecrMisses", "DeleteHits", "DeleteMisses", "Evictions", "GetHits", "GetMisses", "IncrHits", "IncrMisses", "Reclaimed", @@ -42,9 +50,15 @@ func init() { "BytesUsedForCache", "CacheHits", "CacheMisses", "CurrConnections", "Evictions", "HyperLogLogBasedCmds", "NewConnections", "Reclaimed", "ReplicationBytes", "ReplicationLag", "SaveInProgress", "CurrItems", "GetTypeCmds", "HashBasedCmds", "KeyBasedCmds", "ListBasedCmds", "SetBasedCmds", "SetTypeCmds", "SortedSetBasedCmds", "StringBasedCmds", }, - "AWS/EBS": {"VolumeReadBytes", "VolumeWriteBytes", "VolumeReadOps", "VolumeWriteOps", "VolumeTotalReadTime", "VolumeTotalWriteTime", "VolumeIdleTime", "VolumeQueueLength", "VolumeThroughputPercentage", "VolumeConsumedReadWriteOps"}, - "AWS/EC2": {"CPUCreditUsage", "CPUCreditBalance", "CPUUtilization", "DiskReadOps", "DiskWriteOps", "DiskReadBytes", "DiskWriteBytes", "NetworkIn", "NetworkOut", "StatusCheckFailed", "StatusCheckFailed_Instance", "StatusCheckFailed_System"}, - "AWS/ELB": {"HealthyHostCount", "UnHealthyHostCount", "RequestCount", "Latency", "HTTPCode_ELB_4XX", "HTTPCode_ELB_5XX", "HTTPCode_Backend_2XX", "HTTPCode_Backend_3XX", "HTTPCode_Backend_4XX", "HTTPCode_Backend_5XX", "BackendConnectionErrors", "SurgeQueueLength", "SpilloverCount"}, + "AWS/ElasticBeanstalk": { + "EnvironmentHealth", + "ApplicationLatencyP10", "ApplicationLatencyP50", "ApplicationLatencyP75", "ApplicationLatencyP85", "ApplicationLatencyP90", "ApplicationLatencyP95", "ApplicationLatencyP99", "ApplicationLatencyP99.9", + "ApplicationRequests2xx", "ApplicationRequests3xx", "ApplicationRequests4xx", "ApplicationRequests5xx", "ApplicationRequestsTotal", + "CPUIdle", "CPUIowait", "CPUIrq", "CPUNice", "CPUSoftirq", "CPUSystem", "CPUUser", + "InstanceHealth", "InstancesDegraded", "InstancesInfo", "InstancesNoData", "InstancesOk", "InstancesPending", "InstancesSevere", "InstancesUnknown", "InstancesWarning", + "LoadAverage1min", "LoadAverage5min", + "RootFilesystemUtil", + }, "AWS/ElasticMapReduce": {"IsIdle", "JobsRunning", "JobsFailed", "MapTasksRunning", "MapTasksRemaining", "MapSlotsOpen", "RemainingMapTasksPerSlot", "ReduceTasksRunning", "ReduceTasksRemaining", "ReduceSlotsOpen", "CoreNodesRunning", "CoreNodesPending", "LiveDataNodes", "TaskNodesRunning", "TaskNodesPending", "LiveTaskTrackers", @@ -54,55 +68,68 @@ func init() { "CoreNodesRunning", "CoreNodesPending", "LiveDataNodes", "MRTotalNodes", "MRActiveNodes", "MRLostNodes", "MRUnhealthyNodes", "MRDecommissionedNodes", "MRRebootedNodes", "S3BytesWritten", "S3BytesRead", "HDFSUtilization", "HDFSBytesRead", "HDFSBytesWritten", "MissingBlocks", "CorruptBlocks", "TotalLoad", "MemoryTotalMB", "MemoryReservedMB", "MemoryAvailableMB", "MemoryAllocatedMB", "PendingDeletionBlocks", "UnderReplicatedBlocks", "DfsPendingReplicationBlocks", "CapacityRemainingGB", "HbaseBackupFailed", "MostRecentBackupDuration", "TimeSinceLastSuccessfulBackup"}, - "AWS/ES": {"ClusterStatus.green", "ClusterStatus.yellow", "ClusterStatus.red", "Nodes", "SearchableDocuments", "DeletedDocuments", "CPUUtilization", "FreeStorageSpace", "JVMMemoryPressure", "AutomatedSnapshotFailure", "MasterCPUUtilization", "MasterFreeStorageSpace", "MasterJVMMemoryPressure", "ReadLatency", "WriteLatency", "ReadThroughput", "WriteThroughput", "DiskQueueLength", "ReadIOPS", "WriteIOPS"}, - "AWS/Events": {"Invocations", "FailedInvocations", "TriggeredRules", "MatchedEvents", "ThrottledRules"}, - "AWS/Kinesis": {"PutRecord.Bytes", "PutRecord.Latency", "PutRecord.Success", "PutRecords.Bytes", "PutRecords.Latency", "PutRecords.Records", "PutRecords.Success", "IncomingBytes", "IncomingRecords", "GetRecords.Bytes", "GetRecords.IteratorAgeMilliseconds", "GetRecords.Latency", "GetRecords.Success"}, - "AWS/Lambda": {"Invocations", "Errors", "Duration", "Throttles"}, - "AWS/Logs": {"IncomingBytes", "IncomingLogEvents", "ForwardedBytes", "ForwardedLogEvents", "DeliveryErrors", "DeliveryThrottling"}, - "AWS/ML": {"PredictCount", "PredictFailureCount"}, - "AWS/OpsWorks": {"cpu_idle", "cpu_nice", "cpu_system", "cpu_user", "cpu_waitio", "load_1", "load_5", "load_15", "memory_buffers", "memory_cached", "memory_free", "memory_swap", "memory_total", "memory_used", "procs"}, - "AWS/Redshift": {"CPUUtilization", "DatabaseConnections", "HealthStatus", "MaintenanceMode", "NetworkReceiveThroughput", "NetworkTransmitThroughput", "PercentageDiskSpaceUsed", "ReadIOPS", "ReadLatency", "ReadThroughput", "WriteIOPS", "WriteLatency", "WriteThroughput"}, - "AWS/RDS": {"BinLogDiskUsage", "CPUUtilization", "CPUCreditUsage", "CPUCreditBalance", "DatabaseConnections", "DiskQueueDepth", "FreeableMemory", "FreeStorageSpace", "ReplicaLag", "SwapUsage", "ReadIOPS", "WriteIOPS", "ReadLatency", "WriteLatency", "ReadThroughput", "WriteThroughput", "NetworkReceiveThroughput", "NetworkTransmitThroughput"}, - "AWS/Route53": {"HealthCheckStatus", "HealthCheckPercentageHealthy", "ConnectionTime", "SSLHandshakeTime", "TimeToFirstByte"}, - "AWS/SNS": {"NumberOfMessagesPublished", "PublishSize", "NumberOfNotificationsDelivered", "NumberOfNotificationsFailed"}, - "AWS/SQS": {"NumberOfMessagesSent", "SentMessageSize", "NumberOfMessagesReceived", "NumberOfEmptyReceives", "NumberOfMessagesDeleted", "ApproximateNumberOfMessagesDelayed", "ApproximateNumberOfMessagesVisible", "ApproximateNumberOfMessagesNotVisible"}, - "AWS/S3": {"BucketSizeBytes", "NumberOfObjects"}, - "AWS/SWF": {"DecisionTaskScheduleToStartTime", "DecisionTaskStartToCloseTime", "DecisionTasksCompleted", "StartedDecisionTasksTimedOutOnClose", "WorkflowStartToCloseTime", "WorkflowsCanceled", "WorkflowsCompleted", "WorkflowsContinuedAsNew", "WorkflowsFailed", "WorkflowsTerminated", "WorkflowsTimedOut", - "ActivityTaskScheduleToCloseTime", "ActivityTaskScheduleToStartTime", "ActivityTaskStartToCloseTime", "ActivityTasksCanceled", "ActivityTasksCompleted", "ActivityTasksFailed", "ScheduledActivityTasksTimedOutOnClose", "ScheduledActivityTasksTimedOutOnStart", "StartedActivityTasksTimedOutOnClose", "StartedActivityTasksTimedOutOnHeartbeat"}, + "AWS/ES": {"ClusterStatus.green", "ClusterStatus.yellow", "ClusterStatus.red", "Nodes", "SearchableDocuments", "DeletedDocuments", "CPUUtilization", "FreeStorageSpace", "JVMMemoryPressure", "AutomatedSnapshotFailure", "MasterCPUUtilization", "MasterFreeStorageSpace", "MasterJVMMemoryPressure", "ReadLatency", "WriteLatency", "ReadThroughput", "WriteThroughput", "DiskQueueLength", "ReadIOPS", "WriteIOPS"}, + "AWS/Events": {"Invocations", "FailedInvocations", "TriggeredRules", "MatchedEvents", "ThrottledRules"}, + "AWS/Firehose": {"DeliveryToElasticsearch.Bytes", "DeliveryToElasticsearch.Records", "DeliveryToElasticsearch.Success", "DeliveryToRedshift.Bytes", "DeliveryToRedshift.Records", "DeliveryToRedshift.Success", "DeliveryToS3.Bytes", "DeliveryToS3.DataFreshness", "DeliveryToS3.Records", "DeliveryToS3.Success", "IncomingBytes", "IncomingRecords", "DescribeDeliveryStream.Latency", "DescribeDeliveryStream.Requests", "ListDeliveryStreams.Latency", "ListDeliveryStreams.Requests", "PutRecord.Bytes", "PutRecord.Latency", "PutRecord.Requests", "PutRecordBatch.Bytes", "PutRecordBatch.Latency", "PutRecordBatch.Records", "PutRecordBatch.Requests", "UpdateDeliveryStream.Latency", "UpdateDeliveryStream.Requests"}, + "AWS/IoT": {"PublishIn.Success", "PublishOut.Success", "Subscribe.Success", "Ping.Success", "Connect.Success", "GetThingShadow.Accepted"}, + "AWS/Kinesis": {"GetRecords.Bytes", "GetRecords.IteratorAge", "GetRecords.IteratorAgeMilliseconds", "GetRecords.Latency", "GetRecords.Records", "GetRecords.Success", "IncomingBytes", "IncomingRecords", "PutRecord.Bytes", "PutRecord.Latency", "PutRecord.Success", "PutRecords.Bytes", "PutRecords.Latency", "PutRecords.Records", "PutRecords.Success", "ReadProvisionedThroughputExceeded", "WriteProvisionedThroughputExceeded", "IteratorAgeMilliseconds", "OutgoingBytes", "OutgoingRecords"}, + "AWS/KinesisAnalytics": {"Bytes", "MillisBehindLatest", "Records", "Success"}, + "AWS/Lambda": {"Invocations", "Errors", "Duration", "Throttles"}, + "AWS/Logs": {"IncomingBytes", "IncomingLogEvents", "ForwardedBytes", "ForwardedLogEvents", "DeliveryErrors", "DeliveryThrottling"}, + "AWS/ML": {"PredictCount", "PredictFailureCount"}, + "AWS/OpsWorks": {"cpu_idle", "cpu_nice", "cpu_system", "cpu_user", "cpu_waitio", "load_1", "load_5", "load_15", "memory_buffers", "memory_cached", "memory_free", "memory_swap", "memory_total", "memory_used", "procs"}, + "AWS/Redshift": {"CPUUtilization", "DatabaseConnections", "HealthStatus", "MaintenanceMode", "NetworkReceiveThroughput", "NetworkTransmitThroughput", "PercentageDiskSpaceUsed", "ReadIOPS", "ReadLatency", "ReadThroughput", "WriteIOPS", "WriteLatency", "WriteThroughput"}, + "AWS/RDS": {"ActiveTransactions", "AuroraBinlogReplicaLag", "AuroraReplicaLag", "AuroraReplicaLagMaximum", "AuroraReplicaLagMinimum", "BinLogDiskUsage", "BlockedTransactions", "BufferCacheHitRatio", "CommitLatency", "CommitThroughput", "CPUCreditBalance", "CPUCreditUsage", "CPUUtilization", "DatabaseConnections", "DDLLatency", "DDLThroughput", "Deadlocks", "DiskQueueDepth", "DMLLatency", "DMLThroughput", "FailedSqlStatements", "FreeableMemory", "FreeStorageSpace", "LoginFailures", "NetworkReceiveThroughput", "NetworkTransmitThroughput", "ReadIOPS", "ReadLatency", "ReadThroughput", "ReplicaLag", "ResultSetCacheHitRatio", "SelectLatency", "SelectThroughput", "SwapUsage", "TotalConnections", "VolumeReadIOPS", "VolumeWriteIOPS", "WriteIOPS", "WriteLatency", "WriteThroughput"}, + "AWS/Route53": {"HealthCheckStatus", "HealthCheckPercentageHealthy", "ConnectionTime", "SSLHandshakeTime", "TimeToFirstByte"}, + "AWS/S3": {"BucketSizeBytes", "NumberOfObjects"}, + "AWS/SNS": {"NumberOfMessagesPublished", "PublishSize", "NumberOfNotificationsDelivered", "NumberOfNotificationsFailed"}, + "AWS/SQS": {"NumberOfMessagesSent", "SentMessageSize", "NumberOfMessagesReceived", "NumberOfEmptyReceives", "NumberOfMessagesDeleted", "ApproximateNumberOfMessagesDelayed", "ApproximateNumberOfMessagesVisible", "ApproximateNumberOfMessagesNotVisible"}, "AWS/StorageGateway": {"CacheHitPercent", "CachePercentUsed", "CachePercentDirty", "CloudBytesDownloaded", "CloudDownloadLatency", "CloudBytesUploaded", "UploadBufferFree", "UploadBufferPercentUsed", "UploadBufferUsed", "QueuedWrites", "ReadBytes", "ReadTime", "TotalCacheSize", "WriteBytes", "WriteTime", "TimeSinceLastRecoveryPoint", "WorkingStorageFree", "WorkingStoragePercentUsed", "WorkingStorageUsed", "CacheHitPercent", "CachePercentUsed", "CachePercentDirty", "ReadBytes", "ReadTime", "WriteBytes", "WriteTime", "QueuedWrites"}, + "AWS/SWF": {"DecisionTaskScheduleToStartTime", "DecisionTaskStartToCloseTime", "DecisionTasksCompleted", "StartedDecisionTasksTimedOutOnClose", "WorkflowStartToCloseTime", "WorkflowsCanceled", "WorkflowsCompleted", "WorkflowsContinuedAsNew", "WorkflowsFailed", "WorkflowsTerminated", "WorkflowsTimedOut", + "ActivityTaskScheduleToCloseTime", "ActivityTaskScheduleToStartTime", "ActivityTaskStartToCloseTime", "ActivityTasksCanceled", "ActivityTasksCompleted", "ActivityTasksFailed", "ScheduledActivityTasksTimedOutOnClose", "ScheduledActivityTasksTimedOutOnStart", "StartedActivityTasksTimedOutOnClose", "StartedActivityTasksTimedOutOnHeartbeat"}, "AWS/WAF": {"AllowedRequests", "BlockedRequests", "CountedRequests"}, "AWS/WorkSpaces": {"Available", "Unhealthy", "ConnectionAttempt", "ConnectionSuccess", "ConnectionFailure", "SessionLaunchTime", "InSessionLatency", "SessionDisconnect"}, + "KMS": {"SecondsUntilKeyMaterialExpiration"}, } dimensionsMap = map[string][]string{ + "AWS/ApiGateway": {"ApiName", "Method", "Resource", "Stage"}, + "AWS/ApplicationELB": {"LoadBalancer", "TargetGroup", "AvailabilityZone"}, "AWS/AutoScaling": {"AutoScalingGroupName"}, "AWS/Billing": {"ServiceName", "LinkedAccount", "Currency"}, "AWS/CloudFront": {"DistributionId", "Region"}, "AWS/CloudSearch": {}, - "AWS/DynamoDB": {"TableName", "GlobalSecondaryIndexName", "Operation"}, - "AWS/ECS": {"ClusterName", "ServiceName"}, - "AWS/ElastiCache": {"CacheClusterId", "CacheNodeId"}, + "AWS/DynamoDB": {"TableName", "GlobalSecondaryIndexName", "Operation", "StreamLabel"}, "AWS/EBS": {"VolumeId"}, "AWS/EC2": {"AutoScalingGroupName", "ImageId", "InstanceId", "InstanceType"}, + "AWS/EC2Spot": {"AvailabilityZone", "FleetRequestId", "InstanceType"}, + "AWS/ECS": {"ClusterName", "ServiceName"}, + "AWS/EFS": {"FileSystemId"}, "AWS/ELB": {"LoadBalancerName", "AvailabilityZone"}, + "AWS/ElastiCache": {"CacheClusterId", "CacheNodeId"}, + "AWS/ElasticBeanstalk": {"EnvironmentName", "InstanceId"}, "AWS/ElasticMapReduce": {"ClusterId", "JobFlowId", "JobId"}, - "AWS/ES": {}, + "AWS/ES": {"ClientId", "DomainName"}, "AWS/Events": {"RuleName"}, - "AWS/Kinesis": {"StreamName"}, - "AWS/Lambda": {"FunctionName"}, + "AWS/Firehose": {}, + "AWS/IoT": {"Protocol"}, + "AWS/Kinesis": {"StreamName", "ShardID"}, + "AWS/KinesisAnalytics": {"Flow", "Id", "Application"}, + "AWS/Lambda": {"FunctionName", "Resource", "Version", "Alias"}, "AWS/Logs": {"LogGroupName", "DestinationType", "FilterName"}, "AWS/ML": {"MLModelId", "RequestMode"}, "AWS/OpsWorks": {"StackId", "LayerId", "InstanceId"}, "AWS/Redshift": {"NodeID", "ClusterIdentifier"}, - "AWS/RDS": {"DBInstanceIdentifier", "DatabaseClass", "EngineName"}, + "AWS/RDS": {"DBInstanceIdentifier", "DBClusterIdentifier", "DatabaseClass", "EngineName"}, "AWS/Route53": {"HealthCheckId"}, + "AWS/S3": {"BucketName", "StorageType"}, "AWS/SNS": {"Application", "Platform", "TopicName"}, "AWS/SQS": {"QueueName"}, - "AWS/S3": {"BucketName", "StorageType"}, - "AWS/SWF": {"Domain", "WorkflowTypeName", "WorkflowTypeVersion", "ActivityTypeName", "ActivityTypeVersion"}, "AWS/StorageGateway": {"GatewayId", "GatewayName", "VolumeId"}, + "AWS/SWF": {"Domain", "WorkflowTypeName", "WorkflowTypeVersion", "ActivityTypeName", "ActivityTypeVersion"}, "AWS/WAF": {"Rule", "WebACL"}, "AWS/WorkSpaces": {"DirectoryId", "WorkspaceId"}, + "KMS": {"KeyId"}, } customMetricsMetricsMap = make(map[string]map[string]map[string]*CustomMetricsCache) @@ -113,8 +140,8 @@ func init() { // Please update the region list in public/app/plugins/datasource/cloudwatch/partials/config.html func handleGetRegions(req *cwRequest, c *middleware.Context) { regions := []string{ - "ap-northeast-1", "ap-northeast-2", "ap-southeast-1", "ap-southeast-2", "cn-north-1", - "eu-central-1", "eu-west-1", "sa-east-1", "us-east-1", "us-west-1", "us-west-2", + "ap-northeast-1", "ap-northeast-2", "ap-southeast-1", "ap-southeast-2", "ap-south-1", "ca-central-1", "cn-north-1", + "eu-central-1", "eu-west-1", "eu-west-2", "sa-east-1", "us-east-1", "us-east-2", "us-gov-west-1", "us-west-1", "us-west-2", } result := []interface{}{} @@ -166,7 +193,10 @@ func handleGetMetrics(req *cwRequest, c *middleware.Context) { } } else { var err error - if namespaceMetrics, err = getMetricsForCustomMetrics(req.Region, reqParam.Parameters.Namespace, req.DataSource.Database, getAllMetrics); err != nil { + cwData := req.GetDatasourceInfo() + cwData.Namespace = reqParam.Parameters.Namespace + + if namespaceMetrics, err = getMetricsForCustomMetrics(cwData, getAllMetrics); err != nil { c.JsonApiErr(500, "Unable to call AWS API", err) return } @@ -199,7 +229,10 @@ func handleGetDimensions(req *cwRequest, c *middleware.Context) { } } else { var err error - if dimensionValues, err = getDimensionsForCustomMetrics(req.Region, reqParam.Parameters.Namespace, req.DataSource.Database, getAllMetrics); err != nil { + dsInfo := req.GetDatasourceInfo() + dsInfo.Namespace = reqParam.Parameters.Namespace + + if dimensionValues, err = getDimensionsForCustomMetrics(dsInfo, getAllMetrics); err != nil { c.JsonApiErr(500, "Unable to call AWS API", err) return } @@ -214,21 +247,26 @@ func handleGetDimensions(req *cwRequest, c *middleware.Context) { c.JSON(200, result) } -func getAllMetrics(region string, namespace string, database string) (cloudwatch.ListMetricsOutput, error) { +func getAllMetrics(cwData *datasourceInfo) (cloudwatch.ListMetricsOutput, error) { + creds, err := getCredentials(cwData) + if err != nil { + return cloudwatch.ListMetricsOutput{}, err + } cfg := &aws.Config{ - Region: aws.String(region), - Credentials: getCredentials(database), + Region: aws.String(cwData.Region), + Credentials: creds, } svc := cloudwatch.New(session.New(cfg), cfg) params := &cloudwatch.ListMetricsInput{ - Namespace: aws.String(namespace), + Namespace: aws.String(cwData.Namespace), } var resp cloudwatch.ListMetricsOutput - err := svc.ListMetricsPages(params, + err = svc.ListMetricsPages(params, func(page *cloudwatch.ListMetricsOutput, lastPage bool) bool { + metrics.M_Aws_CloudWatch_ListMetrics.Inc(1) metrics, _ := awsutil.ValuesAtPath(page, "Metrics") for _, metric := range metrics { resp.Metrics = append(resp.Metrics, metric.(*cloudwatch.Metric)) @@ -244,8 +282,8 @@ func getAllMetrics(region string, namespace string, database string) (cloudwatch var metricsCacheLock sync.Mutex -func getMetricsForCustomMetrics(region string, namespace string, database string, getAllMetrics func(string, string, string) (cloudwatch.ListMetricsOutput, error)) ([]string, error) { - result, err := getAllMetrics(region, namespace, database) +func getMetricsForCustomMetrics(dsInfo *datasourceInfo, getAllMetrics func(*datasourceInfo) (cloudwatch.ListMetricsOutput, error)) ([]string, error) { + result, err := getAllMetrics(dsInfo) if err != nil { return []string{}, err } @@ -253,37 +291,37 @@ func getMetricsForCustomMetrics(region string, namespace string, database string metricsCacheLock.Lock() defer metricsCacheLock.Unlock() - if _, ok := customMetricsMetricsMap[database]; !ok { - customMetricsMetricsMap[database] = make(map[string]map[string]*CustomMetricsCache) + if _, ok := customMetricsMetricsMap[dsInfo.Profile]; !ok { + customMetricsMetricsMap[dsInfo.Profile] = make(map[string]map[string]*CustomMetricsCache) } - if _, ok := customMetricsMetricsMap[database][region]; !ok { - customMetricsMetricsMap[database][region] = make(map[string]*CustomMetricsCache) + if _, ok := customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region]; !ok { + customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region] = make(map[string]*CustomMetricsCache) } - if _, ok := customMetricsMetricsMap[database][region][namespace]; !ok { - customMetricsMetricsMap[database][region][namespace] = &CustomMetricsCache{} - customMetricsMetricsMap[database][region][namespace].Cache = make([]string, 0) + if _, ok := customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace]; !ok { + customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace] = &CustomMetricsCache{} + customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = make([]string, 0) } - if customMetricsMetricsMap[database][region][namespace].Expire.After(time.Now()) { - return customMetricsMetricsMap[database][region][namespace].Cache, nil + if customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire.After(time.Now()) { + return customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, nil } - customMetricsMetricsMap[database][region][namespace].Cache = make([]string, 0) - customMetricsMetricsMap[database][region][namespace].Expire = time.Now().Add(5 * time.Minute) + customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = make([]string, 0) + customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire = time.Now().Add(5 * time.Minute) for _, metric := range result.Metrics { - if isDuplicate(customMetricsMetricsMap[database][region][namespace].Cache, *metric.MetricName) { + if isDuplicate(customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, *metric.MetricName) { continue } - customMetricsMetricsMap[database][region][namespace].Cache = append(customMetricsMetricsMap[database][region][namespace].Cache, *metric.MetricName) + customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = append(customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, *metric.MetricName) } - return customMetricsMetricsMap[database][region][namespace].Cache, nil + return customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, nil } var dimensionsCacheLock sync.Mutex -func getDimensionsForCustomMetrics(region string, namespace string, database string, getAllMetrics func(string, string, string) (cloudwatch.ListMetricsOutput, error)) ([]string, error) { - result, err := getAllMetrics(region, namespace, database) +func getDimensionsForCustomMetrics(dsInfo *datasourceInfo, getAllMetrics func(*datasourceInfo) (cloudwatch.ListMetricsOutput, error)) ([]string, error) { + result, err := getAllMetrics(dsInfo) if err != nil { return []string{}, err } @@ -291,33 +329,33 @@ func getDimensionsForCustomMetrics(region string, namespace string, database str dimensionsCacheLock.Lock() defer dimensionsCacheLock.Unlock() - if _, ok := customMetricsDimensionsMap[database]; !ok { - customMetricsDimensionsMap[database] = make(map[string]map[string]*CustomMetricsCache) + if _, ok := customMetricsDimensionsMap[dsInfo.Profile]; !ok { + customMetricsDimensionsMap[dsInfo.Profile] = make(map[string]map[string]*CustomMetricsCache) } - if _, ok := customMetricsDimensionsMap[database][region]; !ok { - customMetricsDimensionsMap[database][region] = make(map[string]*CustomMetricsCache) + if _, ok := customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region]; !ok { + customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region] = make(map[string]*CustomMetricsCache) } - if _, ok := customMetricsDimensionsMap[database][region][namespace]; !ok { - customMetricsDimensionsMap[database][region][namespace] = &CustomMetricsCache{} - customMetricsDimensionsMap[database][region][namespace].Cache = make([]string, 0) + if _, ok := customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace]; !ok { + customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace] = &CustomMetricsCache{} + customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = make([]string, 0) } - if customMetricsDimensionsMap[database][region][namespace].Expire.After(time.Now()) { - return customMetricsDimensionsMap[database][region][namespace].Cache, nil + if customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire.After(time.Now()) { + return customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, nil } - customMetricsDimensionsMap[database][region][namespace].Cache = make([]string, 0) - customMetricsDimensionsMap[database][region][namespace].Expire = time.Now().Add(5 * time.Minute) + customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = make([]string, 0) + customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire = time.Now().Add(5 * time.Minute) for _, metric := range result.Metrics { for _, dimension := range metric.Dimensions { - if isDuplicate(customMetricsDimensionsMap[database][region][namespace].Cache, *dimension.Name) { + if isDuplicate(customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, *dimension.Name) { continue } - customMetricsDimensionsMap[database][region][namespace].Cache = append(customMetricsDimensionsMap[database][region][namespace].Cache, *dimension.Name) + customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = append(customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, *dimension.Name) } } - return customMetricsDimensionsMap[database][region][namespace].Cache, nil + return customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, nil } func isDuplicate(nameList []string, target string) bool { diff --git a/pkg/api/cloudwatch/metrics_test.go b/pkg/api/cloudwatch/metrics_test.go index ec39452e116..4ac8a70a273 100644 --- a/pkg/api/cloudwatch/metrics_test.go +++ b/pkg/api/cloudwatch/metrics_test.go @@ -11,10 +11,13 @@ import ( func TestCloudWatchMetrics(t *testing.T) { Convey("When calling getMetricsForCustomMetrics", t, func() { - region := "us-east-1" - namespace := "Foo" - database := "default" - f := func(region string, namespace string, database string) (cloudwatch.ListMetricsOutput, error) { + dsInfo := &datasourceInfo{ + Region: "us-east-1", + Namespace: "Foo", + Profile: "default", + AssumeRoleArn: "", + } + f := func(dsInfo *datasourceInfo) (cloudwatch.ListMetricsOutput, error) { return cloudwatch.ListMetricsOutput{ Metrics: []*cloudwatch.Metric{ { @@ -28,7 +31,7 @@ func TestCloudWatchMetrics(t *testing.T) { }, }, nil } - metrics, _ := getMetricsForCustomMetrics(region, namespace, database, f) + metrics, _ := getMetricsForCustomMetrics(dsInfo, f) Convey("Should contain Test_MetricName", func() { So(metrics, ShouldContain, "Test_MetricName") @@ -36,10 +39,13 @@ func TestCloudWatchMetrics(t *testing.T) { }) Convey("When calling getDimensionsForCustomMetrics", t, func() { - region := "us-east-1" - namespace := "Foo" - database := "default" - f := func(region string, namespace string, database string) (cloudwatch.ListMetricsOutput, error) { + dsInfo := &datasourceInfo{ + Region: "us-east-1", + Namespace: "Foo", + Profile: "default", + AssumeRoleArn: "", + } + f := func(dsInfo *datasourceInfo) (cloudwatch.ListMetricsOutput, error) { return cloudwatch.ListMetricsOutput{ Metrics: []*cloudwatch.Metric{ { @@ -53,7 +59,7 @@ func TestCloudWatchMetrics(t *testing.T) { }, }, nil } - dimensionKeys, _ := getDimensionsForCustomMetrics(region, namespace, database, f) + dimensionKeys, _ := getDimensionsForCustomMetrics(dsInfo, f) Convey("Should contain Test_DimensionName", func() { So(dimensionKeys, ShouldContain, "Test_DimensionName") diff --git a/pkg/api/common.go b/pkg/api/common.go index 5a7d48a5cbe..bd1c8be477d 100644 --- a/pkg/api/common.go +++ b/pkg/api/common.go @@ -4,26 +4,30 @@ import ( "encoding/json" "net/http" - "github.com/grafana/grafana/pkg/log" - "github.com/grafana/grafana/pkg/metrics" "github.com/grafana/grafana/pkg/middleware" "github.com/grafana/grafana/pkg/setting" "gopkg.in/macaron.v1" ) var ( - NotFound = ApiError(404, "Not found", nil) - ServerError = ApiError(500, "Server error", nil) + NotFound = func() Response { + return ApiError(404, "Not found", nil) + } + ServerError = func(err error) Response { + return ApiError(500, "Server error", err) + } ) type Response interface { - WriteTo(out http.ResponseWriter) + WriteTo(ctx *middleware.Context) } type NormalResponse struct { - status int - body []byte - header http.Header + status int + body []byte + header http.Header + errMessage string + err error } func wrap(action interface{}) macaron.Handler { @@ -34,20 +38,24 @@ func wrap(action interface{}) macaron.Handler { if err == nil && val != nil && len(val) > 0 { res = val[0].Interface().(Response) } else { - res = ServerError + res = ServerError(err) } - res.WriteTo(c.Resp) + res.WriteTo(c) } } -func (r *NormalResponse) WriteTo(out http.ResponseWriter) { - header := out.Header() +func (r *NormalResponse) WriteTo(ctx *middleware.Context) { + if r.err != nil { + ctx.Logger.Error(r.errMessage, "error", r.err) + } + + header := ctx.Resp.Header() for k, v := range r.header { header[k] = v } - out.WriteHeader(r.status) - out.Write(r.body) + ctx.Resp.WriteHeader(r.status) + ctx.Resp.Write(r.body) } func (r *NormalResponse) Cache(ttl string) *NormalResponse { @@ -60,7 +68,6 @@ func (r *NormalResponse) Header(key, value string) *NormalResponse { } // functions to create responses - func Empty(status int) *NormalResponse { return Respond(status, nil) } @@ -72,33 +79,37 @@ func Json(status int, body interface{}) *NormalResponse { func ApiSuccess(message string) *NormalResponse { resp := make(map[string]interface{}) resp["message"] = message - return Respond(200, resp) + return Json(200, resp) } func ApiError(status int, message string, err error) *NormalResponse { - resp := make(map[string]interface{}) - - if err != nil { - log.Error(4, "%s: %v", message, err) - if setting.Env != setting.PROD { - resp["error"] = err.Error() - } - } + data := make(map[string]interface{}) switch status { case 404: - metrics.M_Api_Status_404.Inc(1) - resp["message"] = "Not Found" + data["message"] = "Not Found" case 500: - metrics.M_Api_Status_500.Inc(1) - resp["message"] = "Internal Server Error" + data["message"] = "Internal Server Error" } if message != "" { - resp["message"] = message + data["message"] = message } - return Json(status, resp) + if err != nil { + if setting.Env != setting.PROD { + data["error"] = err.Error() + } + } + + resp := Json(status, data) + + if err != nil { + resp.errMessage = message + resp.err = err + } + + return resp } func Respond(status int, body interface{}) *NormalResponse { diff --git a/pkg/api/dashboard.go b/pkg/api/dashboard.go index 22f9e1e22a1..55925c4faf6 100644 --- a/pkg/api/dashboard.go +++ b/pkg/api/dashboard.go @@ -8,9 +8,13 @@ import ( "github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/log" "github.com/grafana/grafana/pkg/metrics" "github.com/grafana/grafana/pkg/middleware" m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/plugins" + "github.com/grafana/grafana/pkg/services/alerting" "github.com/grafana/grafana/pkg/services/search" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util" @@ -30,8 +34,6 @@ func isDashboardStarredByUser(c *middleware.Context, dashId int64) (bool, error) } func GetDashboard(c *middleware.Context) { - metrics.M_Api_Dashboard_Get.Inc(1) - slug := strings.ToLower(c.Params(":slug")) query := m.GetDashboardQuery{Slug: slug, OrgId: c.OrgId} @@ -75,6 +77,7 @@ func GetDashboard(c *middleware.Context) { }, } + c.TimeRequest(metrics.M_Api_Dashboard_Get) c.JSON(200, dto) } @@ -109,7 +112,7 @@ func DeleteDashboard(c *middleware.Context) { c.JSON(200, resp) } -func PostDashboard(c *middleware.Context, cmd m.SaveDashboardCommand) { +func PostDashboard(c *middleware.Context, cmd m.SaveDashboardCommand) Response { cmd.OrgId = c.OrgId if !c.IsSignedIn { @@ -119,51 +122,91 @@ func PostDashboard(c *middleware.Context, cmd m.SaveDashboardCommand) { } dash := cmd.GetDashboardModel() + // Check if Title is empty + if dash.Title == "" { + return ApiError(400, m.ErrDashboardTitleEmpty.Error(), nil) + } if dash.Id == 0 { limitReached, err := middleware.QuotaReached(c, "dashboard") if err != nil { - c.JsonApiErr(500, "failed to get quota", err) - return + return ApiError(500, "failed to get quota", err) } if limitReached { - c.JsonApiErr(403, "Quota reached", nil) - return + return ApiError(403, "Quota reached", nil) } } + validateAlertsCmd := alerting.ValidateDashboardAlertsCommand{ + OrgId: c.OrgId, + UserId: c.UserId, + Dashboard: dash, + } + + if err := bus.Dispatch(&validateAlertsCmd); err != nil { + return ApiError(500, "Invalid alert data. Cannot save dashboard", err) + } + err := bus.Dispatch(&cmd) if err != nil { if err == m.ErrDashboardWithSameNameExists { - c.JSON(412, util.DynMap{"status": "name-exists", "message": err.Error()}) - return + return Json(412, util.DynMap{"status": "name-exists", "message": err.Error()}) } if err == m.ErrDashboardVersionMismatch { - c.JSON(412, util.DynMap{"status": "version-mismatch", "message": err.Error()}) - return + return Json(412, util.DynMap{"status": "version-mismatch", "message": err.Error()}) + } + if pluginErr, ok := err.(m.UpdatePluginDashboardError); ok { + message := "The dashboard belongs to plugin " + pluginErr.PluginId + "." + // look up plugin name + if pluginDef, exist := plugins.Plugins[pluginErr.PluginId]; exist { + message = "The dashboard belongs to plugin " + pluginDef.Name + "." + } + return Json(412, util.DynMap{"status": "plugin-dashboard", "message": message}) } if err == m.ErrDashboardNotFound { - c.JSON(404, util.DynMap{"status": "not-found", "message": err.Error()}) - return + return Json(404, util.DynMap{"status": "not-found", "message": err.Error()}) } - c.JsonApiErr(500, "Failed to save dashboard", err) - return + return ApiError(500, "Failed to save dashboard", err) } - metrics.M_Api_Dashboard_Post.Inc(1) + alertCmd := alerting.UpdateDashboardAlertsCommand{ + OrgId: c.OrgId, + UserId: c.UserId, + Dashboard: cmd.Result, + } - c.JSON(200, util.DynMap{"status": "success", "slug": cmd.Result.Slug, "version": cmd.Result.Version}) + if err := bus.Dispatch(&alertCmd); err != nil { + return ApiError(500, "Failed to save alerts", err) + } + + c.TimeRequest(metrics.M_Api_Dashboard_Save) + return Json(200, util.DynMap{"status": "success", "slug": cmd.Result.Slug, "version": cmd.Result.Version}) } func canEditDashboard(role m.RoleType) bool { return role == m.ROLE_ADMIN || role == m.ROLE_EDITOR || role == m.ROLE_READ_ONLY_EDITOR } -func GetHomeDashboard(c *middleware.Context) { +func GetHomeDashboard(c *middleware.Context) Response { + prefsQuery := m.GetPreferencesWithDefaultsQuery{OrgId: c.OrgId, UserId: c.UserId} + if err := bus.Dispatch(&prefsQuery); err != nil { + return ApiError(500, "Failed to get preferences", err) + } + + if prefsQuery.Result.HomeDashboardId != 0 { + slugQuery := m.GetDashboardSlugByIdQuery{Id: prefsQuery.Result.HomeDashboardId} + err := bus.Dispatch(&slugQuery) + if err == nil { + dashRedirect := dtos.DashboardRedirect{RedirectUri: "db/" + slugQuery.Result} + return Json(200, &dashRedirect) + } else { + log.Warn("Failed to get slug from database, %s", err.Error()) + } + } + filePath := path.Join(setting.StaticRootPath, "dashboards/home.json") file, err := os.Open(filePath) if err != nil { - c.JsonApiErr(500, "Failed to load home dashboard", err) - return + return ApiError(500, "Failed to load home dashboard", err) } dash := dtos.DashboardFullWithMeta{} @@ -171,11 +214,29 @@ func GetHomeDashboard(c *middleware.Context) { dash.Meta.CanEdit = canEditDashboard(c.OrgRole) jsonParser := json.NewDecoder(file) if err := jsonParser.Decode(&dash.Dashboard); err != nil { - c.JsonApiErr(500, "Failed to load home dashboard", err) - return + return ApiError(500, "Failed to load home dashboard", err) } - c.JSON(200, &dash) + if c.HasUserRole(m.ROLE_ADMIN) && !c.HasHelpFlag(m.HelpFlagGettingStartedPanelDismissed) { + addGettingStartedPanelToHomeDashboard(dash.Dashboard) + } + + return Json(200, &dash) +} + +func addGettingStartedPanelToHomeDashboard(dash *simplejson.Json) { + rows := dash.Get("rows").MustArray() + row := simplejson.NewFromAny(rows[0]) + + newpanel := simplejson.NewFromAny(map[string]interface{}{ + "type": "gettingstarted", + "id": 123123, + "span": 12, + }) + + panels := row.Get("panels").MustArray() + panels = append(panels, newpanel) + row.Set("panels", panels) } func GetDashboardFromJsonFile(c *middleware.Context) { diff --git a/pkg/api/dashboard_snapshot.go b/pkg/api/dashboard_snapshot.go index 3c369ca5b7f..cdcb871314d 100644 --- a/pkg/api/dashboard_snapshot.go +++ b/pkg/api/dashboard_snapshot.go @@ -21,6 +21,10 @@ func GetSharingOptions(c *middleware.Context) { } func CreateDashboardSnapshot(c *middleware.Context, cmd m.CreateDashboardSnapshotCommand) { + if cmd.Name == "" { + cmd.Name = "Unnamed snapshot" + } + if cmd.External { // external snapshot ref requires key and delete key if cmd.Key == "" || cmd.DeleteKey == "" { diff --git a/pkg/api/dataproxy.go b/pkg/api/dataproxy.go index eb88045cd51..db4c5166feb 100644 --- a/pkg/api/dataproxy.go +++ b/pkg/api/dataproxy.go @@ -1,8 +1,6 @@ package api import ( - "crypto/tls" - "net" "net/http" "net/http/httputil" "net/url" @@ -10,22 +8,13 @@ import ( "github.com/grafana/grafana/pkg/api/cloudwatch" "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/metrics" "github.com/grafana/grafana/pkg/middleware" m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util" ) -var dataProxyTransport = &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - Proxy: http.ProxyFromEnvironment, - Dial: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - }).Dial, - TLSHandshakeTimeout: 10 * time.Second, -} - func NewReverseProxy(ds *m.DataSource, proxyPath string, targetUrl *url.URL) *httputil.ReverseProxy { director := func(req *http.Request) { req.URL.Scheme = targetUrl.Scheme @@ -41,7 +30,6 @@ func NewReverseProxy(ds *m.DataSource, proxyPath string, targetUrl *url.URL) *ht req.URL.RawQuery = reqQueryVals.Encode() } else if ds.Type == m.DS_INFLUXDB { req.URL.Path = util.JoinUrlFragments(targetUrl.Path, proxyPath) - reqQueryVals.Add("db", ds.Database) req.URL.RawQuery = reqQueryVals.Encode() if !ds.BasicAuth { req.Header.Del("Authorization") @@ -56,6 +44,13 @@ func NewReverseProxy(ds *m.DataSource, proxyPath string, targetUrl *url.URL) *ht req.Header.Add("Authorization", util.GetBasicAuthHeader(ds.BasicAuthUser, ds.BasicAuthPassword)) } + dsAuth := req.Header.Get("X-DS-Authorization") + if len(dsAuth) > 0 { + req.Header.Del("X-DS-Authorization") + req.Header.Del("Authorization") + req.Header.Add("Authorization", dsAuth) + } + // clear cookie headers req.Header.Del("Cookie") req.Header.Del("Set-Cookie") @@ -70,16 +65,31 @@ func getDatasource(id int64, orgId int64) (*m.DataSource, error) { return nil, err } - return &query.Result, nil + return query.Result, nil } func ProxyDataSourceRequest(c *middleware.Context) { + c.TimeRequest(metrics.M_DataSource_ProxyReq_Timer) + ds, err := getDatasource(c.ParamsInt64(":id"), c.OrgId) + if err != nil { c.JsonApiErr(500, "Unable to load datasource meta data", err) return } + if ds.Type == m.DS_CLOUDWATCH { + cloudwatch.HandleRequest(c, ds) + return + } + + if ds.Type == m.DS_INFLUXDB { + if c.Query("db") != ds.Database { + c.JsonApiErr(403, "Datasource is not configured to allow this database", nil) + return + } + } + targetUrl, _ := url.Parse(ds.Url) if len(setting.DataProxyWhiteList) > 0 { if _, exists := setting.DataProxyWhiteList[targetUrl.Host]; !exists { @@ -88,13 +98,29 @@ func ProxyDataSourceRequest(c *middleware.Context) { } } - if ds.Type == m.DS_CLOUDWATCH { - cloudwatch.HandleRequest(c, ds) - } else { - proxyPath := c.Params("*") - proxy := NewReverseProxy(ds, proxyPath, targetUrl) - proxy.Transport = dataProxyTransport - proxy.ServeHTTP(c.Resp, c.Req.Request) - c.Resp.Header().Del("Set-Cookie") + proxyPath := c.Params("*") + + if ds.Type == m.DS_ES { + if c.Req.Request.Method == "DELETE" { + c.JsonApiErr(403, "Deletes not allowed on proxied Elasticsearch datasource", nil) + return + } + if c.Req.Request.Method == "PUT" { + c.JsonApiErr(403, "Puts not allowed on proxied Elasticsearch datasource", nil) + return + } + if c.Req.Request.Method == "POST" && proxyPath != "_msearch" { + c.JsonApiErr(403, "Posts not allowed on proxied Elasticsearch datasource except on /_msearch", nil) + return + } } + + proxy := NewReverseProxy(ds, proxyPath, targetUrl) + proxy.Transport, err = ds.GetHttpTransport() + if err != nil { + c.JsonApiErr(400, "Unable to load TLS certificate", err) + return + } + proxy.ServeHTTP(c.Resp, c.Req.Request) + c.Resp.Header().Del("Set-Cookie") } diff --git a/pkg/api/dataproxy_test.go b/pkg/api/dataproxy_test.go index 0e561c726e1..f3ed6994cff 100644 --- a/pkg/api/dataproxy_test.go +++ b/pkg/api/dataproxy_test.go @@ -11,11 +11,16 @@ import ( ) func TestDataSourceProxy(t *testing.T) { - Convey("When getting graphite datasource proxy", t, func() { ds := m.DataSource{Url: "htttp://graphite:8080", Type: m.DS_GRAPHITE} - targetUrl, _ := url.Parse(ds.Url) + targetUrl, err := url.Parse(ds.Url) proxy := NewReverseProxy(&ds, "/render", targetUrl) + proxy.Transport, err = ds.GetHttpTransport() + So(err, ShouldBeNil) + + transport, ok := proxy.Transport.(*http.Transport) + So(ok, ShouldBeTrue) + So(transport.TLSClientConfig.InsecureSkipVerify, ShouldBeTrue) requestUrl, _ := url.Parse("http://grafana.com/sub") req := http.Request{URL: requestUrl} @@ -54,7 +59,5 @@ func TestDataSourceProxy(t *testing.T) { So(queryVals["u"][0], ShouldEqual, "user") So(queryVals["p"][0], ShouldEqual, "password") }) - }) - } diff --git a/pkg/api/datasources.go b/pkg/api/datasources.go index 63c2ec57b7a..43f4d308ed6 100644 --- a/pkg/api/datasources.go +++ b/pkg/api/datasources.go @@ -5,10 +5,9 @@ import ( "github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/bus" - "github.com/grafana/grafana/pkg/plugins" - //"github.com/grafana/grafana/pkg/log" "github.com/grafana/grafana/pkg/middleware" m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/util" ) @@ -22,7 +21,6 @@ func GetDataSources(c *middleware.Context) { result := make(dtos.DataSourceList, 0) for _, ds := range query.Result { - dsItem := dtos.DataSource{ Id: ds.Id, OrgId: ds.OrgId, @@ -35,6 +33,7 @@ func GetDataSources(c *middleware.Context) { User: ds.User, BasicAuth: ds.BasicAuth, IsDefault: ds.IsDefault, + JsonData: ds.JsonData, } if plugin, exists := plugins.DataSources[ds.Type]; exists { @@ -92,24 +91,68 @@ func AddDataSource(c *middleware.Context, cmd m.AddDataSourceCommand) { cmd.OrgId = c.OrgId if err := bus.Dispatch(&cmd); err != nil { + if err == m.ErrDataSourceNameExists { + c.JsonApiErr(409, err.Error(), err) + return + } + c.JsonApiErr(500, "Failed to add datasource", err) return } - c.JSON(200, util.DynMap{"message": "Datasource added", "id": cmd.Result.Id}) + c.JSON(200, util.DynMap{"message": "Datasource added", "id": cmd.Result.Id, "name": cmd.Result.Name}) } -func UpdateDataSource(c *middleware.Context, cmd m.UpdateDataSourceCommand) { +func UpdateDataSource(c *middleware.Context, cmd m.UpdateDataSourceCommand) Response { cmd.OrgId = c.OrgId cmd.Id = c.ParamsInt64(":id") - err := bus.Dispatch(&cmd) + err := fillWithSecureJsonData(&cmd) if err != nil { - c.JsonApiErr(500, "Failed to update datasource", err) - return + return ApiError(500, "Failed to update datasource", err) } - c.JsonOK("Datasource updated") + err = bus.Dispatch(&cmd) + if err != nil { + return ApiError(500, "Failed to update datasource", err) + } + + return Json(200, util.DynMap{"message": "Datasource updated", "id": cmd.Id, "name": cmd.Name}) +} + +func fillWithSecureJsonData(cmd *m.UpdateDataSourceCommand) error { + if len(cmd.SecureJsonData) == 0 { + return nil + } + + ds, err := getRawDataSourceById(cmd.Id, cmd.OrgId) + + if err != nil { + return err + } + secureJsonData := ds.SecureJsonData.Decrypt() + + for k, v := range secureJsonData { + + if _, ok := cmd.SecureJsonData[k]; !ok { + cmd.SecureJsonData[k] = v + } + } + + return nil +} + +func getRawDataSourceById(id int64, orgId int64) (*m.DataSource, error) { + query := m.GetDataSourceByIdQuery{ + Id: id, + OrgId: orgId, + } + + if err := bus.Dispatch(&query); err != nil { + return nil, err + } + + return query.Result, nil } // Get /api/datasources/name/:name @@ -123,9 +166,7 @@ func GetDataSourceByName(c *middleware.Context) Response { return ApiError(500, "Failed to query datasources", err) } - ds := query.Result - dtos := convertModelToDtos(ds) - + dtos := convertModelToDtos(query.Result) return Json(200, &dtos) } @@ -148,8 +189,8 @@ func GetDataSourceIdByName(c *middleware.Context) Response { return Json(200, &dtos) } -func convertModelToDtos(ds m.DataSource) dtos.DataSource { - return dtos.DataSource{ +func convertModelToDtos(ds *m.DataSource) dtos.DataSource { + dto := dtos.DataSource{ Id: ds.Id, OrgId: ds.OrgId, Name: ds.Name, @@ -165,5 +206,14 @@ func convertModelToDtos(ds m.DataSource) dtos.DataSource { WithCredentials: ds.WithCredentials, IsDefault: ds.IsDefault, JsonData: ds.JsonData, + SecureJsonFields: map[string]bool{}, } + + for k, v := range ds.SecureJsonData { + if len(v) > 0 { + dto.SecureJsonFields[k] = true + } + } + + return dto } diff --git a/pkg/api/dtos/alerting.go b/pkg/api/dtos/alerting.go new file mode 100644 index 00000000000..f3d64f89524 --- /dev/null +++ b/pkg/api/dtos/alerting.go @@ -0,0 +1,70 @@ +package dtos + +import ( + "time" + + "github.com/grafana/grafana/pkg/components/simplejson" + m "github.com/grafana/grafana/pkg/models" +) + +type AlertRule struct { + Id int64 `json:"id"` + DashboardId int64 `json:"dashboardId"` + PanelId int64 `json:"panelId"` + Name string `json:"name"` + Message string `json:"message"` + State m.AlertStateType `json:"state"` + NewStateDate time.Time `json:"newStateDate"` + EvalDate time.Time `json:"evalDate"` + ExecutionError string `json:"executionError"` + DashbboardUri string `json:"dashboardUri"` +} + +type AlertNotification struct { + Id int64 `json:"id"` + Name string `json:"name"` + Type string `json:"type"` + IsDefault bool `json:"isDefault"` + Created time.Time `json:"created"` + Updated time.Time `json:"updated"` +} + +type AlertTestCommand struct { + Dashboard *simplejson.Json `json:"dashboard" binding:"Required"` + PanelId int64 `json:"panelId" binding:"Required"` +} + +type AlertTestResult struct { + Firing bool `json:"firing"` + ConditionEvals string `json:"conditionEvals"` + TimeMs string `json:"timeMs"` + Error string `json:"error,omitempty"` + EvalMatches []*EvalMatch `json:"matches,omitempty"` + Logs []*AlertTestResultLog `json:"logs,omitempty"` +} + +type AlertTestResultLog struct { + Message string `json:"message"` + Data interface{} `json:"data"` +} + +type EvalMatch struct { + Tags map[string]string `json:"tags,omitempty"` + Metric string `json:"metric"` + Value float64 `json:"value"` +} + +type NotificationTestCommand struct { + Name string `json:"name"` + Type string `json:"type"` + Settings *simplejson.Json `json:"settings"` +} + +type PauseAlertCommand struct { + AlertId int64 `json:"alertId"` + Paused bool `json:"paused"` +} + +type PauseAllAlertsCommand struct { + Paused bool `json:"paused"` +} diff --git a/pkg/api/dtos/annotations.go b/pkg/api/dtos/annotations.go new file mode 100644 index 00000000000..45415978ee1 --- /dev/null +++ b/pkg/api/dtos/annotations.go @@ -0,0 +1,23 @@ +package dtos + +import "github.com/grafana/grafana/pkg/components/simplejson" + +type Annotation struct { + AlertId int64 `json:"alertId"` + DashboardId int64 `json:"dashboardId"` + PanelId int64 `json:"panelId"` + NewState string `json:"newState"` + PrevState string `json:"prevState"` + Time int64 `json:"time"` + Title string `json:"title"` + Text string `json:"text"` + Metric string `json:"metric"` + + Data *simplejson.Json `json:"data"` +} + +type DeleteAnnotationsCmd struct { + AlertId int64 `json:"alertId"` + DashboardId int64 `json:"dashboardId"` + PanelId int64 `json:"panelId"` +} diff --git a/pkg/api/dtos/index.go b/pkg/api/dtos/index.go index 21201d30adf..b813c78f2bb 100644 --- a/pkg/api/dtos/index.go +++ b/pkg/api/dtos/index.go @@ -1,13 +1,17 @@ package dtos type IndexViewData struct { - User *CurrentUser - Settings map[string]interface{} - AppUrl string - AppSubUrl string - GoogleAnalyticsId string - GoogleTagManagerId string - MainNavLinks []*NavLink + User *CurrentUser + Settings map[string]interface{} + AppUrl string + AppSubUrl string + GoogleAnalyticsId string + GoogleTagManagerId string + MainNavLinks []*NavLink + BuildVersion string + BuildCommit string + NewGrafanaVersionExists bool + NewGrafanaVersion string } type PluginCss struct { diff --git a/pkg/api/dtos/models.go b/pkg/api/dtos/models.go index 8c1f85c9bd1..13dbe4ea32a 100644 --- a/pkg/api/dtos/models.go +++ b/pkg/api/dtos/models.go @@ -22,17 +22,20 @@ type LoginCommand struct { } type CurrentUser struct { - IsSignedIn bool `json:"isSignedIn"` - Id int64 `json:"id"` - Login string `json:"login"` - Email string `json:"email"` - Name string `json:"name"` - LightTheme bool `json:"lightTheme"` - OrgId int64 `json:"orgId"` - OrgName string `json:"orgName"` - OrgRole m.RoleType `json:"orgRole"` - IsGrafanaAdmin bool `json:"isGrafanaAdmin"` - GravatarUrl string `json:"gravatarUrl"` + IsSignedIn bool `json:"isSignedIn"` + Id int64 `json:"id"` + Login string `json:"login"` + Email string `json:"email"` + Name string `json:"name"` + LightTheme bool `json:"lightTheme"` + OrgId int64 `json:"orgId"` + OrgName string `json:"orgName"` + OrgRole m.RoleType `json:"orgRole"` + IsGrafanaAdmin bool `json:"isGrafanaAdmin"` + GravatarUrl string `json:"gravatarUrl"` + Timezone string `json:"timezone"` + Locale string `json:"locale"` + HelpFlags1 m.HelpFlags1 `json:"helpFlags1"` } type DashboardMeta struct { @@ -57,6 +60,10 @@ type DashboardFullWithMeta struct { Dashboard *simplejson.Json `json:"dashboard"` } +type DashboardRedirect struct { + RedirectUri string `json:"redirectUri"` +} + type DataSource struct { Id int64 `json:"id"` OrgId int64 `json:"orgId"` @@ -74,6 +81,7 @@ type DataSource struct { WithCredentials bool `json:"withCredentials"` IsDefault bool `json:"isDefault"` JsonData *simplejson.Json `json:"jsonData,omitempty"` + SecureJsonFields map[string]bool `json:"secureJsonFields"` } type DataSourceList []DataSource @@ -90,13 +98,10 @@ func (slice DataSourceList) Swap(i, j int) { slice[i], slice[j] = slice[j], slice[i] } -type MetricQueryResultDto struct { - Data []MetricQueryResultDataDto `json:"data"` -} - -type MetricQueryResultDataDto struct { - Target string `json:"target"` - DataPoints [][2]float64 `json:"datapoints"` +type MetricRequest struct { + From string `json:"from"` + To string `json:"to"` + Queries []*simplejson.Json `json:"queries"` } type UserStars struct { diff --git a/pkg/api/dtos/playlist.go b/pkg/api/dtos/playlist.go new file mode 100644 index 00000000000..317ff83339a --- /dev/null +++ b/pkg/api/dtos/playlist.go @@ -0,0 +1,23 @@ +package dtos + +type PlaylistDashboard struct { + Id int64 `json:"id"` + Slug string `json:"slug"` + Title string `json:"title"` + Uri string `json:"uri"` + Order int `json:"order"` +} + +type PlaylistDashboardsSlice []PlaylistDashboard + +func (slice PlaylistDashboardsSlice) Len() int { + return len(slice) +} + +func (slice PlaylistDashboardsSlice) Less(i, j int) bool { + return slice[i].Order < slice[j].Order +} + +func (slice PlaylistDashboardsSlice) Swap(i, j int) { + slice[i], slice[j] = slice[j], slice[i] +} diff --git a/pkg/api/dtos/plugins.go b/pkg/api/dtos/plugins.go index 53c911c10fa..70e732424ab 100644 --- a/pkg/api/dtos/plugins.go +++ b/pkg/api/dtos/plugins.go @@ -1,6 +1,9 @@ package dtos -import "github.com/grafana/grafana/pkg/plugins" +import ( + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/plugins" +) type PluginSetting struct { Name string `json:"name"` @@ -15,15 +18,21 @@ type PluginSetting struct { Dependencies *plugins.PluginDependencies `json:"dependencies"` JsonData map[string]interface{} `json:"jsonData"` DefaultNavUrl string `json:"defaultNavUrl"` + + LatestVersion string `json:"latestVersion"` + HasUpdate bool `json:"hasUpdate"` } type PluginListItem struct { - Name string `json:"name"` - Type string `json:"type"` - Id string `json:"id"` - Enabled bool `json:"enabled"` - Pinned bool `json:"pinned"` - Info *plugins.PluginInfo `json:"info"` + Name string `json:"name"` + Type string `json:"type"` + Id string `json:"id"` + Enabled bool `json:"enabled"` + Pinned bool `json:"pinned"` + Info *plugins.PluginInfo `json:"info"` + LatestVersion string `json:"latestVersion"` + HasUpdate bool `json:"hasUpdate"` + DefaultNavUrl string `json:"defaultNavUrl"` } type PluginList []PluginListItem @@ -43,6 +52,7 @@ func (slice PluginList) Swap(i, j int) { type ImportDashboardCommand struct { PluginId string `json:"pluginId"` Path string `json:"path"` - Reinstall bool `json:"reinstall"` + Overwrite bool `json:"overwrite"` + Dashboard *simplejson.Json `json:"dashboard"` Inputs []plugins.ImportDashboardInput `json:"inputs"` } diff --git a/pkg/api/dtos/prefs.go b/pkg/api/dtos/prefs.go new file mode 100644 index 00000000000..97e20bb4011 --- /dev/null +++ b/pkg/api/dtos/prefs.go @@ -0,0 +1,13 @@ +package dtos + +type Prefs struct { + Theme string `json:"theme"` + HomeDashboardId int64 `json:"homeDashboardId"` + Timezone string `json:"timezone"` +} + +type UpdatePrefsCmd struct { + Theme string `json:"theme"` + HomeDashboardId int64 `json:"homeDashboardId"` + Timezone string `json:"timezone"` +} diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index c84d7faccff..1fd4cd347e7 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -38,7 +38,7 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro url := ds.Url if ds.Access == m.DS_ACCESS_PROXY { - url = setting.AppSubUrl + "/api/datasources/proxy/" + strconv.FormatInt(ds.Id, 10) + url = "/api/datasources/proxy/" + strconv.FormatInt(ds.Id, 10) } var dsMap = map[string]interface{}{ @@ -59,7 +59,7 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro defaultDatasource = ds.Name } - if len(ds.JsonData.MustMap()) > 0 { + if ds.JsonData != nil { dsMap["jsonData"] = ds.JsonData } @@ -105,6 +105,7 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro grafanaDatasourceMeta, _ := plugins.DataSources["grafana"] datasources["-- Grafana --"] = map[string]interface{}{ "type": "grafana", + "name": "-- Grafana --", "meta": grafanaDatasourceMeta, } @@ -121,11 +122,13 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro panels := map[string]interface{}{} for _, panel := range enabledPlugins.Panels { panels[panel.Id] = map[string]interface{}{ - "module": panel.Module, - "baseUrl": panel.BaseUrl, - "name": panel.Name, - "id": panel.Id, - "info": panel.Info, + "module": panel.Module, + "baseUrl": panel.BaseUrl, + "name": panel.Name, + "id": panel.Id, + "info": panel.Info, + "hideFromList": panel.HideFromList, + "sort": getPanelSort(panel.Id), } } @@ -136,16 +139,39 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro "appSubUrl": setting.AppSubUrl, "allowOrgCreate": (setting.AllowUserOrgCreate && c.IsSignedIn) || c.IsGrafanaAdmin, "authProxyEnabled": setting.AuthProxyEnabled, + "ldapEnabled": setting.LdapEnabled, "buildInfo": map[string]interface{}{ - "version": setting.BuildVersion, - "commit": setting.BuildCommit, - "buildstamp": setting.BuildStamp, + "version": setting.BuildVersion, + "commit": setting.BuildCommit, + "buildstamp": setting.BuildStamp, + "latestVersion": plugins.GrafanaLatestVersion, + "hasUpdate": plugins.GrafanaHasUpdate, + "env": setting.Env, }, } return jsonObj, nil } +func getPanelSort(id string) int { + sort := 100 + switch id { + case "graph": + sort = 1 + case "singlestat": + sort = 2 + case "table": + sort = 3 + case "text": + sort = 4 + case "alertlist": + sort = 5 + case "dashlist": + sort = 6 + } + return sort +} + func GetFrontendSettings(c *middleware.Context) { settings, err := getFrontendSettingsMap(c) if err != nil { diff --git a/pkg/api/gnetproxy.go b/pkg/api/gnetproxy.go new file mode 100644 index 00000000000..7761729b8af --- /dev/null +++ b/pkg/api/gnetproxy.go @@ -0,0 +1,51 @@ +package api + +import ( + "crypto/tls" + "net" + "net/http" + "net/http/httputil" + "net/url" + "time" + + "github.com/grafana/grafana/pkg/middleware" + "github.com/grafana/grafana/pkg/setting" + "github.com/grafana/grafana/pkg/util" +) + +var gNetProxyTransport = &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: false}, + Proxy: http.ProxyFromEnvironment, + Dial: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + }).Dial, + TLSHandshakeTimeout: 10 * time.Second, +} + +func ReverseProxyGnetReq(proxyPath string) *httputil.ReverseProxy { + url, _ := url.Parse(setting.GrafanaNetUrl) + + director := func(req *http.Request) { + req.URL.Scheme = url.Scheme + req.URL.Host = url.Host + req.Host = url.Host + + req.URL.Path = util.JoinUrlFragments(url.Path+"/api", proxyPath) + + // clear cookie headers + req.Header.Del("Cookie") + req.Header.Del("Set-Cookie") + req.Header.Del("Authorization") + } + + return &httputil.ReverseProxy{Director: director} +} + +func ProxyGnetRequest(c *middleware.Context) { + proxyPath := c.Params("*") + proxy := ReverseProxyGnetReq(proxyPath) + proxy.Transport = gNetProxyTransport + proxy.ServeHTTP(c.Resp, c.Req.Request) + c.Resp.Header().Del("Set-Cookie") +} diff --git a/pkg/api/index.go b/pkg/api/index.go index a376f9504a4..715baefae78 100644 --- a/pkg/api/index.go +++ b/pkg/api/index.go @@ -1,7 +1,11 @@ package api import ( + "fmt" + "strings" + "github.com/grafana/grafana/pkg/api/dtos" + "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/middleware" m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/plugins" @@ -14,6 +18,31 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) { return nil, err } + prefsQuery := m.GetPreferencesWithDefaultsQuery{OrgId: c.OrgId, UserId: c.UserId} + if err := bus.Dispatch(&prefsQuery); err != nil { + return nil, err + } + prefs := prefsQuery.Result + + // Read locale from acccept-language + acceptLang := c.Req.Header.Get("Accept-Language") + locale := "en-US" + + if len(acceptLang) > 0 { + parts := strings.Split(acceptLang, ",") + locale = parts[0] + } + + appUrl := setting.AppUrl + appSubUrl := setting.AppSubUrl + + // special case when doing localhost call from phantomjs + if c.IsRenderCall { + appUrl = fmt.Sprintf("%s://localhost:%s", setting.Protocol, setting.HttpPort) + appSubUrl = "" + settings["appSubUrl"] = "" + } + var data = dtos.IndexViewData{ User: &dtos.CurrentUser{ Id: c.UserId, @@ -21,18 +50,25 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) { Login: c.Login, Email: c.Email, Name: c.Name, - LightTheme: c.Theme == "light", OrgId: c.OrgId, OrgName: c.OrgName, OrgRole: c.OrgRole, GravatarUrl: dtos.GetGravatarUrl(c.Email), IsGrafanaAdmin: c.IsGrafanaAdmin, + LightTheme: prefs.Theme == "light", + Timezone: prefs.Timezone, + Locale: locale, + HelpFlags1: c.HelpFlags1, }, - Settings: settings, - AppUrl: setting.AppUrl, - AppSubUrl: setting.AppSubUrl, - GoogleAnalyticsId: setting.GoogleAnalyticsId, - GoogleTagManagerId: setting.GoogleTagManagerId, + Settings: settings, + AppUrl: appUrl, + AppSubUrl: appSubUrl, + GoogleAnalyticsId: setting.GoogleAnalyticsId, + GoogleTagManagerId: setting.GoogleTagManagerId, + BuildVersion: setting.BuildVersion, + BuildCommit: setting.BuildCommit, + NewGrafanaVersion: plugins.GrafanaLatestVersion, + NewGrafanaVersionExists: plugins.GrafanaHasUpdate, } if setting.DisableGravatar { @@ -57,7 +93,7 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) { if c.OrgRole == m.ROLE_ADMIN || c.OrgRole == m.ROLE_EDITOR { dashboardChildNavs = append(dashboardChildNavs, &dtos.NavLink{Divider: true}) dashboardChildNavs = append(dashboardChildNavs, &dtos.NavLink{Text: "New", Icon: "fa fa-plus", Url: setting.AppSubUrl + "/dashboard/new"}) - dashboardChildNavs = append(dashboardChildNavs, &dtos.NavLink{Text: "Import", Icon: "fa fa-download", Url: setting.AppSubUrl + "/import/dashboard"}) + dashboardChildNavs = append(dashboardChildNavs, &dtos.NavLink{Text: "Import", Icon: "fa fa-download", Url: setting.AppSubUrl + "/dashboard/new/?editview=import"}) } data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ @@ -67,6 +103,20 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) { Children: dashboardChildNavs, }) + if c.OrgRole == m.ROLE_ADMIN || c.OrgRole == m.ROLE_EDITOR { + alertChildNavs := []*dtos.NavLink{ + {Text: "Alert List", Url: setting.AppSubUrl + "/alerting/list"}, + {Text: "Notification channels", Url: setting.AppSubUrl + "/alerting/notifications"}, + } + + data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ + Text: "Alerting", + Icon: "icon-gf icon-gf-alert", + Url: setting.AppSubUrl + "/alerting/list", + Children: alertChildNavs, + }) + } + if c.OrgRole == m.ROLE_ADMIN { data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Data Sources", @@ -95,6 +145,10 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) { } for _, include := range plugin.Includes { + if !c.HasUserRole(include.Role) { + continue + } + if include.Type == "page" && include.AddToNav { link := &dtos.NavLink{ Url: setting.AppSubUrl + "/plugins/" + plugin.Id + "/page/" + include.Slug, @@ -102,6 +156,7 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) { } appLink.Children = append(appLink.Children, link) } + if include.Type == "dashboard" && include.AddToNav { link := &dtos.NavLink{ Url: setting.AppSubUrl + "/dashboard/db/" + include.Slug, @@ -111,12 +166,14 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) { } } - if c.OrgRole == m.ROLE_ADMIN { + if len(appLink.Children) > 0 && c.OrgRole == m.ROLE_ADMIN { appLink.Children = append(appLink.Children, &dtos.NavLink{Divider: true}) appLink.Children = append(appLink.Children, &dtos.NavLink{Text: "Plugin Config", Icon: "fa fa-cog", Url: setting.AppSubUrl + "/plugins/" + plugin.Id + "/edit"}) } - data.MainNavLinks = append(data.MainNavLinks, appLink) + if len(appLink.Children) > 0 { + data.MainNavLinks = append(data.MainNavLinks, appLink) + } } } diff --git a/pkg/api/login.go b/pkg/api/login.go index 463fa8282a5..8fbe414c08c 100644 --- a/pkg/api/login.go +++ b/pkg/api/login.go @@ -25,10 +25,15 @@ func LoginView(c *middleware.Context) { return } - viewData.Settings["googleAuthEnabled"] = setting.OAuthService.Google - viewData.Settings["githubAuthEnabled"] = setting.OAuthService.GitHub + enabledOAuths := make(map[string]interface{}) + for key, oauth := range setting.OAuthService.OAuthInfos { + enabledOAuths[key] = map[string]string{"name": oauth.Name} + } + + viewData.Settings["oauth"] = enabledOAuths viewData.Settings["disableUserSignUp"] = !setting.AllowUserSignUp viewData.Settings["loginHint"] = setting.LoginHint + viewData.Settings["disableLoginForm"] = setting.DisableLoginForm if !tryLoginUsingRememberCookie(c) { c.HTML(200, VIEW_INDEX, viewData) diff --git a/pkg/api/login_oauth.go b/pkg/api/login_oauth.go index 4244feef664..574d08af09f 100644 --- a/pkg/api/login_oauth.go +++ b/pkg/api/login_oauth.go @@ -1,14 +1,20 @@ package api import ( + "crypto/rand" + "crypto/tls" + "crypto/x509" + "encoding/base64" "errors" "fmt" - "net/url" + "io/ioutil" + "log" + "net/http" + "golang.org/x/net/context" "golang.org/x/oauth2" "github.com/grafana/grafana/pkg/bus" - "github.com/grafana/grafana/pkg/log" "github.com/grafana/grafana/pkg/metrics" "github.com/grafana/grafana/pkg/middleware" m "github.com/grafana/grafana/pkg/models" @@ -16,6 +22,12 @@ import ( "github.com/grafana/grafana/pkg/social" ) +func GenStateString() string { + rnd := make([]byte, 32) + rand.Read(rnd) + return base64.StdEncoding.EncodeToString(rnd) +} + func OAuthLogin(ctx *middleware.Context) { if setting.OAuthService == nil { ctx.Handle(404, "login.OAuthLogin(oauth service not enabled)", nil) @@ -29,43 +41,102 @@ func OAuthLogin(ctx *middleware.Context) { return } + error := ctx.Query("error") + if error != "" { + errorDesc := ctx.Query("error_description") + ctx.Logger.Info("OAuthLogin Failed", "error", error, "errorDesc", errorDesc) + ctx.Redirect(setting.AppSubUrl + "/login?failCode=1003") + return + } + code := ctx.Query("code") if code == "" { - ctx.Redirect(connect.AuthCodeURL("", oauth2.AccessTypeOnline)) + state := GenStateString() + ctx.Session.Set(middleware.SESS_KEY_OAUTH_STATE, state) + if setting.OAuthService.OAuthInfos[name].HostedDomain == "" { + ctx.Redirect(connect.AuthCodeURL(state, oauth2.AccessTypeOnline)) + } else { + ctx.Redirect(connect.AuthCodeURL(state, oauth2.SetParam("hd", setting.OAuthService.OAuthInfos[name].HostedDomain), oauth2.AccessTypeOnline)) + } + return + } + + // verify state string + savedState := ctx.Session.Get(middleware.SESS_KEY_OAUTH_STATE).(string) + queryState := ctx.Query("state") + if savedState != queryState { + ctx.Handle(500, "login.OAuthLogin(state mismatch)", nil) return } // handle call back - token, err := connect.Exchange(oauth2.NoContext, code) + + // initialize oauth2 context + oauthCtx := oauth2.NoContext + if setting.OAuthService.OAuthInfos[name].TlsClientCert != "" { + cert, err := tls.LoadX509KeyPair(setting.OAuthService.OAuthInfos[name].TlsClientCert, setting.OAuthService.OAuthInfos[name].TlsClientKey) + if err != nil { + log.Fatal(err) + } + + // Load CA cert + caCert, err := ioutil.ReadFile(setting.OAuthService.OAuthInfos[name].TlsClientCa) + if err != nil { + log.Fatal(err) + } + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + + tr := &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + Certificates: []tls.Certificate{cert}, + RootCAs: caCertPool, + }, + } + sslcli := &http.Client{Transport: tr} + + oauthCtx = context.Background() + oauthCtx = context.WithValue(oauthCtx, oauth2.HTTPClient, sslcli) + } + + // get token from provider + token, err := connect.Exchange(oauthCtx, code) if err != nil { ctx.Handle(500, "login.OAuthLogin(NewTransportWithCode)", err) return } + // token.TokenType was defaulting to "bearer", which is out of spec, so we explicitly set to "Bearer" + token.TokenType = "Bearer" - log.Trace("login.OAuthLogin(Got token)") + ctx.Logger.Debug("OAuthLogin Got token") - userInfo, err := connect.UserInfo(token) + // set up oauth2 client + client := connect.Client(oauthCtx, token) + + // get user info + userInfo, err := connect.UserInfo(client) if err != nil { if err == social.ErrMissingTeamMembership { - ctx.Redirect(setting.AppSubUrl + "/login?failedMsg=" + url.QueryEscape("Required Github team membership not fulfilled")) + ctx.Redirect(setting.AppSubUrl + "/login?failCode=1000") } else if err == social.ErrMissingOrganizationMembership { - ctx.Redirect(setting.AppSubUrl + "/login?failedMsg=" + url.QueryEscape("Required Github organization membership not fulfilled")) + ctx.Redirect(setting.AppSubUrl + "/login?failCode=1001") } else { ctx.Handle(500, fmt.Sprintf("login.OAuthLogin(get info from %s)", name), err) } return } - log.Trace("login.OAuthLogin(social login): %s", userInfo) + ctx.Logger.Debug("OAuthLogin got user info", "userInfo", userInfo) // validate that the email is allowed to login to grafana if !connect.IsEmailAllowed(userInfo.Email) { - log.Info("OAuth login attempt with unallowed email, %s", userInfo.Email) - ctx.Redirect(setting.AppSubUrl + "/login?failedMsg=" + url.QueryEscape("Required email domain not fulfilled")) + ctx.Logger.Info("OAuth login attempt with unallowed email", "email", userInfo.Email) + ctx.Redirect(setting.AppSubUrl + "/login?failCode=1002") return } - userQuery := m.GetUserByLoginQuery{LoginOrEmail: userInfo.Email} + userQuery := m.GetUserByEmailQuery{Email: userInfo.Email} err = bus.Dispatch(&userQuery) // create account if missing @@ -84,10 +155,11 @@ func OAuthLogin(ctx *middleware.Context) { return } cmd := m.CreateUserCommand{ - Login: userInfo.Email, - Email: userInfo.Email, - Name: userInfo.Name, - Company: userInfo.Company, + Login: userInfo.Login, + Email: userInfo.Email, + Name: userInfo.Name, + Company: userInfo.Company, + DefaultOrgRole: userInfo.Role, } if err = bus.Dispatch(&cmd); err != nil { diff --git a/pkg/api/metrics.go b/pkg/api/metrics.go index 6d9165cd6ab..dad3b159ad6 100644 --- a/pkg/api/metrics.go +++ b/pkg/api/metrics.go @@ -1,36 +1,116 @@ package api import ( + "context" + "encoding/json" + "net/http" + "github.com/grafana/grafana/pkg/api/dtos" + "github.com/grafana/grafana/pkg/metrics" "github.com/grafana/grafana/pkg/middleware" - "math/rand" - "strconv" + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/tsdb" + "github.com/grafana/grafana/pkg/tsdb/testdata" + "github.com/grafana/grafana/pkg/util" ) -func GetTestMetrics(c *middleware.Context) { - from := c.QueryInt64("from") - to := c.QueryInt64("to") - maxDataPoints := c.QueryInt64("maxDataPoints") - stepInSeconds := (to - from) / maxDataPoints +// POST /api/tsdb/query +func QueryMetrics(c *middleware.Context, reqDto dtos.MetricRequest) Response { + timeRange := tsdb.NewTimeRange(reqDto.From, reqDto.To) - result := dtos.MetricQueryResultDto{} - result.Data = make([]dtos.MetricQueryResultDataDto, 1) + request := &tsdb.Request{TimeRange: timeRange} - for seriesIndex := range result.Data { - points := make([][2]float64, maxDataPoints) - walker := rand.Float64() * 100 - time := from - - for i := range points { - points[i][0] = walker - points[i][1] = float64(time) - walker += rand.Float64() - 0.5 - time += stepInSeconds - } - - result.Data[seriesIndex].Target = "test-series-" + strconv.Itoa(seriesIndex) - result.Data[seriesIndex].DataPoints = points + for _, query := range reqDto.Queries { + request.Queries = append(request.Queries, &tsdb.Query{ + RefId: query.Get("refId").MustString("A"), + MaxDataPoints: query.Get("maxDataPoints").MustInt64(100), + IntervalMs: query.Get("intervalMs").MustInt64(1000), + Model: query, + DataSource: &models.DataSource{ + Name: "Grafana TestDataDB", + Type: "grafana-testdata-datasource", + }, + }) } - c.JSON(200, &result) + resp, err := tsdb.HandleRequest(context.TODO(), request) + if err != nil { + return ApiError(500, "Metric request error", err) + } + + return Json(200, &resp) +} + +// GET /api/tsdb/testdata/scenarios +func GetTestDataScenarios(c *middleware.Context) Response { + result := make([]interface{}, 0) + + for _, scenario := range testdata.ScenarioRegistry { + result = append(result, map[string]interface{}{ + "id": scenario.Id, + "name": scenario.Name, + "description": scenario.Description, + "stringInput": scenario.StringInput, + }) + } + + return Json(200, &result) +} + +func GetInternalMetrics(c *middleware.Context) Response { + if metrics.UseNilMetrics { + return Json(200, util.DynMap{"message": "Metrics disabled"}) + } + + snapshots := metrics.MetricStats.GetSnapshots() + + resp := make(map[string]interface{}) + + for _, m := range snapshots { + metricName := m.Name() + m.StringifyTags() + + switch metric := m.(type) { + case metrics.Gauge: + resp[metricName] = map[string]interface{}{ + "value": metric.Value(), + } + case metrics.Counter: + resp[metricName] = map[string]interface{}{ + "count": metric.Count(), + } + case metrics.Timer: + percentiles := metric.Percentiles([]float64{0.25, 0.75, 0.90, 0.99}) + resp[metricName] = map[string]interface{}{ + "count": metric.Count(), + "min": metric.Min(), + "max": metric.Max(), + "mean": metric.Mean(), + "std": metric.StdDev(), + "p25": percentiles[0], + "p75": percentiles[1], + "p90": percentiles[2], + "p99": percentiles[3], + } + } + } + + var b []byte + var err error + if b, err = json.MarshalIndent(resp, "", " "); err != nil { + return ApiError(500, "body json marshal", err) + } + + return &NormalResponse{ + body: b, + status: 200, + header: http.Header{ + "Content-Type": []string{"application/json"}, + }, + } +} + +// Genereates a index out of range error +func GenerateError(c *middleware.Context) Response { + var array []string + return Json(200, array[20]) } diff --git a/pkg/api/org.go b/pkg/api/org.go index 61af62311c6..26b2cf92fd8 100644 --- a/pkg/api/org.go +++ b/pkg/api/org.go @@ -152,6 +152,9 @@ func updateOrgAddressHelper(form dtos.UpdateOrgAddressForm, orgId int64) Respons // GET /api/orgs/:orgId func DeleteOrgById(c *middleware.Context) Response { if err := bus.Dispatch(&m.DeleteOrgCommand{Id: c.ParamsInt64(":orgId")}); err != nil { + if err == m.ErrOrgNotFound { + return ApiError(404, "Failed to delete organization. ID not found", nil) + } return ApiError(500, "Failed to update organization", err) } return ApiSuccess("Organization deleted") diff --git a/pkg/api/org_users.go b/pkg/api/org_users.go index 03570619e6b..02c376eed30 100644 --- a/pkg/api/org_users.go +++ b/pkg/api/org_users.go @@ -38,6 +38,9 @@ func addOrgUserHelper(cmd m.AddOrgUserCommand) Response { cmd.UserId = userToAdd.Id if err := bus.Dispatch(&cmd); err != nil { + if err == m.ErrOrgUserAlreadyAdded { + return ApiError(409, "User is already member of this organization", nil) + } return ApiError(500, "Could not add user to organization", err) } diff --git a/pkg/api/playlist.go b/pkg/api/playlist.go index 7aa3c7d0057..a6c2da26dd8 100644 --- a/pkg/api/playlist.go +++ b/pkg/api/playlist.go @@ -26,6 +26,18 @@ func ValidateOrgPlaylist(c *middleware.Context) { c.JsonApiErr(403, "You are not allowed to edit/view playlist", nil) return } + + items, itemsErr := LoadPlaylistItemDTOs(id) + + if itemsErr != nil { + c.JsonApiErr(404, "Playlist items not found", err) + return + } + + if len(items) == 0 { + c.JsonApiErr(404, "Playlist is empty", itemsErr) + return + } } func SearchPlaylists(c *middleware.Context) Response { diff --git a/pkg/api/playlist_play.go b/pkg/api/playlist_play.go index f3bae6cbcd3..780767531a8 100644 --- a/pkg/api/playlist_play.go +++ b/pkg/api/playlist_play.go @@ -1,16 +1,18 @@ package api import ( + "sort" "strconv" + "github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/bus" _ "github.com/grafana/grafana/pkg/log" m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/search" ) -func populateDashboardsById(dashboardByIds []int64) ([]m.PlaylistDashboardDto, error) { - result := make([]m.PlaylistDashboardDto, 0) +func populateDashboardsById(dashboardByIds []int64, dashboardIdOrder map[int64]int) (dtos.PlaylistDashboardsSlice, error) { + result := make(dtos.PlaylistDashboardsSlice, 0) if len(dashboardByIds) > 0 { dashboardQuery := m.GetDashboardsQuery{DashboardIds: dashboardByIds} @@ -18,12 +20,13 @@ func populateDashboardsById(dashboardByIds []int64) ([]m.PlaylistDashboardDto, e return result, err } - for _, item := range *dashboardQuery.Result { - result = append(result, m.PlaylistDashboardDto{ + for _, item := range dashboardQuery.Result { + result = append(result, dtos.PlaylistDashboard{ Id: item.Id, Slug: item.Slug, Title: item.Title, Uri: "db/" + item.Slug, + Order: dashboardIdOrder[item.Id], }) } } @@ -31,8 +34,8 @@ func populateDashboardsById(dashboardByIds []int64) ([]m.PlaylistDashboardDto, e return result, nil } -func populateDashboardsByTag(orgId, userId int64, dashboardByTag []string) []m.PlaylistDashboardDto { - result := make([]m.PlaylistDashboardDto, 0) +func populateDashboardsByTag(orgId, userId int64, dashboardByTag []string, dashboardTagOrder map[string]int) dtos.PlaylistDashboardsSlice { + result := make(dtos.PlaylistDashboardsSlice, 0) if len(dashboardByTag) > 0 { for _, tag := range dashboardByTag { @@ -47,10 +50,11 @@ func populateDashboardsByTag(orgId, userId int64, dashboardByTag []string) []m.P if err := bus.Dispatch(&searchQuery); err == nil { for _, item := range searchQuery.Result { - result = append(result, m.PlaylistDashboardDto{ + result = append(result, dtos.PlaylistDashboard{ Id: item.Id, Title: item.Title, Uri: item.Uri, + Order: dashboardTagOrder[tag], }) } } @@ -60,28 +64,33 @@ func populateDashboardsByTag(orgId, userId int64, dashboardByTag []string) []m.P return result } -func LoadPlaylistDashboards(orgId, userId, playlistId int64) ([]m.PlaylistDashboardDto, error) { +func LoadPlaylistDashboards(orgId, userId, playlistId int64) (dtos.PlaylistDashboardsSlice, error) { playlistItems, _ := LoadPlaylistItems(playlistId) dashboardByIds := make([]int64, 0) dashboardByTag := make([]string, 0) + dashboardIdOrder := make(map[int64]int) + dashboardTagOrder := make(map[string]int) for _, i := range playlistItems { if i.Type == "dashboard_by_id" { dashboardId, _ := strconv.ParseInt(i.Value, 10, 64) dashboardByIds = append(dashboardByIds, dashboardId) + dashboardIdOrder[dashboardId] = i.Order } if i.Type == "dashboard_by_tag" { dashboardByTag = append(dashboardByTag, i.Value) + dashboardTagOrder[i.Value] = i.Order } } - result := make([]m.PlaylistDashboardDto, 0) + result := make(dtos.PlaylistDashboardsSlice, 0) - var k, _ = populateDashboardsById(dashboardByIds) + var k, _ = populateDashboardsById(dashboardByIds, dashboardIdOrder) result = append(result, k...) - result = append(result, populateDashboardsByTag(orgId, userId, dashboardByTag)...) + result = append(result, populateDashboardsByTag(orgId, userId, dashboardByTag, dashboardTagOrder)...) + sort.Sort(sort.Reverse(result)) return result, nil } diff --git a/pkg/api/pluginproxy/pluginproxy.go b/pkg/api/pluginproxy/pluginproxy.go index 92d07988b64..21d40ecb948 100644 --- a/pkg/api/pluginproxy/pluginproxy.go +++ b/pkg/api/pluginproxy/pluginproxy.go @@ -88,7 +88,7 @@ func NewApiPluginProxy(ctx *middleware.Context, proxyPath string, route *plugins } for key, value := range headers { - log.Info("setting key %v value %v", key, value[0]) + log.Trace("setting key %v value %v", key, value[0]) req.Header.Set(key, value[0]) } } diff --git a/pkg/api/plugins.go b/pkg/api/plugins.go index 0411c0746ef..9d25b9c331e 100644 --- a/pkg/api/plugins.go +++ b/pkg/api/plugins.go @@ -8,12 +8,14 @@ import ( "github.com/grafana/grafana/pkg/middleware" m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/plugins" + "github.com/grafana/grafana/pkg/setting" ) func GetPluginList(c *middleware.Context) Response { typeFilter := c.Query("type") enabledFilter := c.Query("enabled") embeddedFilter := c.Query("embedded") + coreFilter := c.Query("core") pluginSettingsMap, err := plugins.GetPluginSettings(c.OrgId) @@ -28,16 +30,24 @@ func GetPluginList(c *middleware.Context) Response { continue } + // filter out core plugins + if coreFilter == "0" && pluginDef.IsCorePlugin { + continue + } + // filter on type if typeFilter != "" && typeFilter != pluginDef.Type { continue } listItem := dtos.PluginListItem{ - Id: pluginDef.Id, - Name: pluginDef.Name, - Type: pluginDef.Type, - Info: &pluginDef.Info, + Id: pluginDef.Id, + Name: pluginDef.Name, + Type: pluginDef.Type, + Info: &pluginDef.Info, + LatestVersion: pluginDef.GrafanaNetVersion, + HasUpdate: pluginDef.GrafanaNetHasUpdate, + DefaultNavUrl: pluginDef.DefaultNavUrl, } if pluginSetting, exists := pluginSettingsMap[pluginDef.Id]; exists { @@ -45,6 +55,10 @@ func GetPluginList(c *middleware.Context) Response { listItem.Pinned = pluginSetting.Pinned } + if listItem.DefaultNavUrl == "" || !listItem.Enabled { + listItem.DefaultNavUrl = setting.AppSubUrl + "/plugins/" + listItem.Id + "/edit" + } + // filter out disabled if enabledFilter == "1" && !listItem.Enabled { continue @@ -81,6 +95,8 @@ func GetPluginSettingById(c *middleware.Context) Response { BaseUrl: def.BaseUrl, Module: def.Module, DefaultNavUrl: def.DefaultNavUrl, + LatestVersion: def.GrafanaNetVersion, + HasUpdate: def.GrafanaNetHasUpdate, } query := m.GetPluginSettingByIdQuery{PluginId: pluginId, OrgId: c.OrgId} @@ -146,15 +162,17 @@ func GetPluginReadme(c *middleware.Context) Response { func ImportDashboard(c *middleware.Context, apiCmd dtos.ImportDashboardCommand) Response { cmd := plugins.ImportDashboardCommand{ - OrgId: c.OrgId, - UserId: c.UserId, - PluginId: apiCmd.PluginId, - Path: apiCmd.Path, - Inputs: apiCmd.Inputs, + OrgId: c.OrgId, + UserId: c.UserId, + PluginId: apiCmd.PluginId, + Path: apiCmd.Path, + Inputs: apiCmd.Inputs, + Overwrite: apiCmd.Overwrite, + Dashboard: apiCmd.Dashboard, } if err := bus.Dispatch(&cmd); err != nil { - return ApiError(500, "Failed to install dashboard", err) + return ApiError(500, "Failed to import dashboard", err) } return Json(200, cmd.Result) diff --git a/pkg/api/preferences.go b/pkg/api/preferences.go new file mode 100644 index 00000000000..795b8994470 --- /dev/null +++ b/pkg/api/preferences.go @@ -0,0 +1,73 @@ +package api + +import ( + "github.com/grafana/grafana/pkg/api/dtos" + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/middleware" + m "github.com/grafana/grafana/pkg/models" +) + +// POST /api/preferences/set-home-dash +func SetHomeDashboard(c *middleware.Context, cmd m.SavePreferencesCommand) Response { + + cmd.UserId = c.UserId + cmd.OrgId = c.OrgId + + if err := bus.Dispatch(&cmd); err != nil { + return ApiError(500, "Failed to set home dashboard", err) + } + + return ApiSuccess("Home dashboard set") +} + +// GET /api/user/preferences +func GetUserPreferences(c *middleware.Context) Response { + return getPreferencesFor(c.OrgId, c.UserId) +} + +func getPreferencesFor(orgId int64, userId int64) Response { + prefsQuery := m.GetPreferencesQuery{UserId: userId, OrgId: orgId} + + if err := bus.Dispatch(&prefsQuery); err != nil { + return ApiError(500, "Failed to get preferences", err) + } + + dto := dtos.Prefs{ + Theme: prefsQuery.Result.Theme, + HomeDashboardId: prefsQuery.Result.HomeDashboardId, + Timezone: prefsQuery.Result.Timezone, + } + + return Json(200, &dto) +} + +// PUT /api/user/preferences +func UpdateUserPreferences(c *middleware.Context, dtoCmd dtos.UpdatePrefsCmd) Response { + return updatePreferencesFor(c.OrgId, c.UserId, &dtoCmd) +} + +func updatePreferencesFor(orgId int64, userId int64, dtoCmd *dtos.UpdatePrefsCmd) Response { + saveCmd := m.SavePreferencesCommand{ + UserId: userId, + OrgId: orgId, + Theme: dtoCmd.Theme, + Timezone: dtoCmd.Timezone, + HomeDashboardId: dtoCmd.HomeDashboardId, + } + + if err := bus.Dispatch(&saveCmd); err != nil { + return ApiError(500, "Failed to save preferences", err) + } + + return ApiSuccess("Preferences updated") +} + +// GET /api/org/preferences +func GetOrgPreferences(c *middleware.Context) Response { + return getPreferencesFor(c.OrgId, 0) +} + +// PUT /api/org/preferences +func UpdateOrgPreferences(c *middleware.Context, dtoCmd dtos.UpdatePrefsCmd) Response { + return updatePreferencesFor(c.OrgId, 0, &dtoCmd) +} diff --git a/pkg/api/render.go b/pkg/api/render.go index 9ed0c5ee6d7..6018656badb 100644 --- a/pkg/api/render.go +++ b/pkg/api/render.go @@ -6,35 +6,21 @@ import ( "github.com/grafana/grafana/pkg/components/renderer" "github.com/grafana/grafana/pkg/middleware" - "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util" ) func RenderToPng(c *middleware.Context) { queryReader := util.NewUrlQueryReader(c.Req.URL) queryParams := fmt.Sprintf("?%s", c.Req.URL.RawQuery) - sessionId := c.Session.ID() - - // Handle api calls authenticated without session - if sessionId == "" && c.ApiKeyId != 0 { - c.Session.Start(c) - c.Session.Set(middleware.SESS_KEY_APIKEY, c.ApiKeyId) - // release will make sure the new session is persisted before - // we spin up phantomjs - c.Session.Release() - // cleanup session after render is complete - defer func() { c.Session.Destory(c) }() - } renderOpts := &renderer.RenderOpts{ - Url: c.Params("*") + queryParams, - Width: queryReader.Get("width", "800"), - Height: queryReader.Get("height", "400"), - SessionId: c.Session.ID(), - Timeout: queryReader.Get("timeout", "15"), + Path: c.Params("*") + queryParams, + Width: queryReader.Get("width", "800"), + Height: queryReader.Get("height", "400"), + OrgId: c.OrgId, + Timeout: queryReader.Get("timeout", "30"), } - renderOpts.Url = setting.ToAbsUrl(renderOpts.Url) pngPath, err := renderer.RenderToPng(renderOpts) if err != nil { diff --git a/pkg/api/search.go b/pkg/api/search.go index 5ec95971033..c68dc51e986 100644 --- a/pkg/api/search.go +++ b/pkg/api/search.go @@ -4,6 +4,7 @@ import ( "strconv" "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/metrics" "github.com/grafana/grafana/pkg/middleware" "github.com/grafana/grafana/pkg/services/search" ) @@ -42,5 +43,6 @@ func Search(c *middleware.Context) { return } + c.TimeRequest(metrics.M_Api_Dashboard_Search) c.JSON(200, searchQuery.Result) } diff --git a/pkg/api/user.go b/pkg/api/user.go index 5af243eeb22..a22ad028288 100644 --- a/pkg/api/user.go +++ b/pkg/api/user.go @@ -4,6 +4,7 @@ import ( "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/middleware" m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util" ) @@ -29,6 +30,14 @@ func getUserUserProfile(userId int64) Response { // POST /api/user func UpdateSignedInUser(c *middleware.Context, cmd m.UpdateUserCommand) Response { + if setting.AuthProxyEnabled { + if setting.AuthProxyHeaderProperty == "email" && cmd.Email != c.Email { + return ApiError(400, "Not allowed to change email when auth proxy is using email property", nil) + } + if setting.AuthProxyHeaderProperty == "username" && cmd.Login != c.Login { + return ApiError(400, "Not allowed to change username when auth proxy is using username property", nil) + } + } cmd.UserId = c.UserId return handleUpdateUser(cmd) } @@ -39,6 +48,24 @@ func UpdateUser(c *middleware.Context, cmd m.UpdateUserCommand) Response { return handleUpdateUser(cmd) } +//POST /api/users/:id/using/:orgId +func UpdateUserActiveOrg(c *middleware.Context) Response { + userId := c.ParamsInt64(":id") + orgId := c.ParamsInt64(":orgId") + + if !validateUsingOrg(userId, orgId) { + return ApiError(401, "Not a valid organization", nil) + } + + cmd := m.SetUsingOrgCommand{UserId: userId, OrgId: orgId} + + if err := bus.Dispatch(&cmd); err != nil { + return ApiError(500, "Failed change active organization", err) + } + + return ApiSuccess("Active organization changed") +} + func handleUpdateUser(cmd m.UpdateUserCommand) Response { if len(cmd.Login) == 0 { cmd.Login = cmd.Email @@ -109,7 +136,28 @@ func UserSetUsingOrg(c *middleware.Context) Response { return ApiSuccess("Active organization changed") } +// GET /profile/switch-org/:id +func ChangeActiveOrgAndRedirectToHome(c *middleware.Context) { + orgId := c.ParamsInt64(":id") + + if !validateUsingOrg(c.UserId, orgId) { + NotFoundHandler(c) + } + + cmd := m.SetUsingOrgCommand{UserId: c.UserId, OrgId: orgId} + + if err := bus.Dispatch(&cmd); err != nil { + NotFoundHandler(c) + } + + c.Redirect(setting.AppSubUrl + "/") +} + func ChangeUserPassword(c *middleware.Context, cmd m.ChangeUserPasswordCommand) Response { + if setting.LdapEnabled || setting.AuthProxyEnabled { + return ApiError(400, "Not allowed to change password when LDAP or Auth Proxy is enabled", nil) + } + userQuery := m.GetUserByIdQuery{Id: c.UserId} if err := bus.Dispatch(&userQuery); err != nil { @@ -121,8 +169,9 @@ func ChangeUserPassword(c *middleware.Context, cmd m.ChangeUserPasswordCommand) return ApiError(401, "Invalid old password", nil) } - if len(cmd.NewPassword) < 4 { - return ApiError(400, "New password too short", nil) + password := m.Password(cmd.NewPassword) + if password.IsWeak() { + return ApiError(400, "New password is too short", nil) } cmd.UserId = c.UserId @@ -144,3 +193,34 @@ func SearchUsers(c *middleware.Context) Response { return Json(200, query.Result) } + +func SetHelpFlag(c *middleware.Context) Response { + flag := c.ParamsInt64(":id") + + bitmask := &c.HelpFlags1 + bitmask.AddFlag(m.HelpFlags1(flag)) + + cmd := m.SetUserHelpFlagCommand{ + UserId: c.UserId, + HelpFlags1: *bitmask, + } + + if err := bus.Dispatch(&cmd); err != nil { + return ApiError(500, "Failed to update help flag", err) + } + + return Json(200, &util.DynMap{"message": "Help flag set", "helpFlags1": cmd.HelpFlags1}) +} + +func ClearHelpFlags(c *middleware.Context) Response { + cmd := m.SetUserHelpFlagCommand{ + UserId: c.UserId, + HelpFlags1: m.HelpFlags1(0), + } + + if err := bus.Dispatch(&cmd); err != nil { + return ApiError(500, "Failed to update help flag", err) + } + + return Json(200, &util.DynMap{"message": "Help flag set", "helpFlags1": cmd.HelpFlags1}) +} diff --git a/pkg/bus/bus.go b/pkg/bus/bus.go index 6eb4b741a27..59d4592766e 100644 --- a/pkg/bus/bus.go +++ b/pkg/bus/bus.go @@ -1,18 +1,22 @@ package bus import ( + "context" "fmt" "reflect" ) type HandlerFunc interface{} +type CtxHandlerFunc func() type Msg interface{} type Bus interface { Dispatch(msg Msg) error + DispatchCtx(ctx context.Context, msg Msg) error Publish(msg Msg) error AddHandler(handler HandlerFunc) + AddCtxHandler(handler HandlerFunc) AddEventListener(handler HandlerFunc) AddWildcardListener(handler HandlerFunc) } @@ -34,6 +38,27 @@ func New() Bus { return bus } +func (b *InProcBus) DispatchCtx(ctx context.Context, msg Msg) error { + var msgName = reflect.TypeOf(msg).Elem().Name() + + var handler = b.handlers[msgName] + if handler == nil { + return fmt.Errorf("handler not found for %s", msgName) + } + + var params = make([]reflect.Value, 2) + params[0] = reflect.ValueOf(ctx) + params[1] = reflect.ValueOf(msg) + + ret := reflect.ValueOf(handler).Call(params) + err := ret[0].Interface() + if err == nil { + return nil + } else { + return err.(error) + } +} + func (b *InProcBus) Dispatch(msg Msg) error { var msgName = reflect.TypeOf(msg).Elem().Name() @@ -90,6 +115,12 @@ func (b *InProcBus) AddHandler(handler HandlerFunc) { b.handlers[queryTypeName] = handler } +func (b *InProcBus) AddCtxHandler(handler HandlerFunc) { + handlerType := reflect.TypeOf(handler) + queryTypeName := handlerType.In(1).Elem().Name() + b.handlers[queryTypeName] = handler +} + func (b *InProcBus) AddEventListener(handler HandlerFunc) { handlerType := reflect.TypeOf(handler) eventName := handlerType.In(0).Elem().Name() @@ -105,6 +136,11 @@ func AddHandler(implName string, handler HandlerFunc) { globalBus.AddHandler(handler) } +// Package level functions +func AddCtxHandler(implName string, handler HandlerFunc) { + globalBus.AddCtxHandler(handler) +} + // Package level functions func AddEventListener(handler HandlerFunc) { globalBus.AddEventListener(handler) @@ -118,6 +154,10 @@ func Dispatch(msg Msg) error { return globalBus.Dispatch(msg) } +func DispatchCtx(ctx context.Context, msg Msg) error { + return globalBus.DispatchCtx(ctx, msg) +} + func Publish(msg Msg) error { return globalBus.Publish(msg) } diff --git a/pkg/cmd/grafana-cli/commands/command_line.go b/pkg/cmd/grafana-cli/commands/command_line.go index edbdc03d7c2..ce5d04c1bb5 100644 --- a/pkg/cmd/grafana-cli/commands/command_line.go +++ b/pkg/cmd/grafana-cli/commands/command_line.go @@ -16,6 +16,9 @@ type CommandLine interface { GlobalString(name string) string FlagNames() (names []string) Generic(name string) interface{} + + PluginDirectory() string + RepoDirectory() string } type contextCommandLine struct { @@ -33,3 +36,11 @@ func (c *contextCommandLine) ShowVersion() { func (c *contextCommandLine) Application() *cli.App { return c.App } + +func (c *contextCommandLine) PluginDirectory() string { + return c.GlobalString("pluginsDir") +} + +func (c *contextCommandLine) RepoDirectory() string { + return c.GlobalString("repo") +} diff --git a/pkg/cmd/grafana-cli/commands/commands.go b/pkg/cmd/grafana-cli/commands/commands.go index 55a0e2660ec..8b2ecfcf7f5 100644 --- a/pkg/cmd/grafana-cli/commands/commands.go +++ b/pkg/cmd/grafana-cli/commands/commands.go @@ -1,23 +1,56 @@ package commands import ( - "github.com/codegangsta/cli" - "github.com/grafana/grafana/pkg/cmd/grafana-cli/log" + "flag" "os" + + "github.com/codegangsta/cli" + "github.com/fatih/color" + "github.com/grafana/grafana/pkg/cmd/grafana-cli/logger" + "github.com/grafana/grafana/pkg/services/sqlstore" + "github.com/grafana/grafana/pkg/setting" ) -func runCommand(command func(commandLine CommandLine) error) func(context *cli.Context) { +var configFile = flag.String("config", "", "path to config file") +var homePath = flag.String("homepath", "", "path to grafana install/home path, defaults to working directory") + +func runDbCommand(command func(commandLine CommandLine) error) func(context *cli.Context) { return func(context *cli.Context) { + flag.Parse() + setting.NewConfigContext(&setting.CommandLineArgs{ + Config: *configFile, + HomePath: *homePath, + Args: flag.Args(), + }) + + sqlstore.NewEngine() + cmd := &contextCommandLine{context} if err := command(cmd); err != nil { - log.Error("\nError: ") - log.Errorf("%s\n\n", err) + logger.Errorf("\n%s: ", color.RedString("Error")) + logger.Errorf("%s\n\n", err) cmd.ShowHelp() os.Exit(1) } else { - log.Info("\nRestart grafana after installing plugins . \n\n") + logger.Info("\n\n") + } + } +} + +func runPluginCommand(command func(commandLine CommandLine) error) func(context *cli.Context) { + return func(context *cli.Context) { + + cmd := &contextCommandLine{context} + if err := command(cmd); err != nil { + logger.Errorf("\n%s: ", color.RedString("Error")) + logger.Errorf("%s %s\n\n", color.RedString("✗"), err) + + cmd.ShowHelp() + os.Exit(1) + } else { + logger.Info("\nRestart grafana after installing plugins . \n\n") } } } @@ -25,28 +58,43 @@ func runCommand(command func(commandLine CommandLine) error) func(context *cli.C var pluginCommands = []cli.Command{ { Name: "install", - Usage: "install ", - Action: runCommand(installCommand), + Usage: "install ", + Action: runPluginCommand(installCommand), }, { Name: "list-remote", Usage: "list remote available plugins", - Action: runCommand(listremoteCommand), + Action: runPluginCommand(listremoteCommand), }, { - Name: "upgrade", - Usage: "upgrade ", - Action: runCommand(upgradeCommand), + Name: "list-versions", + Usage: "list-versions ", + Action: runPluginCommand(listversionsCommand), }, { - Name: "upgrade-all", - Usage: "upgrades all your installed plugins", - Action: runCommand(upgradeAllCommand), + Name: "update", + Usage: "update ", + Aliases: []string{"upgrade"}, + Action: runPluginCommand(upgradeCommand), + }, { + Name: "update-all", + Aliases: []string{"upgrade-all"}, + Usage: "update all your installed plugins", + Action: runPluginCommand(upgradeAllCommand), }, { Name: "ls", Usage: "list all installed plugins", - Action: runCommand(lsCommand), + Action: runPluginCommand(lsCommand), }, { - Name: "remove", - Usage: "remove ", - Action: runCommand(removeCommand), + Name: "uninstall", + Aliases: []string{"remove"}, + Usage: "uninstall ", + Action: runPluginCommand(removeCommand), + }, +} + +var adminCommands = []cli.Command{ + { + Name: "reset-admin-password", + Usage: "reset-admin-password ", + Action: runDbCommand(resetPasswordCommand), }, } @@ -56,4 +104,9 @@ var Commands = []cli.Command{ Usage: "Manage plugins for grafana", Subcommands: pluginCommands, }, + { + Name: "admin", + Usage: "Grafana admin commands", + Subcommands: adminCommands, + }, } diff --git a/pkg/cmd/grafana-cli/commands/commandstest/fake_commandLine.go b/pkg/cmd/grafana-cli/commands/commandstest/fake_commandLine.go index 4a070b5a192..8366e0feb15 100644 --- a/pkg/cmd/grafana-cli/commands/commandstest/fake_commandLine.go +++ b/pkg/cmd/grafana-cli/commands/commandstest/fake_commandLine.go @@ -93,3 +93,11 @@ func (fcli *FakeCommandLine) Args() cli.Args { func (fcli *FakeCommandLine) ShowVersion() { fcli.VersionShown = true } + +func (fcli *FakeCommandLine) RepoDirectory() string { + return fcli.GlobalString("repo") +} + +func (fcli *FakeCommandLine) PluginDirectory() string { + return fcli.GlobalString("pluginsDir") +} diff --git a/pkg/cmd/grafana-cli/commands/install_command.go b/pkg/cmd/grafana-cli/commands/install_command.go index 0f783d5d3ff..1f391ea10b3 100644 --- a/pkg/cmd/grafana-cli/commands/install_command.go +++ b/pkg/cmd/grafana-cli/commands/install_command.go @@ -14,7 +14,7 @@ import ( "strings" "github.com/fatih/color" - "github.com/grafana/grafana/pkg/cmd/grafana-cli/log" + "github.com/grafana/grafana/pkg/cmd/grafana-cli/logger" m "github.com/grafana/grafana/pkg/cmd/grafana-cli/models" s "github.com/grafana/grafana/pkg/cmd/grafana-cli/services" ) @@ -25,7 +25,7 @@ func validateInput(c CommandLine, pluginFolder string) error { return errors.New("please specify plugin to install") } - pluginsDir := c.GlobalString("pluginsDir") + pluginsDir := c.PluginDirectory() if pluginsDir == "" { return errors.New("missing pluginsDir flag") } @@ -46,7 +46,7 @@ func validateInput(c CommandLine, pluginFolder string) error { } func installCommand(c CommandLine) error { - pluginFolder := c.GlobalString("pluginsDir") + pluginFolder := c.PluginDirectory() if err := validateInput(c, pluginFolder); err != nil { return err } @@ -58,8 +58,8 @@ func installCommand(c CommandLine) error { } func InstallPlugin(pluginName, version string, c CommandLine) error { - plugin, err := s.GetPlugin(pluginName, c.GlobalString("repo")) - pluginFolder := c.GlobalString("pluginsDir") + plugin, err := s.GetPlugin(pluginName, c.RepoDirectory()) + pluginFolder := c.PluginDirectory() if err != nil { return err } @@ -78,25 +78,24 @@ func InstallPlugin(pluginName, version string, c CommandLine) error { pluginName, version) - log.Infof("installing %v @ %v\n", plugin.Id, version) - log.Infof("from url: %v\n", downloadURL) - log.Infof("into: %v\n", pluginFolder) - log.Info("\n") + logger.Infof("installing %v @ %v\n", plugin.Id, version) + logger.Infof("from url: %v\n", downloadURL) + logger.Infof("into: %v\n", pluginFolder) + logger.Info("\n") err = downloadFile(plugin.Id, pluginFolder, downloadURL) if err != nil { return err } - log.Infof("%s Installed %s successfully \n", color.GreenString("✔"), plugin.Id) + logger.Infof("%s Installed %s successfully \n", color.GreenString("✔"), plugin.Id) - /* Enable once we need support for downloading depedencies res, _ := s.ReadPlugin(pluginFolder, pluginName) - for _, v := range res.Dependency.Plugins { + for _, v := range res.Dependencies.Plugins { InstallPlugin(v.Id, version, c) - log.Infof("Installed dependency: %v ✔\n", v.Id) + logger.Infof("Installed dependency: %v ✔\n", v.Id) } - */ + return err } @@ -120,16 +119,22 @@ func RemoveGitBuildFromName(pluginName, filename string) string { } var retryCount = 0 +var permissionsDeniedMessage = "Could not create %s. Permission denied. Make sure you have write access to plugindir" func downloadFile(pluginName, filePath, url string) (err error) { defer func() { if r := recover(); r != nil { retryCount++ - if retryCount == 1 { - log.Debug("\nFailed downloading. Will retry once.\n") - downloadFile(pluginName, filePath, url) + if retryCount < 3 { + fmt.Println("Failed downloading. Will retry once.") + err = downloadFile(pluginName, filePath, url) } else { - panic(r) + failure := fmt.Sprintf("%v", r) + if failure == "runtime error: makeslice: len out of range" { + err = fmt.Errorf("Corrupt http response from source. Please try again.\n") + } else { + panic(r) + } } } }() @@ -153,26 +158,30 @@ func downloadFile(pluginName, filePath, url string) (err error) { newFile := path.Join(filePath, RemoveGitBuildFromName(pluginName, zf.Name)) if zf.FileInfo().IsDir() { - os.Mkdir(newFile, 0777) + err := os.Mkdir(newFile, 0777) + if PermissionsError(err) { + return fmt.Errorf(permissionsDeniedMessage, newFile) + } } else { dst, err := os.Create(newFile) - if err != nil { - if strings.Contains(err.Error(), "permission denied") { - return fmt.Errorf( - "Could not create file %s. permission deined. Make sure you have write access to plugindir", - newFile) - } + if PermissionsError(err) { + return fmt.Errorf(permissionsDeniedMessage, newFile) } - defer dst.Close() + src, err := zf.Open() if err != nil { - log.Errorf("%v", err) + logger.Errorf("Failed to extract file: %v", err) } - defer src.Close() io.Copy(dst, src) + dst.Close() + src.Close() } } return nil } + +func PermissionsError(err error) bool { + return err != nil && strings.Contains(err.Error(), "permission denied") +} diff --git a/pkg/cmd/grafana-cli/commands/listremote_command.go b/pkg/cmd/grafana-cli/commands/listremote_command.go index 0f0c3077ab9..4798369def1 100644 --- a/pkg/cmd/grafana-cli/commands/listremote_command.go +++ b/pkg/cmd/grafana-cli/commands/listremote_command.go @@ -1,12 +1,12 @@ package commands import ( - "github.com/grafana/grafana/pkg/cmd/grafana-cli/log" + "github.com/grafana/grafana/pkg/cmd/grafana-cli/logger" s "github.com/grafana/grafana/pkg/cmd/grafana-cli/services" ) func listremoteCommand(c CommandLine) error { - plugin, err := s.ListAllPlugins(c.GlobalString("repo")) + plugin, err := s.ListAllPlugins(c.RepoDirectory()) if err != nil { return err @@ -18,7 +18,7 @@ func listremoteCommand(c CommandLine) error { pluginVersion = i.Versions[0].Version } - log.Infof("id: %v version: %s\n", i.Id, pluginVersion) + logger.Infof("id: %v version: %s\n", i.Id, pluginVersion) } return nil diff --git a/pkg/cmd/grafana-cli/commands/listversions_command.go b/pkg/cmd/grafana-cli/commands/listversions_command.go new file mode 100644 index 00000000000..95c536e94f0 --- /dev/null +++ b/pkg/cmd/grafana-cli/commands/listversions_command.go @@ -0,0 +1,36 @@ +package commands + +import ( + "errors" + + "github.com/grafana/grafana/pkg/cmd/grafana-cli/logger" + s "github.com/grafana/grafana/pkg/cmd/grafana-cli/services" +) + +func validateVersionInput(c CommandLine) error { + arg := c.Args().First() + if arg == "" { + return errors.New("please specify plugin to list versions for") + } + + return nil +} + +func listversionsCommand(c CommandLine) error { + if err := validateVersionInput(c); err != nil { + return err + } + + pluginToList := c.Args().First() + + plugin, err := s.GetPlugin(pluginToList, c.GlobalString("repo")) + if err != nil { + return err + } + + for _, i := range plugin.Versions { + logger.Infof("%v\n", i.Version) + } + + return nil +} diff --git a/pkg/cmd/grafana-cli/commands/ls_command.go b/pkg/cmd/grafana-cli/commands/ls_command.go index 796f6e500d1..7dcecb9d725 100644 --- a/pkg/cmd/grafana-cli/commands/ls_command.go +++ b/pkg/cmd/grafana-cli/commands/ls_command.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/fatih/color" - "github.com/grafana/grafana/pkg/cmd/grafana-cli/log" + "github.com/grafana/grafana/pkg/cmd/grafana-cli/logger" m "github.com/grafana/grafana/pkg/cmd/grafana-cli/models" s "github.com/grafana/grafana/pkg/cmd/grafana-cli/services" ) @@ -17,7 +17,7 @@ var validateLsCommand = func(pluginDir string) error { return errors.New("missing path flag") } - log.Debug("plugindir: " + pluginDir + "\n") + logger.Debug("plugindir: " + pluginDir + "\n") pluginDirInfo, err := s.IoHelper.Stat(pluginDir) if err != nil { @@ -32,7 +32,7 @@ var validateLsCommand = func(pluginDir string) error { } func lsCommand(c CommandLine) error { - pluginDir := c.GlobalString("pluginsDir") + pluginDir := c.PluginDirectory() if err := validateLsCommand(pluginDir); err != nil { return err } @@ -40,11 +40,11 @@ func lsCommand(c CommandLine) error { plugins := ls_getPlugins(pluginDir) if len(plugins) > 0 { - log.Info("installed plugins:\n") + logger.Info("installed plugins:\n") } for _, plugin := range plugins { - log.Infof("%s %s %s \n", plugin.Id, color.YellowString("@"), plugin.Info.Version) + logger.Infof("%s %s %s \n", plugin.Id, color.YellowString("@"), plugin.Info.Version) } return nil diff --git a/pkg/cmd/grafana-cli/commands/remove_command.go b/pkg/cmd/grafana-cli/commands/remove_command.go index e0ecbb2b788..d5ed73def05 100644 --- a/pkg/cmd/grafana-cli/commands/remove_command.go +++ b/pkg/cmd/grafana-cli/commands/remove_command.go @@ -2,34 +2,31 @@ package commands import ( "errors" - - "github.com/grafana/grafana/pkg/cmd/grafana-cli/log" + "fmt" m "github.com/grafana/grafana/pkg/cmd/grafana-cli/models" services "github.com/grafana/grafana/pkg/cmd/grafana-cli/services" + "strings" ) var getPluginss func(path string) []m.InstalledPlugin = services.GetLocalPlugins var removePlugin func(pluginPath, id string) error = services.RemoveInstalledPlugin func removeCommand(c CommandLine) error { - pluginPath := c.GlobalString("pluginsDir") - localPlugins := getPluginss(pluginPath) - - log.Info("remove!\n") + pluginPath := c.PluginDirectory() plugin := c.Args().First() - log.Info("plugin: " + plugin + "\n") if plugin == "" { return errors.New("Missing plugin parameter") } - log.Infof("plugins : \n%v\n", localPlugins) + err := removePlugin(pluginPath, plugin) - for _, p := range localPlugins { - if p.Id == c.Args().First() { - log.Infof("removing plugin %s", p.Id) - removePlugin(pluginPath, p.Id) + if err != nil { + if strings.Contains(err.Error(), "no such file or directory") { + return fmt.Errorf("Plugin does not exist") } + + return err } return nil diff --git a/pkg/cmd/grafana-cli/commands/reset_password_command.go b/pkg/cmd/grafana-cli/commands/reset_password_command.go new file mode 100644 index 00000000000..af2b8b3f89a --- /dev/null +++ b/pkg/cmd/grafana-cli/commands/reset_password_command.go @@ -0,0 +1,44 @@ +package commands + +import ( + "fmt" + + "github.com/fatih/color" + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/cmd/grafana-cli/logger" + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/util" +) + +const AdminUserId = 1 + +func resetPasswordCommand(c CommandLine) error { + newPassword := c.Args().First() + + password := models.Password(newPassword) + if password.IsWeak() { + return fmt.Errorf("New password is too short") + } + + userQuery := models.GetUserByIdQuery{Id: AdminUserId} + + if err := bus.Dispatch(&userQuery); err != nil { + return fmt.Errorf("Could not read user from database. Error: %v", err) + } + + passwordHashed := util.EncodePassword(newPassword, userQuery.Result.Salt) + + cmd := models.ChangeUserPasswordCommand{ + UserId: AdminUserId, + NewPassword: passwordHashed, + } + + if err := bus.Dispatch(&cmd); err != nil { + return fmt.Errorf("Failed to update user password") + } + + logger.Infof("\n") + logger.Infof("Admin password changed successfully %s", color.GreenString("✔")) + + return nil +} diff --git a/pkg/cmd/grafana-cli/commands/upgrade_all_command.go b/pkg/cmd/grafana-cli/commands/upgrade_all_command.go index e805e8e6f34..636292cce11 100644 --- a/pkg/cmd/grafana-cli/commands/upgrade_all_command.go +++ b/pkg/cmd/grafana-cli/commands/upgrade_all_command.go @@ -1,7 +1,7 @@ package commands import ( - "github.com/grafana/grafana/pkg/cmd/grafana-cli/log" + "github.com/grafana/grafana/pkg/cmd/grafana-cli/logger" m "github.com/grafana/grafana/pkg/cmd/grafana-cli/models" s "github.com/grafana/grafana/pkg/cmd/grafana-cli/services" "github.com/hashicorp/go-version" @@ -28,7 +28,7 @@ func ShouldUpgrade(installed string, remote m.Plugin) bool { } func upgradeAllCommand(c CommandLine) error { - pluginsDir := c.GlobalString("pluginsDir") + pluginsDir := c.PluginDirectory() localPlugins := s.GetLocalPlugins(pluginsDir) @@ -51,10 +51,18 @@ func upgradeAllCommand(c CommandLine) error { } for _, p := range pluginsToUpgrade { - log.Infof("Upgrading %v \n", p.Id) + logger.Infof("Updating %v \n", p.Id) - s.RemoveInstalledPlugin(pluginsDir, p.Id) - InstallPlugin(p.Id, "", c) + var err error + err = s.RemoveInstalledPlugin(pluginsDir, p.Id) + if err != nil { + return err + } + + err = InstallPlugin(p.Id, "", c) + if err != nil { + return err + } } return nil diff --git a/pkg/cmd/grafana-cli/commands/upgrade_command.go b/pkg/cmd/grafana-cli/commands/upgrade_command.go index b9ca834be6d..355ccab3d1c 100644 --- a/pkg/cmd/grafana-cli/commands/upgrade_command.go +++ b/pkg/cmd/grafana-cli/commands/upgrade_command.go @@ -1,11 +1,13 @@ package commands import ( + "github.com/fatih/color" + "github.com/grafana/grafana/pkg/cmd/grafana-cli/logger" s "github.com/grafana/grafana/pkg/cmd/grafana-cli/services" ) func upgradeCommand(c CommandLine) error { - pluginsDir := c.GlobalString("pluginsDir") + pluginsDir := c.PluginDirectory() pluginName := c.Args().First() localPlugin, err := s.ReadPlugin(pluginsDir, pluginName) @@ -14,20 +16,17 @@ func upgradeCommand(c CommandLine) error { return err } - remotePlugins, err2 := s.ListAllPlugins(c.GlobalString("repo")) + v, err2 := s.GetPlugin(localPlugin.Id, c.RepoDirectory()) if err2 != nil { return err2 } - for _, v := range remotePlugins.Plugins { - if localPlugin.Id == v.Id { - if ShouldUpgrade(localPlugin.Info.Version, v) { - s.RemoveInstalledPlugin(pluginsDir, pluginName) - return InstallPlugin(localPlugin.Id, "", c) - } - } + if ShouldUpgrade(localPlugin.Info.Version, v) { + s.RemoveInstalledPlugin(pluginsDir, pluginName) + return InstallPlugin(localPlugin.Id, "", c) } + logger.Infof("%s %s is up to date \n", color.GreenString("✔"), localPlugin.Id) return nil } diff --git a/pkg/cmd/grafana-cli/log/log.go b/pkg/cmd/grafana-cli/logger/logger.go similarity index 97% rename from pkg/cmd/grafana-cli/log/log.go rename to pkg/cmd/grafana-cli/logger/logger.go index c8222d60c81..de98a6f147b 100644 --- a/pkg/cmd/grafana-cli/log/log.go +++ b/pkg/cmd/grafana-cli/logger/logger.go @@ -1,4 +1,4 @@ -package log +package logger import ( "fmt" diff --git a/pkg/cmd/grafana-cli/main.go b/pkg/cmd/grafana-cli/main.go index b5b13ee36e0..658edd0f895 100644 --- a/pkg/cmd/grafana-cli/main.go +++ b/pkg/cmd/grafana-cli/main.go @@ -7,22 +7,17 @@ import ( "github.com/codegangsta/cli" "github.com/grafana/grafana/pkg/cmd/grafana-cli/commands" - "github.com/grafana/grafana/pkg/cmd/grafana-cli/log" + "github.com/grafana/grafana/pkg/cmd/grafana-cli/logger" + "github.com/grafana/grafana/pkg/cmd/grafana-cli/services" + "github.com/grafana/grafana/pkg/cmd/grafana-cli/utils" ) var version = "master" -func getGrafanaPluginDir() string { - os := runtime.GOOS - if os == "windows" { - return "C:\\opt\\grafana\\plugins" - } else { - return "/var/lib/grafana/plugins" - } -} - func main() { - SetupLogging() + setupLogging() + + services.Init(version) app := cli.NewApp() app.Name = "Grafana cli" @@ -34,7 +29,7 @@ func main() { cli.StringFlag{ Name: "pluginsDir", Usage: "path to the grafana plugin directory", - Value: getGrafanaPluginDir(), + Value: utils.GetGrafanaPluginDir(runtime.GOOS), EnvVar: "GF_PLUGIN_DIR", }, cli.StringFlag{ @@ -53,14 +48,14 @@ func main() { app.CommandNotFound = cmdNotFound if err := app.Run(os.Args); err != nil { - log.Errorf("%v", err) + logger.Errorf("%v", err) } } -func SetupLogging() { +func setupLogging() { for _, f := range os.Args { if f == "-D" || f == "--debug" || f == "-debug" { - log.SetDebug(true) + logger.SetDebug(true) } } } diff --git a/pkg/cmd/grafana-cli/models/model.go b/pkg/cmd/grafana-cli/models/model.go index 3a39c5fbe65..0700cb9a9e4 100644 --- a/pkg/cmd/grafana-cli/models/model.go +++ b/pkg/cmd/grafana-cli/models/model.go @@ -9,11 +9,11 @@ type InstalledPlugin struct { Name string `json:"name"` Type string `json:"type"` - Info PluginInfo `json:"info"` - Dependency Dependency `json:"dependencies"` + Info PluginInfo `json:"info"` + Dependencies Dependencies `json:"dependencies"` } -type Dependency struct { +type Dependencies struct { GrafanaVersion string `json:"grafanaVersion"` Plugins []Plugin `json:"plugins"` } diff --git a/pkg/cmd/grafana-cli/services/services.go b/pkg/cmd/grafana-cli/services/services.go index f0ad460842d..6c739f8b0ee 100644 --- a/pkg/cmd/grafana-cli/services/services.go +++ b/pkg/cmd/grafana-cli/services/services.go @@ -1,50 +1,97 @@ package services import ( + "crypto/tls" "encoding/json" "errors" "fmt" + "io/ioutil" + "net" + "net/http" + "net/url" "path" + "time" - "github.com/franela/goreq" - "github.com/grafana/grafana/pkg/cmd/grafana-cli/log" + "github.com/grafana/grafana/pkg/cmd/grafana-cli/logger" m "github.com/grafana/grafana/pkg/cmd/grafana-cli/models" ) -var IoHelper m.IoUtil = IoUtilImp{} +var ( + IoHelper m.IoUtil = IoUtilImp{} + HttpClient http.Client + grafanaVersion string +) + +func Init(version string) { + grafanaVersion = version + + tr := &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + }).DialContext, + MaxIdleConns: 100, + IdleConnTimeout: 90 * time.Second, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, + + TLSClientConfig: &tls.Config{InsecureSkipVerify: false}, + } + + HttpClient = http.Client{ + Timeout: time.Duration(10 * time.Second), + Transport: tr, + } +} func ListAllPlugins(repoUrl string) (m.PluginRepo, error) { - fullUrl := repoUrl + "/repo" - res, err := goreq.Request{Uri: fullUrl, MaxRedirects: 3}.Do() + body, err := sendRequest(repoUrl, "repo") + + if err != nil { + logger.Info("Failed to send request", "error", err) + return m.PluginRepo{}, fmt.Errorf("Failed to send request. error: %v", err) + } + if err != nil { return m.PluginRepo{}, err } - if res.StatusCode != 200 { - return m.PluginRepo{}, fmt.Errorf("Could not access %s statuscode %v", fullUrl, res.StatusCode) - } - var resp m.PluginRepo - err = res.Body.FromJsonTo(&resp) + var data m.PluginRepo + err = json.Unmarshal(body, &data) if err != nil { - return m.PluginRepo{}, errors.New("Could not load plugin data") + logger.Info("Failed to unmarshal graphite response error: %v", err) + return m.PluginRepo{}, err } - return resp, nil + return data, nil } func ReadPlugin(pluginDir, pluginName string) (m.InstalledPlugin, error) { - pluginDataPath := path.Join(pluginDir, pluginName, "plugin.json") - pluginData, _ := IoHelper.ReadFile(pluginDataPath) + distPluginDataPath := path.Join(pluginDir, pluginName, "dist", "plugin.json") + + var data []byte + var err error + data, err = IoHelper.ReadFile(distPluginDataPath) + + if err != nil { + pluginDataPath := path.Join(pluginDir, pluginName, "plugin.json") + data, err = IoHelper.ReadFile(pluginDataPath) + + if err != nil { + return m.InstalledPlugin{}, errors.New("Could not find dist/plugin.json or plugin.json on " + pluginName + " in " + pluginDir) + } + } res := m.InstalledPlugin{} - json.Unmarshal(pluginData, &res) + json.Unmarshal(data, &res) if res.Info.Version == "" { res.Info.Version = "0.0.0" } if res.Id == "" { - return m.InstalledPlugin{}, errors.New("could not read find plugin " + pluginName) + return m.InstalledPlugin{}, errors.New("could not find plugin " + pluginName + " in " + pluginDir) } return res, nil @@ -63,19 +110,66 @@ func GetLocalPlugins(pluginDir string) []m.InstalledPlugin { return result } -func RemoveInstalledPlugin(pluginPath, id string) error { - log.Infof("Removing plugin: %v\n", id) - return IoHelper.RemoveAll(path.Join(pluginPath, id)) +func RemoveInstalledPlugin(pluginPath, pluginName string) error { + logger.Infof("Removing plugin: %v\n", pluginName) + pluginDir := path.Join(pluginPath, pluginName) + + _, err := IoHelper.Stat(pluginDir) + if err != nil { + return err + } + + return IoHelper.RemoveAll(pluginDir) } func GetPlugin(pluginId, repoUrl string) (m.Plugin, error) { - resp, _ := ListAllPlugins(repoUrl) + body, err := sendRequest(repoUrl, "repo", pluginId) - for _, i := range resp.Plugins { - if i.Id == pluginId { - return i, nil - } + if err != nil { + logger.Info("Failed to send request", "error", err) + return m.Plugin{}, fmt.Errorf("Failed to send request. error: %v", err) } - return m.Plugin{}, errors.New("could not find plugin named \"" + pluginId + "\"") + if err != nil { + return m.Plugin{}, err + } + + var data m.Plugin + err = json.Unmarshal(body, &data) + if err != nil { + logger.Info("Failed to unmarshal graphite response error: %v", err) + return m.Plugin{}, err + } + + return data, nil +} + +func sendRequest(repoUrl string, subPaths ...string) ([]byte, error) { + u, _ := url.Parse(repoUrl) + for _, v := range subPaths { + u.Path = path.Join(u.Path, v) + } + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + + req.Header.Set("grafana-version", grafanaVersion) + req.Header.Set("User-Agent", "grafana "+grafanaVersion) + + if err != nil { + return []byte{}, err + } + + res, err := HttpClient.Do(req) + if err != nil { + return []byte{}, err + } + + if res.StatusCode/100 != 2 { + return []byte{}, fmt.Errorf("Api returned invalid status: %s", res.Status) + } + + body, err := ioutil.ReadAll(res.Body) + defer res.Body.Close() + + return body, err } diff --git a/pkg/cmd/grafana-cli/utils/grafana_path.go b/pkg/cmd/grafana-cli/utils/grafana_path.go new file mode 100644 index 00000000000..fa6dc46d783 --- /dev/null +++ b/pkg/cmd/grafana-cli/utils/grafana_path.go @@ -0,0 +1,46 @@ +package utils + +import ( + "os" + + "github.com/grafana/grafana/pkg/cmd/grafana-cli/logger" +) + +func GetGrafanaPluginDir(currentOS string) string { + //currentOS := runtime.GOOS + + if currentOS == "windows" { + return returnOsDefault(currentOS) + } + + pwd, err := os.Getwd() + + if err != nil { + logger.Error("Could not get current path. using default") + return returnOsDefault(currentOS) + } + + if isDevenvironment(pwd) { + return "../data/plugins" + } + + return returnOsDefault(currentOS) +} + +func isDevenvironment(pwd string) bool { + // if ../conf/defaults.ini exists, grafana is not installed as package + // that its in development environment. + _, err := os.Stat("../conf/defaults.ini") + return err == nil +} + +func returnOsDefault(currentOs string) string { + switch currentOs { + case "windows": + return "../data/plugins" + case "darwin": + return "/usr/local/var/lib/grafana/plugins" + default: //"linux" + return "/var/lib/grafana/plugins" + } +} diff --git a/pkg/cmd/grafana-server/main.go b/pkg/cmd/grafana-server/main.go index dad3f437390..46b1d5f2a95 100644 --- a/pkg/cmd/grafana-server/main.go +++ b/pkg/cmd/grafana-server/main.go @@ -13,18 +13,21 @@ import ( "time" "github.com/grafana/grafana/pkg/log" - "github.com/grafana/grafana/pkg/login" - "github.com/grafana/grafana/pkg/metrics" - "github.com/grafana/grafana/pkg/plugins" - "github.com/grafana/grafana/pkg/services/eventpublisher" - "github.com/grafana/grafana/pkg/services/notifications" - "github.com/grafana/grafana/pkg/services/search" + "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/setting" - "github.com/grafana/grafana/pkg/social" + + _ "github.com/grafana/grafana/pkg/services/alerting/conditions" + _ "github.com/grafana/grafana/pkg/services/alerting/notifiers" + _ "github.com/grafana/grafana/pkg/tsdb/graphite" + _ "github.com/grafana/grafana/pkg/tsdb/influxdb" + _ "github.com/grafana/grafana/pkg/tsdb/mqe" + _ "github.com/grafana/grafana/pkg/tsdb/opentsdb" + _ "github.com/grafana/grafana/pkg/tsdb/prometheus" + _ "github.com/grafana/grafana/pkg/tsdb/testdata" ) -var version = "3.0.0-pre1" +var version = "4.1.0" var commit = "NA" var buildstamp string var build_date string @@ -39,7 +42,6 @@ func init() { } func main() { - v := flag.Bool("v", false, "prints current version and exits") flag.Parse() if *v { @@ -48,33 +50,16 @@ func main() { } buildstampInt64, _ := strconv.ParseInt(buildstamp, 10, 64) + if buildstampInt64 == 0 { + buildstampInt64 = time.Now().Unix() + } setting.BuildVersion = version setting.BuildCommit = commit setting.BuildStamp = buildstampInt64 - go listenToSystemSignels() - - flag.Parse() - writePIDFile() - initRuntime() - - search.Init() - login.Init() - social.NewOAuthService() - eventpublisher.Init() - plugins.Init() - - if err := notifications.Init(); err != nil { - log.Fatal(3, "Notification service failed to initialize", err) - } - - if setting.ReportingEnabled { - go metrics.StartUsageReportLoop() - } - - StartServer() - exitChan <- 0 + server := NewGrafanaServer() + server.Start() } func initRuntime() { @@ -88,10 +73,13 @@ func initRuntime() { log.Fatal(3, err.Error()) } - log.Info("Starting Grafana") - log.Info("Version: %v, Commit: %v, Build date: %v", setting.BuildVersion, setting.BuildCommit, time.Unix(setting.BuildStamp, 0)) - setting.LogConfigurationInfo() + logger := log.New("main") + logger.Info("Starting Grafana", "version", version, "commit", commit, "compiled", time.Unix(setting.BuildStamp, 0)) + setting.LogConfigurationInfo() +} + +func initSql() { sqlstore.NewEngine() sqlstore.EnsureAdminUser() } @@ -114,26 +102,18 @@ func writePIDFile() { } } -func listenToSystemSignels() { +func listenToSystemSignals(server models.GrafanaServer) { signalChan := make(chan os.Signal, 1) + ignoreChan := make(chan os.Signal, 1) code := 0 - signal.Notify(signalChan, os.Interrupt) - signal.Notify(signalChan, os.Kill) - signal.Notify(signalChan, syscall.SIGTERM) + signal.Notify(ignoreChan, syscall.SIGHUP) + signal.Notify(signalChan, os.Interrupt, os.Kill, syscall.SIGTERM) select { case sig := <-signalChan: - log.Info("Received signal %s. shutting down", sig) + server.Shutdown(0, fmt.Sprintf("system signal: %s", sig)) case code = <-exitChan: - switch code { - case 0: - log.Info("Shutting down") - default: - log.Warn("Shutting down") - } + server.Shutdown(code, "startup error") } - - log.Close() - os.Exit(code) } diff --git a/pkg/cmd/grafana-server/server.go b/pkg/cmd/grafana-server/server.go new file mode 100644 index 00000000000..2a4682cbb4b --- /dev/null +++ b/pkg/cmd/grafana-server/server.go @@ -0,0 +1,150 @@ +package main + +import ( + "context" + "fmt" + "net/http" + "os" + "time" + + "gopkg.in/macaron.v1" + + "golang.org/x/sync/errgroup" + + "github.com/grafana/grafana/pkg/api" + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/login" + "github.com/grafana/grafana/pkg/metrics" + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/plugins" + "github.com/grafana/grafana/pkg/services/alerting" + "github.com/grafana/grafana/pkg/services/cleanup" + "github.com/grafana/grafana/pkg/services/eventpublisher" + "github.com/grafana/grafana/pkg/services/notifications" + "github.com/grafana/grafana/pkg/services/search" + "github.com/grafana/grafana/pkg/setting" + "github.com/grafana/grafana/pkg/social" +) + +func NewGrafanaServer() models.GrafanaServer { + rootCtx, shutdownFn := context.WithCancel(context.Background()) + childRoutines, childCtx := errgroup.WithContext(rootCtx) + + return &GrafanaServerImpl{ + context: childCtx, + shutdownFn: shutdownFn, + childRoutines: childRoutines, + log: log.New("server"), + } +} + +type GrafanaServerImpl struct { + context context.Context + shutdownFn context.CancelFunc + childRoutines *errgroup.Group + log log.Logger +} + +func (g *GrafanaServerImpl) Start() { + go listenToSystemSignals(g) + + writePIDFile() + initRuntime() + initSql() + metrics.Init() + search.Init() + login.Init() + social.NewOAuthService() + eventpublisher.Init() + plugins.Init() + + // init alerting + if setting.ExecuteAlerts { + engine := alerting.NewEngine() + g.childRoutines.Go(func() error { return engine.Run(g.context) }) + } + + // cleanup service + cleanUpService := cleanup.NewCleanUpService() + g.childRoutines.Go(func() error { return cleanUpService.Run(g.context) }) + + if err := notifications.Init(); err != nil { + g.log.Error("Notification service failed to initialize", "erro", err) + g.Shutdown(1, "Startup failed") + return + } + + g.startHttpServer() +} + +func (g *GrafanaServerImpl) startHttpServer() { + logger = log.New("http.server") + + var err error + m := newMacaron() + api.Register(m) + + listenAddr := fmt.Sprintf("%s:%s", setting.HttpAddr, setting.HttpPort) + g.log.Info("Initializing HTTP Server", "address", listenAddr, "protocol", setting.Protocol, "subUrl", setting.AppSubUrl) + + switch setting.Protocol { + case setting.HTTP: + err = http.ListenAndServe(listenAddr, m) + case setting.HTTPS: + err = ListenAndServeTLS(listenAddr, setting.CertFile, setting.KeyFile, m) + default: + g.log.Error("Invalid protocol", "protocol", setting.Protocol) + g.Shutdown(1, "Startup failed") + } + + if err != nil { + g.log.Error("Fail to start server", "error", err) + g.Shutdown(1, "Startup failed") + return + } +} + +func (g *GrafanaServerImpl) Shutdown(code int, reason string) { + g.log.Info("Shutdown started", "code", code, "reason", reason) + + g.shutdownFn() + err := g.childRoutines.Wait() + + g.log.Info("Shutdown completed", "reason", err) + log.Close() + os.Exit(code) +} + +func ListenAndServeTLS(listenAddr, certfile, keyfile string, m *macaron.Macaron) error { + if certfile == "" { + return fmt.Errorf("cert_file cannot be empty when using HTTPS") + } + + if keyfile == "" { + return fmt.Errorf("cert_key cannot be empty when using HTTPS") + } + + if _, err := os.Stat(setting.CertFile); os.IsNotExist(err) { + return fmt.Errorf(`Cannot find SSL cert_file at %v`, setting.CertFile) + } + + if _, err := os.Stat(setting.KeyFile); os.IsNotExist(err) { + return fmt.Errorf(`Cannot find SSL key_file at %v`, setting.KeyFile) + } + + return http.ListenAndServeTLS(listenAddr, setting.CertFile, setting.KeyFile, m) +} + +// implement context.Context +func (g *GrafanaServerImpl) Deadline() (deadline time.Time, ok bool) { + return g.context.Deadline() +} +func (g *GrafanaServerImpl) Done() <-chan struct{} { + return g.context.Done() +} +func (g *GrafanaServerImpl) Err() error { + return g.context.Err() +} +func (g *GrafanaServerImpl) Value(key interface{}) interface{} { + return g.context.Value(key) +} diff --git a/pkg/cmd/grafana-server/web.go b/pkg/cmd/grafana-server/web.go index 0d78de0daae..07a2f82b172 100644 --- a/pkg/cmd/grafana-server/web.go +++ b/pkg/cmd/grafana-server/web.go @@ -18,12 +18,14 @@ import ( "github.com/grafana/grafana/pkg/setting" ) +var logger log.Logger + func newMacaron() *macaron.Macaron { macaron.Env = setting.Env m := macaron.New() m.Use(middleware.Logger()) - m.Use(macaron.Recovery()) + m.Use(middleware.Recovery()) if setting.EnableGzip { m.Use(middleware.Gziper()) @@ -31,7 +33,7 @@ func newMacaron() *macaron.Macaron { for _, route := range plugins.StaticRoutes { pluginRoute := path.Join("/public/plugins/", route.PluginId) - log.Info("Plugins: Adding route %s -> %s", pluginRoute, route.Directory) + logger.Debug("Plugins: Adding route", "route", pluginRoute, "dir", route.Directory) mapStatic(m, route.Directory, "", pluginRoute) } @@ -44,13 +46,15 @@ func newMacaron() *macaron.Macaron { Delims: macaron.Delims{Left: "[[", Right: "]]"}, })) + m.Use(middleware.GetContextHandler()) + m.Use(middleware.Sessioner(&setting.SessionOptions)) + m.Use(middleware.RequestMetrics()) + + // needs to be after context handler if setting.EnforceDomain { m.Use(middleware.ValidateHostHeader(setting.Domain)) } - m.Use(middleware.GetContextHandler()) - m.Use(middleware.Sessioner(&setting.SessionOptions)) - return m } @@ -75,24 +79,29 @@ func mapStatic(m *macaron.Macaron, rootDir string, dir string, prefix string) { )) } -func StartServer() { +func StartServer() int { + logger = log.New("server") var err error m := newMacaron() api.Register(m) listenAddr := fmt.Sprintf("%s:%s", setting.HttpAddr, setting.HttpPort) - log.Info("Listen: %v://%s%s", setting.Protocol, listenAddr, setting.AppSubUrl) + logger.Info("Server Listening", "address", listenAddr, "protocol", setting.Protocol, "subUrl", setting.AppSubUrl) switch setting.Protocol { case setting.HTTP: err = http.ListenAndServe(listenAddr, m) case setting.HTTPS: err = http.ListenAndServeTLS(listenAddr, setting.CertFile, setting.KeyFile, m) default: - log.Fatal(4, "Invalid protocol: %s", setting.Protocol) + logger.Error("Invalid protocol", "protocol", setting.Protocol) + return 1 } if err != nil { - log.Fatal(4, "Fail to start server: %v", err) + logger.Error("Fail to start server", "error", err) + return 1 } + + return 0 } diff --git a/pkg/components/imguploader/imguploader.go b/pkg/components/imguploader/imguploader.go new file mode 100644 index 00000000000..1cbe55c8572 --- /dev/null +++ b/pkg/components/imguploader/imguploader.go @@ -0,0 +1,64 @@ +package imguploader + +import ( + "fmt" + + "github.com/grafana/grafana/pkg/setting" +) + +type ImageUploader interface { + Upload(path string) (string, error) +} + +type NopImageUploader struct { +} + +func (NopImageUploader) Upload(path string) (string, error) { + return "", nil +} + +func NewImageUploader() (ImageUploader, error) { + + switch setting.ImageUploadProvider { + case "s3": + s3sec, err := setting.Cfg.GetSection("external_image_storage.s3") + if err != nil { + return nil, err + } + + bucket := s3sec.Key("bucket_url").MustString("") + accessKey := s3sec.Key("access_key").MustString("") + secretKey := s3sec.Key("secret_key").MustString("") + + if bucket == "" { + return nil, fmt.Errorf("Could not find bucket setting for image.uploader.s3") + } + + if accessKey == "" { + return nil, fmt.Errorf("Could not find accessKey setting for image.uploader.s3") + } + + if secretKey == "" { + return nil, fmt.Errorf("Could not find secretKey setting for image.uploader.s3") + } + + return NewS3Uploader(bucket, accessKey, secretKey), nil + case "webdav": + webdavSec, err := setting.Cfg.GetSection("external_image_storage.webdav") + if err != nil { + return nil, err + } + + url := webdavSec.Key("url").String() + if url == "" { + return nil, fmt.Errorf("Could not find url key for image.uploader.webdav") + } + + username := webdavSec.Key("username").String() + password := webdavSec.Key("password").String() + + return NewWebdavImageUploader(url, username, password) + } + + return NopImageUploader{}, nil +} diff --git a/pkg/components/imguploader/imguploader_test.go b/pkg/components/imguploader/imguploader_test.go new file mode 100644 index 00000000000..4a18f22c173 --- /dev/null +++ b/pkg/components/imguploader/imguploader_test.go @@ -0,0 +1,62 @@ +package imguploader + +import ( + "testing" + + "github.com/grafana/grafana/pkg/setting" + + . "github.com/smartystreets/goconvey/convey" +) + +func TestImageUploaderFactory(t *testing.T) { + Convey("Can create image uploader for ", t, func() { + Convey("S3ImageUploader", func() { + var err error + setting.NewConfigContext(&setting.CommandLineArgs{ + HomePath: "../../../", + }) + + setting.ImageUploadProvider = "s3" + + s3sec, err := setting.Cfg.GetSection("external_image_storage.s3") + s3sec.NewKey("bucket_url", "bucket_url") + s3sec.NewKey("access_key", "access_key") + s3sec.NewKey("secret_key", "secret_key") + + uploader, err := NewImageUploader() + + So(err, ShouldBeNil) + original, ok := uploader.(*S3Uploader) + + So(ok, ShouldBeTrue) + So(original.accessKey, ShouldEqual, "access_key") + So(original.secretKey, ShouldEqual, "secret_key") + So(original.bucket, ShouldEqual, "bucket_url") + }) + + Convey("Webdav uploader", func() { + var err error + + setting.NewConfigContext(&setting.CommandLineArgs{ + HomePath: "../../../", + }) + + setting.ImageUploadProvider = "webdav" + + webdavSec, err := setting.Cfg.GetSection("external_image_storage.webdav") + webdavSec.NewKey("url", "webdavUrl") + webdavSec.NewKey("username", "username") + webdavSec.NewKey("password", "password") + + uploader, err := NewImageUploader() + + So(err, ShouldBeNil) + original, ok := uploader.(*WebdavUploader) + + So(ok, ShouldBeTrue) + So(original.url, ShouldEqual, "webdavUrl") + So(original.username, ShouldEqual, "username") + So(original.password, ShouldEqual, "password") + }) + }) +} diff --git a/pkg/components/imguploader/s3uploader.go b/pkg/components/imguploader/s3uploader.go new file mode 100644 index 00000000000..59ec598412b --- /dev/null +++ b/pkg/components/imguploader/s3uploader.go @@ -0,0 +1,69 @@ +package imguploader + +import ( + "io/ioutil" + "net/http" + "net/url" + "path" + + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/util" + "github.com/kr/s3/s3util" +) + +type S3Uploader struct { + bucket string + secretKey string + accessKey string + log log.Logger +} + +func NewS3Uploader(bucket, accessKey, secretKey string) *S3Uploader { + return &S3Uploader{ + bucket: bucket, + accessKey: accessKey, + secretKey: secretKey, + log: log.New("s3uploader"), + } +} + +func (u *S3Uploader) Upload(imageDiskPath string) (string, error) { + + s3util.DefaultConfig.AccessKey = u.accessKey + s3util.DefaultConfig.SecretKey = u.secretKey + + header := make(http.Header) + header.Add("x-amz-acl", "public-read") + header.Add("Content-Type", "image/png") + + var imageUrl *url.URL + var err error + + if imageUrl, err = url.Parse(u.bucket); err != nil { + return "", err + } + + // add image to url + imageUrl.Path = path.Join(imageUrl.Path, util.GetRandomString(20)+".png") + imageUrlString := imageUrl.String() + log.Debug("Uploading image to s3", "url", imageUrlString) + + writer, err := s3util.Create(imageUrlString, header, nil) + if err != nil { + return "", err + } + + defer writer.Close() + + imgData, err := ioutil.ReadFile(imageDiskPath) + if err != nil { + return "", err + } + + _, err = writer.Write(imgData) + if err != nil { + return "", err + } + + return imageUrlString, nil +} diff --git a/pkg/components/imguploader/s3uploader_test.go b/pkg/components/imguploader/s3uploader_test.go new file mode 100644 index 00000000000..1204a2db4e2 --- /dev/null +++ b/pkg/components/imguploader/s3uploader_test.go @@ -0,0 +1,23 @@ +package imguploader + +import ( + "testing" + + "github.com/grafana/grafana/pkg/setting" + . "github.com/smartystreets/goconvey/convey" +) + +func TestUploadToS3(t *testing.T) { + SkipConvey("[Integration test] for external_image_store.webdav", t, func() { + setting.NewConfigContext(&setting.CommandLineArgs{ + HomePath: "../../../", + }) + + s3Uploader, _ := NewImageUploader() + + path, err := s3Uploader.Upload("../../../public/img/logo_transparent_400x.png") + + So(err, ShouldBeNil) + So(path, ShouldNotEqual, "") + }) +} diff --git a/pkg/components/imguploader/webdavuploader.go b/pkg/components/imguploader/webdavuploader.go new file mode 100644 index 00000000000..541a44d4b4a --- /dev/null +++ b/pkg/components/imguploader/webdavuploader.go @@ -0,0 +1,51 @@ +package imguploader + +import ( + "bytes" + "fmt" + "io/ioutil" + "net/http" + "net/url" + "path" + + "github.com/grafana/grafana/pkg/util" +) + +type WebdavUploader struct { + url string + username string + password string +} + +func (u *WebdavUploader) Upload(pa string) (string, error) { + url, _ := url.Parse(u.url) + url.Path = path.Join(url.Path, util.GetRandomString(20)+".png") + + imgData, err := ioutil.ReadFile(pa) + req, err := http.NewRequest("PUT", url.String(), bytes.NewReader(imgData)) + + if u.username != "" { + req.SetBasicAuth(u.username, u.password) + } + + res, err := http.DefaultClient.Do(req) + + if err != nil { + return "", err + } + + if res.StatusCode != http.StatusCreated { + body, _ := ioutil.ReadAll(res.Body) + return "", fmt.Errorf("Failed to upload image. Returned statuscode %v body %s", res.StatusCode, body) + } + + return url.String(), nil +} + +func NewWebdavImageUploader(url, username, passwrod string) (*WebdavUploader, error) { + return &WebdavUploader{ + url: url, + username: username, + password: passwrod, + }, nil +} diff --git a/pkg/components/imguploader/webdavuploader_test.go b/pkg/components/imguploader/webdavuploader_test.go new file mode 100644 index 00000000000..273cd1c2a86 --- /dev/null +++ b/pkg/components/imguploader/webdavuploader_test.go @@ -0,0 +1,18 @@ +package imguploader + +import ( + "testing" + + . "github.com/smartystreets/goconvey/convey" +) + +func TestUploadToWebdav(t *testing.T) { + webdavUploader, _ := NewWebdavImageUploader("http://localhost:9998/dav/", "username", "password") + + SkipConvey("[Integration test] for external_image_store.webdav", t, func() { + path, err := webdavUploader.Upload("../../../public/img/logo_transparent_400x.png") + + So(err, ShouldBeNil) + So(path, ShouldNotEqual, "") + }) +} diff --git a/pkg/components/renderer/renderer.go b/pkg/components/renderer/renderer.go index f81da43c295..6db6a6c3d35 100644 --- a/pkg/components/renderer/renderer.go +++ b/pkg/components/renderer/renderer.go @@ -1,6 +1,7 @@ package renderer import ( + "fmt" "io" "os" "os/exec" @@ -8,36 +9,60 @@ import ( "runtime" "time" + "strconv" + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/middleware" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util" - "strconv" ) type RenderOpts struct { - Url string - Width string - Height string - SessionId string - Timeout string + Path string + Width string + Height string + Timeout string + OrgId int64 } +var rendererLog log.Logger = log.New("png-renderer") + func RenderToPng(params *RenderOpts) (string, error) { - log.Info("PhantomRenderer::renderToPng url %v", params.Url) + rendererLog.Info("Rendering", "path", params.Path) var executable = "phantomjs" if runtime.GOOS == "windows" { executable = executable + ".exe" } + localDomain := "localhost" + if setting.HttpAddr != setting.DEFAULT_HTTP_ADDR { + localDomain = setting.HttpAddr + } + + url := fmt.Sprintf("%s://%s:%s/%s", setting.Protocol, localDomain, setting.HttpPort, params.Path) + binPath, _ := filepath.Abs(filepath.Join(setting.PhantomDir, executable)) scriptPath, _ := filepath.Abs(filepath.Join(setting.PhantomDir, "render.js")) pngPath, _ := filepath.Abs(filepath.Join(setting.ImagesDir, util.GetRandomString(20))) pngPath = pngPath + ".png" - cmd := exec.Command(binPath, "--ignore-ssl-errors=true", scriptPath, "url="+params.Url, "width="+params.Width, - "height="+params.Height, "png="+pngPath, "cookiename="+setting.SessionOptions.CookieName, - "domain="+setting.Domain, "sessionid="+params.SessionId) + renderKey := middleware.AddRenderAuthKey(params.OrgId) + defer middleware.RemoveRenderAuthKey(renderKey) + + cmdArgs := []string{ + "--ignore-ssl-errors=true", + "--web-security=false", + scriptPath, + "url=" + url, + "width=" + params.Width, + "height=" + params.Height, + "png=" + pngPath, + "domain=" + localDomain, + "renderKey=" + renderKey, + } + + cmd := exec.Command(binPath, cmdArgs...) stdout, err := cmd.StdoutPipe() if err != nil { @@ -70,10 +95,12 @@ func RenderToPng(params *RenderOpts) (string, error) { select { case <-time.After(time.Duration(timeout) * time.Second): if err := cmd.Process.Kill(); err != nil { - log.Error(4, "failed to kill: %v", err) + rendererLog.Error("failed to kill", "error", err) } + return "", fmt.Errorf("PhantomRenderer::renderToPng timeout (>%vs)", timeout) case <-done: } + rendererLog.Debug("Image rendered", "path", pngPath) return pngPath, nil } diff --git a/pkg/components/securejsondata/securejsondata.go b/pkg/components/securejsondata/securejsondata.go new file mode 100644 index 00000000000..d7bec6894b0 --- /dev/null +++ b/pkg/components/securejsondata/securejsondata.go @@ -0,0 +1,24 @@ +package securejsondata + +import ( + "github.com/grafana/grafana/pkg/setting" + "github.com/grafana/grafana/pkg/util" +) + +type SecureJsonData map[string][]byte + +func (s SecureJsonData) Decrypt() map[string]string { + decrypted := make(map[string]string) + for key, data := range s { + decrypted[key] = string(util.Decrypt(data, setting.SecretKey)) + } + return decrypted +} + +func GetEncryptedJsonData(sjd map[string]string) SecureJsonData { + encrypted := make(SecureJsonData) + for key, data := range sjd { + encrypted[key] = util.Encrypt([]byte(data), setting.SecretKey) + } + return encrypted +} diff --git a/pkg/log/console.go b/pkg/log/console.go deleted file mode 100644 index 401afd7e106..00000000000 --- a/pkg/log/console.go +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2014 The Gogs Authors. All rights reserved. -// Use of this source code is governed by a MIT-style -// license that can be found in the LICENSE file. - -package log - -import ( - "encoding/json" - "fmt" - "log" - "os" - "runtime" -) - -type Brush func(string) string - -func NewBrush(color string) Brush { - pre := "\033[" - reset := "\033[0m" - return func(text string) string { - return pre + color + "m" + text + reset - } -} - -var ( - Red = NewBrush("1;31") - Purple = NewBrush("1;35") - Yellow = NewBrush("1;33") - Green = NewBrush("1;32") - Blue = NewBrush("1;34") - Cyan = NewBrush("1;36") - - colors = []Brush{ - Cyan, // Trace cyan - Blue, // Debug blue - Green, // Info green - Yellow, // Warn yellow - Red, // Error red - Purple, // Critical purple - Red, // Fatal red - } - consoleWriter = &ConsoleWriter{lg: log.New(os.Stdout, "", 0), - Level: TRACE} -) - -// ConsoleWriter implements LoggerInterface and writes messages to terminal. -type ConsoleWriter struct { - lg *log.Logger - Level LogLevel `json:"level"` - Formatting bool `json:"formatting"` -} - -// create ConsoleWriter returning as LoggerInterface. -func NewConsole() LoggerInterface { - return &ConsoleWriter{ - lg: log.New(os.Stderr, "", log.Ldate|log.Ltime), - Level: TRACE, - Formatting: true, - } -} - -func (cw *ConsoleWriter) Init(config string) error { - return json.Unmarshal([]byte(config), cw) -} - -func (cw *ConsoleWriter) WriteMsg(msg string, skip int, level LogLevel) error { - if cw.Level > level { - return nil - } - if runtime.GOOS == "windows" || !cw.Formatting { - cw.lg.Println(msg) - } else { - cw.lg.Println(colors[level](msg)) - } - return nil -} - -func (_ *ConsoleWriter) Flush() { - -} - -func (_ *ConsoleWriter) Destroy() { -} - -func printConsole(level LogLevel, msg string) { - consoleWriter.WriteMsg(msg, 0, level) -} - -func printfConsole(level LogLevel, format string, v ...interface{}) { - consoleWriter.WriteMsg(fmt.Sprintf(format, v...), 0, level) -} - -// ConsoleTrace prints to stdout using TRACE colors -func ConsoleTrace(s string) { - printConsole(TRACE, s) -} - -// ConsoleTracef prints a formatted string to stdout using TRACE colors -func ConsoleTracef(format string, v ...interface{}) { - printfConsole(TRACE, format, v...) -} - -// ConsoleDebug prints to stdout using DEBUG colors -func ConsoleDebug(s string) { - printConsole(DEBUG, s) -} - -// ConsoleDebugf prints a formatted string to stdout using DEBUG colors -func ConsoleDebugf(format string, v ...interface{}) { - printfConsole(DEBUG, format, v...) -} - -// ConsoleInfo prints to stdout using INFO colors -func ConsoleInfo(s string) { - printConsole(INFO, s) -} - -// ConsoleInfof prints a formatted string to stdout using INFO colors -func ConsoleInfof(format string, v ...interface{}) { - printfConsole(INFO, format, v...) -} - -// ConsoleWarn prints to stdout using WARN colors -func ConsoleWarn(s string) { - printConsole(WARN, s) -} - -// ConsoleWarnf prints a formatted string to stdout using WARN colors -func ConsoleWarnf(format string, v ...interface{}) { - printfConsole(WARN, format, v...) -} - -// ConsoleError prints to stdout using ERROR colors -func ConsoleError(s string) { - printConsole(ERROR, s) -} - -// ConsoleErrorf prints a formatted string to stdout using ERROR colors -func ConsoleErrorf(format string, v ...interface{}) { - printfConsole(ERROR, format, v...) -} - -// ConsoleFatal prints to stdout using FATAL colors -func ConsoleFatal(s string) { - printConsole(FATAL, s) - os.Exit(1) -} - -// ConsoleFatalf prints a formatted string to stdout using FATAL colors -func ConsoleFatalf(format string, v ...interface{}) { - printfConsole(FATAL, format, v...) - os.Exit(1) -} - -func init() { - Register("console", NewConsole) -} diff --git a/pkg/log/file.go b/pkg/log/file.go index 6031cd5dede..a8d35ba6b81 100644 --- a/pkg/log/file.go +++ b/pkg/log/file.go @@ -5,43 +5,39 @@ package log import ( - "encoding/json" "errors" "fmt" "io/ioutil" - "log" "os" "path/filepath" "strings" "sync" "time" + + "github.com/inconshreveable/log15" ) // FileLogWriter implements LoggerInterface. // It writes messages by lines limit, file size limit, or time frequency. type FileLogWriter struct { - *log.Logger mw *MuxWriter - // The opened file - Filename string `json:"filename"` - Maxlines int `json:"maxlines"` + Format log15.Format + Filename string + Maxlines int maxlines_curlines int // Rotate at size - Maxsize int `json:"maxsize"` + Maxsize int maxsize_cursize int // Rotate daily - Daily bool `json:"daily"` - Maxdays int64 `json:"maxdays"` + Daily bool + Maxdays int64 daily_opendate int - Rotate bool `json:"rotate"` - - startLock sync.Mutex // Only one log can write to the file - - Level LogLevel `json:"level"` + Rotate bool + startLock sync.Mutex } // an *os.File writer with locker. @@ -66,37 +62,29 @@ func (l *MuxWriter) SetFd(fd *os.File) { } // create a FileLogWriter returning as LoggerInterface. -func NewFileWriter() LoggerInterface { +func NewFileWriter() *FileLogWriter { w := &FileLogWriter{ Filename: "", + Format: log15.LogfmtFormat(), Maxlines: 1000000, Maxsize: 1 << 28, //256 MB Daily: true, Maxdays: 7, Rotate: true, - Level: TRACE, } // use MuxWriter instead direct use os.File for lock write when rotate w.mw = new(MuxWriter) - // set MuxWriter as Logger's io.Writer - w.Logger = log.New(w.mw, "", log.Ldate|log.Ltime) return w } -// Init file logger with json config. -// config like: -// { -// "filename":"log/gogs.log", -// "maxlines":10000, -// "maxsize":1<<30, -// "daily":true, -// "maxdays":15, -// "rotate":true -// } -func (w *FileLogWriter) Init(config string) error { - if err := json.Unmarshal([]byte(config), w); err != nil { - return err - } +func (w *FileLogWriter) Log(r *log15.Record) error { + data := w.Format.Format(r) + w.docheck(len(data)) + _, err := w.mw.Write(data) + return err +} + +func (w *FileLogWriter) Init() error { if len(w.Filename) == 0 { return errors.New("config must have filename") } @@ -131,17 +119,6 @@ func (w *FileLogWriter) docheck(size int) { w.maxsize_cursize += size } -// write logger message into file. -func (w *FileLogWriter) WriteMsg(msg string, skip int, level LogLevel) error { - if level < w.Level { - return nil - } - n := 24 + len(msg) // 24 stand for the length "2013/06/23 21:00:22 [T] " - w.docheck(n) - w.Logger.Println(msg) - return nil -} - func (w *FileLogWriter) createLogFile() (*os.File, error) { // Open the log file return os.OpenFile(w.Filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) @@ -227,7 +204,7 @@ func (w *FileLogWriter) deleteOldLog() { } // destroy file logger, close file writer. -func (w *FileLogWriter) Destroy() { +func (w *FileLogWriter) Close() { w.mw.fd.Close() } @@ -237,7 +214,3 @@ func (w *FileLogWriter) Destroy() { func (w *FileLogWriter) Flush() { w.mw.fd.Sync() } - -func init() { - Register("file", NewFileWriter) -} diff --git a/pkg/log/handlers.go b/pkg/log/handlers.go new file mode 100644 index 00000000000..14a96fdcdb4 --- /dev/null +++ b/pkg/log/handlers.go @@ -0,0 +1,5 @@ +package log + +type DisposableHandler interface { + Close() +} diff --git a/pkg/log/interface.go b/pkg/log/interface.go new file mode 100644 index 00000000000..234b1c38c5c --- /dev/null +++ b/pkg/log/interface.go @@ -0,0 +1,31 @@ +package log + +import "github.com/inconshreveable/log15" + +type Lvl int + +const ( + LvlCrit Lvl = iota + LvlError + LvlWarn + LvlInfo + LvlDebug +) + +type Logger interface { + // New returns a new Logger that has this logger's context plus the given context + New(ctx ...interface{}) log15.Logger + + // GetHandler gets the handler associated with the logger. + GetHandler() log15.Handler + + // SetHandler updates the logger to write records to the specified handler. + SetHandler(h log15.Handler) + + // Log a message at the given level with context key/value pairs + Debug(msg string, ctx ...interface{}) + Info(msg string, ctx ...interface{}) + Warn(msg string, ctx ...interface{}) + Error(msg string, ctx ...interface{}) + Crit(msg string, ctx ...interface{}) +} diff --git a/pkg/log/log.go b/pkg/log/log.go index f6d6ce74def..fe0b312db23 100644 --- a/pkg/log/log.go +++ b/pkg/log/log.go @@ -8,324 +8,250 @@ import ( "fmt" "os" "path/filepath" - "runtime" "strings" - "sync" + + "gopkg.in/ini.v1" + + "github.com/go-stack/stack" + "github.com/inconshreveable/log15" + "github.com/inconshreveable/log15/term" ) -var ( - loggers []*Logger -) +var Root log15.Logger +var loggersToClose []DisposableHandler -func NewLogger(bufLen int64, mode, config string) { - logger := newLogger(bufLen) - - isExist := false - for _, l := range loggers { - if l.adapter == mode { - isExist = true - l = logger - } - } - if !isExist { - loggers = append(loggers, logger) - } - if err := logger.SetLogger(mode, config); err != nil { - Fatal(1, "Fail to set logger(%s): %v", mode, err) - } +func init() { + loggersToClose = make([]DisposableHandler, 0) + Root = log15.Root() + Root.SetHandler(log15.DiscardHandler()) } -// this helps you work around the performance annoyance mentioned in -// https://github.com/grafana/grafana/issues/4055 -// until we refactor this library completely -func Level(level LogLevel) { - for i := range loggers { - loggers[i].level = level - } +func New(logger string, ctx ...interface{}) Logger { + params := append([]interface{}{"logger", logger}, ctx...) + return Root.New(params...) } func Trace(format string, v ...interface{}) { - for _, logger := range loggers { - logger.Trace(format, v...) + var message string + if len(v) > 0 { + message = fmt.Sprintf(format, v) + } else { + message = format } + + Root.Debug(message) } func Debug(format string, v ...interface{}) { - for _, logger := range loggers { - logger.Debug(format, v...) + var message string + if len(v) > 0 { + message = fmt.Sprintf(format, v) + } else { + message = format } + + Root.Debug(message) +} + +func Debug2(message string, v ...interface{}) { + Root.Debug(message, v...) } func Info(format string, v ...interface{}) { - for _, logger := range loggers { - logger.Info(format, v...) + var message string + if len(v) > 0 { + message = fmt.Sprintf(format, v) + } else { + message = format } + + Root.Info(message) +} + +func Info2(message string, v ...interface{}) { + Root.Info(message, v...) } func Warn(format string, v ...interface{}) { - for _, logger := range loggers { - logger.Warn(format, v...) + var message string + if len(v) > 0 { + message = fmt.Sprintf(format, v) + } else { + message = format } + + Root.Warn(message) +} + +func Warn2(message string, v ...interface{}) { + Root.Warn(message, v...) } func Error(skip int, format string, v ...interface{}) { - for _, logger := range loggers { - logger.Error(skip, format, v...) - } + Root.Error(fmt.Sprintf(format, v)) +} + +func Error2(message string, v ...interface{}) { + Root.Error(message, v...) } func Critical(skip int, format string, v ...interface{}) { - for _, logger := range loggers { - logger.Critical(skip, format, v...) - } + Root.Crit(fmt.Sprintf(format, v)) } func Fatal(skip int, format string, v ...interface{}) { - Error(skip, format, v...) - for _, l := range loggers { - l.Close() - } + Root.Crit(fmt.Sprintf(format, v)) + Close() os.Exit(1) } func Close() { - for _, l := range loggers { - l.Close() - // delete the logger. - l = nil + for _, logger := range loggersToClose { + logger.Close() } - // clear the loggers slice. - loggers = nil + loggersToClose = make([]DisposableHandler, 0) } -// .___ __ _____ -// | | _____/ |_ ____________/ ____\____ ____ ____ -// | |/ \ __\/ __ \_ __ \ __\\__ \ _/ ___\/ __ \ -// | | | \ | \ ___/| | \/| | / __ \\ \__\ ___/ -// |___|___| /__| \___ >__| |__| (____ /\___ >___ > -// \/ \/ \/ \/ \/ - -type LogLevel int - -const ( - TRACE LogLevel = iota - DEBUG - INFO - WARN - ERROR - CRITICAL - FATAL -) - -// LoggerInterface represents behaviors of a logger provider. -type LoggerInterface interface { - Init(config string) error - WriteMsg(msg string, skip int, level LogLevel) error - Destroy() - Flush() +var logLevels = map[string]log15.Lvl{ + "trace": log15.LvlDebug, + "debug": log15.LvlDebug, + "info": log15.LvlInfo, + "warn": log15.LvlWarn, + "error": log15.LvlError, + "critical": log15.LvlCrit, } -type loggerType func() LoggerInterface +func getLogLevelFromConfig(key string, defaultName string, cfg *ini.File) (string, log15.Lvl) { + levelName := cfg.Section(key).Key("level").MustString(defaultName) + levelName = strings.ToLower(levelName) + level := getLogLevelFromString(levelName) + return levelName, level +} -var adapters = make(map[string]loggerType) +func getLogLevelFromString(levelName string) log15.Lvl { + level, ok := logLevels[levelName] -// Register registers given logger provider to adapters. -func Register(name string, log loggerType) { - if log == nil { - panic("log: register provider is nil") + if !ok { + Root.Error("Unknown log level", "level", levelName) + return log15.LvlError } - if _, dup := adapters[name]; dup { - panic("log: register called twice for provider \"" + name + "\"") - } - adapters[name] = log + + return level } -type logMsg struct { - skip int - level LogLevel - msg string -} +func getFilters(filterStrArray []string) map[string]log15.Lvl { + filterMap := make(map[string]log15.Lvl) -// Logger is default logger in beego application. -// it can contain several providers and log message into all providers. -type Logger struct { - adapter string - lock sync.Mutex - level LogLevel - msg chan *logMsg - outputs map[string]LoggerInterface - quit chan bool -} - -// newLogger initializes and returns a new logger. -func newLogger(buffer int64) *Logger { - l := &Logger{ - msg: make(chan *logMsg, buffer), - outputs: make(map[string]LoggerInterface), - quit: make(chan bool), - } - go l.StartLogger() - return l -} - -// SetLogger sets new logger instanse with given logger adapter and config. -func (l *Logger) SetLogger(adapter string, config string) error { - l.lock.Lock() - defer l.lock.Unlock() - if log, ok := adapters[adapter]; ok { - lg := log() - if err := lg.Init(config); err != nil { - return err + for _, filterStr := range filterStrArray { + parts := strings.Split(filterStr, ":") + if len(parts) > 1 { + filterMap[parts[0]] = getLogLevelFromString(parts[1]) } - l.outputs[adapter] = lg - l.adapter = adapter - } else { - panic("log: unknown adapter \"" + adapter + "\" (forgotten register?)") } - return nil + + return filterMap } -// DelLogger removes a logger adapter instance. -func (l *Logger) DelLogger(adapter string) error { - l.lock.Lock() - defer l.lock.Unlock() - if lg, ok := l.outputs[adapter]; ok { - lg.Destroy() - delete(l.outputs, adapter) - } else { - panic("log: unknown adapter \"" + adapter + "\" (forgotten register?)") +func getLogFormat(format string) log15.Format { + switch format { + case "console": + if term.IsTty(os.Stdout.Fd()) { + return log15.TerminalFormat() + } + return log15.LogfmtFormat() + case "text": + return log15.LogfmtFormat() + case "json": + return log15.JsonFormat() + default: + return log15.LogfmtFormat() } - return nil } -func (l *Logger) writerMsg(skip int, level LogLevel, msg string) error { - lm := &logMsg{ - skip: skip, - level: level, - } +func ReadLoggingConfig(modes []string, logsPath string, cfg *ini.File) { + Close() - // Only error information needs locate position for debugging. - if lm.level >= ERROR { - pc, file, line, ok := runtime.Caller(skip) - if ok { - // Get caller function name. - fn := runtime.FuncForPC(pc) - var fnName string - if fn == nil { - fnName = "?()" - } else { - fnName = strings.TrimLeft(filepath.Ext(fn.Name()), ".") + "()" + defaultLevelName, _ := getLogLevelFromConfig("log", "info", cfg) + defaultFilters := getFilters(cfg.Section("log").Key("filters").Strings(" ")) + + handlers := make([]log15.Handler, 0) + + for _, mode := range modes { + mode = strings.TrimSpace(mode) + sec, err := cfg.GetSection("log." + mode) + if err != nil { + Root.Error("Unknown log mode", "mode", mode) + } + + // Log level. + _, level := getLogLevelFromConfig("log."+mode, defaultLevelName, cfg) + modeFilters := getFilters(sec.Key("filters").Strings(" ")) + format := getLogFormat(sec.Key("format").MustString("")) + + var handler log15.Handler + + // Generate log configuration. + switch mode { + case "console": + handler = log15.StreamHandler(os.Stdout, format) + case "file": + fileName := sec.Key("file_name").MustString(filepath.Join(logsPath, "grafana.log")) + os.MkdirAll(filepath.Dir(fileName), os.ModePerm) + fileHandler := NewFileWriter() + fileHandler.Filename = fileName + fileHandler.Format = format + fileHandler.Rotate = sec.Key("log_rotate").MustBool(true) + fileHandler.Maxlines = sec.Key("max_lines").MustInt(1000000) + fileHandler.Maxsize = 1 << uint(sec.Key("max_size_shift").MustInt(28)) + fileHandler.Daily = sec.Key("daily_rotate").MustBool(true) + fileHandler.Maxdays = sec.Key("max_days").MustInt64(7) + fileHandler.Init() + + loggersToClose = append(loggersToClose, fileHandler) + handler = fileHandler + case "syslog": + sysLogHandler := NewSyslog(sec, format) + + loggersToClose = append(loggersToClose, sysLogHandler) + handler = sysLogHandler + } + + for key, value := range defaultFilters { + if _, exist := modeFilters[key]; !exist { + modeFilters[key] = value } - - lm.msg = fmt.Sprintf("[%s:%d %s] %s", filepath.Base(file), line, fnName, msg) - } else { - lm.msg = msg } - } else { - lm.msg = msg + + handler = LogFilterHandler(level, modeFilters, handler) + handlers = append(handlers, handler) } - l.msg <- lm - return nil + + Root.SetHandler(log15.MultiHandler(handlers...)) } -// StartLogger starts logger chan reading. -func (l *Logger) StartLogger() { - for { - select { - case bm := <-l.msg: - for _, l := range l.outputs { - if err := l.WriteMsg(bm.msg, bm.skip, bm.level); err != nil { - fmt.Println("ERROR, unable to WriteMsg:", err) +func LogFilterHandler(maxLevel log15.Lvl, filters map[string]log15.Lvl, h log15.Handler) log15.Handler { + return log15.FilterHandler(func(r *log15.Record) (pass bool) { + + if len(filters) > 0 { + for i := 0; i < len(r.Ctx); i += 2 { + key := r.Ctx[i].(string) + if key == "logger" { + loggerName, strOk := r.Ctx[i+1].(string) + if strOk { + if filterLevel, ok := filters[loggerName]; ok { + return r.Lvl <= filterLevel + } + } } } - case <-l.quit: - return } - } + + return r.Lvl <= maxLevel + }, h) } -// Flush flushs all chan data. -func (l *Logger) Flush() { - for _, l := range l.outputs { - l.Flush() - } -} - -// Close closes logger, flush all chan data and destroy all adapter instances. -func (l *Logger) Close() { - l.quit <- true - for { - if len(l.msg) > 0 { - bm := <-l.msg - for _, l := range l.outputs { - if err := l.WriteMsg(bm.msg, bm.skip, bm.level); err != nil { - fmt.Println("ERROR, unable to WriteMsg:", err) - } - } - } else { - break - } - } - for _, l := range l.outputs { - l.Flush() - l.Destroy() - } -} - -func (l *Logger) Trace(format string, v ...interface{}) { - if l.level > TRACE { - return - } - msg := fmt.Sprintf("[T] "+format, v...) - l.writerMsg(0, TRACE, msg) -} - -func (l *Logger) Debug(format string, v ...interface{}) { - if l.level > DEBUG { - return - } - msg := fmt.Sprintf("[D] "+format, v...) - l.writerMsg(0, DEBUG, msg) -} - -func (l *Logger) Info(format string, v ...interface{}) { - if l.level > INFO { - return - } - msg := fmt.Sprintf("[I] "+format, v...) - l.writerMsg(0, INFO, msg) -} - -func (l *Logger) Warn(format string, v ...interface{}) { - if l.level > WARN { - return - } - msg := fmt.Sprintf("[W] "+format, v...) - l.writerMsg(0, WARN, msg) -} - -func (l *Logger) Error(skip int, format string, v ...interface{}) { - if l.level > ERROR { - return - } - msg := fmt.Sprintf("[E] "+format, v...) - l.writerMsg(skip, ERROR, msg) -} - -func (l *Logger) Critical(skip int, format string, v ...interface{}) { - if l.level > CRITICAL { - return - } - msg := fmt.Sprintf("[C] "+format, v...) - l.writerMsg(skip, CRITICAL, msg) -} - -func (l *Logger) Fatal(skip int, format string, v ...interface{}) { - if l.level > FATAL { - return - } - msg := fmt.Sprintf("[F] "+format, v...) - l.writerMsg(skip, FATAL, msg) - l.Close() - os.Exit(1) +func Stack(skip int) string { + call := stack.Caller(skip) + s := stack.Trace().TrimBelow(call).TrimRuntime() + return s.String() } diff --git a/pkg/log/syslog.go b/pkg/log/syslog.go index 7aa58129b5b..2132690cae6 100644 --- a/pkg/log/syslog.go +++ b/pkg/log/syslog.go @@ -3,28 +3,43 @@ package log import ( - "encoding/json" "errors" "log/syslog" + "os" + + "github.com/inconshreveable/log15" + "gopkg.in/ini.v1" ) -type SyslogWriter struct { +type SysLogHandler struct { syslog *syslog.Writer - Network string `json:"network"` - Address string `json:"address"` - Facility string `json:"facility"` - Tag string `json:"tag"` + Network string + Address string + Facility string + Tag string + Format log15.Format } -func NewSyslog() LoggerInterface { - return new(SyslogWriter) -} - -func (sw *SyslogWriter) Init(config string) error { - if err := json.Unmarshal([]byte(config), sw); err != nil { - return err +func NewSyslog(sec *ini.Section, format log15.Format) *SysLogHandler { + handler := &SysLogHandler{ + Format: log15.LogfmtFormat(), } + handler.Format = format + handler.Network = sec.Key("network").MustString("") + handler.Address = sec.Key("address").MustString("") + handler.Facility = sec.Key("facility").MustString("local7") + handler.Tag = sec.Key("tag").MustString("") + + if err := handler.Init(); err != nil { + Root.Error("Failed to init syslog log handler", "error", err) + os.Exit(1) + } + + return handler +} + +func (sw *SysLogHandler) Init() error { prio, err := parseFacility(sw.Facility) if err != nil { return err @@ -39,22 +54,22 @@ func (sw *SyslogWriter) Init(config string) error { return nil } -func (sw *SyslogWriter) WriteMsg(msg string, skip int, level LogLevel) error { +func (sw *SysLogHandler) Log(r *log15.Record) error { var err error - switch level { - case TRACE, DEBUG: + msg := string(sw.Format.Format(r)) + + switch r.Lvl { + case log15.LvlDebug: err = sw.syslog.Debug(msg) - case INFO: + case log15.LvlInfo: err = sw.syslog.Info(msg) - case WARN: + case log15.LvlWarn: err = sw.syslog.Warning(msg) - case ERROR: + case log15.LvlError: err = sw.syslog.Err(msg) - case CRITICAL: + case log15.LvlCrit: err = sw.syslog.Crit(msg) - case FATAL: - err = sw.syslog.Alert(msg) default: err = errors.New("invalid syslog level") } @@ -62,12 +77,10 @@ func (sw *SyslogWriter) WriteMsg(msg string, skip int, level LogLevel) error { return err } -func (sw *SyslogWriter) Destroy() { +func (sw *SysLogHandler) Close() { sw.syslog.Close() } -func (sw *SyslogWriter) Flush() {} - var facilities = map[string]syslog.Priority{ "user": syslog.LOG_USER, "daemon": syslog.LOG_DAEMON, @@ -89,7 +102,3 @@ func parseFacility(facility string) (syslog.Priority, error) { return prio, nil } - -func init() { - Register("syslog", NewSyslog) -} diff --git a/pkg/log/syslog_windows.go b/pkg/log/syslog_windows.go new file mode 100644 index 00000000000..9361d6c5fa5 --- /dev/null +++ b/pkg/log/syslog_windows.go @@ -0,0 +1,22 @@ +//+build windows + +package log + +import ( + "github.com/inconshreveable/log15" + "gopkg.in/ini.v1" +) + +type SysLogHandler struct { +} + +func NewSyslog(sec *ini.Section, format log15.Format) *SysLogHandler { + return &SysLogHandler{} +} + +func (sw *SysLogHandler) Log(r *log15.Record) error { + return nil +} + +func (sw *SysLogHandler) Close() { +} diff --git a/pkg/login/auth.go b/pkg/login/auth.go index f2034476f81..a71837e25bc 100644 --- a/pkg/login/auth.go +++ b/pkg/login/auth.go @@ -32,9 +32,9 @@ func AuthenticateUser(query *LoginUserQuery) error { } if setting.LdapEnabled { - for _, server := range ldapCfg.Servers { + for _, server := range LdapCfg.Servers { auther := NewLdapAuthenticator(server) - err = auther.login(query) + err = auther.Login(query) if err == nil || err != ErrInvalidCredentials { return err } diff --git a/pkg/login/ldap.go b/pkg/login/ldap.go index 48f226ccfa5..be3babac02e 100644 --- a/pkg/login/ldap.go +++ b/pkg/login/ldap.go @@ -13,23 +13,43 @@ import ( "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/log" m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/setting" ) +type ILdapConn interface { + Bind(username, password string) error + Search(*ldap.SearchRequest) (*ldap.SearchResult, error) + StartTLS(*tls.Config) error + Close() +} + +type ILdapAuther interface { + Login(query *LoginUserQuery) error + SyncSignedInUser(signedInUser *m.SignedInUser) error + GetGrafanaUserFor(ldapUser *LdapUserInfo) (*m.User, error) + SyncOrgRoles(user *m.User, ldapUser *LdapUserInfo) error +} + type ldapAuther struct { server *LdapServerConf - conn *ldap.Conn + conn ILdapConn requireSecondBind bool + log log.Logger } -func NewLdapAuthenticator(server *LdapServerConf) *ldapAuther { - return &ldapAuther{server: server} +var NewLdapAuthenticator = func(server *LdapServerConf) ILdapAuther { + return &ldapAuther{server: server, log: log.New("ldap")} +} + +var ldapDial = func(network, addr string) (ILdapConn, error) { + return ldap.Dial(network, addr) } func (a *ldapAuther) Dial() error { var err error var certPool *x509.CertPool if a.server.RootCACert != "" { - certPool := x509.NewCertPool() + certPool = x509.NewCertPool() for _, caCertFile := range strings.Split(a.server.RootCACert, " ") { if pem, err := ioutil.ReadFile(caCertFile); err != nil { return err @@ -48,9 +68,18 @@ func (a *ldapAuther) Dial() error { ServerName: host, RootCAs: certPool, } - a.conn, err = ldap.DialTLS("tcp", address, tlsCfg) + if a.server.StartTLS { + a.conn, err = ldap.Dial("tcp", address) + if err == nil { + if err = a.conn.StartTLS(tlsCfg); err == nil { + return nil + } + } + } else { + a.conn, err = ldap.DialTLS("tcp", address, tlsCfg) + } } else { - a.conn, err = ldap.Dial("tcp", address) + a.conn, err = ldapDial("tcp", address) } if err == nil { @@ -60,7 +89,7 @@ func (a *ldapAuther) Dial() error { return err } -func (a *ldapAuther) login(query *LoginUserQuery) error { +func (a *ldapAuther) Login(query *LoginUserQuery) error { if err := a.Dial(); err != nil { return err } @@ -75,9 +104,7 @@ func (a *ldapAuther) login(query *LoginUserQuery) error { if ldapUser, err := a.searchForUser(query.Username); err != nil { return err } else { - if ldapCfg.VerboseLogging { - log.Info("Ldap User Info: %s", spew.Sdump(ldapUser)) - } + a.log.Debug("Ldap User found", "info", spew.Sdump(ldapUser)) // check if a second user bind is needed if a.requireSecondBind { @@ -86,16 +113,11 @@ func (a *ldapAuther) login(query *LoginUserQuery) error { } } - if grafanaUser, err := a.getGrafanaUserFor(ldapUser); err != nil { + if grafanaUser, err := a.GetGrafanaUserFor(ldapUser); err != nil { return err } else { - // sync user details - if err := a.syncUserInfo(grafanaUser, ldapUser); err != nil { - return err - } - // sync org roles - if err := a.syncOrgRoles(grafanaUser, ldapUser); err != nil { - return err + if syncErr := a.syncInfoAndOrgRoles(grafanaUser, ldapUser); syncErr != nil { + return syncErr } query.User = grafanaUser return nil @@ -103,7 +125,53 @@ func (a *ldapAuther) login(query *LoginUserQuery) error { } } -func (a *ldapAuther) getGrafanaUserFor(ldapUser *ldapUserInfo) (*m.User, error) { +func (a *ldapAuther) SyncSignedInUser(signedInUser *m.SignedInUser) error { + grafanaUser := m.User{ + Id: signedInUser.UserId, + Login: signedInUser.Login, + Email: signedInUser.Email, + Name: signedInUser.Name, + } + + if err := a.Dial(); err != nil { + return err + } + + defer a.conn.Close() + if err := a.serverBind(); err != nil { + return err + } + + if ldapUser, err := a.searchForUser(signedInUser.Login); err != nil { + a.log.Error("Failed searching for user in ldap", "error", err) + + return err + } else { + if err := a.syncInfoAndOrgRoles(&grafanaUser, ldapUser); err != nil { + return err + } + + a.log.Debug("Got Ldap User Info", "user", spew.Sdump(ldapUser)) + } + + return nil +} + +// Sync info for ldap user and grafana user +func (a *ldapAuther) syncInfoAndOrgRoles(user *m.User, ldapUser *LdapUserInfo) error { + // sync user details + if err := a.syncUserInfo(user, ldapUser); err != nil { + return err + } + // sync org roles + if err := a.SyncOrgRoles(user, ldapUser); err != nil { + return err + } + + return nil +} + +func (a *ldapAuther) GetGrafanaUserFor(ldapUser *LdapUserInfo) (*m.User, error) { // validate that the user has access // if there are no ldap group mappings access is true // otherwise a single group must match @@ -116,15 +184,18 @@ func (a *ldapAuther) getGrafanaUserFor(ldapUser *ldapUserInfo) (*m.User, error) } if !access { - log.Info("Ldap Auth: user %s does not belong in any of the specified ldap groups, ldapUser groups: %v", ldapUser.Username, ldapUser.MemberOf) + a.log.Info("Ldap Auth: user does not belong in any of the specified ldap groups", "username", ldapUser.Username, "groups", ldapUser.MemberOf) return nil, ErrInvalidCredentials } // get user from grafana db userQuery := m.GetUserByLoginQuery{LoginOrEmail: ldapUser.Username} if err := bus.Dispatch(&userQuery); err != nil { - if err == m.ErrUserNotFound { + if err == m.ErrUserNotFound && setting.LdapAllowSignup { return a.createGrafanaUser(ldapUser) + } else if err == m.ErrUserNotFound { + a.log.Warn("Not allowing LDAP login, user not found in internal user database, and ldap allow signup = false") + return nil, ErrInvalidCredentials } else { return nil, err } @@ -133,7 +204,7 @@ func (a *ldapAuther) getGrafanaUserFor(ldapUser *ldapUserInfo) (*m.User, error) return userQuery.Result, nil } -func (a *ldapAuther) createGrafanaUser(ldapUser *ldapUserInfo) (*m.User, error) { +func (a *ldapAuther) createGrafanaUser(ldapUser *LdapUserInfo) (*m.User, error) { cmd := m.CreateUserCommand{ Login: ldapUser.Username, Email: ldapUser.Email, @@ -147,13 +218,13 @@ func (a *ldapAuther) createGrafanaUser(ldapUser *ldapUserInfo) (*m.User, error) return &cmd.Result, nil } -func (a *ldapAuther) syncUserInfo(user *m.User, ldapUser *ldapUserInfo) error { +func (a *ldapAuther) syncUserInfo(user *m.User, ldapUser *LdapUserInfo) error { var name = fmt.Sprintf("%s %s", ldapUser.FirstName, ldapUser.LastName) if user.Email == ldapUser.Email && user.Name == name { return nil } - log.Info("Ldap: Syncing user info %s", ldapUser.Username) + a.log.Debug("Syncing user info", "username", ldapUser.Username) updateCmd := m.UpdateUserCommand{} updateCmd.UserId = user.Id updateCmd.Login = user.Login @@ -162,8 +233,9 @@ func (a *ldapAuther) syncUserInfo(user *m.User, ldapUser *ldapUserInfo) error { return bus.Dispatch(&updateCmd) } -func (a *ldapAuther) syncOrgRoles(user *m.User, ldapUser *ldapUserInfo) error { +func (a *ldapAuther) SyncOrgRoles(user *m.User, ldapUser *LdapUserInfo) error { if len(a.server.LdapGroups) == 0 { + a.log.Warn("No group mappings defined") return nil } @@ -219,7 +291,8 @@ func (a *ldapAuther) syncOrgRoles(user *m.User, ldapUser *ldapUserInfo) error { // add role cmd := m.AddOrgUserCommand{UserId: user.Id, Role: group.OrgRole, OrgId: group.OrgId} - if err := bus.Dispatch(&cmd); err != nil { + err := bus.Dispatch(&cmd) + if err != nil && err != m.ErrOrgNotFound { return err } @@ -230,11 +303,25 @@ func (a *ldapAuther) syncOrgRoles(user *m.User, ldapUser *ldapUserInfo) error { return nil } -func (a *ldapAuther) secondBind(ldapUser *ldapUserInfo, userPassword string) error { - if err := a.conn.Bind(ldapUser.DN, userPassword); err != nil { - if ldapCfg.VerboseLogging { - log.Info("LDAP second bind failed, %v", err) +func (a *ldapAuther) serverBind() error { + // bind_dn and bind_password to bind + if err := a.conn.Bind(a.server.BindDN, a.server.BindPassword); err != nil { + a.log.Info("LDAP initial bind failed, %v", err) + + if ldapErr, ok := err.(*ldap.Error); ok { + if ldapErr.ResultCode == 49 { + return ErrInvalidCredentials + } } + return err + } + + return nil +} + +func (a *ldapAuther) secondBind(ldapUser *LdapUserInfo, userPassword string) error { + if err := a.conn.Bind(ldapUser.DN, userPassword); err != nil { + a.log.Info("Second bind failed", "error", err) if ldapErr, ok := err.(*ldap.Error); ok { if ldapErr.ResultCode == 49 { @@ -259,9 +346,7 @@ func (a *ldapAuther) initialBind(username, userPassword string) error { } if err := a.conn.Bind(bindPath, userPassword); err != nil { - if ldapCfg.VerboseLogging { - log.Info("LDAP initial bind failed, %v", err) - } + a.log.Info("Initial bind failed", "error", err) if ldapErr, ok := err.(*ldap.Error); ok { if ldapErr.ResultCode == 49 { @@ -274,7 +359,7 @@ func (a *ldapAuther) initialBind(username, userPassword string) error { return nil } -func (a *ldapAuther) searchForUser(username string) (*ldapUserInfo, error) { +func (a *ldapAuther) searchForUser(username string) (*LdapUserInfo, error) { var searchResult *ldap.SearchResult var err error @@ -290,7 +375,7 @@ func (a *ldapAuther) searchForUser(username string) (*ldapUserInfo, error) { a.server.Attr.Name, a.server.Attr.MemberOf, }, - Filter: strings.Replace(a.server.SearchFilter, "%s", username, -1), + Filter: strings.Replace(a.server.SearchFilter, "%s", ldap.EscapeFilter(username), -1), } searchResult, err = a.conn.Search(&searchReq) @@ -323,11 +408,9 @@ func (a *ldapAuther) searchForUser(username string) (*ldapUserInfo, error) { if a.server.GroupSearchFilterUserAttribute == "" { filter_replace = getLdapAttr(a.server.Attr.Username, searchResult) } - filter := strings.Replace(a.server.GroupSearchFilter, "%s", filter_replace, -1) + filter := strings.Replace(a.server.GroupSearchFilter, "%s", ldap.EscapeFilter(filter_replace), -1) - if ldapCfg.VerboseLogging { - log.Info("LDAP: Searching for user's groups: %s", filter) - } + a.log.Info("Searching for user's groups", "filter", filter) groupSearchReq := ldap.SearchRequest{ BaseDN: groupSearchBase, @@ -354,7 +437,7 @@ func (a *ldapAuther) searchForUser(username string) (*ldapUserInfo, error) { } } - return &ldapUserInfo{ + return &LdapUserInfo{ DN: searchResult.Entries[0].DN, LastName: getLdapAttr(a.server.Attr.Surname, searchResult), FirstName: getLdapAttr(a.server.Attr.Name, searchResult), diff --git a/pkg/login/ldap_test.go b/pkg/login/ldap_test.go index 2e4ed3a32e1..8677bbeae42 100644 --- a/pkg/login/ldap_test.go +++ b/pkg/login/ldap_test.go @@ -1,8 +1,10 @@ package login import ( + "crypto/tls" "testing" + "github.com/go-ldap/ldap" "github.com/grafana/grafana/pkg/bus" m "github.com/grafana/grafana/pkg/models" . "github.com/smartystreets/goconvey/convey" @@ -16,7 +18,7 @@ func TestLdapAuther(t *testing.T) { ldapAuther := NewLdapAuthenticator(&LdapServerConf{ LdapGroups: []*LdapGroupToOrgRole{{}}, }) - _, err := ldapAuther.getGrafanaUserFor(&ldapUserInfo{}) + _, err := ldapAuther.GetGrafanaUserFor(&LdapUserInfo{}) So(err, ShouldEqual, ErrInvalidCredentials) }) @@ -32,7 +34,7 @@ func TestLdapAuther(t *testing.T) { sc.userQueryReturns(user1) - result, err := ldapAuther.getGrafanaUserFor(&ldapUserInfo{}) + result, err := ldapAuther.GetGrafanaUserFor(&LdapUserInfo{}) So(err, ShouldBeNil) So(result, ShouldEqual, user1) }) @@ -46,7 +48,7 @@ func TestLdapAuther(t *testing.T) { sc.userQueryReturns(user1) - result, err := ldapAuther.getGrafanaUserFor(&ldapUserInfo{MemberOf: []string{"cn=users"}}) + result, err := ldapAuther.GetGrafanaUserFor(&LdapUserInfo{MemberOf: []string{"cn=users"}}) So(err, ShouldBeNil) So(result, ShouldEqual, user1) }) @@ -62,7 +64,7 @@ func TestLdapAuther(t *testing.T) { sc.userQueryReturns(nil) - result, err := ldapAuther.getGrafanaUserFor(&ldapUserInfo{ + result, err := ldapAuther.GetGrafanaUserFor(&LdapUserInfo{ Username: "torkelo", Email: "my@email.com", MemberOf: []string{"cn=editor"}, @@ -93,7 +95,7 @@ func TestLdapAuther(t *testing.T) { }) sc.userOrgsQueryReturns([]*m.UserOrgDTO{}) - err := ldapAuther.syncOrgRoles(&m.User{}, &ldapUserInfo{ + err := ldapAuther.SyncOrgRoles(&m.User{}, &LdapUserInfo{ MemberOf: []string{"cn=users"}, }) @@ -112,7 +114,7 @@ func TestLdapAuther(t *testing.T) { }) sc.userOrgsQueryReturns([]*m.UserOrgDTO{{OrgId: 1, Role: m.ROLE_EDITOR}}) - err := ldapAuther.syncOrgRoles(&m.User{}, &ldapUserInfo{ + err := ldapAuther.SyncOrgRoles(&m.User{}, &LdapUserInfo{ MemberOf: []string{"cn=users"}, }) @@ -131,7 +133,7 @@ func TestLdapAuther(t *testing.T) { }) sc.userOrgsQueryReturns([]*m.UserOrgDTO{{OrgId: 1, Role: m.ROLE_EDITOR}}) - err := ldapAuther.syncOrgRoles(&m.User{}, &ldapUserInfo{ + err := ldapAuther.SyncOrgRoles(&m.User{}, &LdapUserInfo{ MemberOf: []string{"cn=other"}, }) @@ -150,7 +152,7 @@ func TestLdapAuther(t *testing.T) { }) sc.userOrgsQueryReturns([]*m.UserOrgDTO{{OrgId: 1, Role: m.ROLE_EDITOR}}) - err := ldapAuther.syncOrgRoles(&m.User{}, &ldapUserInfo{ + err := ldapAuther.SyncOrgRoles(&m.User{}, &LdapUserInfo{ MemberOf: []string{"cn=users"}, }) @@ -170,7 +172,7 @@ func TestLdapAuther(t *testing.T) { }) sc.userOrgsQueryReturns([]*m.UserOrgDTO{{OrgId: 1, Role: m.ROLE_ADMIN}}) - err := ldapAuther.syncOrgRoles(&m.User{}, &ldapUserInfo{ + err := ldapAuther.SyncOrgRoles(&m.User{}, &LdapUserInfo{ MemberOf: []string{"cn=admins"}, }) @@ -189,7 +191,7 @@ func TestLdapAuther(t *testing.T) { }) sc.userOrgsQueryReturns([]*m.UserOrgDTO{}) - err := ldapAuther.syncOrgRoles(&m.User{}, &ldapUserInfo{ + err := ldapAuther.SyncOrgRoles(&m.User{}, &LdapUserInfo{ MemberOf: []string{"cn=admins"}, }) @@ -200,6 +202,95 @@ func TestLdapAuther(t *testing.T) { }) }) + + Convey("When calling SyncSignedInUser", t, func() { + + mockLdapConnection := &mockLdapConn{} + ldapAuther := NewLdapAuthenticator( + &LdapServerConf{ + Host: "", + RootCACert: "", + LdapGroups: []*LdapGroupToOrgRole{ + {GroupDN: "*", OrgRole: "Admin"}, + }, + Attr: LdapAttributeMap{ + Username: "username", + Surname: "surname", + Email: "email", + Name: "name", + MemberOf: "memberof", + }, + SearchBaseDNs: []string{"BaseDNHere"}, + }, + ) + + dialCalled := false + ldapDial = func(network, addr string) (ILdapConn, error) { + dialCalled = true + return mockLdapConnection, nil + } + + entry := ldap.Entry{ + DN: "dn", Attributes: []*ldap.EntryAttribute{ + {Name: "username", Values: []string{"roelgerrits"}}, + {Name: "surname", Values: []string{"Gerrits"}}, + {Name: "email", Values: []string{"roel@test.com"}}, + {Name: "name", Values: []string{"Roel"}}, + {Name: "memberof", Values: []string{"admins"}}, + }} + result := ldap.SearchResult{Entries: []*ldap.Entry{&entry}} + mockLdapConnection.setSearchResult(&result) + + ldapAutherScenario("When ldapUser found call syncInfo and orgRoles", func(sc *scenarioContext) { + // arrange + signedInUser := &m.SignedInUser{ + Email: "roel@test.net", + UserId: 1, + Name: "Roel Gerrits", + Login: "roelgerrits", + } + + sc.userOrgsQueryReturns([]*m.UserOrgDTO{}) + + // act + syncErrResult := ldapAuther.SyncSignedInUser(signedInUser) + + // assert + So(dialCalled, ShouldBeTrue) + So(syncErrResult, ShouldBeNil) + // User should be searched in ldap + So(mockLdapConnection.searchCalled, ShouldBeTrue) + // Info should be updated (email differs) + So(sc.updateUserCmd.Email, ShouldEqual, "roel@test.com") + // User should have admin privileges + So(sc.addOrgUserCmd.UserId, ShouldEqual, 1) + So(sc.addOrgUserCmd.Role, ShouldEqual, "Admin") + }) + }) +} + +type mockLdapConn struct { + result *ldap.SearchResult + searchCalled bool +} + +func (c *mockLdapConn) Bind(username, password string) error { + return nil +} + +func (c *mockLdapConn) Close() {} + +func (c *mockLdapConn) setSearchResult(result *ldap.SearchResult) { + c.result = result +} + +func (c *mockLdapConn) Search(*ldap.SearchRequest) (*ldap.SearchResult, error) { + c.searchCalled = true + return c.result, nil +} + +func (c *mockLdapConn) StartTLS(*tls.Config) error { + return nil } func ldapAutherScenario(desc string, fn scenarioFunc) { @@ -229,6 +320,11 @@ func ldapAutherScenario(desc string, fn scenarioFunc) { return nil }) + bus.AddHandler("test", func(cmd *m.UpdateUserCommand) error { + sc.updateUserCmd = cmd + return nil + }) + fn(sc) }) } @@ -238,6 +334,7 @@ type scenarioContext struct { addOrgUserCmd *m.AddOrgUserCommand updateOrgUserCmd *m.UpdateOrgUserCommand removeOrgUserCmd *m.RemoveOrgUserCommand + updateUserCmd *m.UpdateUserCommand } func (sc *scenarioContext) userQueryReturns(user *m.User) { diff --git a/pkg/login/ldap_user.go b/pkg/login/ldap_user.go index 5a57efe2687..9f1cf3c96b6 100644 --- a/pkg/login/ldap_user.go +++ b/pkg/login/ldap_user.go @@ -1,6 +1,6 @@ package login -type ldapUserInfo struct { +type LdapUserInfo struct { DN string FirstName string LastName string @@ -9,7 +9,7 @@ type ldapUserInfo struct { MemberOf []string } -func (u *ldapUserInfo) isMemberOf(group string) bool { +func (u *LdapUserInfo) isMemberOf(group string) bool { if group == "*" { return true } diff --git a/pkg/login/settings.go b/pkg/login/settings.go index a42476157fe..497d8725e29 100644 --- a/pkg/login/settings.go +++ b/pkg/login/settings.go @@ -2,6 +2,7 @@ package login import ( "fmt" + "os" "github.com/BurntSushi/toml" "github.com/grafana/grafana/pkg/log" @@ -10,14 +11,14 @@ import ( ) type LdapConfig struct { - Servers []*LdapServerConf `toml:"servers"` - VerboseLogging bool `toml:"verbose_logging"` + Servers []*LdapServerConf `toml:"servers"` } type LdapServerConf struct { Host string `toml:"host"` Port int `toml:"port"` UseSSL bool `toml:"use_ssl"` + StartTLS bool `toml:"start_tls"` SkipVerifySSL bool `toml:"ssl_skip_verify"` RootCACert string `toml:"root_ca_cert"` BindDN string `toml:"bind_dn"` @@ -48,26 +49,29 @@ type LdapGroupToOrgRole struct { OrgRole m.RoleType `toml:"org_role"` } -var ldapCfg LdapConfig +var LdapCfg LdapConfig +var ldapLogger log.Logger = log.New("ldap") func loadLdapConfig() { if !setting.LdapEnabled { return } - log.Info("Login: Ldap enabled, reading config file: %s", setting.LdapConfigFile) + ldapLogger.Info("Ldap enabled, reading config file", "file", setting.LdapConfigFile) - _, err := toml.DecodeFile(setting.LdapConfigFile, &ldapCfg) + _, err := toml.DecodeFile(setting.LdapConfigFile, &LdapCfg) if err != nil { - log.Fatal(3, "Failed to load ldap config file: %s", err) + ldapLogger.Crit("Failed to load ldap config file", "error", err) + os.Exit(1) } - if len(ldapCfg.Servers) == 0 { - log.Fatal(3, "ldap enabled but no ldap servers defined in config file: %s", setting.LdapConfigFile) + if len(LdapCfg.Servers) == 0 { + ldapLogger.Crit("ldap enabled but no ldap servers defined in config file") + os.Exit(1) } // set default org id - for _, server := range ldapCfg.Servers { + for _, server := range LdapCfg.Servers { assertNotEmptyCfg(server.SearchFilter, "search_filter") assertNotEmptyCfg(server.SearchBaseDNs, "search_base_dns") @@ -83,11 +87,13 @@ func assertNotEmptyCfg(val interface{}, propName string) { switch v := val.(type) { case string: if v == "" { - log.Fatal(3, "LDAP config file is missing option: %s", propName) + ldapLogger.Crit("LDAP config file is missing option", "option", propName) + os.Exit(1) } case []string: if len(v) == 0 { - log.Fatal(3, "LDAP config file is missing option: %s", propName) + ldapLogger.Crit("LDAP config file is missing option", "option", propName) + os.Exit(1) } default: fmt.Println("unknown") diff --git a/pkg/metrics/EMWA.go b/pkg/metrics/EMWA.go new file mode 100644 index 00000000000..d99dc77b016 --- /dev/null +++ b/pkg/metrics/EMWA.go @@ -0,0 +1,122 @@ +// includes code from +// https://raw.githubusercontent.com/rcrowley/go-metrics/master/sample.go +// Copyright 2012 Richard Crowley. All rights reserved. + +package metrics + +import ( + "math" + "sync" + "sync/atomic" +) + +// EWMAs continuously calculate an exponentially-weighted moving average +// based on an outside source of clock ticks. +type EWMA interface { + Rate() float64 + Snapshot() EWMA + Tick() + Update(int64) +} + +// NewEWMA constructs a new EWMA with the given alpha. +func NewEWMA(alpha float64) EWMA { + if UseNilMetrics { + return NilEWMA{} + } + return &StandardEWMA{alpha: alpha} +} + +// NewEWMA1 constructs a new EWMA for a one-minute moving average. +func NewEWMA1() EWMA { + return NewEWMA(1 - math.Exp(-5.0/60.0/1)) +} + +// NewEWMA5 constructs a new EWMA for a five-minute moving average. +func NewEWMA5() EWMA { + return NewEWMA(1 - math.Exp(-5.0/60.0/5)) +} + +// NewEWMA15 constructs a new EWMA for a fifteen-minute moving average. +func NewEWMA15() EWMA { + return NewEWMA(1 - math.Exp(-5.0/60.0/15)) +} + +// EWMASnapshot is a read-only copy of another EWMA. +type EWMASnapshot float64 + +// Rate returns the rate of events per second at the time the snapshot was +// taken. +func (a EWMASnapshot) Rate() float64 { return float64(a) } + +// Snapshot returns the snapshot. +func (a EWMASnapshot) Snapshot() EWMA { return a } + +// Tick panics. +func (EWMASnapshot) Tick() { + panic("Tick called on an EWMASnapshot") +} + +// Update panics. +func (EWMASnapshot) Update(int64) { + panic("Update called on an EWMASnapshot") +} + +// NilEWMA is a no-op EWMA. +type NilEWMA struct{} + +// Rate is a no-op. +func (NilEWMA) Rate() float64 { return 0.0 } + +// Snapshot is a no-op. +func (NilEWMA) Snapshot() EWMA { return NilEWMA{} } + +// Tick is a no-op. +func (NilEWMA) Tick() {} + +// Update is a no-op. +func (NilEWMA) Update(n int64) {} + +// StandardEWMA is the standard implementation of an EWMA and tracks the number +// of uncounted events and processes them on each tick. It uses the +// sync/atomic package to manage uncounted events. +type StandardEWMA struct { + uncounted int64 // /!\ this should be the first member to ensure 64-bit alignment + alpha float64 + rate float64 + init bool + mutex sync.Mutex +} + +// Rate returns the moving average rate of events per second. +func (a *StandardEWMA) Rate() float64 { + a.mutex.Lock() + defer a.mutex.Unlock() + return a.rate * float64(1e9) +} + +// Snapshot returns a read-only copy of the EWMA. +func (a *StandardEWMA) Snapshot() EWMA { + return EWMASnapshot(a.Rate()) +} + +// Tick ticks the clock to update the moving average. It assumes it is called +// every five seconds. +func (a *StandardEWMA) Tick() { + count := atomic.LoadInt64(&a.uncounted) + atomic.AddInt64(&a.uncounted, -count) + instantRate := float64(count) / float64(5e9) + a.mutex.Lock() + defer a.mutex.Unlock() + if a.init { + a.rate += a.alpha * (instantRate - a.rate) + } else { + a.init = true + a.rate = instantRate + } +} + +// Update adds n uncounted events. +func (a *StandardEWMA) Update(n int64) { + atomic.AddInt64(&a.uncounted, n) +} diff --git a/pkg/metrics/combos.go b/pkg/metrics/combos.go new file mode 100644 index 00000000000..b4da59c5b32 --- /dev/null +++ b/pkg/metrics/combos.go @@ -0,0 +1,46 @@ +package metrics + +// type comboCounterRef struct { +// *MetricMeta +// usageCounter Counter +// metricCounter Counter +// } +// +// func RegComboCounter(name string, tagStrings ...string) Counter { +// meta := NewMetricMeta(name, tagStrings) +// cr := &comboCounterRef{ +// MetricMeta: meta, +// usageCounter: NewCounter(meta), +// metricCounter: NewCounter(meta), +// } +// +// UsageStats.Register(cr.usageCounter) +// MetricStats.Register(cr.metricCounter) +// +// return cr +// } +// +// func (c comboCounterRef) Clear() { +// c.usageCounter.Clear() +// c.metricCounter.Clear() +// } +// +// func (c comboCounterRef) Count() int64 { +// panic("Count called on a combocounter ref") +// } +// +// // Dec panics. +// func (c comboCounterRef) Dec(i int64) { +// c.usageCounter.Dec(i) +// c.metricCounter.Dec(i) +// } +// +// // Inc panics. +// func (c comboCounterRef) Inc(i int64) { +// c.usageCounter.Inc(i) +// c.metricCounter.Inc(i) +// } +// +// func (c comboCounterRef) Snapshot() Metric { +// return c.metricCounter.Snapshot() +// } diff --git a/pkg/metrics/common.go b/pkg/metrics/common.go new file mode 100644 index 00000000000..2043d3a67cf --- /dev/null +++ b/pkg/metrics/common.go @@ -0,0 +1,61 @@ +package metrics + +import "github.com/grafana/grafana/pkg/log" + +type MetricMeta struct { + tags map[string]string + name string +} + +func NewMetricMeta(name string, tagStrings []string) *MetricMeta { + if len(tagStrings)%2 != 0 { + log.Fatal(3, "Metrics: tags array is missing value for key, %v", tagStrings) + } + + tags := make(map[string]string) + for i := 0; i < len(tagStrings); i += 2 { + tags[tagStrings[i]] = tagStrings[i+1] + } + + return &MetricMeta{ + tags: tags, + name: name, + } +} + +func (m *MetricMeta) Name() string { + return m.name +} + +func (m *MetricMeta) GetTagsCopy() map[string]string { + if len(m.tags) == 0 { + return make(map[string]string) + } + + copy := make(map[string]string) + for k2, v2 := range m.tags { + copy[k2] = v2 + } + + return copy +} + +func (m *MetricMeta) StringifyTags() string { + if len(m.tags) == 0 { + return "" + } + + str := "" + for key, value := range m.tags { + str += "." + key + "_" + value + } + + return str +} + +type Metric interface { + Name() string + GetTagsCopy() map[string]string + StringifyTags() string + Snapshot() Metric +} diff --git a/pkg/metrics/counter.go b/pkg/metrics/counter.go index 1a4a88be37b..8322d370a36 100644 --- a/pkg/metrics/counter.go +++ b/pkg/metrics/counter.go @@ -4,46 +4,33 @@ import "sync/atomic" // Counters hold an int64 value that can be incremented and decremented. type Counter interface { + Metric + Clear() Count() int64 Dec(int64) Inc(int64) - Snapshot() Counter } // NewCounter constructs a new StandardCounter. -func NewCounter() Counter { - return &StandardCounter{0} +func NewCounter(meta *MetricMeta) Counter { + return &StandardCounter{ + MetricMeta: meta, + count: 0, + } } -// CounterSnapshot is a read-only copy of another Counter. -type CounterSnapshot int64 - -// Clear panics. -func (CounterSnapshot) Clear() { - panic("Clear called on a CounterSnapshot") +func RegCounter(name string, tagStrings ...string) Counter { + cr := NewCounter(NewMetricMeta(name, tagStrings)) + MetricStats.Register(cr) + return cr } -// Count returns the count at the time the snapshot was taken. -func (c CounterSnapshot) Count() int64 { return int64(c) } - -// Dec panics. -func (CounterSnapshot) Dec(int64) { - panic("Dec called on a CounterSnapshot") -} - -// Inc panics. -func (CounterSnapshot) Inc(int64) { - panic("Inc called on a CounterSnapshot") -} - -// Snapshot returns the snapshot. -func (c CounterSnapshot) Snapshot() Counter { return c } - // StandardCounter is the standard implementation of a Counter and uses the // sync/atomic package to manage a single int64 value. type StandardCounter struct { - count int64 + count int64 //Due to a bug in golang the 64bit variable need to come first to be 64bit aligned. https://golang.org/pkg/sync/atomic/#pkg-note-BUG + *MetricMeta } // Clear sets the counter to zero. @@ -66,7 +53,9 @@ func (c *StandardCounter) Inc(i int64) { atomic.AddInt64(&c.count, i) } -// Snapshot returns a read-only copy of the counter. -func (c *StandardCounter) Snapshot() Counter { - return CounterSnapshot(c.Count()) +func (c *StandardCounter) Snapshot() Metric { + return &StandardCounter{ + MetricMeta: c.MetricMeta, + count: c.count, + } } diff --git a/pkg/metrics/delta.go b/pkg/metrics/delta.go new file mode 100644 index 00000000000..71354178209 --- /dev/null +++ b/pkg/metrics/delta.go @@ -0,0 +1,11 @@ +package metrics + +import "math" + +func calculateDelta(oldValue, newValue int64) int64 { + if oldValue < newValue { + return newValue - oldValue + } else { + return (math.MaxInt64 - oldValue) + (newValue - math.MinInt64) + 1 + } +} diff --git a/pkg/metrics/gauge.go b/pkg/metrics/gauge.go new file mode 100644 index 00000000000..cca32da5622 --- /dev/null +++ b/pkg/metrics/gauge.go @@ -0,0 +1,83 @@ +// includes code from +// https://raw.githubusercontent.com/rcrowley/go-metrics/master/sample.go +// Copyright 2012 Richard Crowley. All rights reserved. + +package metrics + +import "sync/atomic" + +// Gauges hold an int64 value that can be set arbitrarily. +type Gauge interface { + Metric + + Update(int64) + Value() int64 +} + +func NewGauge(meta *MetricMeta) Gauge { + if UseNilMetrics { + return NilGauge{} + } + return &StandardGauge{ + MetricMeta: meta, + value: 0, + } +} + +func RegGauge(name string, tagStrings ...string) Gauge { + tr := NewGauge(NewMetricMeta(name, tagStrings)) + MetricStats.Register(tr) + return tr +} + +// GaugeSnapshot is a read-only copy of another Gauge. +type GaugeSnapshot struct { + value int64 + *MetricMeta +} + +// Snapshot returns the snapshot. +func (g GaugeSnapshot) Snapshot() Metric { return g } + +// Update panics. +func (GaugeSnapshot) Update(int64) { + panic("Update called on a GaugeSnapshot") +} + +// Value returns the value at the time the snapshot was taken. +func (g GaugeSnapshot) Value() int64 { return g.value } + +// NilGauge is a no-op Gauge. +type NilGauge struct{ *MetricMeta } + +// Snapshot is a no-op. +func (NilGauge) Snapshot() Metric { return NilGauge{} } + +// Update is a no-op. +func (NilGauge) Update(v int64) {} + +// Value is a no-op. +func (NilGauge) Value() int64 { return 0 } + +// StandardGauge is the standard implementation of a Gauge and uses the +// sync/atomic package to manage a single int64 value. +// atomic needs 64-bit aligned memory which is ensure for first word +type StandardGauge struct { + value int64 + *MetricMeta +} + +// Snapshot returns a read-only copy of the gauge. +func (g *StandardGauge) Snapshot() Metric { + return GaugeSnapshot{MetricMeta: g.MetricMeta, value: g.value} +} + +// Update updates the gauge's value. +func (g *StandardGauge) Update(v int64) { + atomic.StoreInt64(&g.value, v) +} + +// Value returns the gauge's current value. +func (g *StandardGauge) Value() int64 { + return atomic.LoadInt64(&g.value) +} diff --git a/pkg/metrics/graphite.go b/pkg/metrics/graphite.go new file mode 100644 index 00000000000..59c992776de --- /dev/null +++ b/pkg/metrics/graphite.go @@ -0,0 +1,107 @@ +package metrics + +import ( + "bytes" + "fmt" + "net" + "strings" + "time" + + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/setting" +) + +type GraphitePublisher struct { + address string + protocol string + prefix string + prevCounts map[string]int64 +} + +func CreateGraphitePublisher() (*GraphitePublisher, error) { + graphiteSection, err := setting.Cfg.GetSection("metrics.graphite") + if err != nil { + return nil, nil + } + + address := graphiteSection.Key("address").String() + if address == "" { + return nil, nil + } + + publisher := &GraphitePublisher{} + publisher.prevCounts = make(map[string]int64) + publisher.protocol = "tcp" + publisher.prefix = graphiteSection.Key("prefix").MustString("prod.grafana.%(instance_name)s") + publisher.address = address + + safeInstanceName := strings.Replace(setting.InstanceName, ".", "_", -1) + prefix := graphiteSection.Key("prefix").Value() + + if prefix == "" { + prefix = "prod.grafana.%(instance_name)s." + } + + publisher.prefix = strings.Replace(prefix, "%(instance_name)s", safeInstanceName, -1) + return publisher, nil +} + +func (this *GraphitePublisher) Publish(metrics []Metric) { + conn, err := net.DialTimeout(this.protocol, this.address, time.Second*5) + + if err != nil { + log.Error(3, "Metrics: GraphitePublisher: Failed to connect to %s!", err) + return + } + + buf := bytes.NewBufferString("") + now := time.Now().Unix() + + for _, m := range metrics { + metricName := this.prefix + m.Name() + m.StringifyTags() + + switch metric := m.(type) { + case Counter: + this.addCount(buf, metricName+".count", metric.Count(), now) + case Gauge: + this.addCount(buf, metricName, metric.Value(), now) + case Timer: + percentiles := metric.Percentiles([]float64{0.25, 0.75, 0.90, 0.99}) + this.addCount(buf, metricName+".count", metric.Count(), now) + this.addInt(buf, metricName+".max", metric.Max(), now) + this.addInt(buf, metricName+".min", metric.Min(), now) + this.addFloat(buf, metricName+".mean", metric.Mean(), now) + this.addFloat(buf, metricName+".std", metric.StdDev(), now) + this.addFloat(buf, metricName+".p25", percentiles[0], now) + this.addFloat(buf, metricName+".p75", percentiles[1], now) + this.addFloat(buf, metricName+".p90", percentiles[2], now) + this.addFloat(buf, metricName+".p99", percentiles[3], now) + } + } + + log.Trace("Metrics: GraphitePublisher.Publish() \n%s", buf) + _, err = conn.Write(buf.Bytes()) + + if err != nil { + log.Error(3, "Metrics: GraphitePublisher: Failed to send metrics! %s", err) + } +} + +func (this *GraphitePublisher) addInt(buf *bytes.Buffer, metric string, value int64, now int64) { + buf.WriteString(fmt.Sprintf("%s %d %d\n", metric, value, now)) +} + +func (this *GraphitePublisher) addFloat(buf *bytes.Buffer, metric string, value float64, now int64) { + buf.WriteString(fmt.Sprintf("%s %f %d\n", metric, value, now)) +} + +func (this *GraphitePublisher) addCount(buf *bytes.Buffer, metric string, value int64, now int64) { + delta := value + + if last, ok := this.prevCounts[metric]; ok { + delta = calculateDelta(last, value) + } + + this.prevCounts[metric] = value + buf.WriteString(fmt.Sprintf("%s %d %d\n", metric, delta, now)) +} diff --git a/pkg/metrics/graphite_test.go b/pkg/metrics/graphite_test.go new file mode 100644 index 00000000000..ff2bf530d5e --- /dev/null +++ b/pkg/metrics/graphite_test.go @@ -0,0 +1,77 @@ +package metrics + +import ( + "testing" + + "github.com/grafana/grafana/pkg/setting" + + . "github.com/smartystreets/goconvey/convey" +) + +func TestGraphitePublisher(t *testing.T) { + + setting.CustomInitPath = "conf/does_not_exist.ini" + + Convey("Test graphite prefix replacement", t, func() { + var err error + err = setting.NewConfigContext(&setting.CommandLineArgs{ + HomePath: "../../", + }) + + So(err, ShouldBeNil) + + sec, err := setting.Cfg.NewSection("metrics.graphite") + sec.NewKey("prefix", "prod.grafana.%(instance_name)s.") + sec.NewKey("address", "localhost:2001") + + So(err, ShouldBeNil) + + setting.InstanceName = "hostname.with.dots.com" + publisher, err := CreateGraphitePublisher() + + So(err, ShouldBeNil) + So(publisher, ShouldNotBeNil) + + So(publisher.prefix, ShouldEqual, "prod.grafana.hostname_with_dots_com.") + So(publisher.address, ShouldEqual, "localhost:2001") + }) + + Convey("Test graphite publisher default prefix", t, func() { + var err error + err = setting.NewConfigContext(&setting.CommandLineArgs{ + HomePath: "../../", + }) + + So(err, ShouldBeNil) + + sec, err := setting.Cfg.NewSection("metrics.graphite") + sec.NewKey("address", "localhost:2001") + + So(err, ShouldBeNil) + + setting.InstanceName = "hostname.with.dots.com" + publisher, err := CreateGraphitePublisher() + + So(err, ShouldBeNil) + So(publisher, ShouldNotBeNil) + + So(publisher.prefix, ShouldEqual, "prod.grafana.hostname_with_dots_com.") + So(publisher.address, ShouldEqual, "localhost:2001") + }) + + Convey("Test graphite publisher default values", t, func() { + var err error + err = setting.NewConfigContext(&setting.CommandLineArgs{ + HomePath: "../../", + }) + + So(err, ShouldBeNil) + + _, err = setting.Cfg.NewSection("metrics.graphite") + + publisher, err := CreateGraphitePublisher() + + So(err, ShouldBeNil) + So(publisher, ShouldBeNil) + }) +} diff --git a/pkg/metrics/histogram.go b/pkg/metrics/histogram.go new file mode 100644 index 00000000000..32338da4b69 --- /dev/null +++ b/pkg/metrics/histogram.go @@ -0,0 +1,189 @@ +// includes code from +// https://raw.githubusercontent.com/rcrowley/go-metrics/master/sample.go +// Copyright 2012 Richard Crowley. All rights reserved. + +package metrics + +// Histograms calculate distribution statistics from a series of int64 values. +type Histogram interface { + Metric + + Clear() + Count() int64 + Max() int64 + Mean() float64 + Min() int64 + Percentile(float64) float64 + Percentiles([]float64) []float64 + StdDev() float64 + Sum() int64 + Update(int64) + Variance() float64 +} + +func NewHistogram(meta *MetricMeta, s Sample) Histogram { + return &StandardHistogram{ + MetricMeta: meta, + sample: s, + } +} + +// HistogramSnapshot is a read-only copy of another Histogram. +type HistogramSnapshot struct { + *MetricMeta + sample *SampleSnapshot +} + +// Clear panics. +func (*HistogramSnapshot) Clear() { + panic("Clear called on a HistogramSnapshot") +} + +// Count returns the number of samples recorded at the time the snapshot was +// taken. +func (h *HistogramSnapshot) Count() int64 { return h.sample.Count() } + +// Max returns the maximum value in the sample at the time the snapshot was +// taken. +func (h *HistogramSnapshot) Max() int64 { return h.sample.Max() } + +// Mean returns the mean of the values in the sample at the time the snapshot +// was taken. +func (h *HistogramSnapshot) Mean() float64 { return h.sample.Mean() } + +// Min returns the minimum value in the sample at the time the snapshot was +// taken. +func (h *HistogramSnapshot) Min() int64 { return h.sample.Min() } + +// Percentile returns an arbitrary percentile of values in the sample at the +// time the snapshot was taken. +func (h *HistogramSnapshot) Percentile(p float64) float64 { + return h.sample.Percentile(p) +} + +// Percentiles returns a slice of arbitrary percentiles of values in the sample +// at the time the snapshot was taken. +func (h *HistogramSnapshot) Percentiles(ps []float64) []float64 { + return h.sample.Percentiles(ps) +} + +// Sample returns the Sample underlying the histogram. +func (h *HistogramSnapshot) Sample() Sample { return h.sample } + +// Snapshot returns the snapshot. +func (h *HistogramSnapshot) Snapshot() Metric { return h } + +// StdDev returns the standard deviation of the values in the sample at the +// time the snapshot was taken. +func (h *HistogramSnapshot) StdDev() float64 { return h.sample.StdDev() } + +// Sum returns the sum in the sample at the time the snapshot was taken. +func (h *HistogramSnapshot) Sum() int64 { return h.sample.Sum() } + +// Update panics. +func (*HistogramSnapshot) Update(int64) { + panic("Update called on a HistogramSnapshot") +} + +// Variance returns the variance of inputs at the time the snapshot was taken. +func (h *HistogramSnapshot) Variance() float64 { return h.sample.Variance() } + +// NilHistogram is a no-op Histogram. +type NilHistogram struct { + *MetricMeta +} + +// Clear is a no-op. +func (NilHistogram) Clear() {} + +// Count is a no-op. +func (NilHistogram) Count() int64 { return 0 } + +// Max is a no-op. +func (NilHistogram) Max() int64 { return 0 } + +// Mean is a no-op. +func (NilHistogram) Mean() float64 { return 0.0 } + +// Min is a no-op. +func (NilHistogram) Min() int64 { return 0 } + +// Percentile is a no-op. +func (NilHistogram) Percentile(p float64) float64 { return 0.0 } + +// Percentiles is a no-op. +func (NilHistogram) Percentiles(ps []float64) []float64 { + return make([]float64, len(ps)) +} + +// Sample is a no-op. +func (NilHistogram) Sample() Sample { return NilSample{} } + +// Snapshot is a no-op. +func (n NilHistogram) Snapshot() Metric { return n } + +// StdDev is a no-op. +func (NilHistogram) StdDev() float64 { return 0.0 } + +// Sum is a no-op. +func (NilHistogram) Sum() int64 { return 0 } + +// Update is a no-op. +func (NilHistogram) Update(v int64) {} + +// Variance is a no-op. +func (NilHistogram) Variance() float64 { return 0.0 } + +// StandardHistogram is the standard implementation of a Histogram and uses a +// Sample to bound its memory use. +type StandardHistogram struct { + *MetricMeta + sample Sample +} + +// Clear clears the histogram and its sample. +func (h *StandardHistogram) Clear() { h.sample.Clear() } + +// Count returns the number of samples recorded since the histogram was last +// cleared. +func (h *StandardHistogram) Count() int64 { return h.sample.Count() } + +// Max returns the maximum value in the sample. +func (h *StandardHistogram) Max() int64 { return h.sample.Max() } + +// Mean returns the mean of the values in the sample. +func (h *StandardHistogram) Mean() float64 { return h.sample.Mean() } + +// Min returns the minimum value in the sample. +func (h *StandardHistogram) Min() int64 { return h.sample.Min() } + +// Percentile returns an arbitrary percentile of the values in the sample. +func (h *StandardHistogram) Percentile(p float64) float64 { + return h.sample.Percentile(p) +} + +// Percentiles returns a slice of arbitrary percentiles of the values in the +// sample. +func (h *StandardHistogram) Percentiles(ps []float64) []float64 { + return h.sample.Percentiles(ps) +} + +// Sample returns the Sample underlying the histogram. +func (h *StandardHistogram) Sample() Sample { return h.sample } + +// Snapshot returns a read-only copy of the histogram. +func (h *StandardHistogram) Snapshot() Metric { + return &HistogramSnapshot{sample: h.sample.Snapshot().(*SampleSnapshot)} +} + +// StdDev returns the standard deviation of the values in the sample. +func (h *StandardHistogram) StdDev() float64 { return h.sample.StdDev() } + +// Sum returns the sum in the sample. +func (h *StandardHistogram) Sum() int64 { return h.sample.Sum() } + +// Update samples a new value. +func (h *StandardHistogram) Update(v int64) { h.sample.Update(v) } + +// Variance returns the variance of the values in the sample. +func (h *StandardHistogram) Variance() float64 { return h.sample.Variance() } diff --git a/pkg/metrics/histogram_test.go b/pkg/metrics/histogram_test.go new file mode 100644 index 00000000000..010402123c2 --- /dev/null +++ b/pkg/metrics/histogram_test.go @@ -0,0 +1,90 @@ +// includes code from +// https://raw.githubusercontent.com/rcrowley/go-metrics/master/sample.go +// Copyright 2012 Richard Crowley. All rights reserved. + +package metrics + +import "testing" + +func BenchmarkHistogram(b *testing.B) { + h := NewHistogram(nil, NewUniformSample(100)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + h.Update(int64(i)) + } +} + +func TestHistogram10000(t *testing.T) { + h := NewHistogram(nil, NewUniformSample(100000)) + for i := 1; i <= 10000; i++ { + h.Update(int64(i)) + } + testHistogram10000(t, h) +} + +func TestHistogramEmpty(t *testing.T) { + h := NewHistogram(nil, NewUniformSample(100)) + if count := h.Count(); 0 != count { + t.Errorf("h.Count(): 0 != %v\n", count) + } + if min := h.Min(); 0 != min { + t.Errorf("h.Min(): 0 != %v\n", min) + } + if max := h.Max(); 0 != max { + t.Errorf("h.Max(): 0 != %v\n", max) + } + if mean := h.Mean(); 0.0 != mean { + t.Errorf("h.Mean(): 0.0 != %v\n", mean) + } + if stdDev := h.StdDev(); 0.0 != stdDev { + t.Errorf("h.StdDev(): 0.0 != %v\n", stdDev) + } + ps := h.Percentiles([]float64{0.5, 0.75, 0.99}) + if 0.0 != ps[0] { + t.Errorf("median: 0.0 != %v\n", ps[0]) + } + if 0.0 != ps[1] { + t.Errorf("75th percentile: 0.0 != %v\n", ps[1]) + } + if 0.0 != ps[2] { + t.Errorf("99th percentile: 0.0 != %v\n", ps[2]) + } +} + +func TestHistogramSnapshot(t *testing.T) { + h := NewHistogram(nil, NewUniformSample(100000)) + for i := 1; i <= 10000; i++ { + h.Update(int64(i)) + } + snapshot := h.Snapshot().(Histogram) + h.Update(0) + testHistogram10000(t, snapshot) +} + +func testHistogram10000(t *testing.T, h Histogram) { + if count := h.Count(); 10000 != count { + t.Errorf("h.Count(): 10000 != %v\n", count) + } + if min := h.Min(); 1 != min { + t.Errorf("h.Min(): 1 != %v\n", min) + } + if max := h.Max(); 10000 != max { + t.Errorf("h.Max(): 10000 != %v\n", max) + } + if mean := h.Mean(); 5000.5 != mean { + t.Errorf("h.Mean(): 5000.5 != %v\n", mean) + } + if stdDev := h.StdDev(); 2886.751331514372 != stdDev { + t.Errorf("h.StdDev(): 2886.751331514372 != %v\n", stdDev) + } + ps := h.Percentiles([]float64{0.5, 0.75, 0.99}) + if 5000.5 != ps[0] { + t.Errorf("median: 5000.5 != %v\n", ps[0]) + } + if 7500.75 != ps[1] { + t.Errorf("75th percentile: 7500.75 != %v\n", ps[1]) + } + if 9900.99 != ps[2] { + t.Errorf("99th percentile: 9900.99 != %v\n", ps[2]) + } +} diff --git a/pkg/metrics/meter.go b/pkg/metrics/meter.go new file mode 100644 index 00000000000..8744a5cd040 --- /dev/null +++ b/pkg/metrics/meter.go @@ -0,0 +1,221 @@ +// includes code from +// https://raw.githubusercontent.com/rcrowley/go-metrics/master/sample.go +// Copyright 2012 Richard Crowley. All rights reserved. + +package metrics + +import ( + "sync" + "time" +) + +// Meters count events to produce exponentially-weighted moving average rates +// at one-, five-, and fifteen-minutes and a mean rate. +type Meter interface { + Metric + + Count() int64 + Mark(int64) + Rate1() float64 + Rate5() float64 + Rate15() float64 + RateMean() float64 +} + +// NewMeter constructs a new StandardMeter and launches a goroutine. +func NewMeter(meta *MetricMeta) Meter { + if UseNilMetrics { + return NilMeter{} + } + + m := newStandardMeter(meta) + arbiter.Lock() + defer arbiter.Unlock() + arbiter.meters = append(arbiter.meters, m) + if !arbiter.started { + arbiter.started = true + go arbiter.tick() + } + return m +} + +type MeterSnapshot struct { + *MetricMeta + count int64 + rate1, rate5, rate15, rateMean float64 +} + +// Count returns the count of events at the time the snapshot was taken. +func (m *MeterSnapshot) Count() int64 { return m.count } + +// Mark panics. +func (*MeterSnapshot) Mark(n int64) { + panic("Mark called on a MeterSnapshot") +} + +// Rate1 returns the one-minute moving average rate of events per second at the +// time the snapshot was taken. +func (m *MeterSnapshot) Rate1() float64 { return m.rate1 } + +// Rate5 returns the five-minute moving average rate of events per second at +// the time the snapshot was taken. +func (m *MeterSnapshot) Rate5() float64 { return m.rate5 } + +// Rate15 returns the fifteen-minute moving average rate of events per second +// at the time the snapshot was taken. +func (m *MeterSnapshot) Rate15() float64 { return m.rate15 } + +// RateMean returns the meter's mean rate of events per second at the time the +// snapshot was taken. +func (m *MeterSnapshot) RateMean() float64 { return m.rateMean } + +// Snapshot returns the snapshot. +func (m *MeterSnapshot) Snapshot() Metric { return m } + +// NilMeter is a no-op Meter. +type NilMeter struct{ *MetricMeta } + +// Count is a no-op. +func (NilMeter) Count() int64 { return 0 } + +// Mark is a no-op. +func (NilMeter) Mark(n int64) {} + +// Rate1 is a no-op. +func (NilMeter) Rate1() float64 { return 0.0 } + +// Rate5 is a no-op. +func (NilMeter) Rate5() float64 { return 0.0 } + +// Rate15is a no-op. +func (NilMeter) Rate15() float64 { return 0.0 } + +// RateMean is a no-op. +func (NilMeter) RateMean() float64 { return 0.0 } + +// Snapshot is a no-op. +func (NilMeter) Snapshot() Metric { return NilMeter{} } + +// StandardMeter is the standard implementation of a Meter. +type StandardMeter struct { + *MetricMeta + lock sync.RWMutex + snapshot *MeterSnapshot + a1, a5, a15 EWMA + startTime time.Time +} + +func newStandardMeter(meta *MetricMeta) *StandardMeter { + return &StandardMeter{ + MetricMeta: meta, + snapshot: &MeterSnapshot{MetricMeta: meta}, + a1: NewEWMA1(), + a5: NewEWMA5(), + a15: NewEWMA15(), + startTime: time.Now(), + } +} + +// Count returns the number of events recorded. +func (m *StandardMeter) Count() int64 { + m.lock.RLock() + count := m.snapshot.count + m.lock.RUnlock() + return count +} + +// Mark records the occurance of n events. +func (m *StandardMeter) Mark(n int64) { + m.lock.Lock() + defer m.lock.Unlock() + m.snapshot.count += n + m.a1.Update(n) + m.a5.Update(n) + m.a15.Update(n) + m.updateSnapshot() +} + +// Rate1 returns the one-minute moving average rate of events per second. +func (m *StandardMeter) Rate1() float64 { + m.lock.RLock() + rate1 := m.snapshot.rate1 + m.lock.RUnlock() + return rate1 +} + +// Rate5 returns the five-minute moving average rate of events per second. +func (m *StandardMeter) Rate5() float64 { + m.lock.RLock() + rate5 := m.snapshot.rate5 + m.lock.RUnlock() + return rate5 +} + +// Rate15 returns the fifteen-minute moving average rate of events per second. +func (m *StandardMeter) Rate15() float64 { + m.lock.RLock() + rate15 := m.snapshot.rate15 + m.lock.RUnlock() + return rate15 +} + +// RateMean returns the meter's mean rate of events per second. +func (m *StandardMeter) RateMean() float64 { + m.lock.RLock() + rateMean := m.snapshot.rateMean + m.lock.RUnlock() + return rateMean +} + +// Snapshot returns a read-only copy of the meter. +func (m *StandardMeter) Snapshot() Metric { + m.lock.RLock() + snapshot := *m.snapshot + m.lock.RUnlock() + return &snapshot +} + +func (m *StandardMeter) updateSnapshot() { + // should run with write lock held on m.lock + snapshot := m.snapshot + snapshot.rate1 = m.a1.Rate() + snapshot.rate5 = m.a5.Rate() + snapshot.rate15 = m.a15.Rate() + snapshot.rateMean = float64(snapshot.count) / time.Since(m.startTime).Seconds() +} + +func (m *StandardMeter) tick() { + m.lock.Lock() + defer m.lock.Unlock() + m.a1.Tick() + m.a5.Tick() + m.a15.Tick() + m.updateSnapshot() +} + +type meterArbiter struct { + sync.RWMutex + started bool + meters []*StandardMeter + ticker *time.Ticker +} + +var arbiter = meterArbiter{ticker: time.NewTicker(5e9)} + +// Ticks meters on the scheduled interval +func (ma *meterArbiter) tick() { + for { + select { + case <-ma.ticker.C: + ma.tickMeters() + } + } +} + +func (ma *meterArbiter) tickMeters() { + ma.RLock() + defer ma.RUnlock() + for _, meter := range ma.meters { + meter.tick() + } +} diff --git a/pkg/metrics/metric_ref.go b/pkg/metrics/metric_ref.go deleted file mode 100644 index f9e5d693d4c..00000000000 --- a/pkg/metrics/metric_ref.go +++ /dev/null @@ -1,39 +0,0 @@ -package metrics - -type comboCounterRef struct { - usageCounter Counter - metricCounter Counter -} - -func NewComboCounterRef(name string) Counter { - cr := &comboCounterRef{} - cr.usageCounter = UsageStats.GetOrRegister(name, NewCounter).(Counter) - cr.metricCounter = MetricStats.GetOrRegister(name, NewCounter).(Counter) - return cr -} - -func (c comboCounterRef) Clear() { - c.usageCounter.Clear() - c.metricCounter.Clear() -} - -func (c comboCounterRef) Count() int64 { - panic("Count called on a combocounter ref") -} - -// Dec panics. -func (c comboCounterRef) Dec(i int64) { - c.usageCounter.Dec(i) - c.metricCounter.Dec(i) -} - -// Inc panics. -func (c comboCounterRef) Inc(i int64) { - c.usageCounter.Inc(i) - c.metricCounter.Inc(i) -} - -// Snapshot returns the snapshot. -func (c comboCounterRef) Snapshot() Counter { - panic("snapshot called on a combocounter ref") -} diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index 8e10b2428b4..5f937a5cbd8 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -1,31 +1,133 @@ package metrics -var UsageStats = NewRegistry() -var MetricStats = NewRegistry() +var MetricStats Registry +var UseNilMetrics bool + +func init() { + // init with nil metrics + initMetricVars(&MetricSettings{}) +} var ( - M_Instance_Start = NewComboCounterRef("instance.start") + M_Instance_Start Counter + M_Page_Status_200 Counter + M_Page_Status_500 Counter + M_Page_Status_404 Counter + M_Page_Status_Unknown Counter + M_Api_Status_200 Counter + M_Api_Status_404 Counter + M_Api_Status_500 Counter + M_Api_Status_Unknown Counter + M_Proxy_Status_200 Counter + M_Proxy_Status_404 Counter + M_Proxy_Status_500 Counter + M_Proxy_Status_Unknown Counter + M_Api_User_SignUpStarted Counter + M_Api_User_SignUpCompleted Counter + M_Api_User_SignUpInvite Counter + M_Api_Dashboard_Save Timer + M_Api_Dashboard_Get Timer + M_Api_Dashboard_Search Timer + M_Api_Admin_User_Create Counter + M_Api_Login_Post Counter + M_Api_Login_OAuth Counter + M_Api_Org_Create Counter + M_Api_Dashboard_Snapshot_Create Counter + M_Api_Dashboard_Snapshot_External Counter + M_Api_Dashboard_Snapshot_Get Counter + M_Models_Dashboard_Insert Counter + M_Alerting_Result_State_Alerting Counter + M_Alerting_Result_State_Ok Counter + M_Alerting_Result_State_Paused Counter + M_Alerting_Result_State_NoData Counter + M_Alerting_Result_State_Pending Counter + M_Alerting_Notification_Sent_Slack Counter + M_Alerting_Notification_Sent_Email Counter + M_Alerting_Notification_Sent_Webhook Counter + M_Alerting_Notification_Sent_PagerDuty Counter + M_Alerting_Notification_Sent_Victorops Counter + M_Alerting_Notification_Sent_OpsGenie Counter + M_Alerting_Notification_Sent_Telegram Counter + M_Aws_CloudWatch_GetMetricStatistics Counter + M_Aws_CloudWatch_ListMetrics Counter - M_Page_Status_200 = NewComboCounterRef("page.status.200") - M_Page_Status_500 = NewComboCounterRef("page.status.500") - M_Page_Status_404 = NewComboCounterRef("page.status.404") + // Timers + M_DataSource_ProxyReq_Timer Timer + M_Alerting_Execution_Time Timer - M_Api_Status_500 = NewComboCounterRef("api.status.500") - M_Api_Status_404 = NewComboCounterRef("api.status.404") - - M_Api_User_SignUpStarted = NewComboCounterRef("api.user.signup_started") - M_Api_User_SignUpCompleted = NewComboCounterRef("api.user.signup_completed") - M_Api_User_SignUpInvite = NewComboCounterRef("api.user.signup_invite") - M_Api_Dashboard_Get = NewComboCounterRef("api.dashboard.get") - M_Api_Dashboard_Post = NewComboCounterRef("api.dashboard.post") - M_Api_Admin_User_Create = NewComboCounterRef("api.admin.user_create") - M_Api_Login_Post = NewComboCounterRef("api.login.post") - M_Api_Login_OAuth = NewComboCounterRef("api.login.oauth") - M_Api_Org_Create = NewComboCounterRef("api.org.create") - - M_Api_Dashboard_Snapshot_Create = NewComboCounterRef("api.dashboard_snapshot.create") - M_Api_Dashboard_Snapshot_External = NewComboCounterRef("api.dashboard_snapshot.external") - M_Api_Dashboard_Snapshot_Get = NewComboCounterRef("api.dashboard_snapshot.get") - - M_Models_Dashboard_Insert = NewComboCounterRef("models.dashboard.insert") + // StatTotals + M_Alerting_Active_Alerts Gauge + M_StatTotal_Dashboards Gauge + M_StatTotal_Users Gauge + M_StatTotal_Orgs Gauge + M_StatTotal_Playlists Gauge ) + +func initMetricVars(settings *MetricSettings) { + UseNilMetrics = settings.Enabled == false + MetricStats = NewRegistry() + + M_Instance_Start = RegCounter("instance_start") + + M_Page_Status_200 = RegCounter("page.resp_status", "code", "200") + M_Page_Status_500 = RegCounter("page.resp_status", "code", "500") + M_Page_Status_404 = RegCounter("page.resp_status", "code", "404") + M_Page_Status_Unknown = RegCounter("page.resp_status", "code", "unknown") + + M_Api_Status_200 = RegCounter("api.resp_status", "code", "200") + M_Api_Status_404 = RegCounter("api.resp_status", "code", "404") + M_Api_Status_500 = RegCounter("api.resp_status", "code", "500") + M_Api_Status_Unknown = RegCounter("api.resp_status", "code", "unknown") + + M_Proxy_Status_200 = RegCounter("proxy.resp_status", "code", "200") + M_Proxy_Status_404 = RegCounter("proxy.resp_status", "code", "404") + M_Proxy_Status_500 = RegCounter("proxy.resp_status", "code", "500") + M_Proxy_Status_Unknown = RegCounter("proxy.resp_status", "code", "unknown") + + M_Api_User_SignUpStarted = RegCounter("api.user.signup_started") + M_Api_User_SignUpCompleted = RegCounter("api.user.signup_completed") + M_Api_User_SignUpInvite = RegCounter("api.user.signup_invite") + + M_Api_Dashboard_Save = RegTimer("api.dashboard.save") + M_Api_Dashboard_Get = RegTimer("api.dashboard.get") + M_Api_Dashboard_Search = RegTimer("api.dashboard.search") + + M_Api_Admin_User_Create = RegCounter("api.admin.user_create") + M_Api_Login_Post = RegCounter("api.login.post") + M_Api_Login_OAuth = RegCounter("api.login.oauth") + M_Api_Org_Create = RegCounter("api.org.create") + + M_Api_Dashboard_Snapshot_Create = RegCounter("api.dashboard_snapshot.create") + M_Api_Dashboard_Snapshot_External = RegCounter("api.dashboard_snapshot.external") + M_Api_Dashboard_Snapshot_Get = RegCounter("api.dashboard_snapshot.get") + + M_Models_Dashboard_Insert = RegCounter("models.dashboard.insert") + + M_Alerting_Result_State_Alerting = RegCounter("alerting.result", "state", "alerting") + M_Alerting_Result_State_Ok = RegCounter("alerting.result", "state", "ok") + M_Alerting_Result_State_Paused = RegCounter("alerting.result", "state", "paused") + M_Alerting_Result_State_NoData = RegCounter("alerting.result", "state", "no_data") + M_Alerting_Result_State_Pending = RegCounter("alerting.result", "state", "pending") + + M_Alerting_Notification_Sent_Slack = RegCounter("alerting.notifications_sent", "type", "slack") + M_Alerting_Notification_Sent_Email = RegCounter("alerting.notifications_sent", "type", "email") + M_Alerting_Notification_Sent_Webhook = RegCounter("alerting.notifications_sent", "type", "webhook") + M_Alerting_Notification_Sent_PagerDuty = RegCounter("alerting.notifications_sent", "type", "pagerduty") + M_Alerting_Notification_Sent_Victorops = RegCounter("alerting.notifications_sent", "type", "victorops") + M_Alerting_Notification_Sent_OpsGenie = RegCounter("alerting.notifications_sent", "type", "opsgenie") + M_Alerting_Notification_Sent_Telegram = RegCounter("alerting.notifications_sent", "type", "telegram") + + M_Aws_CloudWatch_GetMetricStatistics = RegCounter("aws.cloudwatch.get_metric_statistics") + M_Aws_CloudWatch_ListMetrics = RegCounter("aws.cloudwatch.list_metrics") + + // Timers + M_DataSource_ProxyReq_Timer = RegTimer("api.dataproxy.request.all") + M_Alerting_Execution_Time = RegTimer("alerting.execution_time") + + // StatTotals + M_Alerting_Active_Alerts = RegGauge("alerting.active_alerts") + M_StatTotal_Dashboards = RegGauge("stat_totals", "stat", "dashboards") + M_StatTotal_Users = RegGauge("stat_totals", "stat", "users") + M_StatTotal_Orgs = RegGauge("stat_totals", "stat", "orgs") + M_StatTotal_Playlists = RegGauge("stat_totals", "stat", "playlists") +} diff --git a/pkg/metrics/publish.go b/pkg/metrics/publish.go new file mode 100644 index 00000000000..70db3fc0f86 --- /dev/null +++ b/pkg/metrics/publish.go @@ -0,0 +1,130 @@ +package metrics + +import ( + "bytes" + "encoding/json" + "net/http" + "strings" + "time" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/log" + m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/plugins" + "github.com/grafana/grafana/pkg/setting" +) + +var metricsLogger log.Logger = log.New("metrics") +var metricPublishCounter int64 = 0 + +func Init() { + settings := readSettings() + initMetricVars(settings) + go instrumentationLoop(settings) +} + +func instrumentationLoop(settings *MetricSettings) chan struct{} { + M_Instance_Start.Inc(1) + + onceEveryDayTick := time.NewTicker(time.Hour * 24) + secondTicker := time.NewTicker(time.Second * time.Duration(settings.IntervalSeconds)) + + for { + select { + case <-onceEveryDayTick.C: + sendUsageStats() + case <-secondTicker.C: + if settings.Enabled { + sendMetrics(settings) + } + } + } +} + +func sendMetrics(settings *MetricSettings) { + if len(settings.Publishers) == 0 { + return + } + + updateTotalStats() + + metrics := MetricStats.GetSnapshots() + for _, publisher := range settings.Publishers { + publisher.Publish(metrics) + } +} + +func updateTotalStats() { + + // every interval also publish totals + metricPublishCounter++ + if metricPublishCounter%10 == 0 { + // get stats + statsQuery := m.GetSystemStatsQuery{} + if err := bus.Dispatch(&statsQuery); err != nil { + metricsLogger.Error("Failed to get system stats", "error", err) + return + } + + M_StatTotal_Dashboards.Update(statsQuery.Result.DashboardCount) + M_StatTotal_Users.Update(statsQuery.Result.UserCount) + M_StatTotal_Playlists.Update(statsQuery.Result.PlaylistCount) + M_StatTotal_Orgs.Update(statsQuery.Result.OrgCount) + } +} + +func sendUsageStats() { + if !setting.ReportingEnabled { + return + } + + metricsLogger.Debug("Sending anonymous usage stats to stats.grafana.org") + + version := strings.Replace(setting.BuildVersion, ".", "_", -1) + + metrics := map[string]interface{}{} + report := map[string]interface{}{ + "version": version, + "metrics": metrics, + } + + statsQuery := m.GetSystemStatsQuery{} + if err := bus.Dispatch(&statsQuery); err != nil { + metricsLogger.Error("Failed to get system stats", "error", err) + return + } + + metrics["stats.dashboards.count"] = statsQuery.Result.DashboardCount + metrics["stats.users.count"] = statsQuery.Result.UserCount + metrics["stats.orgs.count"] = statsQuery.Result.OrgCount + metrics["stats.playlist.count"] = statsQuery.Result.PlaylistCount + metrics["stats.plugins.apps.count"] = len(plugins.Apps) + metrics["stats.plugins.panels.count"] = len(plugins.Panels) + metrics["stats.plugins.datasources.count"] = len(plugins.DataSources) + metrics["stats.alerts.count"] = statsQuery.Result.AlertCount + + dsStats := m.GetDataSourceStatsQuery{} + if err := bus.Dispatch(&dsStats); err != nil { + metricsLogger.Error("Failed to get datasource stats", "error", err) + return + } + + // send counters for each data source + // but ignore any custom data sources + // as sending that name could be sensitive information + dsOtherCount := 0 + for _, dsStat := range dsStats.Result { + if m.IsKnownDataSourcePlugin(dsStat.Type) { + metrics["stats.ds."+dsStat.Type+".count"] = dsStat.Count + } else { + dsOtherCount += dsStat.Count + } + } + metrics["stats.ds.other.count"] = dsOtherCount + + out, _ := json.MarshalIndent(report, "", " ") + data := bytes.NewBuffer(out) + + client := http.Client{Timeout: time.Duration(5 * time.Second)} + go client.Post("https://stats.grafana.org/grafana-usage-report", "application/json", data) +} diff --git a/pkg/metrics/registry.go b/pkg/metrics/registry.go index 9e1618f3691..6c40d4fde9f 100644 --- a/pkg/metrics/registry.go +++ b/pkg/metrics/registry.go @@ -1,102 +1,37 @@ package metrics -import ( - "fmt" - "reflect" - "sync" -) - -// DuplicateMetric is the error returned by Registry.Register when a metric -// already exists. If you mean to Register that metric you must first -// Unregister the existing metric. -type DuplicateMetric string - -func (err DuplicateMetric) Error() string { - return fmt.Sprintf("duplicate metric: %s", string(err)) -} +import "sync" type Registry interface { - // Call the given function for each registered metric. - Each(func(string, interface{})) - - // Get the metric by the given name or nil if none is registered. - Get(string) interface{} - - // Gets an existing metric or registers the given one. - // The interface can be the metric to register if not found in registry, - // or a function returning the metric for lazy instantiation. - GetOrRegister(string, interface{}) interface{} - - // Register the given metric under the given name. - Register(string, interface{}) error + GetSnapshots() []Metric + Register(metric Metric) } // The standard implementation of a Registry is a mutex-protected map // of names to metrics. type StandardRegistry struct { - metrics map[string]interface{} + metrics []Metric mutex sync.Mutex } // Create a new registry. func NewRegistry() Registry { - return &StandardRegistry{metrics: make(map[string]interface{})} + return &StandardRegistry{ + metrics: make([]Metric, 0), + } +} + +func (r *StandardRegistry) Register(metric Metric) { + r.mutex.Lock() + defer r.mutex.Unlock() + r.metrics = append(r.metrics, metric) } // Call the given function for each registered metric. -func (r *StandardRegistry) Each(f func(string, interface{})) { - for name, i := range r.registered() { - f(name, i) - } -} - -// Get the metric by the given name or nil if none is registered. -func (r *StandardRegistry) Get(name string) interface{} { - r.mutex.Lock() - defer r.mutex.Unlock() - return r.metrics[name] -} - -// Gets an existing metric or creates and registers a new one. Threadsafe -// alternative to calling Get and Register on failure. -// The interface can be the metric to register if not found in registry, -// or a function returning the metric for lazy instantiation. -func (r *StandardRegistry) GetOrRegister(name string, i interface{}) interface{} { - r.mutex.Lock() - defer r.mutex.Unlock() - if metric, ok := r.metrics[name]; ok { - return metric - } - if v := reflect.ValueOf(i); v.Kind() == reflect.Func { - i = v.Call(nil)[0].Interface() - } - r.register(name, i) - return i -} - -// Register the given metric under the given name. Returns a DuplicateMetric -// if a metric by the given name is already registered. -func (r *StandardRegistry) Register(name string, i interface{}) error { - r.mutex.Lock() - defer r.mutex.Unlock() - return r.register(name, i) -} - -func (r *StandardRegistry) register(name string, i interface{}) error { - if _, ok := r.metrics[name]; ok { - return DuplicateMetric(name) - } - - r.metrics[name] = i - return nil -} - -func (r *StandardRegistry) registered() map[string]interface{} { - metrics := make(map[string]interface{}, len(r.metrics)) - r.mutex.Lock() - defer r.mutex.Unlock() - for name, i := range r.metrics { - metrics[name] = i +func (r *StandardRegistry) GetSnapshots() []Metric { + metrics := make([]Metric, len(r.metrics)) + for i, metric := range r.metrics { + metrics[i] = metric.Snapshot() } return metrics } diff --git a/pkg/metrics/report_usage.go b/pkg/metrics/report_usage.go deleted file mode 100644 index c5c2afed7f7..00000000000 --- a/pkg/metrics/report_usage.go +++ /dev/null @@ -1,84 +0,0 @@ -package metrics - -import ( - "bytes" - "encoding/json" - "net/http" - "strings" - "time" - - "github.com/grafana/grafana/pkg/bus" - "github.com/grafana/grafana/pkg/log" - m "github.com/grafana/grafana/pkg/models" - "github.com/grafana/grafana/pkg/setting" -) - -func StartUsageReportLoop() chan struct{} { - M_Instance_Start.Inc(1) - - ticker := time.NewTicker(time.Hour * 24) - for { - select { - case <-ticker.C: - sendUsageStats() - } - } -} - -func sendUsageStats() { - log.Trace("Sending anonymous usage stats to stats.grafana.org") - - version := strings.Replace(setting.BuildVersion, ".", "_", -1) - - metrics := map[string]interface{}{} - report := map[string]interface{}{ - "version": version, - "metrics": metrics, - } - - UsageStats.Each(func(name string, i interface{}) { - switch metric := i.(type) { - case Counter: - if metric.Count() > 0 { - metrics[name+".count"] = metric.Count() - metric.Clear() - } - } - }) - - statsQuery := m.GetSystemStatsQuery{} - if err := bus.Dispatch(&statsQuery); err != nil { - log.Error(3, "Failed to get system stats", err) - return - } - - metrics["stats.dashboards.count"] = statsQuery.Result.DashboardCount - metrics["stats.users.count"] = statsQuery.Result.UserCount - metrics["stats.orgs.count"] = statsQuery.Result.OrgCount - metrics["stats.playlist.count"] = statsQuery.Result.PlaylistCount - - dsStats := m.GetDataSourceStatsQuery{} - if err := bus.Dispatch(&dsStats); err != nil { - log.Error(3, "Failed to get datasource stats", err) - return - } - - // send counters for each data source - // but ignore any custom data sources - // as sending that name could be sensitive information - dsOtherCount := 0 - for _, dsStat := range dsStats.Result { - if m.IsKnownDataSourcePlugin(dsStat.Type) { - metrics["stats.ds."+dsStat.Type+".count"] = dsStat.Count - } else { - dsOtherCount += dsStat.Count - } - } - metrics["stats.ds.other.count"] = dsOtherCount - - out, _ := json.MarshalIndent(report, "", " ") - data := bytes.NewBuffer(out) - - client := http.Client{Timeout: time.Duration(5 * time.Second)} - go client.Post("https://stats.grafana.org/grafana-usage-report", "application/json", data) -} diff --git a/pkg/metrics/sample.go b/pkg/metrics/sample.go new file mode 100644 index 00000000000..4288f29cce6 --- /dev/null +++ b/pkg/metrics/sample.go @@ -0,0 +1,607 @@ +// includes code from +// https://raw.githubusercontent.com/rcrowley/go-metrics/master/sample.go +// Copyright 2012 Richard Crowley. All rights reserved. + +package metrics + +import ( + "math" + "math/rand" + "sort" + "sync" + "time" +) + +const rescaleThreshold = time.Hour + +// Samples maintain a statistically-significant selection of values from +// a stream. +type Sample interface { + Clear() + Count() int64 + Max() int64 + Mean() float64 + Min() int64 + Percentile(float64) float64 + Percentiles([]float64) []float64 + Size() int + Snapshot() Sample + StdDev() float64 + Sum() int64 + Update(int64) + Values() []int64 + Variance() float64 +} + +// ExpDecaySample is an exponentially-decaying sample using a forward-decaying +// priority reservoir. See Cormode et al's "Forward Decay: A Practical Time +// Decay Model for Streaming Systems". +// +// +type ExpDecaySample struct { + alpha float64 + count int64 + mutex sync.Mutex + reservoirSize int + t0, t1 time.Time + values *expDecaySampleHeap +} + +// NewExpDecaySample constructs a new exponentially-decaying sample with the +// given reservoir size and alpha. +func NewExpDecaySample(reservoirSize int, alpha float64) Sample { + s := &ExpDecaySample{ + alpha: alpha, + reservoirSize: reservoirSize, + t0: time.Now(), + values: newExpDecaySampleHeap(reservoirSize), + } + s.t1 = s.t0.Add(rescaleThreshold) + return s +} + +// Clear clears all samples. +func (s *ExpDecaySample) Clear() { + s.mutex.Lock() + defer s.mutex.Unlock() + s.count = 0 + s.t0 = time.Now() + s.t1 = s.t0.Add(rescaleThreshold) + s.values.Clear() +} + +// Count returns the number of samples recorded, which may exceed the +// reservoir size. +func (s *ExpDecaySample) Count() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return s.count +} + +// Max returns the maximum value in the sample, which may not be the maximum +// value ever to be part of the sample. +func (s *ExpDecaySample) Max() int64 { + return SampleMax(s.Values()) +} + +// Mean returns the mean of the values in the sample. +func (s *ExpDecaySample) Mean() float64 { + return SampleMean(s.Values()) +} + +// Min returns the minimum value in the sample, which may not be the minimum +// value ever to be part of the sample. +func (s *ExpDecaySample) Min() int64 { + return SampleMin(s.Values()) +} + +// Percentile returns an arbitrary percentile of values in the sample. +func (s *ExpDecaySample) Percentile(p float64) float64 { + return SamplePercentile(s.Values(), p) +} + +// Percentiles returns a slice of arbitrary percentiles of values in the +// sample. +func (s *ExpDecaySample) Percentiles(ps []float64) []float64 { + return SamplePercentiles(s.Values(), ps) +} + +// Size returns the size of the sample, which is at most the reservoir size. +func (s *ExpDecaySample) Size() int { + s.mutex.Lock() + defer s.mutex.Unlock() + return s.values.Size() +} + +// Snapshot returns a read-only copy of the sample. +func (s *ExpDecaySample) Snapshot() Sample { + s.mutex.Lock() + defer s.mutex.Unlock() + vals := s.values.Values() + values := make([]int64, len(vals)) + for i, v := range vals { + values[i] = v.v + } + return &SampleSnapshot{ + count: s.count, + values: values, + } +} + +// StdDev returns the standard deviation of the values in the sample. +func (s *ExpDecaySample) StdDev() float64 { + return SampleStdDev(s.Values()) +} + +// Sum returns the sum of the values in the sample. +func (s *ExpDecaySample) Sum() int64 { + return SampleSum(s.Values()) +} + +// Update samples a new value. +func (s *ExpDecaySample) Update(v int64) { + s.update(time.Now(), v) +} + +// Values returns a copy of the values in the sample. +func (s *ExpDecaySample) Values() []int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + vals := s.values.Values() + values := make([]int64, len(vals)) + for i, v := range vals { + values[i] = v.v + } + return values +} + +// Variance returns the variance of the values in the sample. +func (s *ExpDecaySample) Variance() float64 { + return SampleVariance(s.Values()) +} + +// update samples a new value at a particular timestamp. This is a method all +// its own to facilitate testing. +func (s *ExpDecaySample) update(t time.Time, v int64) { + s.mutex.Lock() + defer s.mutex.Unlock() + s.count++ + if s.values.Size() == s.reservoirSize { + s.values.Pop() + } + s.values.Push(expDecaySample{ + k: math.Exp(t.Sub(s.t0).Seconds()*s.alpha) / rand.Float64(), + v: v, + }) + if t.After(s.t1) { + values := s.values.Values() + t0 := s.t0 + s.values.Clear() + s.t0 = t + s.t1 = s.t0.Add(rescaleThreshold) + for _, v := range values { + v.k = v.k * math.Exp(-s.alpha*s.t0.Sub(t0).Seconds()) + s.values.Push(v) + } + } +} + +// NilSample is a no-op Sample. +type NilSample struct{} + +// Clear is a no-op. +func (NilSample) Clear() {} + +// Count is a no-op. +func (NilSample) Count() int64 { return 0 } + +// Max is a no-op. +func (NilSample) Max() int64 { return 0 } + +// Mean is a no-op. +func (NilSample) Mean() float64 { return 0.0 } + +// Min is a no-op. +func (NilSample) Min() int64 { return 0 } + +// Percentile is a no-op. +func (NilSample) Percentile(p float64) float64 { return 0.0 } + +// Percentiles is a no-op. +func (NilSample) Percentiles(ps []float64) []float64 { + return make([]float64, len(ps)) +} + +// Size is a no-op. +func (NilSample) Size() int { return 0 } + +// Sample is a no-op. +func (NilSample) Snapshot() Sample { return NilSample{} } + +// StdDev is a no-op. +func (NilSample) StdDev() float64 { return 0.0 } + +// Sum is a no-op. +func (NilSample) Sum() int64 { return 0 } + +// Update is a no-op. +func (NilSample) Update(v int64) {} + +// Values is a no-op. +func (NilSample) Values() []int64 { return []int64{} } + +// Variance is a no-op. +func (NilSample) Variance() float64 { return 0.0 } + +// SampleMax returns the maximum value of the slice of int64. +func SampleMax(values []int64) int64 { + if 0 == len(values) { + return 0 + } + var max int64 = math.MinInt64 + for _, v := range values { + if max < v { + max = v + } + } + return max +} + +// SampleMean returns the mean value of the slice of int64. +func SampleMean(values []int64) float64 { + if 0 == len(values) { + return 0.0 + } + return float64(SampleSum(values)) / float64(len(values)) +} + +// SampleMin returns the minimum value of the slice of int64. +func SampleMin(values []int64) int64 { + if 0 == len(values) { + return 0 + } + var min int64 = math.MaxInt64 + for _, v := range values { + if min > v { + min = v + } + } + return min +} + +// SamplePercentiles returns an arbitrary percentile of the slice of int64. +func SamplePercentile(values int64Slice, p float64) float64 { + return SamplePercentiles(values, []float64{p})[0] +} + +// SamplePercentiles returns a slice of arbitrary percentiles of the slice of +// int64. +func SamplePercentiles(values int64Slice, ps []float64) []float64 { + scores := make([]float64, len(ps)) + size := len(values) + if size > 0 { + sort.Sort(values) + for i, p := range ps { + pos := p * float64(size+1) + if pos < 1.0 { + scores[i] = float64(values[0]) + } else if pos >= float64(size) { + scores[i] = float64(values[size-1]) + } else { + lower := float64(values[int(pos)-1]) + upper := float64(values[int(pos)]) + scores[i] = lower + (pos-math.Floor(pos))*(upper-lower) + } + } + } + return scores +} + +// SampleSnapshot is a read-only copy of another Sample. +type SampleSnapshot struct { + count int64 + values []int64 +} + +// Clear panics. +func (*SampleSnapshot) Clear() { + panic("Clear called on a SampleSnapshot") +} + +// Count returns the count of inputs at the time the snapshot was taken. +func (s *SampleSnapshot) Count() int64 { return s.count } + +// Max returns the maximal value at the time the snapshot was taken. +func (s *SampleSnapshot) Max() int64 { return SampleMax(s.values) } + +// Mean returns the mean value at the time the snapshot was taken. +func (s *SampleSnapshot) Mean() float64 { return SampleMean(s.values) } + +// Min returns the minimal value at the time the snapshot was taken. +func (s *SampleSnapshot) Min() int64 { return SampleMin(s.values) } + +// Percentile returns an arbitrary percentile of values at the time the +// snapshot was taken. +func (s *SampleSnapshot) Percentile(p float64) float64 { + return SamplePercentile(s.values, p) +} + +// Percentiles returns a slice of arbitrary percentiles of values at the time +// the snapshot was taken. +func (s *SampleSnapshot) Percentiles(ps []float64) []float64 { + return SamplePercentiles(s.values, ps) +} + +// Size returns the size of the sample at the time the snapshot was taken. +func (s *SampleSnapshot) Size() int { return len(s.values) } + +// Snapshot returns the snapshot. +func (s *SampleSnapshot) Snapshot() Sample { return s } + +// StdDev returns the standard deviation of values at the time the snapshot was +// taken. +func (s *SampleSnapshot) StdDev() float64 { return SampleStdDev(s.values) } + +// Sum returns the sum of values at the time the snapshot was taken. +func (s *SampleSnapshot) Sum() int64 { return SampleSum(s.values) } + +// Update panics. +func (*SampleSnapshot) Update(int64) { + panic("Update called on a SampleSnapshot") +} + +// Values returns a copy of the values in the sample. +func (s *SampleSnapshot) Values() []int64 { + values := make([]int64, len(s.values)) + copy(values, s.values) + return values +} + +// Variance returns the variance of values at the time the snapshot was taken. +func (s *SampleSnapshot) Variance() float64 { return SampleVariance(s.values) } + +// SampleStdDev returns the standard deviation of the slice of int64. +func SampleStdDev(values []int64) float64 { + return math.Sqrt(SampleVariance(values)) +} + +// SampleSum returns the sum of the slice of int64. +func SampleSum(values []int64) int64 { + var sum int64 + for _, v := range values { + sum += v + } + return sum +} + +// SampleVariance returns the variance of the slice of int64. +func SampleVariance(values []int64) float64 { + if 0 == len(values) { + return 0.0 + } + m := SampleMean(values) + var sum float64 + for _, v := range values { + d := float64(v) - m + sum += d * d + } + return sum / float64(len(values)) +} + +// A uniform sample using Vitter's Algorithm R. +// +// +type UniformSample struct { + count int64 + mutex sync.Mutex + reservoirSize int + values []int64 +} + +// NewUniformSample constructs a new uniform sample with the given reservoir +// size. +func NewUniformSample(reservoirSize int) Sample { + return &UniformSample{ + reservoirSize: reservoirSize, + values: make([]int64, 0, reservoirSize), + } +} + +// Clear clears all samples. +func (s *UniformSample) Clear() { + s.mutex.Lock() + defer s.mutex.Unlock() + s.count = 0 + s.values = make([]int64, 0, s.reservoirSize) +} + +// Count returns the number of samples recorded, which may exceed the +// reservoir size. +func (s *UniformSample) Count() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return s.count +} + +// Max returns the maximum value in the sample, which may not be the maximum +// value ever to be part of the sample. +func (s *UniformSample) Max() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleMax(s.values) +} + +// Mean returns the mean of the values in the sample. +func (s *UniformSample) Mean() float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleMean(s.values) +} + +// Min returns the minimum value in the sample, which may not be the minimum +// value ever to be part of the sample. +func (s *UniformSample) Min() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleMin(s.values) +} + +// Percentile returns an arbitrary percentile of values in the sample. +func (s *UniformSample) Percentile(p float64) float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SamplePercentile(s.values, p) +} + +// Percentiles returns a slice of arbitrary percentiles of values in the +// sample. +func (s *UniformSample) Percentiles(ps []float64) []float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SamplePercentiles(s.values, ps) +} + +// Size returns the size of the sample, which is at most the reservoir size. +func (s *UniformSample) Size() int { + s.mutex.Lock() + defer s.mutex.Unlock() + return len(s.values) +} + +// Snapshot returns a read-only copy of the sample. +func (s *UniformSample) Snapshot() Sample { + s.mutex.Lock() + defer s.mutex.Unlock() + values := make([]int64, len(s.values)) + copy(values, s.values) + return &SampleSnapshot{ + count: s.count, + values: values, + } +} + +// StdDev returns the standard deviation of the values in the sample. +func (s *UniformSample) StdDev() float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleStdDev(s.values) +} + +// Sum returns the sum of the values in the sample. +func (s *UniformSample) Sum() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleSum(s.values) +} + +// Update samples a new value. +func (s *UniformSample) Update(v int64) { + s.mutex.Lock() + defer s.mutex.Unlock() + s.count++ + if len(s.values) < s.reservoirSize { + s.values = append(s.values, v) + } else { + r := rand.Int63n(s.count) + if r < int64(len(s.values)) { + s.values[int(r)] = v + } + } +} + +// Values returns a copy of the values in the sample. +func (s *UniformSample) Values() []int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + values := make([]int64, len(s.values)) + copy(values, s.values) + return values +} + +// Variance returns the variance of the values in the sample. +func (s *UniformSample) Variance() float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleVariance(s.values) +} + +// expDecaySample represents an individual sample in a heap. +type expDecaySample struct { + k float64 + v int64 +} + +func newExpDecaySampleHeap(reservoirSize int) *expDecaySampleHeap { + return &expDecaySampleHeap{make([]expDecaySample, 0, reservoirSize)} +} + +// expDecaySampleHeap is a min-heap of expDecaySamples. +// The internal implementation is copied from the standard library's container/heap +type expDecaySampleHeap struct { + s []expDecaySample +} + +func (h *expDecaySampleHeap) Clear() { + h.s = h.s[:0] +} + +func (h *expDecaySampleHeap) Push(s expDecaySample) { + n := len(h.s) + h.s = h.s[0 : n+1] + h.s[n] = s + h.up(n) +} + +func (h *expDecaySampleHeap) Pop() expDecaySample { + n := len(h.s) - 1 + h.s[0], h.s[n] = h.s[n], h.s[0] + h.down(0, n) + + n = len(h.s) + s := h.s[n-1] + h.s = h.s[0 : n-1] + return s +} + +func (h *expDecaySampleHeap) Size() int { + return len(h.s) +} + +func (h *expDecaySampleHeap) Values() []expDecaySample { + return h.s +} + +func (h *expDecaySampleHeap) up(j int) { + for { + i := (j - 1) / 2 // parent + if i == j || !(h.s[j].k < h.s[i].k) { + break + } + h.s[i], h.s[j] = h.s[j], h.s[i] + j = i + } +} + +func (h *expDecaySampleHeap) down(i, n int) { + for { + j1 := 2*i + 1 + if j1 >= n || j1 < 0 { // j1 < 0 after int overflow + break + } + j := j1 // left child + if j2 := j1 + 1; j2 < n && !(h.s[j1].k < h.s[j2].k) { + j = j2 // = 2*i + 2 // right child + } + if !(h.s[j].k < h.s[i].k) { + break + } + h.s[i], h.s[j] = h.s[j], h.s[i] + i = j + } +} + +type int64Slice []int64 + +func (p int64Slice) Len() int { return len(p) } +func (p int64Slice) Less(i, j int) bool { return p[i] < p[j] } +func (p int64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } diff --git a/pkg/metrics/sample_test.go b/pkg/metrics/sample_test.go new file mode 100644 index 00000000000..755a8cf0173 --- /dev/null +++ b/pkg/metrics/sample_test.go @@ -0,0 +1,367 @@ +// includes code from +// https://raw.githubusercontent.com/rcrowley/go-metrics/master/sample.go +// Copyright 2012 Richard Crowley. All rights reserved. + +package metrics + +import ( + "math/rand" + "runtime" + "testing" + "time" +) + +// Benchmark{Compute,Copy}{1000,1000000} demonstrate that, even for relatively +// expensive computations like Variance, the cost of copying the Sample, as +// approximated by a make and copy, is much greater than the cost of the +// computation for small samples and only slightly less for large samples. +func BenchmarkCompute1000(b *testing.B) { + s := make([]int64, 1000) + for i := 0; i < len(s); i++ { + s[i] = int64(i) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + SampleVariance(s) + } +} +func BenchmarkCompute1000000(b *testing.B) { + s := make([]int64, 1000000) + for i := 0; i < len(s); i++ { + s[i] = int64(i) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + SampleVariance(s) + } +} +func BenchmarkCopy1000(b *testing.B) { + s := make([]int64, 1000) + for i := 0; i < len(s); i++ { + s[i] = int64(i) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + sCopy := make([]int64, len(s)) + copy(sCopy, s) + } +} +func BenchmarkCopy1000000(b *testing.B) { + s := make([]int64, 1000000) + for i := 0; i < len(s); i++ { + s[i] = int64(i) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + sCopy := make([]int64, len(s)) + copy(sCopy, s) + } +} + +func BenchmarkExpDecaySample257(b *testing.B) { + benchmarkSample(b, NewExpDecaySample(257, 0.015)) +} + +func BenchmarkExpDecaySample514(b *testing.B) { + benchmarkSample(b, NewExpDecaySample(514, 0.015)) +} + +func BenchmarkExpDecaySample1028(b *testing.B) { + benchmarkSample(b, NewExpDecaySample(1028, 0.015)) +} + +func BenchmarkUniformSample257(b *testing.B) { + benchmarkSample(b, NewUniformSample(257)) +} + +func BenchmarkUniformSample514(b *testing.B) { + benchmarkSample(b, NewUniformSample(514)) +} + +func BenchmarkUniformSample1028(b *testing.B) { + benchmarkSample(b, NewUniformSample(1028)) +} + +func TestExpDecaySample10(t *testing.T) { + rand.Seed(1) + s := NewExpDecaySample(100, 0.99) + for i := 0; i < 10; i++ { + s.Update(int64(i)) + } + if size := s.Count(); 10 != size { + t.Errorf("s.Count(): 10 != %v\n", size) + } + if size := s.Size(); 10 != size { + t.Errorf("s.Size(): 10 != %v\n", size) + } + if l := len(s.Values()); 10 != l { + t.Errorf("len(s.Values()): 10 != %v\n", l) + } + for _, v := range s.Values() { + if v > 10 || v < 0 { + t.Errorf("out of range [0, 10): %v\n", v) + } + } +} + +func TestExpDecaySample100(t *testing.T) { + rand.Seed(1) + s := NewExpDecaySample(1000, 0.01) + for i := 0; i < 100; i++ { + s.Update(int64(i)) + } + if size := s.Count(); 100 != size { + t.Errorf("s.Count(): 100 != %v\n", size) + } + if size := s.Size(); 100 != size { + t.Errorf("s.Size(): 100 != %v\n", size) + } + if l := len(s.Values()); 100 != l { + t.Errorf("len(s.Values()): 100 != %v\n", l) + } + for _, v := range s.Values() { + if v > 100 || v < 0 { + t.Errorf("out of range [0, 100): %v\n", v) + } + } +} + +func TestExpDecaySample1000(t *testing.T) { + rand.Seed(1) + s := NewExpDecaySample(100, 0.99) + for i := 0; i < 1000; i++ { + s.Update(int64(i)) + } + if size := s.Count(); 1000 != size { + t.Errorf("s.Count(): 1000 != %v\n", size) + } + if size := s.Size(); 100 != size { + t.Errorf("s.Size(): 100 != %v\n", size) + } + if l := len(s.Values()); 100 != l { + t.Errorf("len(s.Values()): 100 != %v\n", l) + } + for _, v := range s.Values() { + if v > 1000 || v < 0 { + t.Errorf("out of range [0, 1000): %v\n", v) + } + } +} + +// This test makes sure that the sample's priority is not amplified by using +// nanosecond duration since start rather than second duration since start. +// The priority becomes +Inf quickly after starting if this is done, +// effectively freezing the set of samples until a rescale step happens. +func TestExpDecaySampleNanosecondRegression(t *testing.T) { + rand.Seed(1) + s := NewExpDecaySample(100, 0.99) + for i := 0; i < 100; i++ { + s.Update(10) + } + time.Sleep(1 * time.Millisecond) + for i := 0; i < 100; i++ { + s.Update(20) + } + v := s.Values() + avg := float64(0) + for i := 0; i < len(v); i++ { + avg += float64(v[i]) + } + avg /= float64(len(v)) + if avg > 16 || avg < 14 { + t.Errorf("out of range [14, 16]: %v\n", avg) + } +} + +func TestExpDecaySampleRescale(t *testing.T) { + s := NewExpDecaySample(2, 0.001).(*ExpDecaySample) + s.update(time.Now(), 1) + s.update(time.Now().Add(time.Hour+time.Microsecond), 1) + for _, v := range s.values.Values() { + if v.k == 0.0 { + t.Fatal("v.k == 0.0") + } + } +} + +func TestExpDecaySampleSnapshot(t *testing.T) { + now := time.Now() + rand.Seed(1) + s := NewExpDecaySample(100, 0.99) + for i := 1; i <= 10000; i++ { + s.(*ExpDecaySample).update(now.Add(time.Duration(i)), int64(i)) + } + snapshot := s.Snapshot() + s.Update(1) + testExpDecaySampleStatistics(t, snapshot) +} + +func TestExpDecaySampleStatistics(t *testing.T) { + now := time.Now() + rand.Seed(1) + s := NewExpDecaySample(100, 0.99) + for i := 1; i <= 10000; i++ { + s.(*ExpDecaySample).update(now.Add(time.Duration(i)), int64(i)) + } + testExpDecaySampleStatistics(t, s) +} + +func TestUniformSample(t *testing.T) { + rand.Seed(1) + s := NewUniformSample(100) + for i := 0; i < 1000; i++ { + s.Update(int64(i)) + } + if size := s.Count(); 1000 != size { + t.Errorf("s.Count(): 1000 != %v\n", size) + } + if size := s.Size(); 100 != size { + t.Errorf("s.Size(): 100 != %v\n", size) + } + if l := len(s.Values()); 100 != l { + t.Errorf("len(s.Values()): 100 != %v\n", l) + } + for _, v := range s.Values() { + if v > 1000 || v < 0 { + t.Errorf("out of range [0, 100): %v\n", v) + } + } +} + +func TestUniformSampleIncludesTail(t *testing.T) { + rand.Seed(1) + s := NewUniformSample(100) + max := 100 + for i := 0; i < max; i++ { + s.Update(int64(i)) + } + v := s.Values() + sum := 0 + exp := (max - 1) * max / 2 + for i := 0; i < len(v); i++ { + sum += int(v[i]) + } + if exp != sum { + t.Errorf("sum: %v != %v\n", exp, sum) + } +} + +func TestUniformSampleSnapshot(t *testing.T) { + s := NewUniformSample(100) + for i := 1; i <= 10000; i++ { + s.Update(int64(i)) + } + snapshot := s.Snapshot() + s.Update(1) + testUniformSampleStatistics(t, snapshot) +} + +func TestUniformSampleStatistics(t *testing.T) { + rand.Seed(1) + s := NewUniformSample(100) + for i := 1; i <= 10000; i++ { + s.Update(int64(i)) + } + testUniformSampleStatistics(t, s) +} + +func benchmarkSample(b *testing.B, s Sample) { + var memStats runtime.MemStats + runtime.ReadMemStats(&memStats) + pauseTotalNs := memStats.PauseTotalNs + b.ResetTimer() + for i := 0; i < b.N; i++ { + s.Update(1) + } + b.StopTimer() + runtime.GC() + runtime.ReadMemStats(&memStats) + b.Logf("GC cost: %d ns/op", int(memStats.PauseTotalNs-pauseTotalNs)/b.N) +} + +func testExpDecaySampleStatistics(t *testing.T, s Sample) { + if count := s.Count(); 10000 != count { + t.Errorf("s.Count(): 10000 != %v\n", count) + } + if min := s.Min(); 107 != min { + t.Errorf("s.Min(): 107 != %v\n", min) + } + if max := s.Max(); 10000 != max { + t.Errorf("s.Max(): 10000 != %v\n", max) + } + if mean := s.Mean(); 4965.98 != mean { + t.Errorf("s.Mean(): 4965.98 != %v\n", mean) + } + if stdDev := s.StdDev(); 2959.825156930727 != stdDev { + t.Errorf("s.StdDev(): 2959.825156930727 != %v\n", stdDev) + } + ps := s.Percentiles([]float64{0.5, 0.75, 0.99}) + if 4615 != ps[0] { + t.Errorf("median: 4615 != %v\n", ps[0]) + } + if 7672 != ps[1] { + t.Errorf("75th percentile: 7672 != %v\n", ps[1]) + } + if 9998.99 != ps[2] { + t.Errorf("99th percentile: 9998.99 != %v\n", ps[2]) + } +} + +func testUniformSampleStatistics(t *testing.T, s Sample) { + if count := s.Count(); 10000 != count { + t.Errorf("s.Count(): 10000 != %v\n", count) + } + if min := s.Min(); 37 != min { + t.Errorf("s.Min(): 37 != %v\n", min) + } + if max := s.Max(); 9989 != max { + t.Errorf("s.Max(): 9989 != %v\n", max) + } + if mean := s.Mean(); 4748.14 != mean { + t.Errorf("s.Mean(): 4748.14 != %v\n", mean) + } + if stdDev := s.StdDev(); 2826.684117548333 != stdDev { + t.Errorf("s.StdDev(): 2826.684117548333 != %v\n", stdDev) + } + ps := s.Percentiles([]float64{0.5, 0.75, 0.99}) + if 4599 != ps[0] { + t.Errorf("median: 4599 != %v\n", ps[0]) + } + if 7380.5 != ps[1] { + t.Errorf("75th percentile: 7380.5 != %v\n", ps[1]) + } + if 9986.429999999998 != ps[2] { + t.Errorf("99th percentile: 9986.429999999998 != %v\n", ps[2]) + } +} + +// TestUniformSampleConcurrentUpdateCount would expose data race problems with +// concurrent Update and Count calls on Sample when test is called with -race +// argument +func TestUniformSampleConcurrentUpdateCount(t *testing.T) { + if testing.Short() { + t.Skip("skipping in short mode") + } + s := NewUniformSample(100) + for i := 0; i < 100; i++ { + s.Update(int64(i)) + } + quit := make(chan struct{}) + go func() { + t := time.NewTicker(10 * time.Millisecond) + for { + select { + case <-t.C: + s.Update(rand.Int63()) + case <-quit: + t.Stop() + return + } + } + }() + for i := 0; i < 1000; i++ { + s.Count() + time.Sleep(5 * time.Millisecond) + } + quit <- struct{}{} +} diff --git a/pkg/metrics/settings.go b/pkg/metrics/settings.go new file mode 100644 index 00000000000..691bf6b6e73 --- /dev/null +++ b/pkg/metrics/settings.go @@ -0,0 +1,43 @@ +package metrics + +import "github.com/grafana/grafana/pkg/setting" + +type MetricPublisher interface { + Publish(metrics []Metric) +} + +type MetricSettings struct { + Enabled bool + IntervalSeconds int64 + + Publishers []MetricPublisher +} + +func readSettings() *MetricSettings { + var settings = &MetricSettings{ + Enabled: false, + Publishers: make([]MetricPublisher, 0), + } + + var section, err = setting.Cfg.GetSection("metrics") + if err != nil { + metricsLogger.Crit("Unable to find metrics config section", "error", err) + return nil + } + + settings.Enabled = section.Key("enabled").MustBool(false) + settings.IntervalSeconds = section.Key("interval_seconds").MustInt64(10) + + if !settings.Enabled { + return settings + } + + if graphitePublisher, err := CreateGraphitePublisher(); err != nil { + metricsLogger.Error("Failed to init Graphite metric publisher", "error", err) + } else if graphitePublisher != nil { + metricsLogger.Info("Metrics publisher initialized", "type", "graphite") + settings.Publishers = append(settings.Publishers, graphitePublisher) + } + + return settings +} diff --git a/pkg/metrics/timer.go b/pkg/metrics/timer.go new file mode 100644 index 00000000000..61c3bf9533d --- /dev/null +++ b/pkg/metrics/timer.go @@ -0,0 +1,310 @@ +// includes code from +// https://raw.githubusercontent.com/rcrowley/go-metrics/master/sample.go +// Copyright 2012 Richard Crowley. All rights reserved. + +package metrics + +import ( + "sync" + "time" +) + +// Timers capture the duration and rate of events. +type Timer interface { + Metric + + Count() int64 + Max() int64 + Mean() float64 + Min() int64 + Percentile(float64) float64 + Percentiles([]float64) []float64 + Rate1() float64 + Rate5() float64 + Rate15() float64 + RateMean() float64 + StdDev() float64 + Sum() int64 + Time(func()) + Update(time.Duration) + UpdateSince(time.Time) + Variance() float64 +} + +// NewCustomTimer constructs a new StandardTimer from a Histogram and a Meter. +func NewCustomTimer(meta *MetricMeta, h Histogram, m Meter) Timer { + if UseNilMetrics { + return NilTimer{} + } + return &StandardTimer{ + MetricMeta: meta, + histogram: h, + meter: m, + } +} + +// NewTimer constructs a new StandardTimer using an exponentially-decaying +// sample with the same reservoir size and alpha as UNIX load averages. +func NewTimer(meta *MetricMeta) Timer { + if UseNilMetrics { + return NilTimer{} + } + return &StandardTimer{ + MetricMeta: meta, + histogram: NewHistogram(meta, NewExpDecaySample(1028, 0.015)), + meter: NewMeter(meta), + } +} + +func RegTimer(name string, tagStrings ...string) Timer { + tr := NewTimer(NewMetricMeta(name, tagStrings)) + MetricStats.Register(tr) + return tr +} + +// NilTimer is a no-op Timer. +type NilTimer struct { + *MetricMeta + h Histogram + m Meter +} + +// Count is a no-op. +func (NilTimer) Count() int64 { return 0 } + +// Max is a no-op. +func (NilTimer) Max() int64 { return 0 } + +// Mean is a no-op. +func (NilTimer) Mean() float64 { return 0.0 } + +// Min is a no-op. +func (NilTimer) Min() int64 { return 0 } + +// Percentile is a no-op. +func (NilTimer) Percentile(p float64) float64 { return 0.0 } + +// Percentiles is a no-op. +func (NilTimer) Percentiles(ps []float64) []float64 { + return make([]float64, len(ps)) +} + +// Rate1 is a no-op. +func (NilTimer) Rate1() float64 { return 0.0 } + +// Rate5 is a no-op. +func (NilTimer) Rate5() float64 { return 0.0 } + +// Rate15 is a no-op. +func (NilTimer) Rate15() float64 { return 0.0 } + +// RateMean is a no-op. +func (NilTimer) RateMean() float64 { return 0.0 } + +// Snapshot is a no-op. +func (n NilTimer) Snapshot() Metric { return n } + +// StdDev is a no-op. +func (NilTimer) StdDev() float64 { return 0.0 } + +// Sum is a no-op. +func (NilTimer) Sum() int64 { return 0 } + +// Time is a no-op. +func (NilTimer) Time(func()) {} + +// Update is a no-op. +func (NilTimer) Update(time.Duration) {} + +// UpdateSince is a no-op. +func (NilTimer) UpdateSince(time.Time) {} + +// Variance is a no-op. +func (NilTimer) Variance() float64 { return 0.0 } + +// StandardTimer is the standard implementation of a Timer and uses a Histogram +// and Meter. +type StandardTimer struct { + *MetricMeta + histogram Histogram + meter Meter + mutex sync.Mutex +} + +// Count returns the number of events recorded. +func (t *StandardTimer) Count() int64 { + return t.histogram.Count() +} + +// Max returns the maximum value in the sample. +func (t *StandardTimer) Max() int64 { + return t.histogram.Max() +} + +// Mean returns the mean of the values in the sample. +func (t *StandardTimer) Mean() float64 { + return t.histogram.Mean() +} + +// Min returns the minimum value in the sample. +func (t *StandardTimer) Min() int64 { + return t.histogram.Min() +} + +// Percentile returns an arbitrary percentile of the values in the sample. +func (t *StandardTimer) Percentile(p float64) float64 { + return t.histogram.Percentile(p) +} + +// Percentiles returns a slice of arbitrary percentiles of the values in the +// sample. +func (t *StandardTimer) Percentiles(ps []float64) []float64 { + return t.histogram.Percentiles(ps) +} + +// Rate1 returns the one-minute moving average rate of events per second. +func (t *StandardTimer) Rate1() float64 { + return t.meter.Rate1() +} + +// Rate5 returns the five-minute moving average rate of events per second. +func (t *StandardTimer) Rate5() float64 { + return t.meter.Rate5() +} + +// Rate15 returns the fifteen-minute moving average rate of events per second. +func (t *StandardTimer) Rate15() float64 { + return t.meter.Rate15() +} + +// RateMean returns the meter's mean rate of events per second. +func (t *StandardTimer) RateMean() float64 { + return t.meter.RateMean() +} + +// Snapshot returns a read-only copy of the timer. +func (t *StandardTimer) Snapshot() Metric { + t.mutex.Lock() + defer t.mutex.Unlock() + return &TimerSnapshot{ + MetricMeta: t.MetricMeta, + histogram: t.histogram.Snapshot().(*HistogramSnapshot), + meter: t.meter.Snapshot().(*MeterSnapshot), + } +} + +// StdDev returns the standard deviation of the values in the sample. +func (t *StandardTimer) StdDev() float64 { + return t.histogram.StdDev() +} + +// Sum returns the sum in the sample. +func (t *StandardTimer) Sum() int64 { + return t.histogram.Sum() +} + +// Record the duration of the execution of the given function. +func (t *StandardTimer) Time(f func()) { + ts := time.Now() + f() + t.Update(time.Since(ts)) +} + +// Record the duration of an event. +func (t *StandardTimer) Update(d time.Duration) { + t.mutex.Lock() + defer t.mutex.Unlock() + t.histogram.Update(int64(d)) + t.meter.Mark(1) +} + +// Record the duration of an event that started at a time and ends now. +func (t *StandardTimer) UpdateSince(ts time.Time) { + t.mutex.Lock() + defer t.mutex.Unlock() + sinceMs := time.Since(ts) / time.Millisecond + t.histogram.Update(int64(sinceMs)) + t.meter.Mark(1) +} + +// Variance returns the variance of the values in the sample. +func (t *StandardTimer) Variance() float64 { + return t.histogram.Variance() +} + +// TimerSnapshot is a read-only copy of another Timer. +type TimerSnapshot struct { + *MetricMeta + histogram *HistogramSnapshot + meter *MeterSnapshot +} + +// Count returns the number of events recorded at the time the snapshot was +// taken. +func (t *TimerSnapshot) Count() int64 { return t.histogram.Count() } + +// Max returns the maximum value at the time the snapshot was taken. +func (t *TimerSnapshot) Max() int64 { return t.histogram.Max() } + +// Mean returns the mean value at the time the snapshot was taken. +func (t *TimerSnapshot) Mean() float64 { return t.histogram.Mean() } + +// Min returns the minimum value at the time the snapshot was taken. +func (t *TimerSnapshot) Min() int64 { return t.histogram.Min() } + +// Percentile returns an arbitrary percentile of sampled values at the time the +// snapshot was taken. +func (t *TimerSnapshot) Percentile(p float64) float64 { + return t.histogram.Percentile(p) +} + +// Percentiles returns a slice of arbitrary percentiles of sampled values at +// the time the snapshot was taken. +func (t *TimerSnapshot) Percentiles(ps []float64) []float64 { + return t.histogram.Percentiles(ps) +} + +// Rate1 returns the one-minute moving average rate of events per second at the +// time the snapshot was taken. +func (t *TimerSnapshot) Rate1() float64 { return t.meter.Rate1() } + +// Rate5 returns the five-minute moving average rate of events per second at +// the time the snapshot was taken. +func (t *TimerSnapshot) Rate5() float64 { return t.meter.Rate5() } + +// Rate15 returns the fifteen-minute moving average rate of events per second +// at the time the snapshot was taken. +func (t *TimerSnapshot) Rate15() float64 { return t.meter.Rate15() } + +// RateMean returns the meter's mean rate of events per second at the time the +// snapshot was taken. +func (t *TimerSnapshot) RateMean() float64 { return t.meter.RateMean() } + +// Snapshot returns the snapshot. +func (t *TimerSnapshot) Snapshot() Metric { return t } + +// StdDev returns the standard deviation of the values at the time the snapshot +// was taken. +func (t *TimerSnapshot) StdDev() float64 { return t.histogram.StdDev() } + +// Sum returns the sum at the time the snapshot was taken. +func (t *TimerSnapshot) Sum() int64 { return t.histogram.Sum() } + +// Time panics. +func (*TimerSnapshot) Time(func()) { + panic("Time called on a TimerSnapshot") +} + +// Update panics. +func (*TimerSnapshot) Update(time.Duration) { + panic("Update called on a TimerSnapshot") +} + +// UpdateSince panics. +func (*TimerSnapshot) UpdateSince(time.Time) { + panic("UpdateSince called on a TimerSnapshot") +} + +// Variance returns the variance of the values at the time the snapshot was +// taken. +func (t *TimerSnapshot) Variance() float64 { return t.histogram.Variance() } diff --git a/pkg/middleware/auth_proxy.go b/pkg/middleware/auth_proxy.go index 648c3319305..e02e31f9152 100644 --- a/pkg/middleware/auth_proxy.go +++ b/pkg/middleware/auth_proxy.go @@ -1,8 +1,14 @@ package middleware import ( + "errors" + "fmt" + "strings" + "time" + "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/login" m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/setting" ) @@ -17,6 +23,12 @@ func initContextWithAuthProxy(ctx *Context) bool { return false } + // if auth proxy ip(s) defined, check if request comes from one of those + if err := checkAuthenticationProxy(ctx, proxyHeaderValue); err != nil { + ctx.Handle(407, "Proxy authentication required", err) + return true + } + query := getSignedInUserQueryForProxyAuth(proxyHeaderValue) if err := bus.Dispatch(query); err != nil { if err != m.ErrUserNotFound { @@ -26,6 +38,10 @@ func initContextWithAuthProxy(ctx *Context) bool { if setting.AuthProxyAutoSignUp { cmd := getCreateUserCommandForProxyAuth(proxyHeaderValue) + if setting.LdapEnabled { + cmd.SkipOrgSetup = true + } + if err := bus.Dispatch(cmd); err != nil { ctx.Handle(500, "Failed to create user specified in auth proxy header", err) return true @@ -46,6 +62,30 @@ func initContextWithAuthProxy(ctx *Context) bool { return false } + // Make sure that we cannot share a session between different users! + if getRequestUserId(ctx) > 0 && getRequestUserId(ctx) != query.Result.UserId { + // remove session + if err := ctx.Session.Destory(ctx); err != nil { + log.Error(3, "Failed to destory session, err") + } + + // initialize a new session + if err := ctx.Session.Start(ctx); err != nil { + log.Error(3, "Failed to start session", err) + } + } + + // When ldap is enabled, sync userinfo and org roles + if err := syncGrafanaUserWithLdapUser(ctx, query); err != nil { + if err == login.ErrInvalidCredentials { + ctx.Handle(500, "Unable to authenticate user", err) + return false + } + + ctx.Handle(500, "Failed to sync user", err) + return false + } + ctx.SignedInUser = query.Result ctx.IsSignedIn = true ctx.Session.Set(SESS_KEY_USERID, ctx.UserId) @@ -53,6 +93,56 @@ func initContextWithAuthProxy(ctx *Context) bool { return true } +var syncGrafanaUserWithLdapUser = func(ctx *Context, query *m.GetSignedInUserQuery) error { + if setting.LdapEnabled { + expireEpoch := time.Now().Add(time.Duration(-setting.AuthProxyLdapSyncTtl) * time.Minute).Unix() + + var lastLdapSync int64 + if lastLdapSyncInSession := ctx.Session.Get(SESS_KEY_LASTLDAPSYNC); lastLdapSyncInSession != nil { + lastLdapSync = lastLdapSyncInSession.(int64) + } + + if lastLdapSync < expireEpoch { + ldapCfg := login.LdapCfg + + for _, server := range ldapCfg.Servers { + auther := login.NewLdapAuthenticator(server) + if err := auther.SyncSignedInUser(query.Result); err != nil { + return err + } + } + + ctx.Session.Set(SESS_KEY_LASTLDAPSYNC, time.Now().Unix()) + } + } + + return nil +} + +func checkAuthenticationProxy(ctx *Context, proxyHeaderValue string) error { + if len(strings.TrimSpace(setting.AuthProxyWhitelist)) > 0 { + proxies := strings.Split(setting.AuthProxyWhitelist, ",") + remoteAddrSplit := strings.Split(ctx.Req.RemoteAddr, ":") + sourceIP := remoteAddrSplit[0] + + found := false + for _, proxyIP := range proxies { + if sourceIP == strings.TrimSpace(proxyIP) { + found = true + break + } + } + + if !found { + msg := fmt.Sprintf("Request for user (%s) is not from the authentication proxy", proxyHeaderValue) + err := errors.New(msg) + return err + } + } + + return nil +} + func getSignedInUserQueryForProxyAuth(headerVal string) *m.GetSignedInUserQuery { query := m.GetSignedInUserQuery{} if setting.AuthProxyHeaderProperty == "username" { diff --git a/pkg/middleware/auth_proxy_test.go b/pkg/middleware/auth_proxy_test.go new file mode 100644 index 00000000000..cc9253b6a77 --- /dev/null +++ b/pkg/middleware/auth_proxy_test.go @@ -0,0 +1,123 @@ +package middleware + +import ( + "testing" + "time" + + "github.com/grafana/grafana/pkg/login" + m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/setting" + . "github.com/smartystreets/goconvey/convey" +) + +func TestAuthProxyWithLdapEnabled(t *testing.T) { + Convey("When calling sync grafana user with ldap user", t, func() { + + setting.LdapEnabled = true + setting.AuthProxyLdapSyncTtl = 60 + + servers := []*login.LdapServerConf{{Host: "127.0.0.1"}} + login.LdapCfg = login.LdapConfig{Servers: servers} + mockLdapAuther := mockLdapAuthenticator{} + + login.NewLdapAuthenticator = func(server *login.LdapServerConf) login.ILdapAuther { + return &mockLdapAuther + } + + signedInUser := m.SignedInUser{} + query := m.GetSignedInUserQuery{Result: &signedInUser} + + Convey("When session variable lastLdapSync not set, call syncSignedInUser and set lastLdapSync", func() { + // arrange + session := mockSession{} + ctx := Context{Session: &session} + So(session.Get(SESS_KEY_LASTLDAPSYNC), ShouldBeNil) + + // act + syncGrafanaUserWithLdapUser(&ctx, &query) + + // assert + So(mockLdapAuther.syncSignedInUserCalled, ShouldBeTrue) + So(session.Get(SESS_KEY_LASTLDAPSYNC), ShouldBeGreaterThan, 0) + }) + + Convey("When session variable not expired, don't sync and don't change session var", func() { + // arrange + session := mockSession{} + ctx := Context{Session: &session} + now := time.Now().Unix() + session.Set(SESS_KEY_LASTLDAPSYNC, now) + + // act + syncGrafanaUserWithLdapUser(&ctx, &query) + + // assert + So(session.Get(SESS_KEY_LASTLDAPSYNC), ShouldEqual, now) + So(mockLdapAuther.syncSignedInUserCalled, ShouldBeFalse) + }) + + Convey("When lastldapsync is expired, session variable should be updated", func() { + // arrange + session := mockSession{} + ctx := Context{Session: &session} + expiredTime := time.Now().Add(time.Duration(-120) * time.Minute).Unix() + session.Set(SESS_KEY_LASTLDAPSYNC, expiredTime) + + // act + syncGrafanaUserWithLdapUser(&ctx, &query) + + // assert + So(session.Get(SESS_KEY_LASTLDAPSYNC), ShouldBeGreaterThan, expiredTime) + So(mockLdapAuther.syncSignedInUserCalled, ShouldBeTrue) + }) + }) +} + +type mockSession struct { + value interface{} +} + +func (s *mockSession) Start(c *Context) error { + return nil +} + +func (s *mockSession) Set(k interface{}, v interface{}) error { + s.value = v + return nil +} + +func (s *mockSession) Get(k interface{}) interface{} { + return s.value +} + +func (s *mockSession) ID() string { + return "" +} + +func (s *mockSession) Release() error { + return nil +} + +func (s *mockSession) Destory(c *Context) error { + return nil +} + +type mockLdapAuthenticator struct { + syncSignedInUserCalled bool +} + +func (a *mockLdapAuthenticator) Login(query *login.LoginUserQuery) error { + return nil +} + +func (a *mockLdapAuthenticator) SyncSignedInUser(signedInUser *m.SignedInUser) error { + a.syncSignedInUserCalled = true + return nil +} + +func (a *mockLdapAuthenticator) GetGrafanaUserFor(ldapUser *login.LdapUserInfo) (*m.User, error) { + return nil, nil +} +func (a *mockLdapAuthenticator) SyncOrgRoles(user *m.User, ldapUser *login.LdapUserInfo) error { + return nil +} diff --git a/pkg/middleware/logger.go b/pkg/middleware/logger.go index 4cb8acc6354..9bed7cbe16b 100644 --- a/pkg/middleware/logger.go +++ b/pkg/middleware/logger.go @@ -16,11 +16,10 @@ package middleware import ( - "fmt" "net/http" "time" - "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/metrics" "github.com/grafana/grafana/pkg/setting" "gopkg.in/macaron.v1" ) @@ -28,29 +27,32 @@ import ( func Logger() macaron.Handler { return func(res http.ResponseWriter, req *http.Request, c *macaron.Context) { start := time.Now() - - uname := c.GetCookie(setting.CookieUserName) - if len(uname) == 0 { - uname = "-" - } + c.Data["perfmon.start"] = start rw := res.(macaron.ResponseWriter) c.Next() - content := fmt.Sprintf("Completed %s %s \"%s %s %s\" %v %s %d bytes in %dus", c.RemoteAddr(), uname, req.Method, req.URL.Path, req.Proto, rw.Status(), http.StatusText(rw.Status()), rw.Size(), time.Since(start)/time.Microsecond) + timeTakenMs := time.Since(start) / time.Millisecond - switch rw.Status() { - case 200, 304: - content = fmt.Sprintf("%s", content) + if timer, ok := c.Data["perfmon.timer"]; ok { + timerTyped := timer.(metrics.Timer) + timerTyped.Update(timeTakenMs) + } + + status := rw.Status() + if status == 200 || status == 304 { if !setting.RouterLogging { return } - case 404: - content = fmt.Sprintf("%s", content) - case 500: - content = fmt.Sprintf("%s", content) } - log.Info(content) + if ctx, ok := c.Data["ctx"]; ok { + ctxTyped := ctx.(*Context) + if status == 500 { + ctxTyped.Logger.Error("Request Completed", "method", req.Method, "path", req.URL.Path, "status", status, "remote_addr", c.RemoteAddr(), "time_ms", timeTakenMs, "size", rw.Size()) + } else { + ctxTyped.Logger.Info("Request Completed", "method", req.Method, "path", req.URL.Path, "status", status, "remote_addr", c.RemoteAddr(), "time_ms", timeTakenMs, "size", rw.Size()) + } + } } } diff --git a/pkg/middleware/middleware.go b/pkg/middleware/middleware.go index 7a51fd4e8d8..4b59fada62e 100644 --- a/pkg/middleware/middleware.go +++ b/pkg/middleware/middleware.go @@ -9,6 +9,7 @@ import ( "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/components/apikeygen" "github.com/grafana/grafana/pkg/log" + l "github.com/grafana/grafana/pkg/login" "github.com/grafana/grafana/pkg/metrics" m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/setting" @@ -22,7 +23,9 @@ type Context struct { Session SessionStore IsSignedIn bool + IsRenderCall bool AllowAnonymous bool + Logger log.Logger } func GetContextHandler() macaron.Handler { @@ -33,6 +36,7 @@ func GetContextHandler() macaron.Handler { Session: GetSession(), IsSignedIn: false, AllowAnonymous: false, + Logger: log.New("context"), } // the order in which these are tested are important @@ -40,14 +44,17 @@ func GetContextHandler() macaron.Handler { // then init session and look for userId in session // then look for api key in session (special case for render calls via api) // then test if anonymous access is enabled - if initContextWithApiKey(ctx) || + if initContextWithRenderAuth(ctx) || + initContextWithApiKey(ctx) || initContextWithBasicAuth(ctx) || initContextWithAuthProxy(ctx) || initContextWithUserSessionCookie(ctx) || - initContextWithApiKeyFromSession(ctx) || initContextWithAnonymousUser(ctx) { } + ctx.Logger = log.New("context", "userId", ctx.UserId, "orgId", ctx.OrgId, "uname", ctx.Login) + ctx.Data["ctx"] = ctx + c.Map(ctx) } } @@ -75,7 +82,7 @@ func initContextWithAnonymousUser(ctx *Context) bool { func initContextWithUserSessionCookie(ctx *Context) bool { // initialize session if err := ctx.Session.Start(ctx); err != nil { - log.Error(3, "Failed to start session", err) + ctx.Logger.Error("Failed to start session", "error", err) return false } @@ -86,7 +93,7 @@ func initContextWithUserSessionCookie(ctx *Context) bool { query := m.GetSignedInUserQuery{UserId: userId} if err := bus.Dispatch(&query); err != nil { - log.Error(3, "Failed to get user with id %v", userId) + ctx.Logger.Error("Failed to get user with id", "userId", userId) return false } else { ctx.SignedInUser = query.Result @@ -131,6 +138,7 @@ func initContextWithApiKey(ctx *Context) bool { } func initContextWithBasicAuth(ctx *Context) bool { + if !setting.BasicAuthEnabled { return false } @@ -154,9 +162,9 @@ func initContextWithBasicAuth(ctx *Context) bool { user := loginQuery.Result - // validate password - if util.EncodePassword(password, user.Salt) != user.Password { - ctx.JsonApiErr(401, "Invalid username or password", nil) + loginUserQuery := l.LoginUserQuery{Username: username, Password: password, User: user} + if err := bus.Dispatch(&loginUserQuery); err != nil { + ctx.JsonApiErr(401, "Invalid username or password", err) return true } @@ -171,56 +179,23 @@ func initContextWithBasicAuth(ctx *Context) bool { } } -// special case for panel render calls with api key -func initContextWithApiKeyFromSession(ctx *Context) bool { - keyId := ctx.Session.Get(SESS_KEY_APIKEY) - if keyId == nil { - return false - } - - keyQuery := m.GetApiKeyByIdQuery{ApiKeyId: keyId.(int64)} - if err := bus.Dispatch(&keyQuery); err != nil { - log.Error(3, "Failed to get api key by id", err) - return false - } else { - apikey := keyQuery.Result - - ctx.IsSignedIn = true - ctx.SignedInUser = &m.SignedInUser{} - ctx.OrgRole = apikey.Role - ctx.ApiKeyId = apikey.Id - ctx.OrgId = apikey.OrgId - return true - } -} - // Handle handles and logs error by given status. func (ctx *Context) Handle(status int, title string, err error) { if err != nil { - log.Error(4, "%s: %v", title, err) + ctx.Logger.Error(title, "error", err) if setting.Env != setting.PROD { ctx.Data["ErrorMsg"] = err } } - switch status { - case 200: - metrics.M_Page_Status_200.Inc(1) - case 404: - metrics.M_Page_Status_404.Inc(1) - case 500: - metrics.M_Page_Status_500.Inc(1) - } - ctx.Data["Title"] = title + ctx.Data["AppSubUrl"] = setting.AppSubUrl ctx.HTML(status, strconv.Itoa(status)) } func (ctx *Context) JsonOK(message string) { resp := make(map[string]interface{}) - resp["message"] = message - ctx.JSON(200, resp) } @@ -232,7 +207,7 @@ func (ctx *Context) JsonApiErr(status int, message string, err error) { resp := make(map[string]interface{}) if err != nil { - log.Error(4, "%s: %v", message, err) + ctx.Logger.Error(message, "error", err) if setting.Env != setting.PROD { resp["error"] = err.Error() } @@ -240,10 +215,8 @@ func (ctx *Context) JsonApiErr(status int, message string, err error) { switch status { case 404: - metrics.M_Api_Status_404.Inc(1) resp["message"] = "Not Found" case 500: - metrics.M_Api_Status_500.Inc(1) resp["message"] = "Internal Server Error" } @@ -257,3 +230,11 @@ func (ctx *Context) JsonApiErr(status int, message string, err error) { func (ctx *Context) HasUserRole(role m.RoleType) bool { return ctx.OrgRole.Includes(role) } + +func (ctx *Context) HasHelpFlag(flag m.HelpFlags1) bool { + return ctx.HelpFlags1.HasFlag(flag) +} + +func (ctx *Context) TimeRequest(timer metrics.Timer) { + ctx.Data["perfmon.timer"] = timer +} diff --git a/pkg/middleware/middleware_test.go b/pkg/middleware/middleware_test.go index cb37a809212..5cffa0a2884 100644 --- a/pkg/middleware/middleware_test.go +++ b/pkg/middleware/middleware_test.go @@ -9,6 +9,7 @@ import ( "github.com/go-macaron/session" "github.com/grafana/grafana/pkg/bus" + l "github.com/grafana/grafana/pkg/login" m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util" @@ -58,6 +59,10 @@ func TestMiddlewareContext(t *testing.T) { return nil }) + bus.AddHandler("test", func(loginUserQuery *l.LoginUserQuery) error { + return nil + }) + bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error { query.Result = &m.SignedInUser{OrgId: 2, UserId: 12} return nil @@ -191,9 +196,7 @@ func TestMiddlewareContext(t *testing.T) { } }) - var createUserCmd *m.CreateUserCommand bus.AddHandler("test", func(cmd *m.CreateUserCommand) error { - createUserCmd = cmd cmd.Result = m.User{Id: 33} return nil }) @@ -210,6 +213,99 @@ func TestMiddlewareContext(t *testing.T) { }) }) + middlewareScenario("When auth_proxy is enabled and request RemoteAddr is not trusted", func(sc *scenarioContext) { + setting.AuthProxyEnabled = true + setting.AuthProxyHeaderName = "X-WEBAUTH-USER" + setting.AuthProxyHeaderProperty = "username" + setting.AuthProxyWhitelist = "192.168.1.1, 192.168.2.1" + + sc.fakeReq("GET", "/") + sc.req.Header.Add("X-WEBAUTH-USER", "torkelo") + sc.req.RemoteAddr = "192.168.3.1:12345" + sc.exec() + + Convey("should return 407 status code", func() { + So(sc.resp.Code, ShouldEqual, 407) + }) + }) + + middlewareScenario("When auth_proxy is enabled and request RemoteAddr is trusted", func(sc *scenarioContext) { + setting.AuthProxyEnabled = true + setting.AuthProxyHeaderName = "X-WEBAUTH-USER" + setting.AuthProxyHeaderProperty = "username" + setting.AuthProxyWhitelist = "192.168.1.1, 192.168.2.1" + + bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error { + query.Result = &m.SignedInUser{OrgId: 4, UserId: 33} + return nil + }) + + sc.fakeReq("GET", "/") + sc.req.Header.Add("X-WEBAUTH-USER", "torkelo") + sc.req.RemoteAddr = "192.168.2.1:12345" + sc.exec() + + Convey("Should init context with user info", func() { + So(sc.context.IsSignedIn, ShouldBeTrue) + So(sc.context.UserId, ShouldEqual, 33) + So(sc.context.OrgId, ShouldEqual, 4) + }) + }) + + middlewareScenario("When session exists for previous user, create a new session", func(sc *scenarioContext) { + setting.AuthProxyEnabled = true + setting.AuthProxyHeaderName = "X-WEBAUTH-USER" + setting.AuthProxyHeaderProperty = "username" + setting.AuthProxyWhitelist = "" + + bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error { + query.Result = &m.SignedInUser{OrgId: 4, UserId: 32} + return nil + }) + + // create session + sc.fakeReq("GET", "/").handler(func(c *Context) { + c.Session.Set(SESS_KEY_USERID, int64(33)) + }).exec() + + oldSessionID := sc.context.Session.ID() + + sc.req.Header.Add("X-WEBAUTH-USER", "torkelo") + sc.exec() + + newSessionID := sc.context.Session.ID() + + Convey("Should not share session with other user", func() { + So(oldSessionID, ShouldNotEqual, newSessionID) + }) + }) + + middlewareScenario("When auth_proxy and ldap enabled call sync with ldap user", func(sc *scenarioContext) { + setting.AuthProxyEnabled = true + setting.AuthProxyHeaderName = "X-WEBAUTH-USER" + setting.AuthProxyHeaderProperty = "username" + setting.AuthProxyWhitelist = "" + setting.LdapEnabled = true + + called := false + syncGrafanaUserWithLdapUser = func(ctx *Context, query *m.GetSignedInUserQuery) error { + called = true + return nil + } + + bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error { + query.Result = &m.SignedInUser{OrgId: 4, UserId: 32} + return nil + }) + + sc.fakeReq("GET", "/") + sc.req.Header.Add("X-WEBAUTH-USER", "torkelo") + sc.exec() + + Convey("Should call syncGrafanaUserWithLdapUser", func() { + So(called, ShouldBeTrue) + }) + }) }) } diff --git a/pkg/middleware/perf.go b/pkg/middleware/perf.go new file mode 100644 index 00000000000..e381121a47f --- /dev/null +++ b/pkg/middleware/perf.go @@ -0,0 +1,12 @@ +package middleware + +import ( + "net/http" + + "gopkg.in/macaron.v1" +) + +func MeasureRequestTime() macaron.Handler { + return func(res http.ResponseWriter, req *http.Request, c *Context) { + } +} diff --git a/pkg/middleware/quota.go b/pkg/middleware/quota.go index d9e68f7560a..23f98e78a7e 100644 --- a/pkg/middleware/quota.go +++ b/pkg/middleware/quota.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/grafana/grafana/pkg/bus" - "github.com/grafana/grafana/pkg/log" m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/setting" "gopkg.in/macaron.v1" @@ -35,10 +34,8 @@ func QuotaReached(c *Context, target string) (bool, error) { return false, err } - log.Debug(fmt.Sprintf("checking quota for %s in scopes %v", target, scopes)) - for _, scope := range scopes { - log.Debug(fmt.Sprintf("checking scope %s", scope.Name)) + c.Logger.Debug("Checking quota", "target", target, "scope", scope) switch scope.Name { case "global": @@ -51,7 +48,7 @@ func QuotaReached(c *Context, target string) (bool, error) { if target == "session" { usedSessions := getSessionCount() if int64(usedSessions) > scope.DefaultLimit { - log.Debug(fmt.Sprintf("%d sessions active, limit is %d", usedSessions, scope.DefaultLimit)) + c.Logger.Debug("Sessions limit reached", "active", usedSessions, "limit", scope.DefaultLimit) return true, nil } continue diff --git a/pkg/middleware/recovery.go b/pkg/middleware/recovery.go new file mode 100644 index 00000000000..b63bc623549 --- /dev/null +++ b/pkg/middleware/recovery.go @@ -0,0 +1,148 @@ +// Copyright 2013 Martini Authors +// Copyright 2014 The Macaron Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"): you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + +package middleware + +import ( + "bytes" + "fmt" + "io/ioutil" + "runtime" + + "gopkg.in/macaron.v1" + + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/setting" +) + +var ( + dunno = []byte("???") + centerDot = []byte("·") + dot = []byte(".") + slash = []byte("/") +) + +// stack returns a nicely formated stack frame, skipping skip frames +func stack(skip int) []byte { + buf := new(bytes.Buffer) // the returned data + // As we loop, we open files and read them. These variables record the currently + // loaded file. + var lines [][]byte + var lastFile string + for i := skip; ; i++ { // Skip the expected number of frames + pc, file, line, ok := runtime.Caller(i) + if !ok { + break + } + // Print this much at least. If we can't find the source, it won't show. + fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc) + if file != lastFile { + data, err := ioutil.ReadFile(file) + if err != nil { + continue + } + lines = bytes.Split(data, []byte{'\n'}) + lastFile = file + } + fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line)) + } + return buf.Bytes() +} + +// source returns a space-trimmed slice of the n'th line. +func source(lines [][]byte, n int) []byte { + n-- // in stack trace, lines are 1-indexed but our array is 0-indexed + if n < 0 || n >= len(lines) { + return dunno + } + return bytes.TrimSpace(lines[n]) +} + +// function returns, if possible, the name of the function containing the PC. +func function(pc uintptr) []byte { + fn := runtime.FuncForPC(pc) + if fn == nil { + return dunno + } + name := []byte(fn.Name()) + // The name includes the path name to the package, which is unnecessary + // since the file name is already included. Plus, it has center dots. + // That is, we see + // runtime/debug.*T·ptrmethod + // and want + // *T.ptrmethod + // Also the package path might contains dot (e.g. code.google.com/...), + // so first eliminate the path prefix + if lastslash := bytes.LastIndex(name, slash); lastslash >= 0 { + name = name[lastslash+1:] + } + if period := bytes.Index(name, dot); period >= 0 { + name = name[period+1:] + } + name = bytes.Replace(name, centerDot, dot, -1) + return name +} + +// Recovery returns a middleware that recovers from any panics and writes a 500 if there was one. +// While Martini is in development mode, Recovery will also output the panic as HTML. +func Recovery() macaron.Handler { + return func(c *macaron.Context) { + defer func() { + if err := recover(); err != nil { + stack := stack(3) + + panicLogger := log.Root + // try to get request logger + if ctx, ok := c.Data["ctx"]; ok { + ctxTyped := ctx.(*Context) + panicLogger = ctxTyped.Logger + } + + panicLogger.Error("Request error", "error", err, "stack", string(stack)) + + c.Data["Title"] = "Server Error" + c.Data["AppSubUrl"] = setting.AppSubUrl + + if theErr, ok := err.(error); ok { + c.Data["Title"] = theErr.Error() + } + + if setting.Env == setting.DEV { + c.Data["ErrorMsg"] = string(stack) + } + + c.HTML(500, "500") + + // // Lookup the current responsewriter + // val := c.GetVal(inject.InterfaceOf((*http.ResponseWriter)(nil))) + // res := val.Interface().(http.ResponseWriter) + // + // // respond with panic message while in development mode + // var body []byte + // if setting.Env == setting.DEV { + // res.Header().Set("Content-Type", "text/html") + // body = []byte(fmt.Sprintf(panicHtml, err, err, stack)) + // } + // + // res.WriteHeader(http.StatusInternalServerError) + // if nil != body { + // res.Write(body) + // } + } + }() + + c.Next() + } +} diff --git a/pkg/middleware/render_auth.go b/pkg/middleware/render_auth.go new file mode 100644 index 00000000000..3a57660c9bf --- /dev/null +++ b/pkg/middleware/render_auth.go @@ -0,0 +1,55 @@ +package middleware + +import ( + "sync" + + m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/util" +) + +var renderKeysLock sync.Mutex +var renderKeys map[string]*m.SignedInUser = make(map[string]*m.SignedInUser) + +func initContextWithRenderAuth(ctx *Context) bool { + key := ctx.GetCookie("renderKey") + if key == "" { + return false + } + + renderKeysLock.Lock() + defer renderKeysLock.Unlock() + + if renderUser, exists := renderKeys[key]; !exists { + ctx.JsonApiErr(401, "Invalid Render Key", nil) + return true + } else { + + ctx.IsSignedIn = true + ctx.SignedInUser = renderUser + ctx.IsRenderCall = true + return true + } +} + +type renderContextFunc func(key string) (string, error) + +func AddRenderAuthKey(orgId int64) string { + renderKeysLock.Lock() + + key := util.GetRandomString(32) + + renderKeys[key] = &m.SignedInUser{ + OrgId: orgId, + OrgRole: m.ROLE_VIEWER, + } + + renderKeysLock.Unlock() + + return key +} + +func RemoveRenderAuthKey(key string) { + renderKeysLock.Lock() + delete(renderKeys, key) + renderKeysLock.Unlock() +} diff --git a/pkg/middleware/request_metrics.go b/pkg/middleware/request_metrics.go new file mode 100644 index 00000000000..417a1817d15 --- /dev/null +++ b/pkg/middleware/request_metrics.go @@ -0,0 +1,65 @@ +package middleware + +import ( + "net/http" + "strings" + + "github.com/grafana/grafana/pkg/metrics" + "gopkg.in/macaron.v1" +) + +func RequestMetrics() macaron.Handler { + return func(res http.ResponseWriter, req *http.Request, c *macaron.Context) { + rw := res.(macaron.ResponseWriter) + c.Next() + + status := rw.Status() + + if strings.HasPrefix(req.RequestURI, "/api/datasources/proxy") { + countProxyRequests(status) + } else if strings.HasPrefix(req.RequestURI, "/api/") { + countApiRequests(status) + } else { + countPageRequests(status) + } + } +} + +func countApiRequests(status int) { + switch status { + case 200: + metrics.M_Api_Status_200.Inc(1) + case 404: + metrics.M_Api_Status_404.Inc(1) + case 500: + metrics.M_Api_Status_500.Inc(1) + default: + metrics.M_Api_Status_Unknown.Inc(1) + } +} + +func countPageRequests(status int) { + switch status { + case 200: + metrics.M_Page_Status_200.Inc(1) + case 404: + metrics.M_Page_Status_404.Inc(1) + case 500: + metrics.M_Page_Status_500.Inc(1) + default: + metrics.M_Page_Status_Unknown.Inc(1) + } +} + +func countProxyRequests(status int) { + switch status { + case 200: + metrics.M_Proxy_Status_200.Inc(1) + case 404: + metrics.M_Proxy_Status_404.Inc(1) + case 500: + metrics.M_Proxy_Status_500.Inc(1) + default: + metrics.M_Proxy_Status_Unknown.Inc(1) + } +} diff --git a/pkg/middleware/session.go b/pkg/middleware/session.go index 583c57b85a5..0700612ecc2 100644 --- a/pkg/middleware/session.go +++ b/pkg/middleware/session.go @@ -12,8 +12,10 @@ import ( ) const ( - SESS_KEY_USERID = "uid" - SESS_KEY_APIKEY = "apikey_id" // used fror render requests with api keys + SESS_KEY_USERID = "uid" + SESS_KEY_OAUTH_STATE = "state" + SESS_KEY_APIKEY = "apikey_id" // used for render requests with api keys + SESS_KEY_LASTLDAPSYNC = "last_ldap_sync" ) var sessionManager *session.Manager diff --git a/pkg/middleware/util.go b/pkg/middleware/util.go index babda94d5e7..c392f215450 100644 --- a/pkg/middleware/util.go +++ b/pkg/middleware/util.go @@ -17,6 +17,10 @@ func Gziper() macaron.Handler { return } + if strings.HasPrefix(requestPath, "/api/plugin-proxy/") { + return + } + ctx.Invoke(macaronGziper) } } diff --git a/pkg/middleware/validate_host.go b/pkg/middleware/validate_host.go index 606606b56e4..fa84e783767 100644 --- a/pkg/middleware/validate_host.go +++ b/pkg/middleware/validate_host.go @@ -8,7 +8,12 @@ import ( ) func ValidateHostHeader(domain string) macaron.Handler { - return func(c *macaron.Context) { + return func(c *Context) { + // ignore local render calls + if c.IsRenderCall { + return + } + h := c.Req.Host if i := strings.Index(h, ":"); i >= 0 { h = h[:i] diff --git a/pkg/models/alert.go b/pkg/models/alert.go new file mode 100644 index 00000000000..61976677764 --- /dev/null +++ b/pkg/models/alert.go @@ -0,0 +1,199 @@ +package models + +import ( + "time" + + "fmt" + + "github.com/grafana/grafana/pkg/components/simplejson" +) + +type AlertStateType string +type AlertSeverityType string +type NoDataOption string +type ExecutionErrorOption string + +const ( + AlertStateNoData AlertStateType = "no_data" + AlertStatePaused AlertStateType = "paused" + AlertStateAlerting AlertStateType = "alerting" + AlertStateOK AlertStateType = "ok" + AlertStatePending AlertStateType = "pending" +) + +const ( + NoDataSetOK NoDataOption = "ok" + NoDataSetNoData NoDataOption = "no_data" + NoDataKeepState NoDataOption = "keep_state" + NoDataSetAlerting NoDataOption = "alerting" +) + +const ( + ExecutionErrorSetAlerting ExecutionErrorOption = "alerting" + ExecutionErrorKeepState ExecutionErrorOption = "keep_state" +) + +var ( + ErrCannotChangeStateOnPausedAlert error = fmt.Errorf("Cannot change state on pause alert") +) + +func (s AlertStateType) IsValid() bool { + return s == AlertStateOK || s == AlertStateNoData || s == AlertStatePaused || s == AlertStatePending +} + +func (s NoDataOption) IsValid() bool { + return s == NoDataSetNoData || s == NoDataSetAlerting || s == NoDataKeepState || s == NoDataSetOK +} + +func (s NoDataOption) ToAlertState() AlertStateType { + return AlertStateType(s) +} + +func (s ExecutionErrorOption) IsValid() bool { + return s == ExecutionErrorSetAlerting || s == ExecutionErrorKeepState +} + +func (s ExecutionErrorOption) ToAlertState() AlertStateType { + return AlertStateType(s) +} + +type Alert struct { + Id int64 + Version int64 + OrgId int64 + DashboardId int64 + PanelId int64 + Name string + Message string + Severity string + State AlertStateType + Handler int64 + Silenced bool + ExecutionError string + Frequency int64 + + EvalData *simplejson.Json + NewStateDate time.Time + StateChanges int + + Created time.Time + Updated time.Time + + Settings *simplejson.Json +} + +func (alert *Alert) ValidToSave() bool { + return alert.DashboardId != 0 && alert.OrgId != 0 && alert.PanelId != 0 +} + +func (alert *Alert) ShouldUpdateState(newState AlertStateType) bool { + return alert.State != newState +} + +func (this *Alert) ContainsUpdates(other *Alert) bool { + result := false + result = result || this.Name != other.Name + result = result || this.Message != other.Message + + if this.Settings != nil && other.Settings != nil { + json1, err1 := this.Settings.Encode() + json2, err2 := other.Settings.Encode() + + if err1 != nil || err2 != nil { + return false + } + + result = result || string(json1) != string(json2) + } + + //don't compare .State! That would be insane. + return result +} + +type AlertingClusterInfo struct { + ServerId string + ClusterSize int + UptimePosition int +} + +type HeartBeat struct { + Id int64 + ServerId string + Updated time.Time + Created time.Time +} + +type HeartBeatCommand struct { + ServerId string + Result AlertingClusterInfo +} + +type SaveAlertsCommand struct { + DashboardId int64 + UserId int64 + OrgId int64 + + Alerts []*Alert +} + +type PauseAlertCommand struct { + OrgId int64 + AlertIds []int64 + ResultCount int64 + Paused bool +} + +type PauseAllAlertCommand struct { + ResultCount int64 + Paused bool +} + +type SetAlertStateCommand struct { + AlertId int64 + OrgId int64 + State AlertStateType + Error string + EvalData *simplejson.Json + + Timestamp time.Time +} + +type DeleteAlertCommand struct { + AlertId int64 +} + +//Queries +type GetAlertsQuery struct { + OrgId int64 + State []string + DashboardId int64 + PanelId int64 + Limit int64 + + Result []*Alert +} + +type GetAllAlertsQuery struct { + Result []*Alert +} + +type GetAlertByIdQuery struct { + Id int64 + + Result *Alert +} + +type GetAlertStatesForDashboardQuery struct { + OrgId int64 + DashboardId int64 + + Result []*AlertStateInfoDTO +} + +type AlertStateInfoDTO struct { + Id int64 `json:"id"` + DashboardId int64 `json:"dashboardId"` + PanelId int64 `json:"panelId"` + State AlertStateType `json:"state"` + NewStateDate time.Time `json:"newStateDate"` +} diff --git a/pkg/models/alert_notifications.go b/pkg/models/alert_notifications.go new file mode 100644 index 00000000000..87b515f370c --- /dev/null +++ b/pkg/models/alert_notifications.go @@ -0,0 +1,65 @@ +package models + +import ( + "time" + + "github.com/grafana/grafana/pkg/components/simplejson" +) + +type AlertNotification struct { + Id int64 `json:"id"` + OrgId int64 `json:"-"` + Name string `json:"name"` + Type string `json:"type"` + IsDefault bool `json:"isDefault"` + Settings *simplejson.Json `json:"settings"` + Created time.Time `json:"created"` + Updated time.Time `json:"updated"` +} + +type CreateAlertNotificationCommand struct { + Name string `json:"name" binding:"Required"` + Type string `json:"type" binding:"Required"` + IsDefault bool `json:"isDefault"` + Settings *simplejson.Json `json:"settings"` + + OrgId int64 `json:"-"` + Result *AlertNotification +} + +type UpdateAlertNotificationCommand struct { + Id int64 `json:"id" binding:"Required"` + Name string `json:"name" binding:"Required"` + Type string `json:"type" binding:"Required"` + IsDefault bool `json:"isDefault"` + Settings *simplejson.Json `json:"settings" binding:"Required"` + + OrgId int64 `json:"-"` + Result *AlertNotification +} + +type DeleteAlertNotificationCommand struct { + Id int64 + OrgId int64 +} + +type GetAlertNotificationsQuery struct { + Name string + Id int64 + OrgId int64 + + Result *AlertNotification +} + +type GetAlertNotificationsToSendQuery struct { + Ids []int64 + OrgId int64 + + Result []*AlertNotification +} + +type GetAllAlertNotificationsQuery struct { + OrgId int64 + + Result []*AlertNotification +} diff --git a/pkg/models/alert_test.go b/pkg/models/alert_test.go new file mode 100644 index 00000000000..421b90f1b21 --- /dev/null +++ b/pkg/models/alert_test.go @@ -0,0 +1,39 @@ +package models + +import ( + "testing" + + "github.com/grafana/grafana/pkg/components/simplejson" + . "github.com/smartystreets/goconvey/convey" +) + +func TestAlertingModelTest(t *testing.T) { + Convey("Testing Alerting model", t, func() { + + json1, _ := simplejson.NewJson([]byte(`{ "field": "value" }`)) + json2, _ := simplejson.NewJson([]byte(`{ "field": "value" }`)) + + rule1 := &Alert{ + Settings: json1, + Name: "Namn", + Message: "Message", + } + + rule2 := &Alert{ + Settings: json2, + Name: "Namn", + Message: "Message", + } + + Convey("Testing AlertRule equals", func() { + + So(rule1.ContainsUpdates(rule2), ShouldBeFalse) + }) + + Convey("Changing the expression should contain update", func() { + json2, _ := simplejson.NewJson([]byte(`{ "field": "newValue" }`)) + rule1.Settings = json2 + So(rule1.ContainsUpdates(rule2), ShouldBeTrue) + }) + }) +} diff --git a/pkg/models/dashboard_snapshot.go b/pkg/models/dashboard_snapshot.go index f920e91f2e4..57c5524ace8 100644 --- a/pkg/models/dashboard_snapshot.go +++ b/pkg/models/dashboard_snapshot.go @@ -45,7 +45,7 @@ type DashboardSnapshotDTO struct { type CreateDashboardSnapshotCommand struct { Dashboard *simplejson.Json `json:"dashboard" binding:"Required"` - Name string `json:"name" binding:"Required"` + Name string `json:"name"` Expires int64 `json:"expires"` // these are passed when storing an external snapshot ref @@ -63,6 +63,9 @@ type DeleteDashboardSnapshotCommand struct { DeleteKey string `json:"-"` } +type DeleteExpiredSnapshotsCommand struct { +} + type GetDashboardSnapshotQuery struct { Key string diff --git a/pkg/models/dashboards.go b/pkg/models/dashboards.go index 6243c729624..634b26c3f29 100644 --- a/pkg/models/dashboards.go +++ b/pkg/models/dashboards.go @@ -15,8 +15,17 @@ var ( ErrDashboardSnapshotNotFound = errors.New("Dashboard snapshot not found") ErrDashboardWithSameNameExists = errors.New("A dashboard with the same name already exists") ErrDashboardVersionMismatch = errors.New("The dashboard has been changed by someone else") + ErrDashboardTitleEmpty = errors.New("Dashboard title cannot be empty") ) +type UpdatePluginDashboardError struct { + PluginId string +} + +func (d UpdatePluginDashboardError) Error() string { + return "Dashboard belong to plugin" +} + var ( DashTypeJson = "file" DashTypeDB = "db" @@ -26,10 +35,12 @@ var ( // Dashboard model type Dashboard struct { - Id int64 - Slug string - OrgId int64 - Version int + Id int64 + Slug string + OrgId int64 + GnetId int64 + Version int + PluginId string Created time.Time Updated time.Time @@ -77,6 +88,10 @@ func NewDashboardFromJson(data *simplejson.Json) *Dashboard { dash.Updated = time.Now() } + if gnetId, err := dash.Data.Get("gnetId").Float64(); err == nil { + dash.GnetId = int64(gnetId) + } + return dash } @@ -90,6 +105,7 @@ func (cmd *SaveDashboardCommand) GetDashboardModel() *Dashboard { dash.UpdatedBy = cmd.UserId dash.OrgId = cmd.OrgId + dash.PluginId = cmd.PluginId dash.UpdateSlug() return dash } @@ -114,6 +130,7 @@ type SaveDashboardCommand struct { UserId int64 `json:"userId"` OrgId int64 `json:"-"` Overwrite bool `json:"overwrite"` + PluginId string `json:"-"` Result *Dashboard } @@ -146,5 +163,16 @@ type GetDashboardTagsQuery struct { type GetDashboardsQuery struct { DashboardIds []int64 - Result *[]Dashboard + Result []*Dashboard +} + +type GetDashboardsByPluginIdQuery struct { + OrgId int64 + PluginId string + Result []*Dashboard +} + +type GetDashboardSlugByIdQuery struct { + Id int64 + Result string } diff --git a/pkg/models/datasource.go b/pkg/models/datasource.go index 2e9d98e9700..4a90edd9bfd 100644 --- a/pkg/models/datasource.go +++ b/pkg/models/datasource.go @@ -4,6 +4,7 @@ import ( "errors" "time" + "github.com/grafana/grafana/pkg/components/securejsondata" "github.com/grafana/grafana/pkg/components/simplejson" ) @@ -22,7 +23,8 @@ const ( // Typed errors var ( - ErrDataSourceNotFound = errors.New("Data source not found") + ErrDataSourceNotFound = errors.New("Data source not found") + ErrDataSourceNameExists = errors.New("Data source with same name already exists") ) type DsAccess string @@ -45,6 +47,7 @@ type DataSource struct { WithCredentials bool IsDefault bool JsonData *simplejson.Json + SecureJsonData securejsondata.SecureJsonData Created time.Time Updated time.Time @@ -76,19 +79,20 @@ func IsKnownDataSourcePlugin(dsType string) bool { // Also acts as api DTO type AddDataSourceCommand struct { - Name string `json:"name" binding:"Required"` - Type string `json:"type" binding:"Required"` - Access DsAccess `json:"access" binding:"Required"` - Url string `json:"url"` - Password string `json:"password"` - Database string `json:"database"` - User string `json:"user"` - BasicAuth bool `json:"basicAuth"` - BasicAuthUser string `json:"basicAuthUser"` - BasicAuthPassword string `json:"basicAuthPassword"` - WithCredentials bool `json:"withCredentials"` - IsDefault bool `json:"isDefault"` - JsonData *simplejson.Json `json:"jsonData"` + Name string `json:"name" binding:"Required"` + Type string `json:"type" binding:"Required"` + Access DsAccess `json:"access" binding:"Required"` + Url string `json:"url"` + Password string `json:"password"` + Database string `json:"database"` + User string `json:"user"` + BasicAuth bool `json:"basicAuth"` + BasicAuthUser string `json:"basicAuthUser"` + BasicAuthPassword string `json:"basicAuthPassword"` + WithCredentials bool `json:"withCredentials"` + IsDefault bool `json:"isDefault"` + JsonData *simplejson.Json `json:"jsonData"` + SecureJsonData map[string]string `json:"secureJsonData"` OrgId int64 `json:"-"` @@ -97,19 +101,20 @@ type AddDataSourceCommand struct { // Also acts as api DTO type UpdateDataSourceCommand struct { - Name string `json:"name" binding:"Required"` - Type string `json:"type" binding:"Required"` - Access DsAccess `json:"access" binding:"Required"` - Url string `json:"url"` - Password string `json:"password"` - User string `json:"user"` - Database string `json:"database"` - BasicAuth bool `json:"basicAuth"` - BasicAuthUser string `json:"basicAuthUser"` - BasicAuthPassword string `json:"basicAuthPassword"` - WithCredentials bool `json:"withCredentials"` - IsDefault bool `json:"isDefault"` - JsonData *simplejson.Json `json:"jsonData"` + Name string `json:"name" binding:"Required"` + Type string `json:"type" binding:"Required"` + Access DsAccess `json:"access" binding:"Required"` + Url string `json:"url"` + Password string `json:"password"` + User string `json:"user"` + Database string `json:"database"` + BasicAuth bool `json:"basicAuth"` + BasicAuthUser string `json:"basicAuthUser"` + BasicAuthPassword string `json:"basicAuthPassword"` + WithCredentials bool `json:"withCredentials"` + IsDefault bool `json:"isDefault"` + JsonData *simplejson.Json `json:"jsonData"` + SecureJsonData map[string]string `json:"secureJsonData"` OrgId int64 `json:"-"` Id int64 `json:"-"` @@ -131,13 +136,13 @@ type GetDataSourcesQuery struct { type GetDataSourceByIdQuery struct { Id int64 OrgId int64 - Result DataSource + Result *DataSource } type GetDataSourceByNameQuery struct { Name string OrgId int64 - Result DataSource + Result *DataSource } // --------------------- diff --git a/pkg/models/datasource_cache.go b/pkg/models/datasource_cache.go new file mode 100644 index 00000000000..e32c0ac9e7c --- /dev/null +++ b/pkg/models/datasource_cache.go @@ -0,0 +1,95 @@ +package models + +import ( + "crypto/tls" + "crypto/x509" + "net" + "net/http" + "sync" + "time" +) + +type proxyTransportCache struct { + cache map[int64]cachedTransport + sync.Mutex +} + +type cachedTransport struct { + updated time.Time + + *http.Transport +} + +var ptc = proxyTransportCache{ + cache: make(map[int64]cachedTransport), +} + +func (ds *DataSource) GetHttpClient() (*http.Client, error) { + transport, err := ds.GetHttpTransport() + + if err != nil { + return nil, err + } + + return &http.Client{ + Timeout: time.Duration(30 * time.Second), + Transport: transport, + }, nil +} + +func (ds *DataSource) GetHttpTransport() (*http.Transport, error) { + ptc.Lock() + defer ptc.Unlock() + + if t, present := ptc.cache[ds.Id]; present && ds.Updated.Equal(t.updated) { + return t.Transport, nil + } + + transport := &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, + Proxy: http.ProxyFromEnvironment, + Dial: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + }).Dial, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, + MaxIdleConns: 100, + IdleConnTimeout: 90 * time.Second, + } + + var tlsAuth, tlsAuthWithCACert bool + if ds.JsonData != nil { + tlsAuth = ds.JsonData.Get("tlsAuth").MustBool(false) + tlsAuthWithCACert = ds.JsonData.Get("tlsAuthWithCACert").MustBool(false) + } + + if tlsAuth { + transport.TLSClientConfig.InsecureSkipVerify = false + + decrypted := ds.SecureJsonData.Decrypt() + + if tlsAuthWithCACert && len(decrypted["tlsCACert"]) > 0 { + caPool := x509.NewCertPool() + ok := caPool.AppendCertsFromPEM([]byte(decrypted["tlsCACert"])) + if ok { + transport.TLSClientConfig.RootCAs = caPool + } + } + + cert, err := tls.X509KeyPair([]byte(decrypted["tlsClientCert"]), []byte(decrypted["tlsClientKey"])) + if err != nil { + return nil, err + } + transport.TLSClientConfig.Certificates = []tls.Certificate{cert} + } + + ptc.cache[ds.Id] = cachedTransport{ + Transport: transport, + updated: ds.Updated, + } + + return transport, nil +} diff --git a/pkg/models/datasource_cache_test.go b/pkg/models/datasource_cache_test.go new file mode 100644 index 00000000000..25fee55529d --- /dev/null +++ b/pkg/models/datasource_cache_test.go @@ -0,0 +1,157 @@ +package models + +import ( + "testing" + "time" + + . "github.com/smartystreets/goconvey/convey" + + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/setting" + "github.com/grafana/grafana/pkg/util" +) + +func TestDataSourceCache(t *testing.T) { + Convey("When caching a datasource proxy", t, func() { + clearCache() + ds := DataSource{ + Id: 1, + Url: "http://k8s:8001", + Type: "Kubernetes", + } + + t1, err := ds.GetHttpTransport() + So(err, ShouldBeNil) + + t2, err := ds.GetHttpTransport() + So(err, ShouldBeNil) + + Convey("Should be using the cached proxy", func() { + So(t2, ShouldEqual, t1) + }) + }) + + Convey("When getting kubernetes datasource proxy", t, func() { + clearCache() + setting.SecretKey = "password" + + json := simplejson.New() + json.Set("tlsAuth", true) + json.Set("tlsAuthWithCACert", true) + + t := time.Now() + ds := DataSource{ + Url: "http://k8s:8001", + Type: "Kubernetes", + Updated: t.Add(-2 * time.Minute), + } + + transport, err := ds.GetHttpTransport() + So(err, ShouldBeNil) + + Convey("Should have no cert", func() { + So(transport.TLSClientConfig.InsecureSkipVerify, ShouldEqual, true) + }) + + ds.JsonData = json + ds.SecureJsonData = map[string][]byte{ + "tlsCACert": util.Encrypt([]byte(caCert), "password"), + "tlsClientCert": util.Encrypt([]byte(clientCert), "password"), + "tlsClientKey": util.Encrypt([]byte(clientKey), "password"), + } + ds.Updated = t.Add(-1 * time.Minute) + + transport, err = ds.GetHttpTransport() + So(err, ShouldBeNil) + + Convey("Should add cert", func() { + So(transport.TLSClientConfig.InsecureSkipVerify, ShouldEqual, false) + So(len(transport.TLSClientConfig.Certificates), ShouldEqual, 1) + }) + + ds.JsonData = nil + ds.SecureJsonData = map[string][]byte{} + ds.Updated = t + + transport, err = ds.GetHttpTransport() + So(err, ShouldBeNil) + + Convey("Should remove cert", func() { + So(transport.TLSClientConfig.InsecureSkipVerify, ShouldEqual, true) + So(len(transport.TLSClientConfig.Certificates), ShouldEqual, 0) + }) + }) +} + +func clearCache() { + ptc.Lock() + defer ptc.Unlock() + + ptc.cache = make(map[int64]cachedTransport) +} + +const caCert string = `-----BEGIN CERTIFICATE----- +MIIDATCCAemgAwIBAgIJAMQ5hC3CPDTeMA0GCSqGSIb3DQEBCwUAMBcxFTATBgNV +BAMMDGNhLWs4cy1zdGhsbTAeFw0xNjEwMjcwODQyMjdaFw00NDAzMTQwODQyMjda +MBcxFTATBgNVBAMMDGNhLWs4cy1zdGhsbTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAMLe2AmJ6IleeUt69vgNchOjjmxIIxz5sp1vFu94m1vUip7CqnOg +QkpUsHeBPrGYv8UGloARCL1xEWS+9FVZeXWQoDmbC0SxXhFwRIESNCET7Q8KMi/4 +4YPvnMLGZi3Fjwxa8BdUBCN1cx4WEooMVTWXm7RFMtZgDfuOAn3TNXla732sfT/d +1HNFrh48b0wA+HhmA3nXoBnBEblA665hCeo7lIAdRr0zJxJpnFnWXkyTClsAUTMN +iL905LdBiiIRenojipfKXvMz88XSaWTI7JjZYU3BvhyXndkT6f12cef3I96NY3WJ +0uIK4k04WrbzdYXMU3rN6NqlvbHqnI+E7aMCAwEAAaNQME4wHQYDVR0OBBYEFHHx +2+vSPw9bECHj3O51KNo5VdWOMB8GA1UdIwQYMBaAFHHx2+vSPw9bECHj3O51KNo5 +VdWOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAH2eV5NcV3LBJHs9 +I+adbiTPg2vyumrGWwy73T0X8Dtchgt8wU7Q9b9Ucg2fOTmSSyS0iMqEu1Yb2ORB +CknM9mixHC9PwEBbkGCom3VVkqdLwSP6gdILZgyLoH4i8sTUz+S1yGPepi+Vzhs7 +adOXtryjcGnwft6HdfKPNklMOHFnjw6uqpho54oj/z55jUpicY/8glDHdrr1bh3k +MHuiWLGewHXPvxfG6UoUx1te65IhifVcJGFZDQwfEmhBflfCmtAJlZEsgTLlBBCh +FHoXIyGOdq1chmRVocdGBCF8fUoGIbuF14r53rpvcbEKtKnnP8+96luKAZLq0a4n +3lb92xM= +-----END CERTIFICATE-----` + +const clientCert string = `-----BEGIN CERTIFICATE----- +MIICsjCCAZoCCQCcd8sOfstQLzANBgkqhkiG9w0BAQsFADAXMRUwEwYDVQQDDAxj +YS1rOHMtc3RobG0wHhcNMTYxMTAyMDkyNTE1WhcNMTcxMTAyMDkyNTE1WjAfMR0w +GwYDVQQDDBRhZG0tZGFuaWVsLWs4cy1zdGhsbTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAOMliaWyNEUJKM37vWCl5bGub3lMicyRAqGQyY/qxD9yKKM2 +FbucVcmWmg5vvTqQVl5rlQ+c7GI8OD6ptmFl8a26coEki7bFr8bkpSyBSEc5p27b +Z0ORFSqBHWHQbr9PkxPLYW6T3gZYUtRYv3OQgGxLXlvUh85n/mQfuR3N1FgmShHo +GtAFi/ht6leXa0Ms+jNSDLCmXpJm1GIEqgyKX7K3+g3vzo9coYqXq4XTa8Efs2v8 +SCwqWfBC3rHfgs/5DLB8WT4Kul8QzxkytzcaBQfRfzhSV6bkgm7oTzt2/1eRRsf4 +YnXzLE9YkCC9sAn+Owzqf+TYC1KRluWDfqqBTJUCAwEAATANBgkqhkiG9w0BAQsF +AAOCAQEAdMsZg6edWGC+xngizn0uamrUg1ViaDqUsz0vpzY5NWLA4MsBc4EtxWRP +ueQvjUimZ3U3+AX0YWNLIrH1FCVos2jdij/xkTUmHcwzr8rQy+B17cFi+a8jtpgw +AU6WWoaAIEhhbWQfth/Diz3mivl1ARB+YqiWca2mjRPLTPcKJEURDVddQ423el0Q +4JNxS5icu7T2zYTYHAo/cT9zVdLZl0xuLxYm3asK1IONJ/evxyVZima3il6MPvhe +58Hwz+m+HdqHxi24b/1J/VKYbISG4huOQCdLzeNXgvwFlGPUmHSnnKo1/KbQDAR5 +llG/Sw5+FquFuChaA6l5KWy7F3bQyA== +-----END CERTIFICATE-----` + +const clientKey string = `-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEA4yWJpbI0RQkozfu9YKXlsa5veUyJzJECoZDJj+rEP3IoozYV +u5xVyZaaDm+9OpBWXmuVD5zsYjw4Pqm2YWXxrbpygSSLtsWvxuSlLIFIRzmnbttn +Q5EVKoEdYdBuv0+TE8thbpPeBlhS1Fi/c5CAbEteW9SHzmf+ZB+5Hc3UWCZKEega +0AWL+G3qV5drQyz6M1IMsKZekmbUYgSqDIpfsrf6De/Oj1yhiperhdNrwR+za/xI +LCpZ8ELesd+Cz/kMsHxZPgq6XxDPGTK3NxoFB9F/OFJXpuSCbuhPO3b/V5FGx/hi +dfMsT1iQIL2wCf47DOp/5NgLUpGW5YN+qoFMlQIDAQABAoIBAQCzy4u312XeW1Cs +Mx6EuOwmh59/ESFmBkZh4rxZKYgrfE5EWlQ7i5SwG4BX+wR6rbNfy6JSmHDXlTkk +CKvvToVNcW6fYHEivDnVojhIERFIJ4+rhQmpBtcNLOQ3/4cZ8X/GxE6b+3lb5l+x +64mnjPLKRaIr5/+TVuebEy0xNTJmjnJ7yiB2HRz7uXEQaVSk/P7KAkkyl/9J3/LM +8N9AX1w6qDaNQZ4/P0++1H4SQenosM/b/GqGTomarEk/GE0NcB9rzmR9VCXa7FRh +WV5jyt9vUrwIEiK/6nUnOkGO8Ei3kB7Y+e+2m6WdaNoU5RAfqXmXa0Q/a0lLRruf +vTMo2WrBAoGBAPRaK4cx76Q+3SJ/wfznaPsMM06OSR8A3ctKdV+ip/lyKtb1W8Pz +k8MYQDH7GwPtSu5QD8doL00pPjugZL/ba7X9nAsI+pinyEErfnB9y7ORNEjIYYzs +DiqDKup7ANgw1gZvznWvb9Ge0WUSXvWS0pFkgootQAf+RmnnbWGH6l6RAoGBAO35 +aGUrLro5u9RD24uSXNU3NmojINIQFK5dHAT3yl0BBYstL43AEsye9lX95uMPTvOQ +Cqcn42Hjp/bSe3n0ObyOZeXVrWcDFAfE0wwB1BkvL1lpgnFO9+VQORlH4w3Ppnpo +jcPkR2TFeDaAYtvckhxe/Bk3OnuFmnsQ3VzM75fFAoGBAI6PvS2XeNU+yA3EtA01 +hg5SQ+zlHswz2TMuMeSmJZJnhY78f5mHlwIQOAPxGQXlf/4iP9J7en1uPpzTK3S0 +M9duK4hUqMA/w5oiIhbHjf0qDnMYVbG+V1V+SZ+cPBXmCDihKreGr5qBKnHpkfV8 +v9WL6o1rcRw4wiQvnaV1gsvBAoGBALtzVTczr6gDKCAIn5wuWy+cQSGTsBunjRLX +xuVm5iEiV+KMYkPvAx/pKzMLP96lRVR3ptyKgAKwl7LFk3u50+zh4gQLr35QH2wL +Lw7rNc3srAhrItPsFzqrWX6/cGuFoKYVS239l/sZzRppQPXcpb7xVvTp2whHcir0 +Wtnpl+TdAoGAGqKqo2KU3JoY3IuTDUk1dsNAm8jd9EWDh+s1x4aG4N79mwcss5GD +FF8MbFPneK7xQd8L6HisKUDAUi2NOyynM81LAftPkvN6ZuUVeFDfCL4vCA0HUXLD ++VrOhtUZkNNJlLMiVRJuQKUOGlg8PpObqYbstQAf/0/yFJMRHG82Tcg= +-----END RSA PRIVATE KEY-----` diff --git a/pkg/models/emails.go b/pkg/models/emails.go deleted file mode 100644 index 74da180f7d8..00000000000 --- a/pkg/models/emails.go +++ /dev/null @@ -1,22 +0,0 @@ -package models - -import "errors" - -var ErrInvalidEmailCode = errors.New("Invalid or expired email code") - -type SendEmailCommand struct { - To []string - Template string - Data map[string]interface{} - Massive bool - Info string -} - -type SendResetPasswordEmailCommand struct { - User *User -} - -type ValidateResetPasswordCodeQuery struct { - Code string - Result *User -} diff --git a/pkg/models/helpflags.go b/pkg/models/helpflags.go new file mode 100644 index 00000000000..1bab730e265 --- /dev/null +++ b/pkg/models/helpflags.go @@ -0,0 +1,18 @@ +package models + +type HelpFlags1 uint64 + +const ( + HelpFlagGettingStartedPanelDismissed HelpFlags1 = 1 << iota + HelpFlagDashboardHelp1 +) + +func (f HelpFlags1) HasFlag(flag HelpFlags1) bool { return f&flag != 0 } +func (f *HelpFlags1) AddFlag(flag HelpFlags1) { *f |= flag } +func (f *HelpFlags1) ClearFlag(flag HelpFlags1) { *f &= ^flag } +func (f *HelpFlags1) ToggleFlag(flag HelpFlags1) { *f ^= flag } + +type SetUserHelpFlagCommand struct { + HelpFlags1 HelpFlags1 + UserId int64 +} diff --git a/pkg/models/models.go b/pkg/models/models.go index 189e594576b..3f4b27ed6ab 100644 --- a/pkg/models/models.go +++ b/pkg/models/models.go @@ -6,4 +6,6 @@ const ( GITHUB OAuthType = iota + 1 GOOGLE TWITTER + GENERIC + GRAFANANET ) diff --git a/pkg/models/notifications.go b/pkg/models/notifications.go new file mode 100644 index 00000000000..42ebda9ea44 --- /dev/null +++ b/pkg/models/notifications.go @@ -0,0 +1,35 @@ +package models + +import "errors" + +var ErrInvalidEmailCode = errors.New("Invalid or expired email code") + +type SendEmailCommand struct { + To []string + Template string + Subject string + Data map[string]interface{} + Info string + EmbededFiles []string +} + +type SendEmailCommandSync struct { + SendEmailCommand +} + +type SendWebhookSync struct { + Url string + User string + Password string + Body string + HttpMethod string +} + +type SendResetPasswordEmailCommand struct { + User *User +} + +type ValidateResetPasswordCodeQuery struct { + Code string + Result *User +} diff --git a/pkg/models/org_user.go b/pkg/models/org_user.go index 48d17deb9db..d7a918751ef 100644 --- a/pkg/models/org_user.go +++ b/pkg/models/org_user.go @@ -1,7 +1,9 @@ package models import ( + "encoding/json" "errors" + "fmt" "time" ) @@ -37,6 +39,26 @@ func (r RoleType) Includes(other RoleType) bool { return r == other } +func (r *RoleType) UnmarshalJSON(data []byte) error { + var str string + err := json.Unmarshal(data, &str) + if err != nil { + return err + } + + *r = RoleType(str) + + if (*r).IsValid() == false { + if (*r) != "" { + return errors.New(fmt.Sprintf("JSON validation error: invalid role value: %s", *r)) + } + + *r = ROLE_VIEWER + } + + return nil +} + type OrgUser struct { Id int64 OrgId int64 diff --git a/pkg/models/playlist.go b/pkg/models/playlist.go index 4c6eacbb6a6..5c49bb9256c 100644 --- a/pkg/models/playlist.go +++ b/pkg/models/playlist.go @@ -57,17 +57,6 @@ func (this PlaylistDashboard) TableName() string { type Playlists []*Playlist type PlaylistDashboards []*PlaylistDashboard -// -// DTOS -// - -type PlaylistDashboardDto struct { - Id int64 `json:"id"` - Slug string `json:"slug"` - Title string `json:"title"` - Uri string `json:"uri"` -} - // // COMMANDS // diff --git a/pkg/models/plugin_settings.go b/pkg/models/plugin_settings.go index d030c125ba9..bbfbaabd8c6 100644 --- a/pkg/models/plugin_settings.go +++ b/pkg/models/plugin_settings.go @@ -4,8 +4,7 @@ import ( "errors" "time" - "github.com/grafana/grafana/pkg/setting" - "github.com/grafana/grafana/pkg/util" + "github.com/grafana/grafana/pkg/components/securejsondata" ) var ( @@ -19,22 +18,13 @@ type PluginSetting struct { Enabled bool Pinned bool JsonData map[string]interface{} - SecureJsonData SecureJsonData + SecureJsonData securejsondata.SecureJsonData + PluginVersion string Created time.Time Updated time.Time } -type SecureJsonData map[string][]byte - -func (s SecureJsonData) Decrypt() map[string]string { - decrypted := make(map[string]string) - for key, data := range s { - decrypted[key] = string(util.Decrypt(data, setting.SecretKey)) - } - return decrypted -} - // ---------------------- // COMMANDS @@ -44,17 +34,21 @@ type UpdatePluginSettingCmd struct { Pinned bool `json:"pinned"` JsonData map[string]interface{} `json:"jsonData"` SecureJsonData map[string]string `json:"secureJsonData"` + PluginVersion string `json:"version"` PluginId string `json:"-"` OrgId int64 `json:"-"` } -func (cmd *UpdatePluginSettingCmd) GetEncryptedJsonData() SecureJsonData { - encrypted := make(SecureJsonData) - for key, data := range cmd.SecureJsonData { - encrypted[key] = util.Encrypt([]byte(data), setting.SecretKey) - } - return encrypted +// specific command, will only update version +type UpdatePluginSettingVersionCmd struct { + PluginVersion string + PluginId string `json:"-"` + OrgId int64 `json:"-"` +} + +func (cmd *UpdatePluginSettingCmd) GetEncryptedJsonData() securejsondata.SecureJsonData { + return securejsondata.GetEncryptedJsonData(cmd.SecureJsonData) } // --------------------- @@ -65,10 +59,11 @@ type GetPluginSettingsQuery struct { } type PluginSettingInfoDTO struct { - OrgId int64 - PluginId string - Enabled bool - Pinned bool + OrgId int64 + PluginId string + Enabled bool + Pinned bool + PluginVersion string } type GetPluginSettingByIdQuery struct { @@ -76,3 +71,9 @@ type GetPluginSettingByIdQuery struct { OrgId int64 Result *PluginSetting } + +type PluginStateChangedEvent struct { + PluginId string + OrgId int64 + Enabled bool +} diff --git a/pkg/models/preferences.go b/pkg/models/preferences.go new file mode 100644 index 00000000000..4c77bc96d4d --- /dev/null +++ b/pkg/models/preferences.go @@ -0,0 +1,53 @@ +package models + +import ( + "errors" + "time" +) + +// Typed errors +var ( + ErrPreferencesNotFound = errors.New("Preferences not found") +) + +type Preferences struct { + Id int64 + OrgId int64 + UserId int64 + Version int + HomeDashboardId int64 + Timezone string + Theme string + Created time.Time + Updated time.Time +} + +// --------------------- +// QUERIES + +type GetPreferencesQuery struct { + Id int64 + OrgId int64 + UserId int64 + + Result *Preferences +} + +type GetPreferencesWithDefaultsQuery struct { + Id int64 + OrgId int64 + UserId int64 + + Result *Preferences +} + +// --------------------- +// COMMANDS +type SavePreferencesCommand struct { + UserId int64 + OrgId int64 + + HomeDashboardId int64 `json:"homeDashboardId"` + Timezone string `json:"timezone"` + Theme string `json:"theme"` +} diff --git a/pkg/models/server.go b/pkg/models/server.go new file mode 100644 index 00000000000..876fc91dd01 --- /dev/null +++ b/pkg/models/server.go @@ -0,0 +1,10 @@ +package models + +import "context" + +type GrafanaServer interface { + context.Context + + Start() + Shutdown(code int, reason string) +} diff --git a/pkg/models/stats.go b/pkg/models/stats.go index 63f946b956b..09c251b6cd7 100644 --- a/pkg/models/stats.go +++ b/pkg/models/stats.go @@ -1,10 +1,11 @@ package models type SystemStats struct { - DashboardCount int - UserCount int - OrgCount int - PlaylistCount int + DashboardCount int64 + UserCount int64 + OrgCount int64 + PlaylistCount int64 + AlertCount int64 } type DataSourceStats struct { @@ -21,15 +22,15 @@ type GetDataSourceStatsQuery struct { } type AdminStats struct { - UserCount int `json:"user_count"` - OrgCount int `json:"org_count"` - DashboardCount int `json:"dashboard_count"` - DbSnapshotCount int `json:"db_snapshot_count"` - DbTagCount int `json:"db_tag_count"` - DataSourceCount int `json:"data_source_count"` - PlaylistCount int `json:"playlist_count"` - StarredDbCount int `json:"starred_db_count"` - GrafanaAdminCount int `json:"grafana_admin_count"` + UserCount int `json:"user_count"` + OrgCount int `json:"org_count"` + DashboardCount int `json:"dashboard_count"` + DbSnapshotCount int `json:"db_snapshot_count"` + DbTagCount int `json:"db_tag_count"` + DataSourceCount int `json:"data_source_count"` + PlaylistCount int `json:"playlist_count"` + StarredDbCount int `json:"starred_db_count"` + AlertCount int `json:"alert_count"` } type GetAdminStatsQuery struct { diff --git a/pkg/models/user.go b/pkg/models/user.go index 2842bad490d..e14f4486ba3 100644 --- a/pkg/models/user.go +++ b/pkg/models/user.go @@ -10,6 +10,12 @@ var ( ErrUserNotFound = errors.New("User not found") ) +type Password string + +func (p Password) IsWeak() bool { + return len(p) <= 4 +} + type User struct { Id int64 Version int @@ -22,6 +28,7 @@ type User struct { Company string EmailVerified bool Theme string + HelpFlags1 HelpFlags1 IsAdmin bool OrgId int64 @@ -44,15 +51,16 @@ func (u *User) NameOrFallback() string { // COMMANDS type CreateUserCommand struct { - Email string - Login string - Name string - Company string - OrgName string - Password string - EmailVerified bool - IsAdmin bool - SkipOrgSetup bool + Email string + Login string + Name string + Company string + OrgName string + Password string + EmailVerified bool + IsAdmin bool + SkipOrgSetup bool + DefaultOrgRole string Result User } @@ -95,6 +103,11 @@ type GetUserByLoginQuery struct { Result *User } +type GetUserByEmailQuery struct { + Email string + Result *User +} + type GetUserByIdQuery struct { Id int64 Result *User @@ -136,9 +149,9 @@ type SignedInUser struct { Login string Name string Email string - Theme string ApiKeyId int64 IsGrafanaAdmin bool + HelpFlags1 HelpFlags1 } type UserProfileDTO struct { diff --git a/pkg/plugins/app_plugin.go b/pkg/plugins/app_plugin.go index f565b0e2b22..cc588bf1d55 100644 --- a/pkg/plugins/app_plugin.go +++ b/pkg/plugins/app_plugin.go @@ -76,8 +76,6 @@ func (app *AppPlugin) initApp() { } } - app.DefaultNavUrl = setting.AppSubUrl + "/plugins/" + app.Id + "/edit" - // slugify pages for _, include := range app.Includes { if include.Slug == "" { diff --git a/pkg/plugins/dashboard_importer.go b/pkg/plugins/dashboard_importer.go index 834bfabd048..1b3e4bac182 100644 --- a/pkg/plugins/dashboard_importer.go +++ b/pkg/plugins/dashboard_importer.go @@ -11,12 +11,14 @@ import ( ) type ImportDashboardCommand struct { - Path string `json:"string"` - Inputs []ImportDashboardInput `json:"inputs"` + Dashboard *simplejson.Json + Path string + Inputs []ImportDashboardInput + Overwrite bool - OrgId int64 `json:"-"` - UserId int64 `json:"-"` - PluginId string `json:"-"` + OrgId int64 + UserId int64 + PluginId string Result *PluginDashboardInfoDTO } @@ -40,17 +42,15 @@ func init() { } func ImportDashboard(cmd *ImportDashboardCommand) error { - plugin, exists := Plugins[cmd.PluginId] - - if !exists { - return PluginNotFoundError{cmd.PluginId} - } - var dashboard *m.Dashboard var err error - if dashboard, err = loadPluginDashboard(plugin, cmd.Path); err != nil { - return err + if cmd.PluginId != "" { + if dashboard, err = loadPluginDashboard(cmd.PluginId, cmd.Path); err != nil { + return err + } + } else { + dashboard = m.NewDashboardFromJson(cmd.Dashboard) } evaluator := &DashTemplateEvaluator{ @@ -67,6 +67,8 @@ func ImportDashboard(cmd *ImportDashboardCommand) error { Dashboard: generatedDash, OrgId: cmd.OrgId, UserId: cmd.UserId, + Overwrite: cmd.Overwrite, + PluginId: cmd.PluginId, } if err := bus.Dispatch(&saveCmd); err != nil { @@ -74,13 +76,13 @@ func ImportDashboard(cmd *ImportDashboardCommand) error { } cmd.Result = &PluginDashboardInfoDTO{ - PluginId: cmd.PluginId, - Title: dashboard.Title, - Path: cmd.Path, - Revision: dashboard.GetString("revision", "1.0"), - InstalledUri: "db/" + saveCmd.Result.Slug, - InstalledRevision: dashboard.GetString("revision", "1.0"), - Installed: true, + PluginId: cmd.PluginId, + Title: dashboard.Title, + Path: cmd.Path, + Revision: dashboard.Data.Get("revision").MustInt64(1), + ImportedUri: "db/" + saveCmd.Result.Slug, + ImportedRevision: dashboard.Data.Get("revision").MustInt64(1), + Imported: true, } return nil @@ -108,7 +110,7 @@ func (this *DashTemplateEvaluator) findInput(varName string, varType string) *Im func (this *DashTemplateEvaluator) Eval() (*simplejson.Json, error) { this.result = simplejson.New() this.variables = make(map[string]string) - this.varRegex, _ = regexp.Compile(`(\$\{\w+\})`) + this.varRegex, _ = regexp.Compile(`(\$\{.+\})`) // check that we have all inputs we need for _, inputDef := range this.template.Get("__inputs").MustArray() { diff --git a/pkg/plugins/dashboards.go b/pkg/plugins/dashboards.go index 932196a42a9..5d26766b8e5 100644 --- a/pkg/plugins/dashboards.go +++ b/pkg/plugins/dashboards.go @@ -10,14 +10,16 @@ import ( ) type PluginDashboardInfoDTO struct { - PluginId string `json:"pluginId"` - Title string `json:"title"` - Installed bool `json:"installed"` - InstalledUri string `json:"installedUri"` - InstalledRevision string `json:"installedRevision"` - Revision string `json:"revision"` - Description string `json:"description"` - Path string `json:"path"` + PluginId string `json:"pluginId"` + Title string `json:"title"` + Imported bool `json:"imported"` + ImportedUri string `json:"importedUri"` + Slug string `json:"slug"` + ImportedRevision int64 `json:"importedRevision"` + Revision int64 `json:"revision"` + Description string `json:"description"` + Path string `json:"path"` + Removed bool `json:"removed"` } func GetPluginDashboards(orgId int64, pluginId string) ([]*PluginDashboardInfoDTO, error) { @@ -29,20 +31,64 @@ func GetPluginDashboards(orgId int64, pluginId string) ([]*PluginDashboardInfoDT result := make([]*PluginDashboardInfoDTO, 0) + // load current dashboards + query := m.GetDashboardsByPluginIdQuery{OrgId: orgId, PluginId: pluginId} + if err := bus.Dispatch(&query); err != nil { + return nil, err + } + + existingMatches := make(map[int64]bool) + for _, include := range plugin.Includes { - if include.Type == PluginTypeDashboard { - if dashInfo, err := getDashboardImportStatus(orgId, plugin, include.Path); err != nil { - return nil, err - } else { - result = append(result, dashInfo) + if include.Type != PluginTypeDashboard { + continue + } + + res := &PluginDashboardInfoDTO{} + var dashboard *m.Dashboard + var err error + + if dashboard, err = loadPluginDashboard(plugin.Id, include.Path); err != nil { + return nil, err + } + + res.Path = include.Path + res.PluginId = plugin.Id + res.Title = dashboard.Title + res.Revision = dashboard.Data.Get("revision").MustInt64(1) + + // find existing dashboard + for _, existingDash := range query.Result { + if existingDash.Slug == dashboard.Slug { + res.Imported = true + res.ImportedUri = "db/" + existingDash.Slug + res.ImportedRevision = existingDash.Data.Get("revision").MustInt64(1) + existingMatches[existingDash.Id] = true } } + + result = append(result, res) + } + + // find deleted dashboards + for _, dash := range query.Result { + if _, exists := existingMatches[dash.Id]; !exists { + result = append(result, &PluginDashboardInfoDTO{ + Slug: dash.Slug, + Removed: true, + }) + } } return result, nil } -func loadPluginDashboard(plugin *PluginBase, path string) (*m.Dashboard, error) { +func loadPluginDashboard(pluginId, path string) (*m.Dashboard, error) { + plugin, exists := Plugins[pluginId] + + if !exists { + return nil, PluginNotFoundError{pluginId} + } dashboardFilePath := filepath.Join(plugin.PluginDir, path) reader, err := os.Open(dashboardFilePath) @@ -59,33 +105,3 @@ func loadPluginDashboard(plugin *PluginBase, path string) (*m.Dashboard, error) return m.NewDashboardFromJson(data), nil } - -func getDashboardImportStatus(orgId int64, plugin *PluginBase, path string) (*PluginDashboardInfoDTO, error) { - res := &PluginDashboardInfoDTO{} - - var dashboard *m.Dashboard - var err error - - if dashboard, err = loadPluginDashboard(plugin, path); err != nil { - return nil, err - } - - res.Path = path - res.PluginId = plugin.Id - res.Title = dashboard.Title - res.Revision = dashboard.GetString("revision", "1.0") - - query := m.GetDashboardQuery{OrgId: orgId, Slug: dashboard.Slug} - - if err := bus.Dispatch(&query); err != nil { - if err != m.ErrDashboardNotFound { - return nil, err - } - } else { - res.Installed = true - res.InstalledUri = "db/" + query.Result.Slug - res.InstalledRevision = query.Result.GetString("revision", "1.0") - } - - return res, nil -} diff --git a/pkg/plugins/dashboards_test.go b/pkg/plugins/dashboards_test.go index bdd08ceefd2..980d7bb91bd 100644 --- a/pkg/plugins/dashboards_test.go +++ b/pkg/plugins/dashboards_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/components/simplejson" m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/setting" . "github.com/smartystreets/goconvey/convey" @@ -31,6 +32,17 @@ func TestPluginDashboards(t *testing.T) { return m.ErrDashboardNotFound }) + bus.AddHandler("test", func(query *m.GetDashboardsByPluginIdQuery) error { + var data = simplejson.New() + data.Set("title", "Nginx Connections") + data.Set("revision", 22) + + query.Result = []*m.Dashboard{ + {Slug: "nginx-connections", Data: data}, + } + return nil + }) + dashboards, err := GetPluginDashboards(1, "test-app") So(err, ShouldBeNil) @@ -41,12 +53,12 @@ func TestPluginDashboards(t *testing.T) { Convey("should include installed version info", func() { So(dashboards[0].Title, ShouldEqual, "Nginx Connections") - So(dashboards[0].Revision, ShouldEqual, "1.5") - So(dashboards[0].InstalledRevision, ShouldEqual, "1.1") - So(dashboards[0].InstalledUri, ShouldEqual, "db/nginx-connections") + So(dashboards[0].Revision, ShouldEqual, 25) + So(dashboards[0].ImportedRevision, ShouldEqual, 22) + So(dashboards[0].ImportedUri, ShouldEqual, "db/nginx-connections") - So(dashboards[1].Revision, ShouldEqual, "2.0") - So(dashboards[1].InstalledRevision, ShouldEqual, "") + So(dashboards[1].Revision, ShouldEqual, 2) + So(dashboards[1].ImportedRevision, ShouldEqual, 0) }) }) diff --git a/pkg/plugins/dashboards_updater.go b/pkg/plugins/dashboards_updater.go new file mode 100644 index 00000000000..52a623e73dd --- /dev/null +++ b/pkg/plugins/dashboards_updater.go @@ -0,0 +1,139 @@ +package plugins + +import ( + "time" + + "github.com/grafana/grafana/pkg/bus" + m "github.com/grafana/grafana/pkg/models" +) + +func init() { + bus.AddEventListener(handlePluginStateChanged) +} + +func updateAppDashboards() { + time.Sleep(time.Second * 5) + + plog.Debug("Looking for App Dashboard Updates") + + query := m.GetPluginSettingsQuery{OrgId: 0} + + if err := bus.Dispatch(&query); err != nil { + plog.Error("Failed to get all plugin settings", "error", err) + return + } + + for _, pluginSetting := range query.Result { + // ignore disabled plugins + if !pluginSetting.Enabled { + continue + } + + if pluginDef, exist := Plugins[pluginSetting.PluginId]; exist { + if pluginDef.Info.Version != pluginSetting.PluginVersion { + syncPluginDashboards(pluginDef, pluginSetting.OrgId) + } + } + } +} + +func autoUpdateAppDashboard(pluginDashInfo *PluginDashboardInfoDTO, orgId int64) error { + if dash, err := loadPluginDashboard(pluginDashInfo.PluginId, pluginDashInfo.Path); err != nil { + return err + } else { + plog.Info("Auto updating App dashboard", "dashboard", dash.Title, "newRev", pluginDashInfo.Revision, "oldRev", pluginDashInfo.ImportedRevision) + updateCmd := ImportDashboardCommand{ + OrgId: orgId, + PluginId: pluginDashInfo.PluginId, + Overwrite: true, + Dashboard: dash.Data, + UserId: 0, + Path: pluginDashInfo.Path, + } + + if err := bus.Dispatch(&updateCmd); err != nil { + return err + } + } + return nil +} + +func syncPluginDashboards(pluginDef *PluginBase, orgId int64) { + plog.Info("Syncing plugin dashboards to DB", "pluginId", pluginDef.Id) + + // Get plugin dashboards + dashboards, err := GetPluginDashboards(orgId, pluginDef.Id) + + if err != nil { + plog.Error("Failed to load app dashboards", "error", err) + return + } + + // Update dashboards with updated revisions + for _, dash := range dashboards { + // remove removed ones + if dash.Removed { + plog.Info("Deleting plugin dashboard", "pluginId", pluginDef.Id, "dashboard", dash.Slug) + + deleteCmd := m.DeleteDashboardCommand{OrgId: orgId, Slug: dash.Slug} + if err := bus.Dispatch(&deleteCmd); err != nil { + plog.Error("Failed to auto update app dashboard", "pluginId", pluginDef.Id, "error", err) + return + } + + continue + } + + // update updated ones + if dash.ImportedRevision != dash.Revision { + if err := autoUpdateAppDashboard(dash, orgId); err != nil { + plog.Error("Failed to auto update app dashboard", "pluginId", pluginDef.Id, "error", err) + return + } + } + } + + // update version in plugin_setting table to mark that we have processed the update + query := m.GetPluginSettingByIdQuery{PluginId: pluginDef.Id, OrgId: orgId} + if err := bus.Dispatch(&query); err != nil { + plog.Error("Failed to read plugin setting by id", "error", err) + return + } + + appSetting := query.Result + cmd := m.UpdatePluginSettingVersionCmd{ + OrgId: appSetting.OrgId, + PluginId: appSetting.PluginId, + PluginVersion: pluginDef.Info.Version, + } + + if err := bus.Dispatch(&cmd); err != nil { + plog.Error("Failed to update plugin setting version", "error", err) + } +} + +func handlePluginStateChanged(event *m.PluginStateChangedEvent) error { + plog.Info("Plugin state changed", "pluginId", event.PluginId, "enabled", event.Enabled) + + if event.Enabled { + syncPluginDashboards(Plugins[event.PluginId], event.OrgId) + } else { + query := m.GetDashboardsByPluginIdQuery{PluginId: event.PluginId, OrgId: event.OrgId} + + if err := bus.Dispatch(&query); err != nil { + return err + } else { + for _, dash := range query.Result { + deleteCmd := m.DeleteDashboardCommand{OrgId: dash.OrgId, Slug: dash.Slug} + + plog.Info("Deleting plugin dashboard", "pluginId", event.PluginId, "dashboard", dash.Slug) + + if err := bus.Dispatch(&deleteCmd); err != nil { + return err + } + } + } + } + + return nil +} diff --git a/pkg/plugins/datasource_plugin.go b/pkg/plugins/datasource_plugin.go index b8c79f22998..aa092c2bc20 100644 --- a/pkg/plugins/datasource_plugin.go +++ b/pkg/plugins/datasource_plugin.go @@ -6,6 +6,7 @@ type DataSourcePlugin struct { FrontendPluginBase Annotations bool `json:"annotations"` Metrics bool `json:"metrics"` + Alerting bool `json:"alerting"` BuiltIn bool `json:"builtIn"` Mixed bool `json:"mixed"` App string `json:"app"` diff --git a/pkg/plugins/frontend_plugin.go b/pkg/plugins/frontend_plugin.go index 55690777b2a..8db480f947d 100644 --- a/pkg/plugins/frontend_plugin.go +++ b/pkg/plugins/frontend_plugin.go @@ -14,7 +14,7 @@ type FrontendPluginBase struct { } func (fp *FrontendPluginBase) initFrontendPlugin() { - if isInternalPlugin(fp.PluginDir) { + if isExternalPlugin(fp.PluginDir) { StaticRoutes = append(StaticRoutes, &PluginStaticRoute{ Directory: fp.PluginDir, PluginId: fp.Id, @@ -43,22 +43,28 @@ func (fp *FrontendPluginBase) setPathsBasedOnApp(app *AppPlugin) { appSubPath := strings.Replace(fp.PluginDir, app.PluginDir, "", 1) fp.IncludedInAppId = app.Id fp.BaseUrl = app.BaseUrl - fp.Module = util.JoinUrlFragments("plugins/"+app.Id, appSubPath) + "/module" + + if isExternalPlugin(app.PluginDir) { + fp.Module = util.JoinUrlFragments("plugins/"+app.Id, appSubPath) + "/module" + } else { + fp.Module = util.JoinUrlFragments("app/plugins/app/"+app.Id, appSubPath) + "/module" + } } func (fp *FrontendPluginBase) handleModuleDefaults() { - if isInternalPlugin(fp.PluginDir) { + if isExternalPlugin(fp.PluginDir) { fp.Module = path.Join("plugins", fp.Id, "module") fp.BaseUrl = path.Join("public/plugins", fp.Id) return } + fp.IsCorePlugin = true fp.Module = path.Join("app/plugins", fp.Type, fp.Id, "module") fp.BaseUrl = path.Join("public/app/plugins", fp.Type, fp.Id) } -func isInternalPlugin(pluginDir string) bool { +func isExternalPlugin(pluginDir string) bool { return !strings.Contains(pluginDir, setting.StaticRootPath) } diff --git a/pkg/plugins/models.go b/pkg/plugins/models.go index 30f794285e1..7de12b4036c 100644 --- a/pkg/plugins/models.go +++ b/pkg/plugins/models.go @@ -6,8 +6,7 @@ import ( "fmt" "strings" - "github.com/grafana/grafana/pkg/log" - "github.com/grafana/grafana/pkg/models" + m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/setting" ) @@ -39,10 +38,15 @@ type PluginBase struct { Includes []*PluginInclude `json:"includes"` Module string `json:"module"` BaseUrl string `json:"baseUrl"` + HideFromList bool `json:"hideFromList"` IncludedInAppId string `json:"-"` PluginDir string `json:"-"` DefaultNavUrl string `json:"-"` + IsCorePlugin bool `json:"-"` + + GrafanaNetVersion string `json:"-"` + GrafanaNetHasUpdate bool `json:"-"` // cache for readme file contents Readme []byte `json:"-"` @@ -54,7 +58,7 @@ func (pb *PluginBase) registerPlugin(pluginDir string) error { } if !strings.HasPrefix(pluginDir, setting.StaticRootPath) { - log.Info("Plugins: Registering plugin %v", pb.Name) + plog.Info("Registering plugin", "name", pb.Name) } if len(pb.Dependencies.Plugins) == 0 { @@ -65,6 +69,12 @@ func (pb *PluginBase) registerPlugin(pluginDir string) error { pb.Dependencies.GrafanaVersion = "*" } + for _, include := range pb.Includes { + if include.Role == "" { + include.Role = m.RoleType(m.ROLE_VIEWER) + } + } + pb.PluginDir = pluginDir Plugins[pb.Id] = pb return nil @@ -76,14 +86,14 @@ type PluginDependencies struct { } type PluginInclude struct { - Name string `json:"name"` - Path string `json:"path"` - Type string `json:"type"` - Component string `json:"component"` - Role models.RoleType `json:"role"` - AddToNav bool `json:"addToNav"` - DefaultNav bool `json:"defaultNav"` - Slug string `json:"slug"` + Name string `json:"name"` + Path string `json:"path"` + Type string `json:"type"` + Component string `json:"component"` + Role m.RoleType `json:"role"` + AddToNav bool `json:"addToNav"` + DefaultNav bool `json:"defaultNav"` + Slug string `json:"slug"` Id string `json:"-"` } diff --git a/pkg/plugins/plugins.go b/pkg/plugins/plugins.go index 0d69d5745b9..b6c3639cbbf 100644 --- a/pkg/plugins/plugins.go +++ b/pkg/plugins/plugins.go @@ -22,6 +22,10 @@ var ( Apps map[string]*AppPlugin Plugins map[string]*PluginBase PluginTypes map[string]interface{} + + GrafanaLatestVersion string + GrafanaHasUpdate bool + plog log.Logger ) type PluginScanner struct { @@ -30,6 +34,8 @@ type PluginScanner struct { } func Init() error { + plog = log.New("plugins") + DataSources = make(map[string]*DataSourcePlugin) StaticRoutes = make([]*PluginStaticRoute, 0) Panels = make(map[string]*PanelPlugin) @@ -41,16 +47,16 @@ func Init() error { "app": AppPlugin{}, } - log.Info("Plugins: Scan starting") + plog.Info("Starting plugin search") scan(path.Join(setting.StaticRootPath, "app/plugins")) // check if plugins dir exists if _, err := os.Stat(setting.PluginsPath); os.IsNotExist(err) { - log.Warn("Plugins: Plugin dir %v does not exist", setting.PluginsPath) + plog.Warn("Plugin dir does not exist", "dir", setting.PluginsPath) if err = os.MkdirAll(setting.PluginsPath, os.ModePerm); err != nil { - log.Warn("Plugins: Failed to create plugin dir: %v, error: %v", setting.PluginsPath, err) + plog.Warn("Failed to create plugin dir", "dir", setting.PluginsPath, "error", err) } else { - log.Info("Plugins: Plugin dir %v created", setting.PluginsPath) + plog.Info("Plugin dir created", "dir", setting.PluginsPath) scan(setting.PluginsPath) } } else { @@ -70,6 +76,9 @@ func Init() error { app.initApp() } + go StartPluginUpdateChecker() + go updateAppDashboards() + return nil } diff --git a/pkg/plugins/queries.go b/pkg/plugins/queries.go index b930c9575a3..5ae1825a88f 100644 --- a/pkg/plugins/queries.go +++ b/pkg/plugins/queries.go @@ -24,7 +24,16 @@ func GetPluginSettings(orgId int64) (map[string]*m.PluginSettingInfoDTO, error) } // default to enabled true - opt := &m.PluginSettingInfoDTO{Enabled: true} + opt := &m.PluginSettingInfoDTO{ + PluginId: pluginDef.Id, + OrgId: orgId, + Enabled: true, + } + + // apps are disabled by default + if pluginDef.Type == PluginTypeApp { + opt.Enabled = false + } // if it's included in app check app settings if pluginDef.IncludedInAppId != "" { diff --git a/pkg/plugins/update_checker.go b/pkg/plugins/update_checker.go new file mode 100644 index 00000000000..76c566803ac --- /dev/null +++ b/pkg/plugins/update_checker.go @@ -0,0 +1,136 @@ +package plugins + +import ( + "encoding/json" + "io/ioutil" + "net/http" + "strings" + "time" + + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/setting" + "github.com/hashicorp/go-version" +) + +var ( + httpClient http.Client = http.Client{Timeout: time.Duration(10 * time.Second)} +) + +type GrafanaNetPlugin struct { + Slug string `json:"slug"` + Version string `json:"version"` +} + +type GithubLatest struct { + Stable string `json:"stable"` + Testing string `json:"testing"` +} + +func StartPluginUpdateChecker() { + if !setting.CheckForUpdates { + return + } + + // do one check directly + go checkForUpdates() + + ticker := time.NewTicker(time.Minute * 10) + for { + select { + case <-ticker.C: + checkForUpdates() + } + } +} + +func getAllExternalPluginSlugs() string { + var result []string + for _, plug := range Plugins { + if plug.IsCorePlugin { + continue + } + + result = append(result, plug.Id) + } + + return strings.Join(result, ",") +} + +func checkForUpdates() { + log.Trace("Checking for updates") + + pluginSlugs := getAllExternalPluginSlugs() + resp, err := httpClient.Get("https://grafana.net/api/plugins/versioncheck?slugIn=" + pluginSlugs + "&grafanaVersion=" + setting.BuildVersion) + + if err != nil { + log.Trace("Failed to get plugins repo from grafana.net, %v", err.Error()) + return + } + + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Trace("Update check failed, reading response from grafana.net, %v", err.Error()) + return + } + + gNetPlugins := []GrafanaNetPlugin{} + err = json.Unmarshal(body, &gNetPlugins) + if err != nil { + log.Trace("Failed to unmarshal plugin repo, reading response from grafana.net, %v", err.Error()) + return + } + + for _, plug := range Plugins { + for _, gplug := range gNetPlugins { + if gplug.Slug == plug.Id { + plug.GrafanaNetVersion = gplug.Version + + plugVersion, err1 := version.NewVersion(plug.Info.Version) + gplugVersion, err2 := version.NewVersion(gplug.Version) + + if err1 != nil || err2 != nil { + plug.GrafanaNetHasUpdate = plug.Info.Version != plug.GrafanaNetVersion + } else { + plug.GrafanaNetHasUpdate = plugVersion.LessThan(gplugVersion) + } + } + } + } + + resp2, err := httpClient.Get("https://raw.githubusercontent.com/grafana/grafana/master/latest.json") + if err != nil { + log.Trace("Failed to get latest.json repo from github: %v", err.Error()) + return + } + + defer resp2.Body.Close() + body, err = ioutil.ReadAll(resp2.Body) + if err != nil { + log.Trace("Update check failed, reading response from github.com, %v", err.Error()) + return + } + + var githubLatest GithubLatest + err = json.Unmarshal(body, &githubLatest) + if err != nil { + log.Trace("Failed to unmarshal github latest, reading response from github: %v", err.Error()) + return + } + + if strings.Contains(setting.BuildVersion, "-") { + GrafanaLatestVersion = githubLatest.Testing + GrafanaHasUpdate = !strings.HasPrefix(setting.BuildVersion, githubLatest.Testing) + } else { + GrafanaLatestVersion = githubLatest.Stable + GrafanaHasUpdate = githubLatest.Stable != setting.BuildVersion + } + + currVersion, err1 := version.NewVersion(setting.BuildVersion) + latestVersion, err2 := version.NewVersion(GrafanaLatestVersion) + + if err1 == nil && err2 == nil { + GrafanaHasUpdate = currVersion.LessThan(latestVersion) + } +} diff --git a/pkg/services/alerting/commands.go b/pkg/services/alerting/commands.go new file mode 100644 index 00000000000..62671a559fa --- /dev/null +++ b/pkg/services/alerting/commands.go @@ -0,0 +1,55 @@ +package alerting + +import ( + "github.com/grafana/grafana/pkg/bus" + m "github.com/grafana/grafana/pkg/models" +) + +type UpdateDashboardAlertsCommand struct { + UserId int64 + OrgId int64 + Dashboard *m.Dashboard +} + +type ValidateDashboardAlertsCommand struct { + UserId int64 + OrgId int64 + Dashboard *m.Dashboard +} + +func init() { + bus.AddHandler("alerting", updateDashboardAlerts) + bus.AddHandler("alerting", validateDashboardAlerts) +} + +func validateDashboardAlerts(cmd *ValidateDashboardAlertsCommand) error { + extractor := NewDashAlertExtractor(cmd.Dashboard, cmd.OrgId) + + if _, err := extractor.GetAlerts(); err != nil { + return err + } + + return nil +} + +func updateDashboardAlerts(cmd *UpdateDashboardAlertsCommand) error { + saveAlerts := m.SaveAlertsCommand{ + OrgId: cmd.OrgId, + UserId: cmd.UserId, + DashboardId: cmd.Dashboard.Id, + } + + extractor := NewDashAlertExtractor(cmd.Dashboard, cmd.OrgId) + + if alerts, err := extractor.GetAlerts(); err != nil { + return err + } else { + saveAlerts.Alerts = alerts + } + + if err := bus.Dispatch(&saveAlerts); err != nil { + return err + } + + return nil +} diff --git a/pkg/services/alerting/conditions/evaluator.go b/pkg/services/alerting/conditions/evaluator.go new file mode 100644 index 00000000000..57abb2edd25 --- /dev/null +++ b/pkg/services/alerting/conditions/evaluator.go @@ -0,0 +1,135 @@ +package conditions + +import ( + "encoding/json" + + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/services/alerting" + "gopkg.in/guregu/null.v3" +) + +var ( + defaultTypes []string = []string{"gt", "lt"} + rangedTypes []string = []string{"within_range", "outside_range"} +) + +type AlertEvaluator interface { + Eval(reducedValue null.Float) bool +} + +type NoValueEvaluator struct{} + +func (e *NoValueEvaluator) Eval(reducedValue null.Float) bool { + return reducedValue.Valid == false +} + +type ThresholdEvaluator struct { + Type string + Threshold float64 +} + +func newThresholdEvaluator(typ string, model *simplejson.Json) (*ThresholdEvaluator, error) { + params := model.Get("params").MustArray() + if len(params) == 0 { + return nil, alerting.ValidationError{Reason: "Evaluator missing threshold parameter"} + } + + firstParam, ok := params[0].(json.Number) + if !ok { + return nil, alerting.ValidationError{Reason: "Evaluator has invalid parameter"} + } + + defaultEval := &ThresholdEvaluator{Type: typ} + defaultEval.Threshold, _ = firstParam.Float64() + return defaultEval, nil +} + +func (e *ThresholdEvaluator) Eval(reducedValue null.Float) bool { + if reducedValue.Valid == false { + return false + } + + switch e.Type { + case "gt": + return reducedValue.Float64 > e.Threshold + case "lt": + return reducedValue.Float64 < e.Threshold + } + + return false +} + +type RangedEvaluator struct { + Type string + Lower float64 + Upper float64 +} + +func newRangedEvaluator(typ string, model *simplejson.Json) (*RangedEvaluator, error) { + params := model.Get("params").MustArray() + if len(params) == 0 { + return nil, alerting.ValidationError{Reason: "Evaluator missing threshold parameter"} + } + + firstParam, ok := params[0].(json.Number) + if !ok { + return nil, alerting.ValidationError{Reason: "Evaluator has invalid parameter"} + } + + secondParam, ok := params[1].(json.Number) + if !ok { + return nil, alerting.ValidationError{Reason: "Evaluator has invalid second parameter"} + } + + rangedEval := &RangedEvaluator{Type: typ} + rangedEval.Lower, _ = firstParam.Float64() + rangedEval.Upper, _ = secondParam.Float64() + return rangedEval, nil +} + +func (e *RangedEvaluator) Eval(reducedValue null.Float) bool { + if reducedValue.Valid == false { + return false + } + + floatValue := reducedValue.Float64 + + switch e.Type { + case "within_range": + return (e.Lower < floatValue && e.Upper > floatValue) || (e.Upper < floatValue && e.Lower > floatValue) + case "outside_range": + return (e.Upper < floatValue && e.Lower < floatValue) || (e.Upper > floatValue && e.Lower > floatValue) + } + + return false +} + +func NewAlertEvaluator(model *simplejson.Json) (AlertEvaluator, error) { + typ := model.Get("type").MustString() + if typ == "" { + return nil, alerting.ValidationError{Reason: "Evaluator missing type property"} + } + + if inSlice(typ, defaultTypes) { + return newThresholdEvaluator(typ, model) + } + + if inSlice(typ, rangedTypes) { + return newRangedEvaluator(typ, model) + } + + if typ == "no_value" { + return &NoValueEvaluator{}, nil + } + + return nil, alerting.ValidationError{Reason: "Evaluator invalid evaluator type: " + typ} +} + +func inSlice(a string, list []string) bool { + for _, b := range list { + if b == a { + return true + } + } + return false +} diff --git a/pkg/services/alerting/conditions/evaluator_test.go b/pkg/services/alerting/conditions/evaluator_test.go new file mode 100644 index 00000000000..e2a3cb48396 --- /dev/null +++ b/pkg/services/alerting/conditions/evaluator_test.go @@ -0,0 +1,63 @@ +package conditions + +import ( + "testing" + + "gopkg.in/guregu/null.v3" + + "github.com/grafana/grafana/pkg/components/simplejson" + . "github.com/smartystreets/goconvey/convey" +) + +func evalutorScenario(json string, reducedValue float64, datapoints ...float64) bool { + jsonModel, err := simplejson.NewJson([]byte(json)) + So(err, ShouldBeNil) + + evaluator, err := NewAlertEvaluator(jsonModel) + So(err, ShouldBeNil) + + return evaluator.Eval(null.FloatFrom(reducedValue)) +} + +func TestEvalutors(t *testing.T) { + Convey("greater then", t, func() { + So(evalutorScenario(`{"type": "gt", "params": [1] }`, 3), ShouldBeTrue) + So(evalutorScenario(`{"type": "gt", "params": [3] }`, 1), ShouldBeFalse) + }) + + Convey("less then", t, func() { + So(evalutorScenario(`{"type": "lt", "params": [1] }`, 3), ShouldBeFalse) + So(evalutorScenario(`{"type": "lt", "params": [3] }`, 1), ShouldBeTrue) + }) + + Convey("within_range", t, func() { + So(evalutorScenario(`{"type": "within_range", "params": [1, 100] }`, 3), ShouldBeTrue) + So(evalutorScenario(`{"type": "within_range", "params": [1, 100] }`, 300), ShouldBeFalse) + So(evalutorScenario(`{"type": "within_range", "params": [100, 1] }`, 3), ShouldBeTrue) + So(evalutorScenario(`{"type": "within_range", "params": [100, 1] }`, 300), ShouldBeFalse) + }) + + Convey("outside_range", t, func() { + So(evalutorScenario(`{"type": "outside_range", "params": [1, 100] }`, 1000), ShouldBeTrue) + So(evalutorScenario(`{"type": "outside_range", "params": [1, 100] }`, 50), ShouldBeFalse) + So(evalutorScenario(`{"type": "outside_range", "params": [100, 1] }`, 1000), ShouldBeTrue) + So(evalutorScenario(`{"type": "outside_range", "params": [100, 1] }`, 50), ShouldBeFalse) + }) + + Convey("no_value", t, func() { + Convey("should be false if serie have values", func() { + So(evalutorScenario(`{"type": "no_value", "params": [] }`, 50), ShouldBeFalse) + }) + + Convey("should be true when the serie have no value", func() { + jsonModel, err := simplejson.NewJson([]byte(`{"type": "no_value", "params": [] }`)) + So(err, ShouldBeNil) + + evaluator, err := NewAlertEvaluator(jsonModel) + So(err, ShouldBeNil) + + So(evaluator.Eval(null.FloatFromPtr(nil)), ShouldBeTrue) + + }) + }) +} diff --git a/pkg/services/alerting/conditions/query.go b/pkg/services/alerting/conditions/query.go new file mode 100644 index 00000000000..d7e0a0c29e3 --- /dev/null +++ b/pkg/services/alerting/conditions/query.go @@ -0,0 +1,191 @@ +package conditions + +import ( + "fmt" + "strings" + "time" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/components/simplejson" + m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/alerting" + "github.com/grafana/grafana/pkg/tsdb" +) + +func init() { + alerting.RegisterCondition("query", func(model *simplejson.Json, index int) (alerting.Condition, error) { + return NewQueryCondition(model, index) + }) +} + +type QueryCondition struct { + Index int + Query AlertQuery + Reducer QueryReducer + Evaluator AlertEvaluator + Operator string + HandleRequest tsdb.HandleRequestFunc +} + +type AlertQuery struct { + Model *simplejson.Json + DatasourceId int64 + From string + To string +} + +func (c *QueryCondition) Eval(context *alerting.EvalContext) (*alerting.ConditionResult, error) { + timeRange := tsdb.NewTimeRange(c.Query.From, c.Query.To) + + seriesList, err := c.executeQuery(context, timeRange) + if err != nil { + return nil, err + } + + emptySerieCount := 0 + evalMatchCount := 0 + var matches []*alerting.EvalMatch + for _, series := range seriesList { + reducedValue := c.Reducer.Reduce(series) + evalMatch := c.Evaluator.Eval(reducedValue) + + if reducedValue.Valid == false { + emptySerieCount++ + continue + } + + if context.IsTestRun { + context.Logs = append(context.Logs, &alerting.ResultLogEntry{ + Message: fmt.Sprintf("Condition[%d]: Eval: %v, Metric: %s, Value: %1.3f", c.Index, evalMatch, series.Name, reducedValue.Float64), + }) + } + + if evalMatch { + evalMatchCount++ + + matches = append(matches, &alerting.EvalMatch{ + Metric: series.Name, + Value: reducedValue.Float64, + }) + } + } + + return &alerting.ConditionResult{ + Firing: evalMatchCount > 0, + NoDataFound: emptySerieCount == len(seriesList), + Operator: c.Operator, + EvalMatches: matches, + }, nil +} + +func (c *QueryCondition) executeQuery(context *alerting.EvalContext, timeRange *tsdb.TimeRange) (tsdb.TimeSeriesSlice, error) { + getDsInfo := &m.GetDataSourceByIdQuery{ + Id: c.Query.DatasourceId, + OrgId: context.Rule.OrgId, + } + + if err := bus.Dispatch(getDsInfo); err != nil { + return nil, fmt.Errorf("Could not find datasource") + } + + req := c.getRequestForAlertRule(getDsInfo.Result, timeRange) + result := make(tsdb.TimeSeriesSlice, 0) + + resp, err := c.HandleRequest(context.Ctx, req) + if err != nil { + return nil, fmt.Errorf("tsdb.HandleRequest() error %v", err) + } + + for _, v := range resp.Results { + if v.Error != nil { + return nil, fmt.Errorf("tsdb.HandleRequest() response error %v", v) + } + + result = append(result, v.Series...) + + if context.IsTestRun { + context.Logs = append(context.Logs, &alerting.ResultLogEntry{ + Message: fmt.Sprintf("Condition[%d]: Query Result", c.Index), + Data: v.Series, + }) + } + } + + return result, nil +} + +func (c *QueryCondition) getRequestForAlertRule(datasource *m.DataSource, timeRange *tsdb.TimeRange) *tsdb.Request { + req := &tsdb.Request{ + TimeRange: timeRange, + Queries: []*tsdb.Query{ + { + RefId: "A", + Model: c.Query.Model, + DataSource: datasource, + }, + }, + } + + return req +} + +func NewQueryCondition(model *simplejson.Json, index int) (*QueryCondition, error) { + condition := QueryCondition{} + condition.Index = index + condition.HandleRequest = tsdb.HandleRequest + + queryJson := model.Get("query") + + condition.Query.Model = queryJson.Get("model") + condition.Query.From = queryJson.Get("params").MustArray()[1].(string) + condition.Query.To = queryJson.Get("params").MustArray()[2].(string) + + if err := validateFromValue(condition.Query.From); err != nil { + return nil, err + } + + if err := validateToValue(condition.Query.To); err != nil { + return nil, err + } + + condition.Query.DatasourceId = queryJson.Get("datasourceId").MustInt64() + + reducerJson := model.Get("reducer") + condition.Reducer = NewSimpleReducer(reducerJson.Get("type").MustString()) + + evaluatorJson := model.Get("evaluator") + evaluator, err := NewAlertEvaluator(evaluatorJson) + if err != nil { + return nil, err + } + condition.Evaluator = evaluator + + operatorJson := model.Get("operator") + operator := operatorJson.Get("type").MustString("and") + condition.Operator = operator + + return &condition, nil +} + +func validateFromValue(from string) error { + fromRaw := strings.Replace(from, "now-", "", 1) + + _, err := time.ParseDuration("-" + fromRaw) + return err +} + +func validateToValue(to string) error { + if to == "now" { + return nil + } else if strings.HasPrefix(to, "now-") { + withoutNow := strings.Replace(to, "now-", "", 1) + + _, err := time.ParseDuration("-" + withoutNow) + if err == nil { + return nil + } + } + + _, err := time.ParseDuration(to) + return err +} diff --git a/pkg/services/alerting/conditions/query_test.go b/pkg/services/alerting/conditions/query_test.go new file mode 100644 index 00000000000..c3797beaf37 --- /dev/null +++ b/pkg/services/alerting/conditions/query_test.go @@ -0,0 +1,167 @@ +package conditions + +import ( + "context" + "testing" + + null "gopkg.in/guregu/null.v3" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/components/simplejson" + m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/alerting" + "github.com/grafana/grafana/pkg/tsdb" + . "github.com/smartystreets/goconvey/convey" +) + +func TestQueryCondition(t *testing.T) { + + Convey("when evaluating query condition", t, func() { + + queryConditionScenario("Given avg() and > 100", func(ctx *queryConditionTestContext) { + + ctx.reducer = `{"type": "avg"}` + ctx.evaluator = `{"type": "gt", "params": [100]}` + + Convey("Can read query condition from json model", func() { + ctx.exec() + + So(ctx.condition.Query.From, ShouldEqual, "5m") + So(ctx.condition.Query.To, ShouldEqual, "now") + So(ctx.condition.Query.DatasourceId, ShouldEqual, 1) + + Convey("Can read query reducer", func() { + reducer, ok := ctx.condition.Reducer.(*SimpleReducer) + So(ok, ShouldBeTrue) + So(reducer.Type, ShouldEqual, "avg") + }) + + Convey("Can read evaluator", func() { + evaluator, ok := ctx.condition.Evaluator.(*ThresholdEvaluator) + So(ok, ShouldBeTrue) + So(evaluator.Type, ShouldEqual, "gt") + }) + }) + + Convey("should fire when avg is above 100", func() { + points := tsdb.NewTimeSeriesPointsFromArgs(120, 0) + ctx.series = tsdb.TimeSeriesSlice{tsdb.NewTimeSeries("test1", points)} + cr, err := ctx.exec() + + So(err, ShouldBeNil) + So(cr.Firing, ShouldBeTrue) + }) + + Convey("Should not fire when avg is below 100", func() { + points := tsdb.NewTimeSeriesPointsFromArgs(90, 0) + ctx.series = tsdb.TimeSeriesSlice{tsdb.NewTimeSeries("test1", points)} + cr, err := ctx.exec() + + So(err, ShouldBeNil) + So(cr.Firing, ShouldBeFalse) + }) + + Convey("Should fire if only first serie matches", func() { + ctx.series = tsdb.TimeSeriesSlice{ + tsdb.NewTimeSeries("test1", tsdb.NewTimeSeriesPointsFromArgs(120, 0)), + tsdb.NewTimeSeries("test2", tsdb.NewTimeSeriesPointsFromArgs(0, 0)), + } + cr, err := ctx.exec() + + So(err, ShouldBeNil) + So(cr.Firing, ShouldBeTrue) + }) + + Convey("Empty series", func() { + Convey("Should set NoDataFound both series are empty", func() { + ctx.series = tsdb.TimeSeriesSlice{ + tsdb.NewTimeSeries("test1", tsdb.NewTimeSeriesPointsFromArgs()), + tsdb.NewTimeSeries("test2", tsdb.NewTimeSeriesPointsFromArgs()), + } + cr, err := ctx.exec() + + So(err, ShouldBeNil) + So(cr.NoDataFound, ShouldBeTrue) + }) + + Convey("Should set NoDataFound both series contains null", func() { + ctx.series = tsdb.TimeSeriesSlice{ + tsdb.NewTimeSeries("test1", tsdb.TimeSeriesPoints{tsdb.TimePoint{null.FloatFromPtr(nil), null.FloatFrom(0)}}), + tsdb.NewTimeSeries("test2", tsdb.TimeSeriesPoints{tsdb.TimePoint{null.FloatFromPtr(nil), null.FloatFrom(0)}}), + } + cr, err := ctx.exec() + + So(err, ShouldBeNil) + So(cr.NoDataFound, ShouldBeTrue) + }) + + Convey("Should not set NoDataFound if one serie is empty", func() { + ctx.series = tsdb.TimeSeriesSlice{ + tsdb.NewTimeSeries("test1", tsdb.NewTimeSeriesPointsFromArgs()), + tsdb.NewTimeSeries("test2", tsdb.NewTimeSeriesPointsFromArgs(120, 0)), + } + cr, err := ctx.exec() + + So(err, ShouldBeNil) + So(cr.NoDataFound, ShouldBeFalse) + }) + }) + }) + }) +} + +type queryConditionTestContext struct { + reducer string + evaluator string + series tsdb.TimeSeriesSlice + result *alerting.EvalContext + condition *QueryCondition +} + +type queryConditionScenarioFunc func(c *queryConditionTestContext) + +func (ctx *queryConditionTestContext) exec() (*alerting.ConditionResult, error) { + jsonModel, err := simplejson.NewJson([]byte(`{ + "type": "query", + "query": { + "params": ["A", "5m", "now"], + "datasourceId": 1, + "model": {"target": "aliasByNode(statsd.fakesite.counters.session_start.mobile.count, 4)"} + }, + "reducer":` + ctx.reducer + `, + "evaluator":` + ctx.evaluator + ` + }`)) + So(err, ShouldBeNil) + + condition, err := NewQueryCondition(jsonModel, 0) + So(err, ShouldBeNil) + + ctx.condition = condition + + condition.HandleRequest = func(context context.Context, req *tsdb.Request) (*tsdb.Response, error) { + return &tsdb.Response{ + Results: map[string]*tsdb.QueryResult{ + "A": {Series: ctx.series}, + }, + }, nil + } + + return condition.Eval(ctx.result) +} + +func queryConditionScenario(desc string, fn queryConditionScenarioFunc) { + Convey(desc, func() { + + bus.AddHandler("test", func(query *m.GetDataSourceByIdQuery) error { + query.Result = &m.DataSource{Id: 1, Type: "graphite"} + return nil + }) + + ctx := &queryConditionTestContext{} + ctx.result = &alerting.EvalContext{ + Rule: &alerting.Rule{}, + } + + fn(ctx) + }) +} diff --git a/pkg/services/alerting/conditions/reducer.go b/pkg/services/alerting/conditions/reducer.go new file mode 100644 index 00000000000..b7816a61d1d --- /dev/null +++ b/pkg/services/alerting/conditions/reducer.go @@ -0,0 +1,108 @@ +package conditions + +import ( + "math" + + "sort" + + "github.com/grafana/grafana/pkg/tsdb" + "gopkg.in/guregu/null.v3" +) + +type QueryReducer interface { + Reduce(timeSeries *tsdb.TimeSeries) null.Float +} + +type SimpleReducer struct { + Type string +} + +func (s *SimpleReducer) Reduce(series *tsdb.TimeSeries) null.Float { + if len(series.Points) == 0 { + return null.FloatFromPtr(nil) + } + + value := float64(0) + allNull := true + + switch s.Type { + case "avg": + validPointsCount := 0 + for _, point := range series.Points { + if point[0].Valid { + value += point[0].Float64 + validPointsCount += 1 + allNull = false + } + } + if validPointsCount > 0 { + value = value / float64(validPointsCount) + } + case "sum": + for _, point := range series.Points { + if point[0].Valid { + value += point[0].Float64 + allNull = false + } + } + case "min": + value = math.MaxFloat64 + for _, point := range series.Points { + if point[0].Valid { + allNull = false + if value > point[0].Float64 { + value = point[0].Float64 + } + } + } + case "max": + value = -math.MaxFloat64 + for _, point := range series.Points { + if point[0].Valid { + allNull = false + if value < point[0].Float64 { + value = point[0].Float64 + } + } + } + case "count": + value = float64(len(series.Points)) + allNull = false + case "last": + points := series.Points + for i := len(points) - 1; i >= 0; i-- { + if points[i][0].Valid { + value = points[i][0].Float64 + allNull = false + break + } + } + case "median": + var values []float64 + for _, v := range series.Points { + if v[0].Valid { + allNull = false + values = append(values, v[0].Float64) + } + } + if len(values) >= 1 { + sort.Float64s(values) + length := len(values) + if length%2 == 1 { + value = values[(length-1)/2] + } else { + value = (values[(length/2)-1] + values[length/2]) / 2 + } + } + } + + if allNull { + return null.FloatFromPtr(nil) + } + + return null.FloatFrom(value) +} + +func NewSimpleReducer(typ string) *SimpleReducer { + return &SimpleReducer{Type: typ} +} diff --git a/pkg/services/alerting/conditions/reducer_test.go b/pkg/services/alerting/conditions/reducer_test.go new file mode 100644 index 00000000000..7d6cee466fc --- /dev/null +++ b/pkg/services/alerting/conditions/reducer_test.go @@ -0,0 +1,87 @@ +package conditions + +import ( + "testing" + + "gopkg.in/guregu/null.v3" + + "github.com/grafana/grafana/pkg/tsdb" + . "github.com/smartystreets/goconvey/convey" +) + +func TestSimpleReducer(t *testing.T) { + Convey("Test simple reducer by calculating", t, func() { + + Convey("sum", func() { + result := testReducer("sum", 1, 2, 3) + So(result, ShouldEqual, float64(6)) + }) + + Convey("min", func() { + result := testReducer("min", 3, 2, 1) + So(result, ShouldEqual, float64(1)) + }) + + Convey("max", func() { + result := testReducer("max", 1, 2, 3) + So(result, ShouldEqual, float64(3)) + }) + + Convey("count", func() { + result := testReducer("count", 1, 2, 3000) + So(result, ShouldEqual, float64(3)) + }) + + Convey("last", func() { + result := testReducer("last", 1, 2, 3000) + So(result, ShouldEqual, float64(3000)) + }) + + Convey("median odd amount of numbers", func() { + result := testReducer("median", 1, 2, 3000) + So(result, ShouldEqual, float64(2)) + }) + + Convey("median even amount of numbers", func() { + result := testReducer("median", 1, 2, 4, 3000) + So(result, ShouldEqual, float64(3)) + }) + + Convey("median with one values", func() { + result := testReducer("median", 1) + So(result, ShouldEqual, float64(1)) + }) + + Convey("avg", func() { + result := testReducer("avg", 1, 2, 3) + So(result, ShouldEqual, float64(2)) + }) + + Convey("avg of number values and null values should ignore nulls", func() { + reducer := NewSimpleReducer("avg") + series := &tsdb.TimeSeries{ + Name: "test time serie", + } + + series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFrom(3), 1)) + series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFromPtr(nil), 2)) + series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFromPtr(nil), 3)) + series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFrom(3), 4)) + + So(reducer.Reduce(series).Float64, ShouldEqual, float64(3)) + }) + }) +} + +func testReducer(typ string, datapoints ...float64) float64 { + reducer := NewSimpleReducer(typ) + series := &tsdb.TimeSeries{ + Name: "test time serie", + } + + for idx := range datapoints { + series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFrom(datapoints[idx]), 1234134)) + } + + return reducer.Reduce(series).Float64 +} diff --git a/pkg/services/alerting/engine.go b/pkg/services/alerting/engine.go new file mode 100644 index 00000000000..b99b7506614 --- /dev/null +++ b/pkg/services/alerting/engine.go @@ -0,0 +1,137 @@ +package alerting + +import ( + "context" + "time" + + "github.com/benbjohnson/clock" + "github.com/grafana/grafana/pkg/log" + "golang.org/x/sync/errgroup" +) + +type Engine struct { + execQueue chan *Job + clock clock.Clock + ticker *Ticker + scheduler Scheduler + evalHandler EvalHandler + ruleReader RuleReader + log log.Logger + resultHandler ResultHandler +} + +func NewEngine() *Engine { + e := &Engine{ + ticker: NewTicker(time.Now(), time.Second*0, clock.New()), + execQueue: make(chan *Job, 1000), + scheduler: NewScheduler(), + evalHandler: NewEvalHandler(), + ruleReader: NewRuleReader(), + log: log.New("alerting.engine"), + resultHandler: NewResultHandler(), + } + + return e +} + +func (e *Engine) Run(ctx context.Context) error { + e.log.Info("Initializing Alerting") + + alertGroup, ctx := errgroup.WithContext(ctx) + + alertGroup.Go(func() error { return e.alertingTicker(ctx) }) + alertGroup.Go(func() error { return e.runJobDispatcher(ctx) }) + + err := alertGroup.Wait() + + e.log.Info("Stopped Alerting", "reason", err) + return err +} + +func (e *Engine) alertingTicker(grafanaCtx context.Context) error { + defer func() { + if err := recover(); err != nil { + e.log.Error("Scheduler Panic: stopping alertingTicker", "error", err, "stack", log.Stack(1)) + } + }() + + tickIndex := 0 + + for { + select { + case <-grafanaCtx.Done(): + return grafanaCtx.Err() + case tick := <-e.ticker.C: + // TEMP SOLUTION update rules ever tenth tick + if tickIndex%10 == 0 { + e.scheduler.Update(e.ruleReader.Fetch()) + } + + e.scheduler.Tick(tick, e.execQueue) + tickIndex++ + } + } +} + +func (e *Engine) runJobDispatcher(grafanaCtx context.Context) error { + dispatcherGroup, alertCtx := errgroup.WithContext(grafanaCtx) + + for { + select { + case <-grafanaCtx.Done(): + return dispatcherGroup.Wait() + case job := <-e.execQueue: + dispatcherGroup.Go(func() error { return e.processJob(alertCtx, job) }) + } + } +} + +var ( + unfinishedWorkTimeout time.Duration = time.Second * 5 + alertTimeout time.Duration = time.Second * 30 +) + +func (e *Engine) processJob(grafanaCtx context.Context, job *Job) error { + defer func() { + if err := recover(); err != nil { + e.log.Error("Alert Panic", "error", err, "stack", log.Stack(1)) + } + }() + + alertCtx, cancelFn := context.WithTimeout(context.TODO(), alertTimeout) + + job.Running = true + evalContext := NewEvalContext(alertCtx, job.Rule) + + done := make(chan struct{}) + + go func() { + defer func() { + if err := recover(); err != nil { + e.log.Error("Alert Panic", "error", err, "stack", log.Stack(1)) + close(done) + } + }() + + e.evalHandler.Eval(evalContext) + e.resultHandler.Handle(evalContext) + close(done) + }() + + var err error = nil + select { + case <-grafanaCtx.Done(): + select { + case <-time.After(unfinishedWorkTimeout): + cancelFn() + err = grafanaCtx.Err() + case <-done: + } + case <-done: + } + + e.log.Debug("Job Execution completed", "timeMs", evalContext.GetDurationMs(), "alertId", evalContext.Rule.Id, "name", evalContext.Rule.Name, "firing", evalContext.Firing) + job.Running = false + cancelFn() + return err +} diff --git a/pkg/services/alerting/eval_context.go b/pkg/services/alerting/eval_context.go new file mode 100644 index 00000000000..2b252da8c4b --- /dev/null +++ b/pkg/services/alerting/eval_context.go @@ -0,0 +1,119 @@ +package alerting + +import ( + "context" + "fmt" + "time" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/log" + m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/setting" +) + +type EvalContext struct { + Firing bool + IsTestRun bool + EvalMatches []*EvalMatch + Logs []*ResultLogEntry + Error error + ConditionEvals string + StartTime time.Time + EndTime time.Time + Rule *Rule + log log.Logger + dashboardSlug string + ImagePublicUrl string + ImageOnDiskPath string + NoDataFound bool + PrevAlertState m.AlertStateType + + Ctx context.Context +} + +func NewEvalContext(alertCtx context.Context, rule *Rule) *EvalContext { + return &EvalContext{ + Ctx: alertCtx, + StartTime: time.Now(), + Rule: rule, + Logs: make([]*ResultLogEntry, 0), + EvalMatches: make([]*EvalMatch, 0), + log: log.New("alerting.evalContext"), + PrevAlertState: rule.State, + } +} + +type StateDescription struct { + Color string + Text string + Data string +} + +func (c *EvalContext) GetStateModel() *StateDescription { + switch c.Rule.State { + case m.AlertStateOK: + return &StateDescription{ + Color: "#36a64f", + Text: "OK", + } + case m.AlertStateNoData: + return &StateDescription{ + Color: "#888888", + Text: "No Data", + } + case m.AlertStateAlerting: + return &StateDescription{ + Color: "#D63232", + Text: "Alerting", + } + default: + panic("Unknown rule state " + c.Rule.State) + } +} + +func (c *EvalContext) ShouldUpdateAlertState() bool { + return c.Rule.State != c.PrevAlertState +} + +func (c *EvalContext) ShouldSendNotification() bool { + if (c.PrevAlertState == m.AlertStatePending) && (c.Rule.State == m.AlertStateOK) { + return false + } + + return true +} + +func (a *EvalContext) GetDurationMs() float64 { + return float64(a.EndTime.Nanosecond()-a.StartTime.Nanosecond()) / float64(1000000) +} + +func (c *EvalContext) GetNotificationTitle() string { + return "[" + c.GetStateModel().Text + "] " + c.Rule.Name +} + +func (c *EvalContext) GetDashboardSlug() (string, error) { + if c.dashboardSlug != "" { + return c.dashboardSlug, nil + } + + slugQuery := &m.GetDashboardSlugByIdQuery{Id: c.Rule.DashboardId} + if err := bus.Dispatch(slugQuery); err != nil { + return "", err + } + + c.dashboardSlug = slugQuery.Result + return c.dashboardSlug, nil +} + +func (c *EvalContext) GetRuleUrl() (string, error) { + if c.IsTestRun { + return setting.AppUrl, nil + } + + if slug, err := c.GetDashboardSlug(); err != nil { + return "", err + } else { + ruleUrl := fmt.Sprintf("%sdashboard/db/%s?fullscreen&edit&tab=alert&panelId=%d", setting.AppUrl, slug, c.Rule.PanelId) + return ruleUrl, nil + } +} diff --git a/pkg/services/alerting/eval_context_test.go b/pkg/services/alerting/eval_context_test.go new file mode 100644 index 00000000000..5cff2996ca6 --- /dev/null +++ b/pkg/services/alerting/eval_context_test.go @@ -0,0 +1,48 @@ +package alerting + +import ( + "context" + "testing" + + "github.com/grafana/grafana/pkg/models" + . "github.com/smartystreets/goconvey/convey" +) + +func TestAlertingEvalContext(t *testing.T) { + Convey("Eval context", t, func() { + ctx := NewEvalContext(context.TODO(), &Rule{Conditions: []Condition{&conditionStub{firing: true}}}) + + Convey("Should update alert state", func() { + + Convey("ok -> alerting", func() { + ctx.PrevAlertState = models.AlertStateOK + ctx.Rule.State = models.AlertStateAlerting + + So(ctx.ShouldUpdateAlertState(), ShouldBeTrue) + }) + + Convey("ok -> ok", func() { + ctx.PrevAlertState = models.AlertStateOK + ctx.Rule.State = models.AlertStateOK + + So(ctx.ShouldUpdateAlertState(), ShouldBeFalse) + }) + }) + + Convey("Should send notifications", func() { + Convey("pending -> ok", func() { + ctx.PrevAlertState = models.AlertStatePending + ctx.Rule.State = models.AlertStateOK + + So(ctx.ShouldSendNotification(), ShouldBeFalse) + }) + + Convey("ok -> alerting", func() { + ctx.PrevAlertState = models.AlertStateOK + ctx.Rule.State = models.AlertStateAlerting + + So(ctx.ShouldSendNotification(), ShouldBeTrue) + }) + }) + }) +} diff --git a/pkg/services/alerting/eval_handler.go b/pkg/services/alerting/eval_handler.go new file mode 100644 index 00000000000..867226738b8 --- /dev/null +++ b/pkg/services/alerting/eval_handler.go @@ -0,0 +1,65 @@ +package alerting + +import ( + "strconv" + "strings" + "time" + + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/metrics" +) + +type DefaultEvalHandler struct { + log log.Logger + alertJobTimeout time.Duration +} + +func NewEvalHandler() *DefaultEvalHandler { + return &DefaultEvalHandler{ + log: log.New("alerting.evalHandler"), + alertJobTimeout: time.Second * 5, + } +} + +func (e *DefaultEvalHandler) Eval(context *EvalContext) { + firing := true + noDataFound := true + conditionEvals := "" + + for i := 0; i < len(context.Rule.Conditions); i++ { + condition := context.Rule.Conditions[i] + cr, err := condition.Eval(context) + if err != nil { + context.Error = err + } + + // break if condition could not be evaluated + if context.Error != nil { + break + } + + // calculating Firing based on operator + if cr.Operator == "or" { + firing = firing || cr.Firing + noDataFound = noDataFound || cr.NoDataFound + } else { + firing = firing && cr.Firing + noDataFound = noDataFound && cr.NoDataFound + } + + if i > 0 { + conditionEvals = "[" + conditionEvals + " " + strings.ToUpper(cr.Operator) + " " + strconv.FormatBool(cr.Firing) + "]" + } else { + conditionEvals = strconv.FormatBool(firing) + } + + context.EvalMatches = append(context.EvalMatches, cr.EvalMatches...) + } + + context.ConditionEvals = conditionEvals + " = " + strconv.FormatBool(firing) + context.Firing = firing + context.NoDataFound = noDataFound + context.EndTime = time.Now() + elapsedTime := context.EndTime.Sub(context.StartTime) / time.Millisecond + metrics.M_Alerting_Execution_Time.Update(elapsedTime) +} diff --git a/pkg/services/alerting/eval_handler_test.go b/pkg/services/alerting/eval_handler_test.go new file mode 100644 index 00000000000..73d675e3fa7 --- /dev/null +++ b/pkg/services/alerting/eval_handler_test.go @@ -0,0 +1,168 @@ +package alerting + +import ( + "context" + "testing" + + . "github.com/smartystreets/goconvey/convey" +) + +type conditionStub struct { + firing bool + operator string + matches []*EvalMatch + noData bool +} + +func (c *conditionStub) Eval(context *EvalContext) (*ConditionResult, error) { + return &ConditionResult{Firing: c.firing, EvalMatches: c.matches, Operator: c.operator, NoDataFound: c.noData}, nil +} + +func TestAlertingExecutor(t *testing.T) { + Convey("Test alert execution", t, func() { + handler := NewEvalHandler() + + Convey("Show return triggered with single passing condition", func() { + context := NewEvalContext(context.TODO(), &Rule{ + Conditions: []Condition{&conditionStub{ + firing: true, + }}, + }) + + handler.Eval(context) + So(context.Firing, ShouldEqual, true) + So(context.ConditionEvals, ShouldEqual, "true = true") + }) + + Convey("Show return false with not passing asdf", func() { + context := NewEvalContext(context.TODO(), &Rule{ + Conditions: []Condition{ + &conditionStub{firing: true, operator: "and", matches: []*EvalMatch{&EvalMatch{}, &EvalMatch{}}}, + &conditionStub{firing: false, operator: "and"}, + }, + }) + + handler.Eval(context) + So(context.Firing, ShouldEqual, false) + So(context.ConditionEvals, ShouldEqual, "[true AND false] = false") + }) + + Convey("Show return true if any of the condition is passing with OR operator", func() { + context := NewEvalContext(context.TODO(), &Rule{ + Conditions: []Condition{ + &conditionStub{firing: true, operator: "and"}, + &conditionStub{firing: false, operator: "or"}, + }, + }) + + handler.Eval(context) + So(context.Firing, ShouldEqual, true) + So(context.ConditionEvals, ShouldEqual, "[true OR false] = true") + }) + + Convey("Show return false if any of the condition is failing with AND operator", func() { + context := NewEvalContext(context.TODO(), &Rule{ + Conditions: []Condition{ + &conditionStub{firing: true, operator: "and"}, + &conditionStub{firing: false, operator: "and"}, + }, + }) + + handler.Eval(context) + So(context.Firing, ShouldEqual, false) + So(context.ConditionEvals, ShouldEqual, "[true AND false] = false") + }) + + Convey("Show return true if one condition is failing with nested OR operator", func() { + context := NewEvalContext(context.TODO(), &Rule{ + Conditions: []Condition{ + &conditionStub{firing: true, operator: "and"}, + &conditionStub{firing: true, operator: "and"}, + &conditionStub{firing: false, operator: "or"}, + }, + }) + + handler.Eval(context) + So(context.Firing, ShouldEqual, true) + So(context.ConditionEvals, ShouldEqual, "[[true AND true] OR false] = true") + }) + + Convey("Show return false if one condition is passing with nested OR operator", func() { + context := NewEvalContext(context.TODO(), &Rule{ + Conditions: []Condition{ + &conditionStub{firing: true, operator: "and"}, + &conditionStub{firing: false, operator: "and"}, + &conditionStub{firing: false, operator: "or"}, + }, + }) + + handler.Eval(context) + So(context.Firing, ShouldEqual, false) + So(context.ConditionEvals, ShouldEqual, "[[true AND false] OR false] = false") + }) + + Convey("Show return false if a condition is failing with nested AND operator", func() { + context := NewEvalContext(context.TODO(), &Rule{ + Conditions: []Condition{ + &conditionStub{firing: true, operator: "and"}, + &conditionStub{firing: false, operator: "and"}, + &conditionStub{firing: true, operator: "and"}, + }, + }) + + handler.Eval(context) + So(context.Firing, ShouldEqual, false) + So(context.ConditionEvals, ShouldEqual, "[[true AND false] AND true] = false") + }) + + Convey("Show return true if a condition is passing with nested OR operator", func() { + context := NewEvalContext(context.TODO(), &Rule{ + Conditions: []Condition{ + &conditionStub{firing: true, operator: "and"}, + &conditionStub{firing: false, operator: "or"}, + &conditionStub{firing: true, operator: "or"}, + }, + }) + + handler.Eval(context) + So(context.Firing, ShouldEqual, true) + So(context.ConditionEvals, ShouldEqual, "[[true OR false] OR true] = true") + }) + + Convey("Should return no data if one condition has nodata", func() { + context := NewEvalContext(context.TODO(), &Rule{ + Conditions: []Condition{ + &conditionStub{operator: "and", noData: true}, + }, + }) + + handler.Eval(context) + So(context.Firing, ShouldEqual, false) + So(context.NoDataFound, ShouldBeTrue) + }) + + Convey("Should return no data if both conditions have no data and using AND", func() { + context := NewEvalContext(context.TODO(), &Rule{ + Conditions: []Condition{ + &conditionStub{operator: "and", noData: true}, + &conditionStub{operator: "and", noData: false}, + }, + }) + + handler.Eval(context) + So(context.NoDataFound, ShouldBeFalse) + }) + + Convey("Should not return no data if both conditions have no data and using OR", func() { + context := NewEvalContext(context.TODO(), &Rule{ + Conditions: []Condition{ + &conditionStub{operator: "or", noData: true}, + &conditionStub{operator: "or", noData: false}, + }, + }) + + handler.Eval(context) + So(context.NoDataFound, ShouldBeTrue) + }) + }) +} diff --git a/pkg/services/alerting/extractor.go b/pkg/services/alerting/extractor.go new file mode 100644 index 00000000000..6e064c8cf76 --- /dev/null +++ b/pkg/services/alerting/extractor.go @@ -0,0 +1,147 @@ +package alerting + +import ( + "errors" + + "fmt" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/log" + m "github.com/grafana/grafana/pkg/models" +) + +type DashAlertExtractor struct { + Dash *m.Dashboard + OrgId int64 + log log.Logger +} + +func NewDashAlertExtractor(dash *m.Dashboard, orgId int64) *DashAlertExtractor { + return &DashAlertExtractor{ + Dash: dash, + OrgId: orgId, + log: log.New("alerting.extractor"), + } +} + +func (e *DashAlertExtractor) lookupDatasourceId(dsName string) (*m.DataSource, error) { + if dsName == "" { + query := &m.GetDataSourcesQuery{OrgId: e.OrgId} + if err := bus.Dispatch(query); err != nil { + return nil, err + } else { + for _, ds := range query.Result { + if ds.IsDefault { + return ds, nil + } + } + } + } else { + query := &m.GetDataSourceByNameQuery{Name: dsName, OrgId: e.OrgId} + if err := bus.Dispatch(query); err != nil { + return nil, err + } else { + return query.Result, nil + } + } + + return nil, errors.New("Could not find datasource id for " + dsName) +} + +func findPanelQueryByRefId(panel *simplejson.Json, refId string) *simplejson.Json { + for _, targetsObj := range panel.Get("targets").MustArray() { + target := simplejson.NewFromAny(targetsObj) + + if target.Get("refId").MustString() == refId { + return target + } + } + return nil +} + +func (e *DashAlertExtractor) GetAlerts() ([]*m.Alert, error) { + e.log.Debug("GetAlerts") + + alerts := make([]*m.Alert, 0) + + for _, rowObj := range e.Dash.Data.Get("rows").MustArray() { + row := simplejson.NewFromAny(rowObj) + + for _, panelObj := range row.Get("panels").MustArray() { + panel := simplejson.NewFromAny(panelObj) + jsonAlert, hasAlert := panel.CheckGet("alert") + + if !hasAlert { + continue + } + + // backward compatability check, can be removed later + enabled, hasEnabled := jsonAlert.CheckGet("enabled") + if hasEnabled && enabled.MustBool() == false { + continue + } + + frequency, err := getTimeDurationStringToSeconds(jsonAlert.Get("frequency").MustString()) + if err != nil { + return nil, ValidationError{Reason: "Could not parse frequency"} + } + + alert := &m.Alert{ + DashboardId: e.Dash.Id, + OrgId: e.OrgId, + PanelId: panel.Get("id").MustInt64(), + Id: jsonAlert.Get("id").MustInt64(), + Name: jsonAlert.Get("name").MustString(), + Handler: jsonAlert.Get("handler").MustInt64(), + Message: jsonAlert.Get("message").MustString(), + Frequency: frequency, + } + + for _, condition := range jsonAlert.Get("conditions").MustArray() { + jsonCondition := simplejson.NewFromAny(condition) + + jsonQuery := jsonCondition.Get("query") + queryRefId := jsonQuery.Get("params").MustArray()[0].(string) + panelQuery := findPanelQueryByRefId(panel, queryRefId) + + if panelQuery == nil { + reason := fmt.Sprintf("Alert on PanelId: %v refers to query(%s) that cannot be found", alert.PanelId, queryRefId) + return nil, ValidationError{Reason: reason} + } + + dsName := "" + if panelQuery.Get("datasource").MustString() != "" { + dsName = panelQuery.Get("datasource").MustString() + } else if panel.Get("datasource").MustString() != "" { + dsName = panel.Get("datasource").MustString() + } + + if datasource, err := e.lookupDatasourceId(dsName); err != nil { + return nil, err + } else { + jsonQuery.SetPath([]string{"datasourceId"}, datasource.Id) + } + + if interval, err := panel.Get("interval").String(); err == nil { + panelQuery.Set("interval", interval) + } + + jsonQuery.Set("model", panelQuery.Interface()) + } + + alert.Settings = jsonAlert + + // validate + _, err = NewRuleFromDBAlert(alert) + if err == nil && alert.ValidToSave() { + alerts = append(alerts, alert) + } else { + return nil, err + } + } + } + + e.log.Debug("Extracted alerts from dashboard", "alertCount", len(alerts)) + return alerts, nil +} diff --git a/pkg/services/alerting/extractor_test.go b/pkg/services/alerting/extractor_test.go new file mode 100644 index 00000000000..e72e6d938d8 --- /dev/null +++ b/pkg/services/alerting/extractor_test.go @@ -0,0 +1,487 @@ +package alerting + +import ( + "testing" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/components/simplejson" + m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/setting" + . "github.com/smartystreets/goconvey/convey" +) + +func TestAlertRuleExtraction(t *testing.T) { + + Convey("Parsing alert rules from dashboard json", t, func() { + + RegisterCondition("query", func(model *simplejson.Json, index int) (Condition, error) { + return &FakeCondition{}, nil + }) + + setting.NewConfigContext(&setting.CommandLineArgs{ + HomePath: "../../../", + }) + + // mock data + defaultDs := &m.DataSource{Id: 12, OrgId: 1, Name: "I am default", IsDefault: true} + graphite2Ds := &m.DataSource{Id: 15, OrgId: 1, Name: "graphite2"} + influxDBDs := &m.DataSource{Id: 16, OrgId: 1, Name: "InfluxDB"} + + bus.AddHandler("test", func(query *m.GetDataSourcesQuery) error { + query.Result = []*m.DataSource{defaultDs, graphite2Ds} + return nil + }) + + bus.AddHandler("test", func(query *m.GetDataSourceByNameQuery) error { + if query.Name == defaultDs.Name { + query.Result = defaultDs + } + if query.Name == graphite2Ds.Name { + query.Result = graphite2Ds + } + if query.Name == influxDBDs.Name { + query.Result = influxDBDs + } + return nil + }) + + json := ` + { + "id": 57, + "title": "Graphite 4", + "originalTitle": "Graphite 4", + "tags": ["graphite"], + "rows": [ + { + "panels": [ + { + "title": "Active desktop users", + "editable": true, + "type": "graph", + "id": 3, + "targets": [ + { + "refId": "A", + "target": "aliasByNode(statsd.fakesite.counters.session_start.desktop.count, 4)" + } + ], + "datasource": null, + "alert": { + "name": "name1", + "message": "desc1", + "handler": 1, + "frequency": "60s", + "conditions": [ + { + "type": "query", + "query": {"params": ["A", "5m", "now"]}, + "reducer": {"type": "avg", "params": []}, + "evaluator": {"type": ">", "params": [100]} + } + ] + } + }, + { + "title": "Active mobile users", + "id": 4, + "targets": [ + {"refId": "A", "target": ""}, + {"refId": "B", "target": "aliasByNode(statsd.fakesite.counters.session_start.mobile.count, 4)"} + ], + "datasource": "graphite2", + "alert": { + "name": "name2", + "message": "desc2", + "handler": 0, + "frequency": "60s", + "severity": "warning", + "conditions": [ + { + "type": "query", + "query": {"params": ["B", "5m", "now"]}, + "reducer": {"type": "avg", "params": []}, + "evaluator": {"type": ">", "params": [100]} + } + ] + } + } + ] + } + ] + }` + + Convey("Parsing and validating dashboard containing graphite alerts", func() { + + dashJson, err := simplejson.NewJson([]byte(json)) + So(err, ShouldBeNil) + + dash := m.NewDashboardFromJson(dashJson) + extractor := NewDashAlertExtractor(dash, 1) + + alerts, err := extractor.GetAlerts() + + Convey("Get rules without error", func() { + So(err, ShouldBeNil) + }) + + Convey("all properties have been set", func() { + So(len(alerts), ShouldEqual, 2) + + for _, v := range alerts { + So(v.DashboardId, ShouldEqual, 57) + So(v.Name, ShouldNotBeEmpty) + So(v.Message, ShouldNotBeEmpty) + + settings := simplejson.NewFromAny(v.Settings) + So(settings.Get("interval").MustString(""), ShouldEqual, "") + } + + Convey("should extract handler property", func() { + So(alerts[0].Handler, ShouldEqual, 1) + So(alerts[1].Handler, ShouldEqual, 0) + }) + + Convey("should extract frequency in seconds", func() { + So(alerts[0].Frequency, ShouldEqual, 60) + So(alerts[1].Frequency, ShouldEqual, 60) + }) + + Convey("should extract panel idc", func() { + So(alerts[0].PanelId, ShouldEqual, 3) + So(alerts[1].PanelId, ShouldEqual, 4) + }) + + Convey("should extract name and desc", func() { + So(alerts[0].Name, ShouldEqual, "name1") + So(alerts[0].Message, ShouldEqual, "desc1") + So(alerts[1].Name, ShouldEqual, "name2") + So(alerts[1].Message, ShouldEqual, "desc2") + }) + + Convey("should set datasourceId", func() { + condition := simplejson.NewFromAny(alerts[0].Settings.Get("conditions").MustArray()[0]) + query := condition.Get("query") + So(query.Get("datasourceId").MustInt64(), ShouldEqual, 12) + }) + + Convey("should copy query model to condition", func() { + condition := simplejson.NewFromAny(alerts[0].Settings.Get("conditions").MustArray()[0]) + model := condition.Get("query").Get("model") + So(model.Get("target").MustString(), ShouldEqual, "aliasByNode(statsd.fakesite.counters.session_start.desktop.count, 4)") + }) + }) + }) + + Convey("Parse and validate dashboard containing influxdb alert", func() { + + json2 := `{ + "id": 4, + "title": "Influxdb", + "tags": [ + "apa" + ], + "style": "dark", + "timezone": "browser", + "editable": true, + "hideControls": false, + "sharedCrosshair": false, + "rows": [ + { + "collapse": false, + "editable": true, + "height": "450px", + "panels": [ + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 10 + ], + "type": "gt" + }, + "query": { + "params": [ + "B", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "frequency": "3s", + "handler": 1, + "name": "Influxdb", + "noDataState": "no_data", + "notifications": [ + { + "id": 6 + } + ] + }, + "alerting": {}, + "aliasColors": { + "logins.count.count": "#890F02" + }, + "bars": false, + "datasource": "InfluxDB", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "id": 1, + "interval": ">10s", + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "datacenter" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "hide": false, + "measurement": "logins.count", + "policy": "default", + "query": "SELECT 8 * count(\"value\") FROM \"logins.count\" WHERE $timeFilter GROUP BY time($interval), \"datacenter\" fill(none)", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "count" + } + ] + ], + "tags": [] + }, + { + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "hide": true, + "measurement": "cpu", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ], + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "sum" + } + ] + ], + "tags": [] + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 10 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Panel Title", + "tooltip": { + "msResolution": false, + "ordering": "alphabetical", + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "editable": true, + "error": false, + "id": 2, + "isNew": true, + "limit": 10, + "links": [], + "show": "current", + "span": 2, + "stateFilter": [ + "alerting" + ], + "title": "Alert status", + "type": "alertlist" + } + ], + "title": "Row" + } + ], + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": { + "now": true, + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "templating": { + "list": [] + }, + "annotations": { + "list": [] + }, + "schemaVersion": 13, + "version": 120, + "links": [], + "gnetId": null + }` + + dashJson, err := simplejson.NewJson([]byte(json2)) + So(err, ShouldBeNil) + dash := m.NewDashboardFromJson(dashJson) + extractor := NewDashAlertExtractor(dash, 1) + + alerts, err := extractor.GetAlerts() + + Convey("Get rules without error", func() { + So(err, ShouldBeNil) + }) + + Convey("should be able to read interval", func() { + So(len(alerts), ShouldEqual, 1) + + for _, alert := range alerts { + So(alert.DashboardId, ShouldEqual, 4) + + conditions := alert.Settings.Get("conditions").MustArray() + cond := simplejson.NewFromAny(conditions[0]) + + So(cond.Get("query").Get("model").Get("interval").MustString(), ShouldEqual, ">10s") + } + }) + }) + }) +} diff --git a/pkg/services/alerting/interfaces.go b/pkg/services/alerting/interfaces.go new file mode 100644 index 00000000000..566fbdb2898 --- /dev/null +++ b/pkg/services/alerting/interfaces.go @@ -0,0 +1,33 @@ +package alerting + +import "time" + +type EvalHandler interface { + Eval(evalContext *EvalContext) +} + +type Scheduler interface { + Tick(time time.Time, execQueue chan *Job) + Update(rules []*Rule) +} + +type Notifier interface { + Notify(evalContext *EvalContext) error + GetType() string + NeedsImage() bool + PassesFilter(rule *Rule) bool + + GetNotifierId() int64 + GetIsDefault() bool +} + +type ConditionResult struct { + Firing bool + NoDataFound bool + Operator string + EvalMatches []*EvalMatch +} + +type Condition interface { + Eval(result *EvalContext) (*ConditionResult, error) +} diff --git a/pkg/services/alerting/models.go b/pkg/services/alerting/models.go new file mode 100644 index 00000000000..140c545fb2f --- /dev/null +++ b/pkg/services/alerting/models.go @@ -0,0 +1,25 @@ +package alerting + +type Job struct { + Offset int64 + OffsetWait bool + Delay bool + Running bool + Rule *Rule +} + +type ResultLogEntry struct { + Message string + Data interface{} +} + +type EvalMatch struct { + Value float64 `json:"value"` + Metric string `json:"metric"` + Tags map[string]string `json:"tags"` +} + +type Level struct { + Operator string + Value float64 +} diff --git a/pkg/services/alerting/notifier.go b/pkg/services/alerting/notifier.go new file mode 100644 index 00000000000..7e213058cd0 --- /dev/null +++ b/pkg/services/alerting/notifier.go @@ -0,0 +1,177 @@ +package alerting + +import ( + "errors" + "fmt" + + "golang.org/x/sync/errgroup" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/components/imguploader" + "github.com/grafana/grafana/pkg/components/renderer" + "github.com/grafana/grafana/pkg/log" + m "github.com/grafana/grafana/pkg/models" +) + +type NotifierPlugin struct { + Type string `json:"type"` + Name string `json:"name"` + Description string `json:"description"` + OptionsTemplate string `json:"optionsTemplate"` + Factory NotifierFactory `json:"-"` +} + +type RootNotifier struct { + log log.Logger +} + +func NewRootNotifier() *RootNotifier { + return &RootNotifier{ + log: log.New("alerting.notifier"), + } +} + +func (n *RootNotifier) GetType() string { + return "root" +} + +func (n *RootNotifier) NeedsImage() bool { + return false +} + +func (n *RootNotifier) PassesFilter(rule *Rule) bool { + return false +} + +func (n *RootNotifier) GetNotifierId() int64 { + return 0 +} + +func (n *RootNotifier) GetIsDefault() bool { + return false +} + +func (n *RootNotifier) Notify(context *EvalContext) error { + notifiers, err := n.getNotifiers(context.Rule.OrgId, context.Rule.Notifications, context) + if err != nil { + return err + } + + n.log.Info("Sending notifications for", "ruleId", context.Rule.Id, "sent count", len(notifiers)) + + if len(notifiers) == 0 { + return nil + } + + if err = n.uploadImage(context); err != nil { + n.log.Error("Failed to upload alert panel image.", "error", err) + } + + return n.sendNotifications(context, notifiers) +} + +func (n *RootNotifier) sendNotifications(context *EvalContext, notifiers []Notifier) error { + g, _ := errgroup.WithContext(context.Ctx) + + for _, notifier := range notifiers { + not := notifier //avoid updating scope variable in go routine + n.log.Info("Sending notification", "type", not.GetType(), "id", not.GetNotifierId(), "isDefault", not.GetIsDefault()) + g.Go(func() error { return not.Notify(context) }) + } + + return g.Wait() +} + +func (n *RootNotifier) uploadImage(context *EvalContext) (err error) { + uploader, err := imguploader.NewImageUploader() + if err != nil { + return err + } + + renderOpts := &renderer.RenderOpts{ + Width: "800", + Height: "400", + Timeout: "30", + OrgId: context.Rule.OrgId, + } + + if slug, err := context.GetDashboardSlug(); err != nil { + return err + } else { + renderOpts.Path = fmt.Sprintf("dashboard-solo/db/%s?&panelId=%d", slug, context.Rule.PanelId) + } + + if imagePath, err := renderer.RenderToPng(renderOpts); err != nil { + return err + } else { + context.ImageOnDiskPath = imagePath + } + + context.ImagePublicUrl, err = uploader.Upload(context.ImageOnDiskPath) + if err != nil { + return err + } + + n.log.Info("uploaded", "url", context.ImagePublicUrl) + return nil +} + +func (n *RootNotifier) getNotifiers(orgId int64, notificationIds []int64, context *EvalContext) ([]Notifier, error) { + query := &m.GetAlertNotificationsToSendQuery{OrgId: orgId, Ids: notificationIds} + + if err := bus.Dispatch(query); err != nil { + return nil, err + } + + var result []Notifier + for _, notification := range query.Result { + if not, err := n.createNotifierFor(notification); err != nil { + return nil, err + } else { + if shouldUseNotification(not, context) { + result = append(result, not) + } + } + } + + return result, nil +} + +func (n *RootNotifier) createNotifierFor(model *m.AlertNotification) (Notifier, error) { + notifierPlugin, found := notifierFactories[model.Type] + if !found { + return nil, errors.New("Unsupported notification type") + } + + return notifierPlugin.Factory(model) +} + +func shouldUseNotification(notifier Notifier, context *EvalContext) bool { + if !context.Firing { + return true + } + + if context.Error != nil { + return true + } + + return notifier.PassesFilter(context.Rule) +} + +type NotifierFactory func(notification *m.AlertNotification) (Notifier, error) + +var notifierFactories map[string]*NotifierPlugin = make(map[string]*NotifierPlugin) + +func RegisterNotifier(plugin *NotifierPlugin) { + notifierFactories[plugin.Type] = plugin +} + +func GetNotifiers() []*NotifierPlugin { + list := make([]*NotifierPlugin, 0) + + for _, value := range notifierFactories { + list = append(list, value) + } + + return list +} diff --git a/pkg/services/alerting/notifier_test.go b/pkg/services/alerting/notifier_test.go new file mode 100644 index 00000000000..5e378dec890 --- /dev/null +++ b/pkg/services/alerting/notifier_test.go @@ -0,0 +1,89 @@ +package alerting + +import ( + "testing" + + "fmt" + + "github.com/grafana/grafana/pkg/models" + m "github.com/grafana/grafana/pkg/models" + . "github.com/smartystreets/goconvey/convey" +) + +type FakeNotifier struct { + FakeMatchResult bool +} + +func (fn *FakeNotifier) GetType() string { + return "FakeNotifier" +} + +func (fn *FakeNotifier) NeedsImage() bool { + return true +} + +func (n *FakeNotifier) GetNotifierId() int64 { + return 0 +} + +func (n *FakeNotifier) GetIsDefault() bool { + return false +} + +func (fn *FakeNotifier) Notify(alertResult *EvalContext) error { return nil } + +func (fn *FakeNotifier) PassesFilter(rule *Rule) bool { + return fn.FakeMatchResult +} + +func TestAlertNotificationExtraction(t *testing.T) { + + Convey("Notifier tests", t, func() { + Convey("none firing alerts", func() { + ctx := &EvalContext{ + Firing: false, + Rule: &Rule{ + State: m.AlertStateAlerting, + }, + } + notifier := &FakeNotifier{FakeMatchResult: false} + + So(shouldUseNotification(notifier, ctx), ShouldBeTrue) + }) + + Convey("execution error cannot be ignored", func() { + ctx := &EvalContext{ + Firing: true, + Error: fmt.Errorf("I used to be a programmer just like you"), + Rule: &Rule{ + State: m.AlertStateOK, + }, + } + notifier := &FakeNotifier{FakeMatchResult: false} + + So(shouldUseNotification(notifier, ctx), ShouldBeTrue) + }) + + Convey("firing alert that match", func() { + ctx := &EvalContext{ + Firing: true, + Rule: &Rule{ + State: models.AlertStateAlerting, + }, + } + notifier := &FakeNotifier{FakeMatchResult: true} + + So(shouldUseNotification(notifier, ctx), ShouldBeTrue) + }) + + Convey("firing alert that dont match", func() { + ctx := &EvalContext{ + Firing: true, + Rule: &Rule{State: m.AlertStateOK}, + } + notifier := &FakeNotifier{FakeMatchResult: false} + + So(shouldUseNotification(notifier, ctx), ShouldBeFalse) + }) + }) +} diff --git a/pkg/services/alerting/notifiers/base.go b/pkg/services/alerting/notifiers/base.go new file mode 100644 index 00000000000..f1e748207d8 --- /dev/null +++ b/pkg/services/alerting/notifiers/base.go @@ -0,0 +1,42 @@ +package notifiers + +import ( + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/services/alerting" +) + +type NotifierBase struct { + Name string + Type string + Id int64 + IsDeault bool +} + +func NewNotifierBase(id int64, isDefault bool, name, notifierType string, model *simplejson.Json) NotifierBase { + return NotifierBase{ + Id: id, + Name: name, + IsDeault: isDefault, + Type: notifierType, + } +} + +func (n *NotifierBase) PassesFilter(rule *alerting.Rule) bool { + return true +} + +func (n *NotifierBase) GetType() string { + return n.Type +} + +func (n *NotifierBase) NeedsImage() bool { + return true +} + +func (n *NotifierBase) GetNotifierId() int64 { + return n.Id +} + +func (n *NotifierBase) GetIsDefault() bool { + return n.IsDeault +} diff --git a/pkg/services/alerting/notifiers/email.go b/pkg/services/alerting/notifiers/email.go new file mode 100644 index 00000000000..4058d3860b5 --- /dev/null +++ b/pkg/services/alerting/notifiers/email.go @@ -0,0 +1,111 @@ +package notifiers + +import ( + "os" + "strings" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/metrics" + m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/alerting" + "github.com/grafana/grafana/pkg/setting" +) + +func init() { + alerting.RegisterNotifier(&alerting.NotifierPlugin{ + Type: "email", + Name: "Email", + Description: "Sends notifications using Grafana server configured STMP settings", + Factory: NewEmailNotifier, + OptionsTemplate: ` +

    Email addresses

    +
    + +
    +
    + You can enter multiple email addresses using a ";" separator +
    + `, + }) +} + +type EmailNotifier struct { + NotifierBase + Addresses []string + log log.Logger +} + +func NewEmailNotifier(model *m.AlertNotification) (alerting.Notifier, error) { + addressesString := model.Settings.Get("addresses").MustString() + + if addressesString == "" { + return nil, alerting.ValidationError{Reason: "Could not find addresses in settings"} + } + + // split addresses with a few different ways + addresses := strings.FieldsFunc(addressesString, func(r rune) bool { + switch r { + case ',', ';', '\n': + return true + } + return false + }) + + return &EmailNotifier{ + NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings), + Addresses: addresses, + log: log.New("alerting.notifier.email"), + }, nil +} + +func (this *EmailNotifier) Notify(evalContext *alerting.EvalContext) error { + this.log.Info("Sending alert notification to", "addresses", this.Addresses) + metrics.M_Alerting_Notification_Sent_Email.Inc(1) + + ruleUrl, err := evalContext.GetRuleUrl() + if err != nil { + this.log.Error("Failed get rule link", "error", err) + return err + } + + cmd := &m.SendEmailCommandSync{ + SendEmailCommand: m.SendEmailCommand{ + Subject: evalContext.GetNotificationTitle(), + Data: map[string]interface{}{ + "Title": evalContext.GetNotificationTitle(), + "State": evalContext.Rule.State, + "Name": evalContext.Rule.Name, + "StateModel": evalContext.GetStateModel(), + "Message": evalContext.Rule.Message, + "RuleUrl": ruleUrl, + "ImageLink": "", + "EmbededImage": "", + "AlertPageUrl": setting.AppUrl + "alerting", + "EvalMatches": evalContext.EvalMatches, + }, + To: this.Addresses, + Template: "alert_notification.html", + EmbededFiles: []string{}, + }, + } + + if evalContext.ImagePublicUrl != "" { + cmd.Data["ImageLink"] = evalContext.ImagePublicUrl + } else { + file, err := os.Stat(evalContext.ImageOnDiskPath) + if err == nil { + cmd.EmbededFiles = []string{evalContext.ImageOnDiskPath} + cmd.Data["EmbededImage"] = file.Name() + } + } + + err = bus.DispatchCtx(evalContext.Ctx, cmd) + + if err != nil { + this.log.Error("Failed to send alert notification email", "error", err) + return err + } + return nil + +} diff --git a/pkg/services/alerting/notifiers/email_test.go b/pkg/services/alerting/notifiers/email_test.go new file mode 100644 index 00000000000..9750cbc2833 --- /dev/null +++ b/pkg/services/alerting/notifiers/email_test.go @@ -0,0 +1,79 @@ +package notifiers + +import ( + "testing" + + "github.com/grafana/grafana/pkg/components/simplejson" + m "github.com/grafana/grafana/pkg/models" + . "github.com/smartystreets/goconvey/convey" +) + +func TestEmailNotifier(t *testing.T) { + Convey("Email notifier tests", t, func() { + + Convey("Parsing alert notification from settings", func() { + Convey("empty settings should return error", func() { + json := `{ }` + + settingsJSON, _ := simplejson.NewJson([]byte(json)) + model := &m.AlertNotification{ + Name: "ops", + Type: "email", + Settings: settingsJSON, + } + + _, err := NewEmailNotifier(model) + So(err, ShouldNotBeNil) + }) + + Convey("from settings", func() { + json := ` + { + "addresses": "ops@grafana.org" + }` + + settingsJSON, _ := simplejson.NewJson([]byte(json)) + model := &m.AlertNotification{ + Name: "ops", + Type: "email", + Settings: settingsJSON, + } + + not, err := NewEmailNotifier(model) + emailNotifier := not.(*EmailNotifier) + + So(err, ShouldBeNil) + So(emailNotifier.Name, ShouldEqual, "ops") + So(emailNotifier.Type, ShouldEqual, "email") + So(emailNotifier.Addresses[0], ShouldEqual, "ops@grafana.org") + }) + + Convey("from settings with two emails", func() { + json := ` + { + "addresses": "ops@grafana.org;dev@grafana.org" + }` + + settingsJSON, err := simplejson.NewJson([]byte(json)) + So(err, ShouldBeNil) + + model := &m.AlertNotification{ + Name: "ops", + Type: "email", + Settings: settingsJSON, + } + + not, err := NewEmailNotifier(model) + emailNotifier := not.(*EmailNotifier) + + So(err, ShouldBeNil) + So(emailNotifier.Name, ShouldEqual, "ops") + So(emailNotifier.Type, ShouldEqual, "email") + So(len(emailNotifier.Addresses), ShouldEqual, 2) + + So(emailNotifier.Addresses[0], ShouldEqual, "ops@grafana.org") + So(emailNotifier.Addresses[1], ShouldEqual, "dev@grafana.org") + }) + }) + }) +} diff --git a/pkg/services/alerting/notifiers/opsgenie.go b/pkg/services/alerting/notifiers/opsgenie.go new file mode 100644 index 00000000000..742aeb922b6 --- /dev/null +++ b/pkg/services/alerting/notifiers/opsgenie.go @@ -0,0 +1,140 @@ +package notifiers + +import ( + "fmt" + "strconv" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/metrics" + m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/alerting" +) + +func init() { + alerting.RegisterNotifier(&alerting.NotifierPlugin{ + Type: "opsgenie", + Name: "OpsGenie", + Description: "Sends notifications to OpsGenie", + Factory: NewOpsGenieNotifier, + OptionsTemplate: ` +

    OpsGenie settings

    +
    + API Key + +
    +
    + + +
    + `, + }) +} + +var ( + opsgenieCreateAlertURL string = "https://api.opsgenie.com/v1/json/alert" + opsgenieCloseAlertURL string = "https://api.opsgenie.com/v1/json/alert/close" +) + +func NewOpsGenieNotifier(model *m.AlertNotification) (alerting.Notifier, error) { + autoClose := model.Settings.Get("autoClose").MustBool(true) + apiKey := model.Settings.Get("apiKey").MustString() + if apiKey == "" { + return nil, alerting.ValidationError{Reason: "Could not find api key property in settings"} + } + + return &OpsGenieNotifier{ + NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings), + ApiKey: apiKey, + AutoClose: autoClose, + log: log.New("alerting.notifier.opsgenie"), + }, nil +} + +type OpsGenieNotifier struct { + NotifierBase + ApiKey string + AutoClose bool + log log.Logger +} + +func (this *OpsGenieNotifier) Notify(evalContext *alerting.EvalContext) error { + metrics.M_Alerting_Notification_Sent_OpsGenie.Inc(1) + + var err error + switch evalContext.Rule.State { + case m.AlertStateOK: + if this.AutoClose { + err = this.closeAlert(evalContext) + } + case m.AlertStateAlerting: + err = this.createAlert(evalContext) + } + return err +} + +func (this *OpsGenieNotifier) createAlert(evalContext *alerting.EvalContext) error { + this.log.Info("Creating OpsGenie alert", "ruleId", evalContext.Rule.Id, "notification", this.Name) + + ruleUrl, err := evalContext.GetRuleUrl() + if err != nil { + this.log.Error("Failed get rule link", "error", err) + return err + } + + bodyJSON := simplejson.New() + bodyJSON.Set("apiKey", this.ApiKey) + bodyJSON.Set("message", evalContext.Rule.Name) + bodyJSON.Set("source", "Grafana") + bodyJSON.Set("alias", "alertId-"+strconv.FormatInt(evalContext.Rule.Id, 10)) + bodyJSON.Set("description", fmt.Sprintf("%s - %s\n%s", evalContext.Rule.Name, ruleUrl, evalContext.Rule.Message)) + + details := simplejson.New() + details.Set("url", ruleUrl) + if evalContext.ImagePublicUrl != "" { + details.Set("image", evalContext.ImagePublicUrl) + } + + bodyJSON.Set("details", details) + body, _ := bodyJSON.MarshalJSON() + + cmd := &m.SendWebhookSync{ + Url: opsgenieCreateAlertURL, + Body: string(body), + HttpMethod: "POST", + } + + if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil { + this.log.Error("Failed to send notification to OpsGenie", "error", err, "body", string(body)) + } + + return nil +} + +func (this *OpsGenieNotifier) closeAlert(evalContext *alerting.EvalContext) error { + this.log.Info("Closing OpsGenie alert", "ruleId", evalContext.Rule.Id, "notification", this.Name) + + bodyJSON := simplejson.New() + bodyJSON.Set("apiKey", this.ApiKey) + bodyJSON.Set("alias", "alertId-"+strconv.FormatInt(evalContext.Rule.Id, 10)) + body, _ := bodyJSON.MarshalJSON() + + cmd := &m.SendWebhookSync{ + Url: opsgenieCloseAlertURL, + Body: string(body), + HttpMethod: "POST", + } + + if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil { + this.log.Error("Failed to send notification to OpsGenie", "error", err, "body", string(body)) + return err + } + + return nil +} diff --git a/pkg/services/alerting/notifiers/opsgenie_test.go b/pkg/services/alerting/notifiers/opsgenie_test.go new file mode 100644 index 00000000000..9dcb9f3c600 --- /dev/null +++ b/pkg/services/alerting/notifiers/opsgenie_test.go @@ -0,0 +1,52 @@ +package notifiers + +import ( + "testing" + + "github.com/grafana/grafana/pkg/components/simplejson" + m "github.com/grafana/grafana/pkg/models" + . "github.com/smartystreets/goconvey/convey" +) + +func TestOpsGenieNotifier(t *testing.T) { + Convey("OpsGenie notifier tests", t, func() { + + Convey("Parsing alert notification from settings", func() { + Convey("empty settings should return error", func() { + json := `{ }` + + settingsJSON, _ := simplejson.NewJson([]byte(json)) + model := &m.AlertNotification{ + Name: "opsgenie_testing", + Type: "opsgenie", + Settings: settingsJSON, + } + + _, err := NewOpsGenieNotifier(model) + So(err, ShouldNotBeNil) + }) + + Convey("settings should trigger incident", func() { + json := ` + { + "apiKey": "abcdefgh0123456789" + }` + + settingsJSON, _ := simplejson.NewJson([]byte(json)) + model := &m.AlertNotification{ + Name: "opsgenie_testing", + Type: "opsgenie", + Settings: settingsJSON, + } + + not, err := NewOpsGenieNotifier(model) + opsgenieNotifier := not.(*OpsGenieNotifier) + + So(err, ShouldBeNil) + So(opsgenieNotifier.Name, ShouldEqual, "opsgenie_testing") + So(opsgenieNotifier.Type, ShouldEqual, "opsgenie") + So(opsgenieNotifier.ApiKey, ShouldEqual, "abcdefgh0123456789") + }) + }) + }) +} diff --git a/pkg/services/alerting/notifiers/pagerduty.go b/pkg/services/alerting/notifiers/pagerduty.go new file mode 100644 index 00000000000..0c98ab00e20 --- /dev/null +++ b/pkg/services/alerting/notifiers/pagerduty.go @@ -0,0 +1,117 @@ +package notifiers + +import ( + "strconv" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/metrics" + m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/alerting" +) + +func init() { + alerting.RegisterNotifier(&alerting.NotifierPlugin{ + Type: "pagerduty", + Name: "PagerDuty", + Description: "Sends notifications to PagerDuty", + Factory: NewPagerdutyNotifier, + OptionsTemplate: ` +

    PagerDuty settings

    +
    + Integration Key + +
    +
    + + +
    + `, + }) +} + +var ( + pagerdutyEventApiUrl string = "https://events.pagerduty.com/generic/2010-04-15/create_event.json" +) + +func NewPagerdutyNotifier(model *m.AlertNotification) (alerting.Notifier, error) { + autoResolve := model.Settings.Get("autoResolve").MustBool(true) + key := model.Settings.Get("integrationKey").MustString() + if key == "" { + return nil, alerting.ValidationError{Reason: "Could not find integration key property in settings"} + } + + return &PagerdutyNotifier{ + NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings), + Key: key, + AutoResolve: autoResolve, + log: log.New("alerting.notifier.pagerduty"), + }, nil +} + +type PagerdutyNotifier struct { + NotifierBase + Key string + AutoResolve bool + log log.Logger +} + +func (this *PagerdutyNotifier) Notify(evalContext *alerting.EvalContext) error { + metrics.M_Alerting_Notification_Sent_PagerDuty.Inc(1) + + if evalContext.Rule.State == m.AlertStateOK && !this.AutoResolve { + this.log.Info("Not sending a trigger to Pagerduty", "state", evalContext.Rule.State, "auto resolve", this.AutoResolve) + return nil + } + + eventType := "trigger" + if evalContext.Rule.State == m.AlertStateOK { + eventType = "resolve" + } + + this.log.Info("Notifying Pagerduty", "event_type", eventType) + + bodyJSON := simplejson.New() + bodyJSON.Set("service_key", this.Key) + bodyJSON.Set("description", evalContext.Rule.Name+" - "+evalContext.Rule.Message) + bodyJSON.Set("client", "Grafana") + bodyJSON.Set("event_type", eventType) + bodyJSON.Set("incident_key", "alertId-"+strconv.FormatInt(evalContext.Rule.Id, 10)) + + ruleUrl, err := evalContext.GetRuleUrl() + if err != nil { + this.log.Error("Failed get rule link", "error", err) + return err + } + bodyJSON.Set("client_url", ruleUrl) + + if evalContext.ImagePublicUrl != "" { + contexts := make([]interface{}, 1) + imageJSON := simplejson.New() + imageJSON.Set("type", "image") + imageJSON.Set("src", evalContext.ImagePublicUrl) + contexts[0] = imageJSON + bodyJSON.Set("contexts", contexts) + } + + body, _ := bodyJSON.MarshalJSON() + + cmd := &m.SendWebhookSync{ + Url: pagerdutyEventApiUrl, + Body: string(body), + HttpMethod: "POST", + } + + if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil { + this.log.Error("Failed to send notification to Pagerduty", "error", err, "body", string(body)) + return err + } + + return nil +} diff --git a/pkg/services/alerting/notifiers/pagerduty_test.go b/pkg/services/alerting/notifiers/pagerduty_test.go new file mode 100644 index 00000000000..522bb133d77 --- /dev/null +++ b/pkg/services/alerting/notifiers/pagerduty_test.go @@ -0,0 +1,53 @@ +package notifiers + +import ( + "testing" + + "github.com/grafana/grafana/pkg/components/simplejson" + m "github.com/grafana/grafana/pkg/models" + . "github.com/smartystreets/goconvey/convey" +) + +func TestPagerdutyNotifier(t *testing.T) { + Convey("Pagerduty notifier tests", t, func() { + + Convey("Parsing alert notification from settings", func() { + Convey("empty settings should return error", func() { + json := `{ }` + + settingsJSON, _ := simplejson.NewJson([]byte(json)) + model := &m.AlertNotification{ + Name: "pageduty_testing", + Type: "pagerduty", + Settings: settingsJSON, + } + + _, err := NewPagerdutyNotifier(model) + So(err, ShouldNotBeNil) + }) + + Convey("settings should trigger incident", func() { + json := ` + { + "integrationKey": "abcdefgh0123456789" + }` + + settingsJSON, _ := simplejson.NewJson([]byte(json)) + model := &m.AlertNotification{ + Name: "pagerduty_testing", + Type: "pagerduty", + Settings: settingsJSON, + } + + not, err := NewPagerdutyNotifier(model) + pagerdutyNotifier := not.(*PagerdutyNotifier) + + So(err, ShouldBeNil) + So(pagerdutyNotifier.Name, ShouldEqual, "pagerduty_testing") + So(pagerdutyNotifier.Type, ShouldEqual, "pagerduty") + So(pagerdutyNotifier.Key, ShouldEqual, "abcdefgh0123456789") + }) + + }) + }) +} diff --git a/pkg/services/alerting/notifiers/slack.go b/pkg/services/alerting/notifiers/slack.go new file mode 100644 index 00000000000..7b2bfd09c9a --- /dev/null +++ b/pkg/services/alerting/notifiers/slack.go @@ -0,0 +1,147 @@ +package notifiers + +import ( + "encoding/json" + "time" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/metrics" + m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/alerting" + "github.com/grafana/grafana/pkg/setting" +) + +func init() { + alerting.RegisterNotifier(&alerting.NotifierPlugin{ + Type: "slack", + Name: "Slack", + Description: "Sends notifications using Grafana server configured STMP settings", + Factory: NewSlackNotifier, + OptionsTemplate: ` +

    Slack settings

    +
    + Url + +
    +
    + Recipient + + + + Override default channel or user, use #channel-name or @username + +
    +
    + Mention + + + + Mention a user or a group using @ when notifying in a channel + +
    + `, + }) + +} + +func NewSlackNotifier(model *m.AlertNotification) (alerting.Notifier, error) { + url := model.Settings.Get("url").MustString() + if url == "" { + return nil, alerting.ValidationError{Reason: "Could not find url property in settings"} + } + + recipient := model.Settings.Get("recipient").MustString() + mention := model.Settings.Get("mention").MustString() + + return &SlackNotifier{ + NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings), + Url: url, + Recipient: recipient, + Mention: mention, + log: log.New("alerting.notifier.slack"), + }, nil +} + +type SlackNotifier struct { + NotifierBase + Url string + Recipient string + Mention string + log log.Logger +} + +func (this *SlackNotifier) Notify(evalContext *alerting.EvalContext) error { + this.log.Info("Executing slack notification", "ruleId", evalContext.Rule.Id, "notification", this.Name) + metrics.M_Alerting_Notification_Sent_Slack.Inc(1) + + ruleUrl, err := evalContext.GetRuleUrl() + if err != nil { + this.log.Error("Failed get rule link", "error", err) + return err + } + + fields := make([]map[string]interface{}, 0) + fieldLimitCount := 4 + for index, evt := range evalContext.EvalMatches { + fields = append(fields, map[string]interface{}{ + "title": evt.Metric, + "value": evt.Value, + "short": true, + }) + if index > fieldLimitCount { + break + } + } + + if evalContext.Error != nil { + fields = append(fields, map[string]interface{}{ + "title": "Error message", + "value": evalContext.Error.Error(), + "short": false, + }) + } + + message := this.Mention + if evalContext.Rule.State != m.AlertStateOK { //dont add message when going back to alert state ok. + message += " " + evalContext.Rule.Message + } + + body := map[string]interface{}{ + "attachments": []map[string]interface{}{ + { + "color": evalContext.GetStateModel().Color, + "title": evalContext.GetNotificationTitle(), + "title_link": ruleUrl, + "text": message, + "fields": fields, + "image_url": evalContext.ImagePublicUrl, + "footer": "Grafana v" + setting.BuildVersion, + "footer_icon": "http://grafana.org/assets/img/fav32.png", + "ts": time.Now().Unix(), + }, + }, + "parse": "full", // to linkify urls, users and channels in alert message. + } + + //recipient override + if this.Recipient != "" { + body["channel"] = this.Recipient + } + + data, _ := json.Marshal(&body) + cmd := &m.SendWebhookSync{Url: this.Url, Body: string(data)} + + if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil { + this.log.Error("Failed to send slack notification", "error", err, "webhook", this.Name) + return err + } + + return nil +} diff --git a/pkg/services/alerting/notifiers/slack_test.go b/pkg/services/alerting/notifiers/slack_test.go new file mode 100644 index 00000000000..5b1763064aa --- /dev/null +++ b/pkg/services/alerting/notifiers/slack_test.go @@ -0,0 +1,81 @@ +package notifiers + +import ( + "testing" + + "github.com/grafana/grafana/pkg/components/simplejson" + m "github.com/grafana/grafana/pkg/models" + . "github.com/smartystreets/goconvey/convey" +) + +func TestSlackNotifier(t *testing.T) { + Convey("Slack notifier tests", t, func() { + + Convey("Parsing alert notification from settings", func() { + Convey("empty settings should return error", func() { + json := `{ }` + + settingsJSON, _ := simplejson.NewJson([]byte(json)) + model := &m.AlertNotification{ + Name: "ops", + Type: "slack", + Settings: settingsJSON, + } + + _, err := NewSlackNotifier(model) + So(err, ShouldNotBeNil) + }) + + Convey("from settings", func() { + json := ` + { + "url": "http://google.com" + }` + + settingsJSON, _ := simplejson.NewJson([]byte(json)) + model := &m.AlertNotification{ + Name: "ops", + Type: "slack", + Settings: settingsJSON, + } + + not, err := NewSlackNotifier(model) + slackNotifier := not.(*SlackNotifier) + + So(err, ShouldBeNil) + So(slackNotifier.Name, ShouldEqual, "ops") + So(slackNotifier.Type, ShouldEqual, "slack") + So(slackNotifier.Url, ShouldEqual, "http://google.com") + So(slackNotifier.Recipient, ShouldEqual, "") + So(slackNotifier.Mention, ShouldEqual, "") + }) + + Convey("from settings with Recipient and Mention", func() { + json := ` + { + "url": "http://google.com", + "recipient": "#ds-opentsdb", + "mention": "@carl" + }` + + settingsJSON, _ := simplejson.NewJson([]byte(json)) + model := &m.AlertNotification{ + Name: "ops", + Type: "slack", + Settings: settingsJSON, + } + + not, err := NewSlackNotifier(model) + slackNotifier := not.(*SlackNotifier) + + So(err, ShouldBeNil) + So(slackNotifier.Name, ShouldEqual, "ops") + So(slackNotifier.Type, ShouldEqual, "slack") + So(slackNotifier.Url, ShouldEqual, "http://google.com") + So(slackNotifier.Recipient, ShouldEqual, "#ds-opentsdb") + So(slackNotifier.Mention, ShouldEqual, "@carl") + }) + + }) + }) +} diff --git a/pkg/services/alerting/notifiers/telegram.go b/pkg/services/alerting/notifiers/telegram.go new file mode 100644 index 00000000000..dd3011a49ec --- /dev/null +++ b/pkg/services/alerting/notifiers/telegram.go @@ -0,0 +1,113 @@ +package notifiers + +import ( + "fmt" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/metrics" + m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/alerting" +) + +var ( + telegeramApiUrl string = "https://api.telegram.org/bot%s/%s" +) + +func init() { + alerting.RegisterNotifier(&alerting.NotifierPlugin{ + Type: "telegram", + Name: "Telegram", + Description: "Sends notifications to Telegram", + Factory: NewOpsGenieNotifier, + OptionsTemplate: ` +

    Telegram API settings

    +
    + BOT API Token + +
    +
    + Chat ID + + + + Integer Telegram Chat Identifier + +
    + `, + }) + +} + +type TelegramNotifier struct { + NotifierBase + BotToken string + ChatID string + log log.Logger +} + +func NewTelegramNotifier(model *m.AlertNotification) (alerting.Notifier, error) { + if model.Settings == nil { + return nil, alerting.ValidationError{Reason: "No Settings Supplied"} + } + + botToken := model.Settings.Get("bottoken").MustString() + chatId := model.Settings.Get("chatid").MustString() + + if botToken == "" { + return nil, alerting.ValidationError{Reason: "Could not find Bot Token in settings"} + } + + if chatId == "" { + return nil, alerting.ValidationError{Reason: "Could not find Chat Id in settings"} + } + + return &TelegramNotifier{ + NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings), + BotToken: botToken, + ChatID: chatId, + log: log.New("alerting.notifier.telegram"), + }, nil +} + +func (this *TelegramNotifier) Notify(evalContext *alerting.EvalContext) error { + this.log.Info("Sending alert notification to", "bot_token", this.BotToken) + this.log.Info("Sending alert notification to", "chat_id", this.ChatID) + metrics.M_Alerting_Notification_Sent_Telegram.Inc(1) + + bodyJSON := simplejson.New() + + bodyJSON.Set("chat_id", this.ChatID) + bodyJSON.Set("parse_mode", "html") + + message := fmt.Sprintf("%s\nState: %s\nMessage: %s\n", evalContext.GetNotificationTitle(), evalContext.Rule.Name, evalContext.Rule.Message) + + ruleUrl, err := evalContext.GetRuleUrl() + if err == nil { + message = message + fmt.Sprintf("URL: %s\n", ruleUrl) + } + bodyJSON.Set("text", message) + + url := fmt.Sprintf(telegeramApiUrl, this.BotToken, "sendMessage") + body, _ := bodyJSON.MarshalJSON() + + cmd := &m.SendWebhookSync{ + Url: url, + Body: string(body), + HttpMethod: "POST", + } + + if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil { + this.log.Error("Failed to send webhook", "error", err, "webhook", this.Name) + return err + } + + return nil +} diff --git a/pkg/services/alerting/notifiers/telegram_test.go b/pkg/services/alerting/notifiers/telegram_test.go new file mode 100644 index 00000000000..3e8066e273b --- /dev/null +++ b/pkg/services/alerting/notifiers/telegram_test.go @@ -0,0 +1,55 @@ +package notifiers + +import ( + "testing" + + "github.com/grafana/grafana/pkg/components/simplejson" + m "github.com/grafana/grafana/pkg/models" + . "github.com/smartystreets/goconvey/convey" +) + +func TestTelegramNotifier(t *testing.T) { + Convey("Telegram notifier tests", t, func() { + + Convey("Parsing alert notification from settings", func() { + Convey("empty settings should return error", func() { + json := `{ }` + + settingsJSON, _ := simplejson.NewJson([]byte(json)) + model := &m.AlertNotification{ + Name: "telegram_testing", + Type: "telegram", + Settings: settingsJSON, + } + + _, err := NewTelegramNotifier(model) + So(err, ShouldNotBeNil) + }) + + Convey("settings should trigger incident", func() { + json := ` + { + "bottoken": "abcdefgh0123456789", + "chatid": "-1234567890" + }` + + settingsJSON, _ := simplejson.NewJson([]byte(json)) + model := &m.AlertNotification{ + Name: "telegram_testing", + Type: "telegram", + Settings: settingsJSON, + } + + not, err := NewTelegramNotifier(model) + telegramNotifier := not.(*TelegramNotifier) + + So(err, ShouldBeNil) + So(telegramNotifier.Name, ShouldEqual, "telegram_testing") + So(telegramNotifier.Type, ShouldEqual, "telegram") + So(telegramNotifier.BotToken, ShouldEqual, "abcdefgh0123456789") + So(telegramNotifier.ChatID, ShouldEqual, "-1234567890") + }) + + }) + }) +} diff --git a/pkg/services/alerting/notifiers/victorops.go b/pkg/services/alerting/notifiers/victorops.go new file mode 100644 index 00000000000..a4e34a40b8a --- /dev/null +++ b/pkg/services/alerting/notifiers/victorops.go @@ -0,0 +1,113 @@ +package notifiers + +import ( + "encoding/json" + "time" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/metrics" + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/alerting" + "github.com/grafana/grafana/pkg/setting" +) + +// AlertStateCritical - Victorops uses "CRITICAL" string to indicate "Alerting" state +const AlertStateCritical = "CRITICAL" + +func init() { + alerting.RegisterNotifier(&alerting.NotifierPlugin{ + Type: "victorops", + Name: "VictorOps", + Description: "Sends notifications to VictorOps", + Factory: NewVictoropsNotifier, + OptionsTemplate: ` +

    VictorOps settings

    +
    + Url + +
    + `, + }) +} + +// NewVictoropsNotifier creates an instance of VictoropsNotifier that +// handles posting notifications to Victorops REST API +func NewVictoropsNotifier(model *models.AlertNotification) (alerting.Notifier, error) { + url := model.Settings.Get("url").MustString() + if url == "" { + return nil, alerting.ValidationError{Reason: "Could not find victorops url property in settings"} + } + + return &VictoropsNotifier{ + NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings), + URL: url, + log: log.New("alerting.notifier.victorops"), + }, nil +} + +// VictoropsNotifier defines URL property for Victorops REST API +// and handles notification process by formatting POST body according to +// Victorops specifications (http://victorops.force.com/knowledgebase/articles/Integration/Alert-Ingestion-API-Documentation/) +type VictoropsNotifier struct { + NotifierBase + URL string + log log.Logger +} + +// Notify sends notification to Victorops via POST to URL endpoint +func (this *VictoropsNotifier) Notify(evalContext *alerting.EvalContext) error { + this.log.Info("Executing victorops notification", "ruleId", evalContext.Rule.Id, "notification", this.Name) + metrics.M_Alerting_Notification_Sent_Victorops.Inc(1) + + ruleUrl, err := evalContext.GetRuleUrl() + if err != nil { + this.log.Error("Failed get rule link", "error", err) + return err + } + + fields := make([]map[string]interface{}, 0) + fieldLimitCount := 4 + for index, evt := range evalContext.EvalMatches { + fields = append(fields, map[string]interface{}{ + "title": evt.Metric, + "value": evt.Value, + "short": true, + }) + if index > fieldLimitCount { + break + } + } + + if evalContext.Error != nil { + fields = append(fields, map[string]interface{}{ + "title": "Error message", + "value": evalContext.Error.Error(), + "short": false, + }) + } + + messageType := evalContext.Rule.State + if evalContext.Rule.State == models.AlertStateAlerting { // translate 'Alerting' to 'CRITICAL' (Victorops analog) + messageType = AlertStateCritical + } + + body := map[string]interface{}{ + "message_type": messageType, + "entity_id": evalContext.Rule.Name, + "timestamp": time.Now().Unix(), + "state_start_time": evalContext.StartTime.Unix(), + "state_message": evalContext.Rule.Message + "\n" + ruleUrl, + "monitoring_tool": "Grafana v" + setting.BuildVersion, + } + + data, _ := json.Marshal(&body) + cmd := &models.SendWebhookSync{Url: this.URL, Body: string(data)} + + if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil { + this.log.Error("Failed to send victorops notification", "error", err, "webhook", this.Name) + return err + } + + return nil +} diff --git a/pkg/services/alerting/notifiers/victorops_test.go b/pkg/services/alerting/notifiers/victorops_test.go new file mode 100644 index 00000000000..6ac806a82cc --- /dev/null +++ b/pkg/services/alerting/notifiers/victorops_test.go @@ -0,0 +1,52 @@ +package notifiers + +import ( + "testing" + + "github.com/grafana/grafana/pkg/components/simplejson" + m "github.com/grafana/grafana/pkg/models" + . "github.com/smartystreets/goconvey/convey" +) + +func TestVictoropsNotifier(t *testing.T) { + Convey("Victorops notifier tests", t, func() { + + Convey("Parsing alert notification from settings", func() { + Convey("empty settings should return error", func() { + json := `{ }` + + settingsJSON, _ := simplejson.NewJson([]byte(json)) + model := &m.AlertNotification{ + Name: "victorops_testing", + Type: "victorops", + Settings: settingsJSON, + } + + _, err := NewVictoropsNotifier(model) + So(err, ShouldNotBeNil) + }) + + Convey("from settings", func() { + json := ` + { + "url": "http://google.com" + }` + + settingsJSON, _ := simplejson.NewJson([]byte(json)) + model := &m.AlertNotification{ + Name: "victorops_testing", + Type: "victorops", + Settings: settingsJSON, + } + + not, err := NewVictoropsNotifier(model) + victoropsNotifier := not.(*VictoropsNotifier) + + So(err, ShouldBeNil) + So(victoropsNotifier.Name, ShouldEqual, "victorops_testing") + So(victoropsNotifier.Type, ShouldEqual, "victorops") + So(victoropsNotifier.URL, ShouldEqual, "http://google.com") + }) + }) + }) +} diff --git a/pkg/services/alerting/notifiers/webhook.go b/pkg/services/alerting/notifiers/webhook.go new file mode 100644 index 00000000000..25ed22a65f5 --- /dev/null +++ b/pkg/services/alerting/notifiers/webhook.go @@ -0,0 +1,109 @@ +package notifiers + +import ( + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/metrics" + m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/alerting" +) + +func init() { + alerting.RegisterNotifier(&alerting.NotifierPlugin{ + Type: "webhook", + Name: "webhook", + Description: "Sends HTTP POST request to a URL", + Factory: NewWebHookNotifier, + OptionsTemplate: ` +

    Webhook settings

    +
    + Url + +
    +
    + Http Method +
    + +
    +
    +
    + Username + +
    +
    + Password + +
    + `, + }) + +} + +func NewWebHookNotifier(model *m.AlertNotification) (alerting.Notifier, error) { + url := model.Settings.Get("url").MustString() + if url == "" { + return nil, alerting.ValidationError{Reason: "Could not find url property in settings"} + } + + return &WebhookNotifier{ + NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings), + Url: url, + User: model.Settings.Get("user").MustString(), + Password: model.Settings.Get("password").MustString(), + HttpMethod: model.Settings.Get("httpMethod").MustString("POST"), + log: log.New("alerting.notifier.webhook"), + }, nil +} + +type WebhookNotifier struct { + NotifierBase + Url string + User string + Password string + HttpMethod string + log log.Logger +} + +func (this *WebhookNotifier) Notify(evalContext *alerting.EvalContext) error { + this.log.Info("Sending webhook") + metrics.M_Alerting_Notification_Sent_Webhook.Inc(1) + + bodyJSON := simplejson.New() + bodyJSON.Set("title", evalContext.GetNotificationTitle()) + bodyJSON.Set("ruleId", evalContext.Rule.Id) + bodyJSON.Set("ruleName", evalContext.Rule.Name) + bodyJSON.Set("state", evalContext.Rule.State) + bodyJSON.Set("evalMatches", evalContext.EvalMatches) + + ruleUrl, err := evalContext.GetRuleUrl() + if err == nil { + bodyJSON.Set("ruleUrl", ruleUrl) + } + + if evalContext.ImagePublicUrl != "" { + bodyJSON.Set("imageUrl", evalContext.ImagePublicUrl) + } + + if evalContext.Rule.Message != "" { + bodyJSON.Set("message", evalContext.Rule.Message) + } + + body, _ := bodyJSON.MarshalJSON() + + cmd := &m.SendWebhookSync{ + Url: this.Url, + User: this.User, + Password: this.Password, + Body: string(body), + HttpMethod: this.HttpMethod, + } + + if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil { + this.log.Error("Failed to send webhook", "error", err, "webhook", this.Name) + return err + } + + return nil +} diff --git a/pkg/services/alerting/notifiers/webhook_test.go b/pkg/services/alerting/notifiers/webhook_test.go new file mode 100644 index 00000000000..eb25130e4e1 --- /dev/null +++ b/pkg/services/alerting/notifiers/webhook_test.go @@ -0,0 +1,52 @@ +package notifiers + +import ( + "testing" + + "github.com/grafana/grafana/pkg/components/simplejson" + m "github.com/grafana/grafana/pkg/models" + . "github.com/smartystreets/goconvey/convey" +) + +func TestWebhookNotifier(t *testing.T) { + Convey("Webhook notifier tests", t, func() { + + Convey("Parsing alert notification from settings", func() { + Convey("empty settings should return error", func() { + json := `{ }` + + settingsJSON, _ := simplejson.NewJson([]byte(json)) + model := &m.AlertNotification{ + Name: "ops", + Type: "email", + Settings: settingsJSON, + } + + _, err := NewWebHookNotifier(model) + So(err, ShouldNotBeNil) + }) + + Convey("from settings", func() { + json := ` + { + "url": "http://google.com" + }` + + settingsJSON, _ := simplejson.NewJson([]byte(json)) + model := &m.AlertNotification{ + Name: "ops", + Type: "email", + Settings: settingsJSON, + } + + not, err := NewWebHookNotifier(model) + webhookNotifier := not.(*WebhookNotifier) + + So(err, ShouldBeNil) + So(webhookNotifier.Name, ShouldEqual, "ops") + So(webhookNotifier.Type, ShouldEqual, "email") + So(webhookNotifier.Url, ShouldEqual, "http://google.com") + }) + }) + }) +} diff --git a/pkg/services/alerting/reader.go b/pkg/services/alerting/reader.go new file mode 100644 index 00000000000..1ecef79c434 --- /dev/null +++ b/pkg/services/alerting/reader.go @@ -0,0 +1,69 @@ +package alerting + +import ( + "sync" + "time" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/metrics" + m "github.com/grafana/grafana/pkg/models" +) + +type RuleReader interface { + Fetch() []*Rule +} + +type DefaultRuleReader struct { + sync.RWMutex + serverID string + serverPosition int + clusterSize int + log log.Logger +} + +func NewRuleReader() *DefaultRuleReader { + ruleReader := &DefaultRuleReader{ + log: log.New("alerting.ruleReader"), + } + + go ruleReader.initReader() + return ruleReader +} + +func (arr *DefaultRuleReader) initReader() { + heartbeat := time.NewTicker(time.Second * 10) + + for { + select { + case <-heartbeat.C: + arr.heartbeat() + } + } +} + +func (arr *DefaultRuleReader) Fetch() []*Rule { + cmd := &m.GetAllAlertsQuery{} + + if err := bus.Dispatch(cmd); err != nil { + arr.log.Error("Could not load alerts", "error", err) + return []*Rule{} + } + + res := make([]*Rule, 0) + for _, ruleDef := range cmd.Result { + if model, err := NewRuleFromDBAlert(ruleDef); err != nil { + arr.log.Error("Could not build alert model for rule", "ruleId", ruleDef.Id, "error", err) + } else { + res = append(res, model) + } + } + + metrics.M_Alerting_Active_Alerts.Update(int64(len(res))) + return res +} + +func (arr *DefaultRuleReader) heartbeat() { + arr.clusterSize = 1 + arr.serverPosition = 1 +} diff --git a/pkg/services/alerting/result_handler.go b/pkg/services/alerting/result_handler.go new file mode 100644 index 00000000000..aab109088cb --- /dev/null +++ b/pkg/services/alerting/result_handler.go @@ -0,0 +1,137 @@ +package alerting + +import ( + "time" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/metrics" + m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/annotations" +) + +type ResultHandler interface { + Handle(evalContext *EvalContext) error +} + +type DefaultResultHandler struct { + notifier Notifier + log log.Logger +} + +func NewResultHandler() *DefaultResultHandler { + return &DefaultResultHandler{ + log: log.New("alerting.resultHandler"), + notifier: NewRootNotifier(), + } +} + +func (handler *DefaultResultHandler) GetStateFromEvaluation(evalContext *EvalContext) m.AlertStateType { + if evalContext.Error != nil { + handler.log.Error("Alert Rule Result Error", + "ruleId", evalContext.Rule.Id, + "name", evalContext.Rule.Name, + "error", evalContext.Error, + "changing state to", evalContext.Rule.ExecutionErrorState.ToAlertState()) + + if evalContext.Rule.ExecutionErrorState == m.ExecutionErrorKeepState { + return evalContext.PrevAlertState + } else { + return evalContext.Rule.ExecutionErrorState.ToAlertState() + } + } else if evalContext.Firing { + return m.AlertStateAlerting + } else if evalContext.NoDataFound { + handler.log.Info("Alert Rule returned no data", + "ruleId", evalContext.Rule.Id, + "name", evalContext.Rule.Name, + "changing state to", evalContext.Rule.NoDataState.ToAlertState()) + + if evalContext.Rule.NoDataState == m.NoDataKeepState { + return evalContext.PrevAlertState + } else { + return evalContext.Rule.NoDataState.ToAlertState() + } + } + + return m.AlertStateOK +} + +func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error { + executionError := "" + annotationData := simplejson.New() + + evalContext.Rule.State = handler.GetStateFromEvaluation(evalContext) + + if evalContext.Error != nil { + executionError = evalContext.Error.Error() + annotationData.Set("errorMessage", executionError) + } + + if evalContext.Firing { + annotationData = simplejson.NewFromAny(evalContext.EvalMatches) + } + + countStateResult(evalContext.Rule.State) + if evalContext.ShouldUpdateAlertState() { + handler.log.Info("New state change", "alertId", evalContext.Rule.Id, "newState", evalContext.Rule.State, "prev state", evalContext.PrevAlertState) + + cmd := &m.SetAlertStateCommand{ + AlertId: evalContext.Rule.Id, + OrgId: evalContext.Rule.OrgId, + State: evalContext.Rule.State, + Error: executionError, + EvalData: annotationData, + } + + if err := bus.Dispatch(cmd); err != nil { + if err == m.ErrCannotChangeStateOnPausedAlert { + handler.log.Error("Cannot change state on alert thats pause", "error", err) + return err + } + handler.log.Error("Failed to save state", "error", err) + } + + // save annotation + item := annotations.Item{ + OrgId: evalContext.Rule.OrgId, + DashboardId: evalContext.Rule.DashboardId, + PanelId: evalContext.Rule.PanelId, + Type: annotations.AlertType, + AlertId: evalContext.Rule.Id, + Title: evalContext.Rule.Name, + Text: evalContext.GetStateModel().Text, + NewState: string(evalContext.Rule.State), + PrevState: string(evalContext.PrevAlertState), + Epoch: time.Now().Unix(), + Data: annotationData, + } + + annotationRepo := annotations.GetRepository() + if err := annotationRepo.Save(&item); err != nil { + handler.log.Error("Failed to save annotation for new alert state", "error", err) + } + + if evalContext.ShouldSendNotification() { + handler.notifier.Notify(evalContext) + } + } + + return nil +} + +func countStateResult(state m.AlertStateType) { + switch state { + case m.AlertStatePending: + metrics.M_Alerting_Result_State_Pending.Inc(1) + case m.AlertStateAlerting: + metrics.M_Alerting_Result_State_Alerting.Inc(1) + case m.AlertStateOK: + metrics.M_Alerting_Result_State_Ok.Inc(1) + case m.AlertStatePaused: + metrics.M_Alerting_Result_State_Paused.Inc(1) + case m.AlertStateNoData: + metrics.M_Alerting_Result_State_NoData.Inc(1) + } +} diff --git a/pkg/services/alerting/result_handler_test.go b/pkg/services/alerting/result_handler_test.go new file mode 100644 index 00000000000..321838d4f4c --- /dev/null +++ b/pkg/services/alerting/result_handler_test.go @@ -0,0 +1,90 @@ +package alerting + +import ( + "context" + "testing" + + "fmt" + + "github.com/grafana/grafana/pkg/models" + . "github.com/smartystreets/goconvey/convey" +) + +func TestAlertingResultHandler(t *testing.T) { + Convey("Result handler", t, func() { + ctx := NewEvalContext(context.TODO(), &Rule{Conditions: []Condition{&conditionStub{firing: true}}}) + dummieError := fmt.Errorf("dummie") + handler := NewResultHandler() + + Convey("Should update alert state", func() { + + Convey("ok -> alerting", func() { + ctx.PrevAlertState = models.AlertStateOK + ctx.Firing = true + + So(handler.GetStateFromEvaluation(ctx), ShouldEqual, models.AlertStateAlerting) + So(ctx.ShouldUpdateAlertState(), ShouldBeTrue) + }) + + Convey("ok -> error(alerting)", func() { + ctx.PrevAlertState = models.AlertStateOK + ctx.Error = dummieError + ctx.Rule.ExecutionErrorState = models.ExecutionErrorSetAlerting + + ctx.Rule.State = handler.GetStateFromEvaluation(ctx) + So(ctx.Rule.State, ShouldEqual, models.AlertStateAlerting) + So(ctx.ShouldUpdateAlertState(), ShouldBeTrue) + }) + + Convey("ok -> error(keep_last)", func() { + ctx.PrevAlertState = models.AlertStateOK + ctx.Error = dummieError + ctx.Rule.ExecutionErrorState = models.ExecutionErrorKeepState + + ctx.Rule.State = handler.GetStateFromEvaluation(ctx) + So(ctx.Rule.State, ShouldEqual, models.AlertStateOK) + So(ctx.ShouldUpdateAlertState(), ShouldBeFalse) + }) + + Convey("pending -> error(keep_last)", func() { + ctx.PrevAlertState = models.AlertStatePending + ctx.Error = dummieError + ctx.Rule.ExecutionErrorState = models.ExecutionErrorKeepState + + ctx.Rule.State = handler.GetStateFromEvaluation(ctx) + So(ctx.Rule.State, ShouldEqual, models.AlertStatePending) + So(ctx.ShouldUpdateAlertState(), ShouldBeFalse) + }) + + Convey("ok -> no_data(alerting)", func() { + ctx.PrevAlertState = models.AlertStateOK + ctx.Rule.NoDataState = models.NoDataSetAlerting + ctx.NoDataFound = true + + ctx.Rule.State = handler.GetStateFromEvaluation(ctx) + So(ctx.Rule.State, ShouldEqual, models.AlertStateAlerting) + So(ctx.ShouldUpdateAlertState(), ShouldBeTrue) + }) + + Convey("ok -> no_data(keep_last)", func() { + ctx.PrevAlertState = models.AlertStateOK + ctx.Rule.NoDataState = models.NoDataKeepState + ctx.NoDataFound = true + + ctx.Rule.State = handler.GetStateFromEvaluation(ctx) + So(ctx.Rule.State, ShouldEqual, models.AlertStateOK) + So(ctx.ShouldUpdateAlertState(), ShouldBeFalse) + }) + + Convey("pending -> no_data(keep_last)", func() { + ctx.PrevAlertState = models.AlertStatePending + ctx.Rule.NoDataState = models.NoDataKeepState + ctx.NoDataFound = true + + ctx.Rule.State = handler.GetStateFromEvaluation(ctx) + So(ctx.Rule.State, ShouldEqual, models.AlertStatePending) + So(ctx.ShouldUpdateAlertState(), ShouldBeFalse) + }) + }) + }) +} diff --git a/pkg/services/alerting/rule.go b/pkg/services/alerting/rule.go new file mode 100644 index 00000000000..bdf53798e34 --- /dev/null +++ b/pkg/services/alerting/rule.go @@ -0,0 +1,140 @@ +package alerting + +import ( + "fmt" + "regexp" + "strconv" + + "github.com/grafana/grafana/pkg/components/simplejson" + + m "github.com/grafana/grafana/pkg/models" +) + +type Rule struct { + Id int64 + OrgId int64 + DashboardId int64 + PanelId int64 + Frequency int64 + Name string + Message string + NoDataState m.NoDataOption + ExecutionErrorState m.ExecutionErrorOption + State m.AlertStateType + Conditions []Condition + Notifications []int64 +} + +type ValidationError struct { + Reason string + Err error + Alertid int64 + DashboardId int64 + PanelId int64 +} + +func (e ValidationError) Error() string { + extraInfo := "" + if e.Alertid != 0 { + extraInfo = fmt.Sprintf("%s AlertId: %v", extraInfo, e.Alertid) + } + + if e.PanelId != 0 { + extraInfo = fmt.Sprintf("%s PanelId: %v ", extraInfo, e.PanelId) + } + + if e.DashboardId != 0 { + extraInfo = fmt.Sprintf("%s DashboardId: %v", extraInfo, e.DashboardId) + } + + if e.Err != nil { + return fmt.Sprintf("%s %s%s", e.Err.Error(), e.Reason, extraInfo) + } + + return fmt.Sprintf("Failed to extract alert.Reason: %s %s", e.Reason, extraInfo) +} + +var ( + ValueFormatRegex = regexp.MustCompile("^\\d+") + UnitFormatRegex = regexp.MustCompile("\\w{1}$") +) + +var unitMultiplier = map[string]int{ + "s": 1, + "m": 60, + "h": 3600, +} + +func getTimeDurationStringToSeconds(str string) (int64, error) { + multiplier := 1 + + matches := ValueFormatRegex.FindAllString(str, 1) + + if len(matches) <= 0 { + return 0, fmt.Errorf("Frequency could not be parsed") + } + + value, err := strconv.Atoi(matches[0]) + if err != nil { + return 0, err + } + + unit := UnitFormatRegex.FindAllString(str, 1)[0] + + if val, ok := unitMultiplier[unit]; ok { + multiplier = val + } + + return int64(value * multiplier), nil +} + +func NewRuleFromDBAlert(ruleDef *m.Alert) (*Rule, error) { + model := &Rule{} + model.Id = ruleDef.Id + model.OrgId = ruleDef.OrgId + model.DashboardId = ruleDef.DashboardId + model.PanelId = ruleDef.PanelId + model.Name = ruleDef.Name + model.Message = ruleDef.Message + model.Frequency = ruleDef.Frequency + model.State = ruleDef.State + model.NoDataState = m.NoDataOption(ruleDef.Settings.Get("noDataState").MustString("no_data")) + model.ExecutionErrorState = m.ExecutionErrorOption(ruleDef.Settings.Get("executionErrorState").MustString("alerting")) + + for _, v := range ruleDef.Settings.Get("notifications").MustArray() { + jsonModel := simplejson.NewFromAny(v) + if id, err := jsonModel.Get("id").Int64(); err != nil { + return nil, ValidationError{Reason: "Invalid notification schema", DashboardId: model.DashboardId, Alertid: model.Id, PanelId: model.PanelId} + } else { + model.Notifications = append(model.Notifications, id) + } + } + + for index, condition := range ruleDef.Settings.Get("conditions").MustArray() { + conditionModel := simplejson.NewFromAny(condition) + conditionType := conditionModel.Get("type").MustString() + if factory, exist := conditionFactories[conditionType]; !exist { + return nil, ValidationError{Reason: "Unknown alert condition: " + conditionType, DashboardId: model.DashboardId, Alertid: model.Id, PanelId: model.PanelId} + } else { + if queryCondition, err := factory(conditionModel, index); err != nil { + return nil, ValidationError{Err: err, DashboardId: model.DashboardId, Alertid: model.Id, PanelId: model.PanelId} + } else { + model.Conditions = append(model.Conditions, queryCondition) + } + } + } + + if len(model.Conditions) == 0 { + return nil, fmt.Errorf("Alert is missing conditions") + } + + return model, nil +} + +type ConditionFactory func(model *simplejson.Json, index int) (Condition, error) + +var conditionFactories map[string]ConditionFactory = make(map[string]ConditionFactory) + +func RegisterCondition(typeName string, factory ConditionFactory) { + conditionFactories[typeName] = factory +} diff --git a/pkg/services/alerting/rule_test.go b/pkg/services/alerting/rule_test.go new file mode 100644 index 00000000000..2a9e95e5723 --- /dev/null +++ b/pkg/services/alerting/rule_test.go @@ -0,0 +1,93 @@ +package alerting + +import ( + "testing" + + "github.com/grafana/grafana/pkg/components/simplejson" + m "github.com/grafana/grafana/pkg/models" + . "github.com/smartystreets/goconvey/convey" +) + +type FakeCondition struct{} + +func (f *FakeCondition) Eval(context *EvalContext) (*ConditionResult, error) { + return &ConditionResult{}, nil +} + +func TestAlertRuleModel(t *testing.T) { + Convey("Testing alert rule", t, func() { + + RegisterCondition("test", func(model *simplejson.Json, index int) (Condition, error) { + return &FakeCondition{}, nil + }) + + Convey("Can parse seconds", func() { + seconds, _ := getTimeDurationStringToSeconds("10s") + So(seconds, ShouldEqual, 10) + }) + + Convey("Can parse minutes", func() { + seconds, _ := getTimeDurationStringToSeconds("10m") + So(seconds, ShouldEqual, 600) + }) + + Convey("Can parse hours", func() { + seconds, _ := getTimeDurationStringToSeconds("1h") + So(seconds, ShouldEqual, 3600) + }) + + Convey("defaults to seconds", func() { + seconds, _ := getTimeDurationStringToSeconds("1o") + So(seconds, ShouldEqual, 1) + }) + + Convey("should return err for empty string", func() { + _, err := getTimeDurationStringToSeconds("") + So(err, ShouldNotBeNil) + }) + + Convey("can construct alert rule model", func() { + json := ` + { + "name": "name2", + "description": "desc2", + "handler": 0, + "noDataMode": "critical", + "enabled": true, + "frequency": "60s", + "conditions": [ + { + "type": "test", + "prop": 123 + } + ], + "notifications": [ + {"id": 1134}, + {"id": 22} + ] + } + ` + + alertJSON, jsonErr := simplejson.NewJson([]byte(json)) + So(jsonErr, ShouldBeNil) + + alert := &m.Alert{ + Id: 1, + OrgId: 1, + DashboardId: 1, + PanelId: 1, + + Settings: alertJSON, + } + + alertRule, err := NewRuleFromDBAlert(alert) + So(err, ShouldBeNil) + + So(len(alertRule.Conditions), ShouldEqual, 1) + + Convey("Can read notifications", func() { + So(len(alertRule.Notifications), ShouldEqual, 2) + }) + }) + }) +} diff --git a/pkg/services/alerting/scheduler.go b/pkg/services/alerting/scheduler.go new file mode 100644 index 00000000000..151f802ec15 --- /dev/null +++ b/pkg/services/alerting/scheduler.go @@ -0,0 +1,78 @@ +package alerting + +import ( + "math" + "time" + + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/models" +) + +type SchedulerImpl struct { + jobs map[int64]*Job + log log.Logger +} + +func NewScheduler() Scheduler { + return &SchedulerImpl{ + jobs: make(map[int64]*Job, 0), + log: log.New("alerting.scheduler"), + } +} + +func (s *SchedulerImpl) Update(rules []*Rule) { + s.log.Debug("Scheduling update", "ruleCount", len(rules)) + + jobs := make(map[int64]*Job, 0) + + for i, rule := range rules { + var job *Job + if s.jobs[rule.Id] != nil { + job = s.jobs[rule.Id] + } else { + job = &Job{ + Running: false, + } + } + + job.Rule = rule + + offset := ((rule.Frequency * 1000) / int64(len(rules))) * int64(i) + job.Offset = int64(math.Floor(float64(offset) / 1000)) + if job.Offset == 0 { //zero offset causes division with 0 panics. + job.Offset = 1 + } + jobs[rule.Id] = job + } + + s.jobs = jobs +} + +func (s *SchedulerImpl) Tick(tickTime time.Time, execQueue chan *Job) { + now := tickTime.Unix() + + for _, job := range s.jobs { + if job.Running || job.Rule.State == models.AlertStatePaused { + continue + } + + if job.OffsetWait && now%job.Offset == 0 { + job.OffsetWait = false + s.enque(job, execQueue) + continue + } + + if now%job.Rule.Frequency == 0 { + if job.Offset > 0 { + job.OffsetWait = true + } else { + s.enque(job, execQueue) + } + } + } +} + +func (s *SchedulerImpl) enque(job *Job, execQueue chan *Job) { + s.log.Debug("Scheduler: Putting job on to exec queue", "name", job.Rule.Name, "id", job.Rule.Id) + execQueue <- job +} diff --git a/pkg/services/alerting/test_notification.go b/pkg/services/alerting/test_notification.go new file mode 100644 index 00000000000..fd908d6f95d --- /dev/null +++ b/pkg/services/alerting/test_notification.go @@ -0,0 +1,75 @@ +package alerting + +import ( + "context" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/log" + m "github.com/grafana/grafana/pkg/models" +) + +type NotificationTestCommand struct { + State m.AlertStateType + Name string + Type string + Settings *simplejson.Json +} + +func init() { + bus.AddHandler("alerting", handleNotificationTestCommand) + +} + +func handleNotificationTestCommand(cmd *NotificationTestCommand) error { + notifier := NewRootNotifier() + + model := &m.AlertNotification{ + Name: cmd.Name, + Type: cmd.Type, + Settings: cmd.Settings, + } + + notifiers, err := notifier.createNotifierFor(model) + + if err != nil { + log.Error2("Failed to create notifier", "error", err.Error()) + return err + } + + return notifier.sendNotifications(createTestEvalContext(), []Notifier{notifiers}) +} + +func createTestEvalContext() *EvalContext { + testRule := &Rule{ + DashboardId: 1, + PanelId: 1, + Name: "Test notification", + Message: "Someone is testing the alert notification within grafana.", + State: m.AlertStateAlerting, + } + + ctx := NewEvalContext(context.TODO(), testRule) + ctx.ImagePublicUrl = "http://grafana.org/assets/img/blog/mixed_styles.png" + ctx.IsTestRun = true + ctx.Firing = true + ctx.Error = nil + ctx.EvalMatches = evalMatchesBasedOnState() + + return ctx +} + +func evalMatchesBasedOnState() []*EvalMatch { + matches := make([]*EvalMatch, 0) + matches = append(matches, &EvalMatch{ + Metric: "High value", + Value: 100, + }) + + matches = append(matches, &EvalMatch{ + Metric: "Higher Value", + Value: 200, + }) + + return matches +} diff --git a/pkg/services/alerting/test_rule.go b/pkg/services/alerting/test_rule.go new file mode 100644 index 00000000000..82b1a6276a1 --- /dev/null +++ b/pkg/services/alerting/test_rule.go @@ -0,0 +1,58 @@ +package alerting + +import ( + "context" + "fmt" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/components/simplejson" + m "github.com/grafana/grafana/pkg/models" +) + +type AlertTestCommand struct { + Dashboard *simplejson.Json + PanelId int64 + OrgId int64 + + Result *EvalContext +} + +func init() { + bus.AddHandler("alerting", handleAlertTestCommand) +} + +func handleAlertTestCommand(cmd *AlertTestCommand) error { + + dash := m.NewDashboardFromJson(cmd.Dashboard) + + extractor := NewDashAlertExtractor(dash, cmd.OrgId) + alerts, err := extractor.GetAlerts() + if err != nil { + return err + } + + for _, alert := range alerts { + if alert.PanelId == cmd.PanelId { + rule, err := NewRuleFromDBAlert(alert) + if err != nil { + return err + } + + cmd.Result = testAlertRule(rule) + return nil + } + } + + return fmt.Errorf("Could not find alert with panel id %d", cmd.PanelId) +} + +func testAlertRule(rule *Rule) *EvalContext { + handler := NewEvalHandler() + + context := NewEvalContext(context.TODO(), rule) + context.IsTestRun = true + + handler.Eval(context) + + return context +} diff --git a/pkg/services/alerting/ticker.go b/pkg/services/alerting/ticker.go new file mode 100644 index 00000000000..5ce19b1b232 --- /dev/null +++ b/pkg/services/alerting/ticker.go @@ -0,0 +1,60 @@ +package alerting + +import ( + "time" + + "github.com/benbjohnson/clock" +) + +// ticker is a ticker to power the alerting scheduler. it's like a time.Ticker, except: +// * it doesn't drop ticks for slow receivers, rather, it queues up. so that callers are in control to instrument what's going on. +// * it automatically ticks every second, which is the right thing in our current design +// * it ticks on second marks or very shortly after. this provides a predictable load pattern +// (this shouldn't cause too much load contention issues because the next steps in the pipeline just process at their own pace) +// * the timestamps are used to mark "last datapoint to query for" and as such, are a configurable amount of seconds in the past +// * because we want to allow: +// - a clean "resume where we left off" and "don't yield ticks we already did" +// - adjusting offset over time to compensate for storage backing up or getting fast and providing lower latency +// you specify a lastProcessed timestamp as well as an offset at creation, or runtime +type Ticker struct { + C chan time.Time + clock clock.Clock + last time.Time + offset time.Duration + newOffset chan time.Duration +} + +// NewTicker returns a ticker that ticks on second marks or very shortly after, and never drops ticks +func NewTicker(last time.Time, initialOffset time.Duration, c clock.Clock) *Ticker { + t := &Ticker{ + C: make(chan time.Time), + clock: c, + last: last, + offset: initialOffset, + newOffset: make(chan time.Duration), + } + go t.run() + return t +} + +func (t *Ticker) updateOffset(offset time.Duration) { + t.newOffset <- offset +} + +func (t *Ticker) run() { + for { + next := t.last.Add(time.Duration(1) * time.Second) + diff := t.clock.Now().Add(-t.offset).Sub(next) + if diff >= 0 { + t.C <- next + t.last = next + continue + } + // tick is too young. try again when ... + select { + case <-t.clock.After(-diff): // ...it'll definitely be old enough + case offset := <-t.newOffset: // ...it might be old enough + t.offset = offset + } + } +} diff --git a/pkg/services/alerting/ticker_test.go b/pkg/services/alerting/ticker_test.go new file mode 100644 index 00000000000..d4a5b958cdb --- /dev/null +++ b/pkg/services/alerting/ticker_test.go @@ -0,0 +1,121 @@ +package alerting + +import ( + "testing" + "time" + + "github.com/benbjohnson/clock" +) + +func inspectTick(tick time.Time, last time.Time, offset time.Duration, t *testing.T) { + if !tick.Equal(last.Add(time.Duration(1) * time.Second)) { + t.Fatalf("expected a tick 1 second more than prev, %s. got: %s", last, tick) + } +} + +// returns the new last tick seen +func assertAdvanceUntil(ticker *Ticker, last, desiredLast time.Time, offset, wait time.Duration, t *testing.T) time.Time { + for { + select { + case tick := <-ticker.C: + inspectTick(tick, last, offset, t) + last = tick + case <-time.NewTimer(wait).C: + if last.Before(desiredLast) { + t.Fatalf("waited %s for ticker to advance to %s, but only went up to %s", wait, desiredLast, last) + } + if last.After(desiredLast) { + t.Fatalf("timer advanced too far. should only have gone up to %s, but it went up to %s", desiredLast, last) + } + return last + } + } +} + +func assertNoAdvance(ticker *Ticker, desiredLast time.Time, wait time.Duration, t *testing.T) { + for { + select { + case tick := <-ticker.C: + t.Fatalf("timer should have stayed at %s, instead it advanced to %s", desiredLast, tick) + case <-time.NewTimer(wait).C: + return + } + } +} + +func TestTickerRetro1Hour(t *testing.T) { + offset := time.Duration(10) * time.Second + last := time.Unix(0, 0) + mock := clock.NewMock() + mock.Add(time.Duration(1) * time.Hour) + desiredLast := mock.Now().Add(-offset) + ticker := NewTicker(last, offset, mock) + + last = assertAdvanceUntil(ticker, last, desiredLast, offset, time.Duration(10)*time.Millisecond, t) + assertNoAdvance(ticker, last, time.Duration(500)*time.Millisecond, t) + +} + +func TestAdvanceWithUpdateOffset(t *testing.T) { + offset := time.Duration(10) * time.Second + last := time.Unix(0, 0) + mock := clock.NewMock() + mock.Add(time.Duration(1) * time.Hour) + desiredLast := mock.Now().Add(-offset) + ticker := NewTicker(last, offset, mock) + + last = assertAdvanceUntil(ticker, last, desiredLast, offset, time.Duration(10)*time.Millisecond, t) + assertNoAdvance(ticker, last, time.Duration(500)*time.Millisecond, t) + + // lowering offset should see a few more ticks + offset = time.Duration(5) * time.Second + ticker.updateOffset(offset) + desiredLast = mock.Now().Add(-offset) + last = assertAdvanceUntil(ticker, last, desiredLast, offset, time.Duration(9)*time.Millisecond, t) + assertNoAdvance(ticker, last, time.Duration(500)*time.Millisecond, t) + + // advancing clock should see even more ticks + mock.Add(time.Duration(1) * time.Hour) + desiredLast = mock.Now().Add(-offset) + last = assertAdvanceUntil(ticker, last, desiredLast, offset, time.Duration(8)*time.Millisecond, t) + assertNoAdvance(ticker, last, time.Duration(500)*time.Millisecond, t) + +} + +func getCase(lastSeconds, offsetSeconds int) (time.Time, time.Duration) { + last := time.Unix(int64(lastSeconds), 0) + offset := time.Duration(offsetSeconds) * time.Second + return last, offset +} + +func TestTickerNoAdvance(t *testing.T) { + + // it's 00:01:00 now. what are some cases where we don't want the ticker to advance? + mock := clock.NewMock() + mock.Add(time.Duration(60) * time.Second) + + type Case struct { + last int + offset int + } + + // note that some cases add up to now, others go into the future + cases := []Case{ + {50, 10}, + {50, 30}, + {59, 1}, + {59, 10}, + {59, 30}, + {60, 1}, + {60, 10}, + {60, 30}, + {90, 1}, + {90, 10}, + {90, 30}, + } + for _, c := range cases { + last, offset := getCase(c.last, c.offset) + ticker := NewTicker(last, offset, mock) + assertNoAdvance(ticker, last, time.Duration(500)*time.Millisecond, t) + } +} diff --git a/pkg/services/annotations/annotations.go b/pkg/services/annotations/annotations.go new file mode 100644 index 00000000000..3fc3bafe5c5 --- /dev/null +++ b/pkg/services/annotations/annotations.go @@ -0,0 +1,63 @@ +package annotations + +import "github.com/grafana/grafana/pkg/components/simplejson" + +type Repository interface { + Save(item *Item) error + Find(query *ItemQuery) ([]*Item, error) + Delete(params *DeleteParams) error +} + +type ItemQuery struct { + OrgId int64 `json:"orgId"` + From int64 `json:"from"` + To int64 `json:"from"` + Type ItemType `json:"type"` + AlertId int64 `json:"alertId"` + DashboardId int64 `json:"dashboardId"` + PanelId int64 `json:"panelId"` + NewState []string `json:"newState"` + + Limit int64 `json:"alertId"` +} + +type DeleteParams struct { + AlertId int64 `json:"alertId"` + DashboardId int64 `json:"dashboardId"` + PanelId int64 `json:"panelId"` +} + +var repositoryInstance Repository + +func GetRepository() Repository { + return repositoryInstance +} + +func SetRepository(rep Repository) { + repositoryInstance = rep +} + +type ItemType string + +const ( + AlertType ItemType = "alert" +) + +type Item struct { + Id int64 `json:"id"` + OrgId int64 `json:"orgId"` + DashboardId int64 `json:"dashboardId"` + PanelId int64 `json:"panelId"` + CategoryId int64 `json:"panelId"` + Type ItemType `json:"type"` + Title string `json:"title"` + Text string `json:"text"` + Metric string `json:"metric"` + AlertId int64 `json:"alertId"` + UserId int64 `json:"userId"` + PrevState string `json:"prevState"` + NewState string `json:"newState"` + Epoch int64 `json:"epoch"` + + Data *simplejson.Json `json:"data"` +} diff --git a/pkg/services/cleanup/cleanup.go b/pkg/services/cleanup/cleanup.go new file mode 100644 index 00000000000..ffaa75de9cc --- /dev/null +++ b/pkg/services/cleanup/cleanup.go @@ -0,0 +1,85 @@ +package cleanup + +import ( + "context" + "io/ioutil" + "os" + "path" + "time" + + "golang.org/x/sync/errgroup" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/log" + m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/setting" +) + +type CleanUpService struct { + log log.Logger +} + +func NewCleanUpService() *CleanUpService { + return &CleanUpService{ + log: log.New("cleanup"), + } +} + +func (service *CleanUpService) Run(ctx context.Context) error { + service.log.Info("Initializing CleanUpService") + + g, _ := errgroup.WithContext(ctx) + g.Go(func() error { return service.start(ctx) }) + + err := g.Wait() + service.log.Info("Stopped CleanUpService", "reason", err) + return err +} + +func (service *CleanUpService) start(ctx context.Context) error { + service.cleanUpTmpFiles() + + ticker := time.NewTicker(time.Hour * 1) + for { + select { + case <-ticker.C: + service.cleanUpTmpFiles() + service.deleteExpiredSnapshots() + case <-ctx.Done(): + return ctx.Err() + } + } +} + +func (service *CleanUpService) cleanUpTmpFiles() { + if _, err := os.Stat(setting.ImagesDir); os.IsNotExist(err) { + return + } + + files, err := ioutil.ReadDir(setting.ImagesDir) + if err != nil { + service.log.Error("Problem reading image dir", "error", err) + return + } + + var toDelete []os.FileInfo + for _, file := range files { + if file.ModTime().AddDate(0, 0, 1).Before(time.Now()) { + toDelete = append(toDelete, file) + } + } + + for _, file := range toDelete { + fullPath := path.Join(setting.ImagesDir, file.Name()) + err := os.Remove(fullPath) + if err != nil { + service.log.Error("Failed to delete temp file", "file", file.Name(), "error", err) + } + } + + service.log.Debug("Found old rendered image to delete", "deleted", len(toDelete), "keept", len(files)) +} + +func (service *CleanUpService) deleteExpiredSnapshots() { + bus.Dispatch(&m.DeleteExpiredSnapshotsCommand{}) +} diff --git a/pkg/services/notifications/email.go b/pkg/services/notifications/email.go index f81f3e1007b..803f2096b56 100644 --- a/pkg/services/notifications/email.go +++ b/pkg/services/notifications/email.go @@ -6,19 +6,12 @@ import ( ) type Message struct { - To []string - From string - Subject string - Body string - Massive bool - Info string -} - -// create mail content -func (m *Message) Content() string { - contentType := "text/html; charset=UTF-8" - content := "From: " + m.From + "\r\nSubject: " + m.Subject + "\r\nContent-Type: " + contentType + "\r\n\r\n" + m.Body - return content + To []string + From string + Subject string + Body string + Info string + EmbededFiles []string } func setDefaultTemplateData(data map[string]interface{}, u *m.User) { diff --git a/pkg/services/notifications/mailer.go b/pkg/services/notifications/mailer.go index 309436cb7d9..97bf75fdcb9 100644 --- a/pkg/services/notifications/mailer.go +++ b/pkg/services/notifications/mailer.go @@ -5,16 +5,19 @@ package notifications import ( + "bytes" "crypto/tls" + "errors" "fmt" + "html/template" "net" - "net/mail" - "net/smtp" - "os" + "strconv" "strings" "github.com/grafana/grafana/pkg/log" + m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/setting" + "gopkg.in/gomail.v2" ) var mailQueue chan *Message @@ -28,7 +31,7 @@ func processMailQueue() { for { select { case msg := <-mailQueue: - num, err := buildAndSend(msg) + num, err := send(msg) tos := strings.Join(msg.To, "; ") info := "" if err != nil { @@ -47,10 +50,40 @@ var addToMailQueue = func(msg *Message) { mailQueue <- msg } -func sendToSmtpServer(recipients []string, msgContent []byte) error { - host, port, err := net.SplitHostPort(setting.Smtp.Host) +func send(msg *Message) (int, error) { + dialer, err := createDialer() if err != nil { - return err + return 0, err + } + + for _, address := range msg.To { + m := gomail.NewMessage() + m.SetHeader("From", msg.From) + m.SetHeader("To", address) + m.SetHeader("Subject", msg.Subject) + for _, file := range msg.EmbededFiles { + m.Embed(file) + } + + m.SetBody("text/html", msg.Body) + + if err := dialer.DialAndSend(m); err != nil { + return 0, err + } + } + + return len(msg.To), nil +} + +func createDialer() (*gomail.Dialer, error) { + host, port, err := net.SplitHostPort(setting.Smtp.Host) + + if err != nil { + return nil, err + } + iPort, err := strconv.Atoi(port) + if err != nil { + return nil, err } tlsconfig := &tls.Config{ @@ -61,126 +94,64 @@ func sendToSmtpServer(recipients []string, msgContent []byte) error { if setting.Smtp.CertFile != "" { cert, err := tls.LoadX509KeyPair(setting.Smtp.CertFile, setting.Smtp.KeyFile) if err != nil { - return err + return nil, fmt.Errorf("Could not load cert or key file. error: %v", err) } tlsconfig.Certificates = []tls.Certificate{cert} } - conn, err := net.Dial("tcp", net.JoinHostPort(host, port)) - if err != nil { - return err - } - defer conn.Close() - - isSecureConn := false - // Start TLS directly if the port ends with 465 (SMTPS protocol) - if strings.HasSuffix(port, "465") { - conn = tls.Client(conn, tlsconfig) - isSecureConn = true - } - - client, err := smtp.NewClient(conn, host) - if err != nil { - return err - } - - hostname, err := os.Hostname() - if err != nil { - return err - } - - if err = client.Hello(hostname); err != nil { - return err - } - - // If not using SMTPS, alway use STARTTLS if available - hasStartTLS, _ := client.Extension("STARTTLS") - if !isSecureConn && hasStartTLS { - if err = client.StartTLS(tlsconfig); err != nil { - return err - } - } - - canAuth, options := client.Extension("AUTH") - - if canAuth && len(setting.Smtp.User) > 0 { - var auth smtp.Auth - - if strings.Contains(options, "CRAM-MD5") { - auth = smtp.CRAMMD5Auth(setting.Smtp.User, setting.Smtp.Password) - } else if strings.Contains(options, "PLAIN") { - auth = smtp.PlainAuth("", setting.Smtp.User, setting.Smtp.Password, host) - } - - if auth != nil { - if err = client.Auth(auth); err != nil { - return err - } - } - } - - if fromAddress, err := mail.ParseAddress(setting.Smtp.FromAddress); err != nil { - return err - } else { - if err = client.Mail(fromAddress.Address); err != nil { - return err - } - } - - for _, rec := range recipients { - if err = client.Rcpt(rec); err != nil { - return err - } - } - - w, err := client.Data() - if err != nil { - return err - } - if _, err = w.Write([]byte(msgContent)); err != nil { - return err - } - - if err = w.Close(); err != nil { - return err - } - - return client.Quit() + d := gomail.NewDialer(host, iPort, setting.Smtp.User, setting.Smtp.Password) + d.TLSConfig = tlsconfig + return d, nil } -func buildAndSend(msg *Message) (int, error) { - log.Trace("Sending mails to: %s", strings.Join(msg.To, "; ")) - - // get message body - content := msg.Content() - - if len(msg.To) == 0 { - return 0, fmt.Errorf("empty receive emails") - } else if len(msg.Body) == 0 { - return 0, fmt.Errorf("empty email body") +func buildEmailMessage(cmd *m.SendEmailCommand) (*Message, error) { + if !setting.Smtp.Enabled { + return nil, errors.New("Grafana mailing/smtp options not configured, contact your Grafana admin") } - if msg.Massive { - // send mail to multiple emails one by one - num := 0 - for _, to := range msg.To { - body := []byte("To: " + to + "\r\n" + content) - err := sendToSmtpServer([]string{to}, body) - if err != nil { - return num, err - } - num++ - } - return num, nil - } else { - body := []byte("To: " + strings.Join(msg.To, ";") + "\r\n" + content) + var buffer bytes.Buffer + var err error - // send to multiple emails in one message - err := sendToSmtpServer(msg.To, body) + data := cmd.Data + if data == nil { + data = make(map[string]interface{}, 10) + } + + setDefaultTemplateData(data, nil) + err = mailTemplates.ExecuteTemplate(&buffer, cmd.Template, data) + if err != nil { + return nil, err + } + + subject := cmd.Subject + if cmd.Subject == "" { + var subjectText interface{} + subjectData := data["Subject"].(map[string]interface{}) + subjectText, hasSubject := subjectData["value"] + + if !hasSubject { + return nil, errors.New(fmt.Sprintf("Missing subject in Template %s", cmd.Template)) + } + + subjectTmpl, err := template.New("subject").Parse(subjectText.(string)) if err != nil { - return 0, err - } else { - return 1, nil + return nil, err } + + var subjectBuffer bytes.Buffer + err = subjectTmpl.ExecuteTemplate(&subjectBuffer, "subject", data) + if err != nil { + return nil, err + } + + subject = subjectBuffer.String() } + + return &Message{ + To: cmd.To, + From: setting.Smtp.FromAddress, + Subject: subject, + Body: buffer.String(), + EmbededFiles: cmd.EmbededFiles, + }, nil } diff --git a/pkg/services/notifications/notifications.go b/pkg/services/notifications/notifications.go index 63ce7219618..c1ed9ac9e74 100644 --- a/pkg/services/notifications/notifications.go +++ b/pkg/services/notifications/notifications.go @@ -1,7 +1,7 @@ package notifications import ( - "bytes" + "context" "errors" "fmt" "html/template" @@ -23,11 +23,16 @@ var tmplWelcomeOnSignUp = "welcome_on_signup.html" func Init() error { initMailQueue() + initWebhookQueue() bus.AddHandler("email", sendResetPasswordEmail) bus.AddHandler("email", validateResetPasswordCode) bus.AddHandler("email", sendEmailCommandHandler) + bus.AddCtxHandler("email", sendEmailCommandHandlerSync) + + bus.AddCtxHandler("webhook", SendWebhookSync) + bus.AddEventListener(signUpStartedHandler) bus.AddEventListener(signUpCompletedHandler) @@ -53,56 +58,49 @@ func Init() error { return nil } +func SendWebhookSync(ctx context.Context, cmd *m.SendWebhookSync) error { + return sendWebRequestSync(ctx, &Webhook{ + Url: cmd.Url, + User: cmd.User, + Password: cmd.Password, + Body: cmd.Body, + HttpMethod: cmd.HttpMethod, + }) +} + func subjectTemplateFunc(obj map[string]interface{}, value string) string { obj["value"] = value return "" } -func sendEmailCommandHandler(cmd *m.SendEmailCommand) error { - if !setting.Smtp.Enabled { - return errors.New("Grafana mailing/smtp options not configured, contact your Grafana admin") - } - - var buffer bytes.Buffer - var err error - var subjectText interface{} - - data := cmd.Data - if data == nil { - data = make(map[string]interface{}, 10) - } - - setDefaultTemplateData(data, nil) - err = mailTemplates.ExecuteTemplate(&buffer, cmd.Template, data) - if err != nil { - return err - } - - subjectData := data["Subject"].(map[string]interface{}) - subjectText, hasSubject := subjectData["value"] - - if !hasSubject { - return errors.New(fmt.Sprintf("Missing subject in Template %s", cmd.Template)) - } - - subjectTmpl, err := template.New("subject").Parse(subjectText.(string)) - if err != nil { - return err - } - - var subjectBuffer bytes.Buffer - err = subjectTmpl.ExecuteTemplate(&subjectBuffer, "subject", data) - if err != nil { - return err - } - - addToMailQueue(&Message{ - To: cmd.To, - From: setting.Smtp.FromAddress, - Subject: subjectBuffer.String(), - Body: buffer.String(), +func sendEmailCommandHandlerSync(ctx context.Context, cmd *m.SendEmailCommandSync) error { + message, err := buildEmailMessage(&m.SendEmailCommand{ + Data: cmd.Data, + Info: cmd.Info, + Template: cmd.Template, + To: cmd.To, + EmbededFiles: cmd.EmbededFiles, + Subject: cmd.Subject, }) + if err != nil { + return err + } + + _, err = send(message) + + return err +} + +func sendEmailCommandHandler(cmd *m.SendEmailCommand) error { + message, err := buildEmailMessage(cmd) + + if err != nil { + return err + } + + addToMailQueue(message) + return nil } diff --git a/pkg/services/notifications/notifications_test.go b/pkg/services/notifications/notifications_test.go index 110e24cb810..79db664e893 100644 --- a/pkg/services/notifications/notifications_test.go +++ b/pkg/services/notifications/notifications_test.go @@ -3,16 +3,21 @@ package notifications import ( "testing" - "github.com/grafana/grafana/pkg/bus" m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/setting" . "github.com/smartystreets/goconvey/convey" ) +type testTriggeredAlert struct { + ActualValue float64 + Name string + State string +} + func TestNotifications(t *testing.T) { Convey("Given the notifications service", t, func() { - bus.ClearBusHandlers() + //bus.ClearBusHandlers() setting.StaticRootPath = "../../../public/" setting.Smtp.Enabled = true @@ -35,5 +40,4 @@ func TestNotifications(t *testing.T) { So(sentMsg.Body, ShouldNotContainSubstring, "Subject") }) }) - } diff --git a/pkg/services/notifications/send_email_integration_test.go b/pkg/services/notifications/send_email_integration_test.go new file mode 100644 index 00000000000..1a4406dc13a --- /dev/null +++ b/pkg/services/notifications/send_email_integration_test.go @@ -0,0 +1,62 @@ +package notifications + +import ( + "io/ioutil" + "testing" + + "github.com/grafana/grafana/pkg/bus" + m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/setting" + . "github.com/smartystreets/goconvey/convey" +) + +func TestEmailIntegrationTest(t *testing.T) { + SkipConvey("Given the notifications service", t, func() { + bus.ClearBusHandlers() + + setting.StaticRootPath = "../../../public/" + setting.Smtp.Enabled = true + setting.Smtp.TemplatesPattern = "emails/*.html" + setting.Smtp.FromAddress = "from@address.com" + setting.BuildVersion = "4.0.0" + + err := Init() + So(err, ShouldBeNil) + + addToMailQueue = func(msg *Message) { + ioutil.WriteFile("../../../tmp/test_email.html", []byte(msg.Body), 0777) + } + + Convey("When sending reset email password", func() { + cmd := &m.SendEmailCommand{ + + Data: map[string]interface{}{ + "Title": "[CRITICAL] Imaginary timeserie alert", + "State": "Firing", + "Name": "Imaginary timeserie alert", + "Severity": "ok", + "SeverityColor": "#D63232", + "Message": "Alert message that will support markdown in some distant future.", + "RuleUrl": "http://localhost:3000/dashboard/db/graphite-dashboard", + "ImageLink": "http://localhost:3000/render/dashboard-solo/db/graphite-dashboard?panelId=1&from=1471008499616&to=1471012099617&width=1000&height=500", + "AlertPageUrl": "http://localhost:3000/alerting", + "EvalMatches": []map[string]string{ + { + "Metric": "desktop", + "Value": "40", + }, + { + "Metric": "mobile", + "Value": "20", + }, + }, + }, + To: []string{"asdf@asdf.com "}, + Template: "alert_notification.html", + } + + err := sendEmailCommandHandler(cmd) + So(err, ShouldBeNil) + }) + }) +} diff --git a/pkg/services/notifications/webhook.go b/pkg/services/notifications/webhook.go new file mode 100644 index 00000000000..ac46a43f294 --- /dev/null +++ b/pkg/services/notifications/webhook.go @@ -0,0 +1,87 @@ +package notifications + +import ( + "bytes" + "context" + "fmt" + "io/ioutil" + "net/http" + + "golang.org/x/net/context/ctxhttp" + + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/util" +) + +type Webhook struct { + Url string + User string + Password string + Body string + HttpMethod string +} + +var ( + webhookQueue chan *Webhook + webhookLog log.Logger +) + +func initWebhookQueue() { + webhookLog = log.New("notifications.webhook") + webhookQueue = make(chan *Webhook, 10) + go processWebhookQueue() +} + +func processWebhookQueue() { + for { + select { + case webhook := <-webhookQueue: + err := sendWebRequestSync(context.TODO(), webhook) + + if err != nil { + webhookLog.Error("Failed to send webrequest ", "error", err) + } + } + } +} + +func sendWebRequestSync(ctx context.Context, webhook *Webhook) error { + webhookLog.Debug("Sending webhook", "url", webhook.Url, "http method", webhook.HttpMethod) + + if webhook.HttpMethod == "" { + webhook.HttpMethod = http.MethodPost + } + + request, err := http.NewRequest(webhook.HttpMethod, webhook.Url, bytes.NewReader([]byte(webhook.Body))) + if err != nil { + return err + } + + request.Header.Add("Content-Type", "application/json") + request.Header.Add("User-Agent", "Grafana") + if webhook.User != "" && webhook.Password != "" { + request.Header.Add("Authorization", util.GetBasicAuthHeader(webhook.User, webhook.Password)) + } + + resp, err := ctxhttp.Do(ctx, http.DefaultClient, request) + if err != nil { + return err + } + + if resp.StatusCode/100 == 2 { + return nil + } + + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err + } + + webhookLog.Debug("Webhook failed", "statuscode", resp.Status, "body", string(body)) + return fmt.Errorf("Webhook response status %v", resp.Status) +} + +var addToWebhookQueue = func(msg *Webhook) { + webhookQueue <- msg +} diff --git a/pkg/services/sqlstore/alert.go b/pkg/services/sqlstore/alert.go new file mode 100644 index 00000000000..8718b03e786 --- /dev/null +++ b/pkg/services/sqlstore/alert.go @@ -0,0 +1,315 @@ +package sqlstore + +import ( + "bytes" + "fmt" + "strings" + "time" + + "github.com/go-xorm/xorm" + "github.com/grafana/grafana/pkg/bus" + m "github.com/grafana/grafana/pkg/models" +) + +func init() { + bus.AddHandler("sql", SaveAlerts) + bus.AddHandler("sql", HandleAlertsQuery) + bus.AddHandler("sql", GetAlertById) + bus.AddHandler("sql", DeleteAlertById) + bus.AddHandler("sql", GetAllAlertQueryHandler) + bus.AddHandler("sql", SetAlertState) + bus.AddHandler("sql", GetAlertStatesForDashboard) + bus.AddHandler("sql", PauseAlert) + bus.AddHandler("sql", PauseAllAlerts) +} + +func GetAlertById(query *m.GetAlertByIdQuery) error { + alert := m.Alert{} + has, err := x.Id(query.Id).Get(&alert) + if !has { + return fmt.Errorf("could not find alert") + } + if err != nil { + return err + } + + query.Result = &alert + return nil +} + +func GetAllAlertQueryHandler(query *m.GetAllAlertsQuery) error { + var alerts []*m.Alert + err := x.Sql("select * from alert").Find(&alerts) + if err != nil { + return err + } + + query.Result = alerts + return nil +} + +func deleteAlertByIdInternal(alertId int64, reason string, sess *xorm.Session) error { + sqlog.Debug("Deleting alert", "id", alertId, "reason", reason) + + if _, err := sess.Exec("DELETE FROM alert WHERE id = ?", alertId); err != nil { + return err + } + + if _, err := sess.Exec("DELETE FROM annotation WHERE alert_id = ?", alertId); err != nil { + return err + } + + return nil +} + +func DeleteAlertById(cmd *m.DeleteAlertCommand) error { + return inTransaction(func(sess *xorm.Session) error { + return deleteAlertByIdInternal(cmd.AlertId, "DeleteAlertCommand", sess) + }) +} + +func HandleAlertsQuery(query *m.GetAlertsQuery) error { + var sql bytes.Buffer + params := make([]interface{}, 0) + + sql.WriteString(`SELECT * + from alert + `) + + sql.WriteString(`WHERE org_id = ?`) + params = append(params, query.OrgId) + + if query.DashboardId != 0 { + sql.WriteString(` AND dashboard_id = ?`) + params = append(params, query.DashboardId) + } + + if query.PanelId != 0 { + sql.WriteString(` AND panel_id = ?`) + params = append(params, query.PanelId) + } + + if len(query.State) > 0 && query.State[0] != "ALL" { + sql.WriteString(` AND (`) + for i, v := range query.State { + if i > 0 { + sql.WriteString(" OR ") + } + sql.WriteString("state = ? ") + params = append(params, v) + } + sql.WriteString(")") + } + + if query.Limit != 0 { + sql.WriteString(" LIMIT ?") + params = append(params, query.Limit) + } + + sql.WriteString(" ORDER BY name ASC") + + alerts := make([]*m.Alert, 0) + if err := x.Sql(sql.String(), params...).Find(&alerts); err != nil { + return err + } + + query.Result = alerts + return nil +} + +func DeleteAlertDefinition(dashboardId int64, sess *xorm.Session) error { + alerts := make([]*m.Alert, 0) + sess.Where("dashboard_id = ?", dashboardId).Find(&alerts) + + for _, alert := range alerts { + deleteAlertByIdInternal(alert.Id, "Dashboard deleted", sess) + } + + return nil +} + +func SaveAlerts(cmd *m.SaveAlertsCommand) error { + return inTransaction(func(sess *xorm.Session) error { + existingAlerts, err := GetAlertsByDashboardId2(cmd.DashboardId, sess) + if err != nil { + return err + } + + if err := upsertAlerts(existingAlerts, cmd, sess); err != nil { + return err + } + + if err := deleteMissingAlerts(existingAlerts, cmd, sess); err != nil { + return err + } + + return nil + }) +} + +func upsertAlerts(existingAlerts []*m.Alert, cmd *m.SaveAlertsCommand, sess *xorm.Session) error { + for _, alert := range cmd.Alerts { + update := false + var alertToUpdate *m.Alert + + for _, k := range existingAlerts { + if alert.PanelId == k.PanelId { + update = true + alert.Id = k.Id + alertToUpdate = k + break + } + } + + if update { + if alertToUpdate.ContainsUpdates(alert) { + alert.Updated = time.Now() + alert.State = alertToUpdate.State + _, err := sess.Id(alert.Id).Update(alert) + if err != nil { + return err + } + + sqlog.Debug("Alert updated", "name", alert.Name, "id", alert.Id) + } + } else { + alert.Updated = time.Now() + alert.Created = time.Now() + alert.State = m.AlertStatePending + alert.NewStateDate = time.Now() + + _, err := sess.Insert(alert) + if err != nil { + return err + } + + sqlog.Debug("Alert inserted", "name", alert.Name, "id", alert.Id) + } + } + + return nil +} + +func deleteMissingAlerts(alerts []*m.Alert, cmd *m.SaveAlertsCommand, sess *xorm.Session) error { + for _, missingAlert := range alerts { + missing := true + + for _, k := range cmd.Alerts { + if missingAlert.PanelId == k.PanelId { + missing = false + break + } + } + + if missing { + deleteAlertByIdInternal(missingAlert.Id, "Removed from dashboard", sess) + } + } + + return nil +} + +func GetAlertsByDashboardId2(dashboardId int64, sess *xorm.Session) ([]*m.Alert, error) { + alerts := make([]*m.Alert, 0) + err := sess.Where("dashboard_id = ?", dashboardId).Find(&alerts) + + if err != nil { + return []*m.Alert{}, err + } + + return alerts, nil +} + +func SetAlertState(cmd *m.SetAlertStateCommand) error { + return inTransaction(func(sess *xorm.Session) error { + alert := m.Alert{} + + if has, err := sess.Id(cmd.AlertId).Get(&alert); err != nil { + return err + } else if !has { + return fmt.Errorf("Could not find alert") + } + + if alert.State == m.AlertStatePaused { + return m.ErrCannotChangeStateOnPausedAlert + } + + alert.State = cmd.State + alert.StateChanges += 1 + alert.NewStateDate = time.Now() + alert.EvalData = cmd.EvalData + + if cmd.Error == "" { + alert.ExecutionError = " " //without this space, xorm skips updating this field + } else { + alert.ExecutionError = cmd.Error + } + + sess.Id(alert.Id).Update(&alert) + return nil + }) +} + +func PauseAlert(cmd *m.PauseAlertCommand) error { + return inTransaction(func(sess *xorm.Session) error { + if len(cmd.AlertIds) == 0 { + return fmt.Errorf("command contains no alertids") + } + + var buffer bytes.Buffer + params := make([]interface{}, 0) + + buffer.WriteString(`UPDATE alert SET state = ?`) + if cmd.Paused { + params = append(params, string(m.AlertStatePaused)) + } else { + params = append(params, string(m.AlertStatePending)) + } + + buffer.WriteString(` WHERE id IN (?` + strings.Repeat(",?", len(cmd.AlertIds)-1) + `)`) + for _, v := range cmd.AlertIds { + params = append(params, v) + } + + res, err := sess.Exec(buffer.String(), params...) + if err != nil { + return err + } + cmd.ResultCount, _ = res.RowsAffected() + return nil + }) +} + +func PauseAllAlerts(cmd *m.PauseAllAlertCommand) error { + return inTransaction(func(sess *xorm.Session) error { + var newState string + if cmd.Paused { + newState = string(m.AlertStatePaused) + } else { + newState = string(m.AlertStatePending) + } + + res, err := sess.Exec(`UPDATE alert SET state = ?`, newState) + if err != nil { + return err + } + cmd.ResultCount, _ = res.RowsAffected() + return nil + }) +} + +func GetAlertStatesForDashboard(query *m.GetAlertStatesForDashboardQuery) error { + var rawSql = `SELECT + id, + dashboard_id, + panel_id, + state, + new_state_date + FROM alert + WHERE org_id = ? AND dashboard_id = ?` + + query.Result = make([]*m.AlertStateInfoDTO, 0) + err := x.Sql(rawSql, query.OrgId, query.DashboardId).Find(&query.Result) + + return err +} diff --git a/pkg/services/sqlstore/alert_notification.go b/pkg/services/sqlstore/alert_notification.go new file mode 100644 index 00000000000..5acb53c3c09 --- /dev/null +++ b/pkg/services/sqlstore/alert_notification.go @@ -0,0 +1,200 @@ +package sqlstore + +import ( + "bytes" + "fmt" + "strings" + "time" + + "github.com/go-xorm/xorm" + "github.com/grafana/grafana/pkg/bus" + m "github.com/grafana/grafana/pkg/models" +) + +func init() { + bus.AddHandler("sql", GetAlertNotifications) + bus.AddHandler("sql", CreateAlertNotificationCommand) + bus.AddHandler("sql", UpdateAlertNotification) + bus.AddHandler("sql", DeleteAlertNotification) + bus.AddHandler("sql", GetAlertNotificationsToSend) + bus.AddHandler("sql", GetAllAlertNotifications) +} + +func DeleteAlertNotification(cmd *m.DeleteAlertNotificationCommand) error { + return inTransaction(func(sess *xorm.Session) error { + sql := "DELETE FROM alert_notification WHERE alert_notification.org_id = ? AND alert_notification.id = ?" + _, err := sess.Exec(sql, cmd.OrgId, cmd.Id) + + if err != nil { + return err + } + + return nil + }) +} + +func GetAlertNotifications(query *m.GetAlertNotificationsQuery) error { + return getAlertNotificationInternal(query, x.NewSession()) +} + +func GetAllAlertNotifications(query *m.GetAllAlertNotificationsQuery) error { + results := make([]*m.AlertNotification, 0) + if err := x.Where("org_id = ?", query.OrgId).Find(&results); err != nil { + return err + } + + query.Result = results + return nil +} + +func GetAlertNotificationsToSend(query *m.GetAlertNotificationsToSendQuery) error { + var sql bytes.Buffer + params := make([]interface{}, 0) + + sql.WriteString(`SELECT + alert_notification.id, + alert_notification.org_id, + alert_notification.name, + alert_notification.type, + alert_notification.created, + alert_notification.updated, + alert_notification.settings, + alert_notification.is_default + FROM alert_notification + `) + + sql.WriteString(` WHERE alert_notification.org_id = ?`) + params = append(params, query.OrgId) + + sql.WriteString(` AND ((alert_notification.is_default = ?)`) + params = append(params, dialect.BooleanStr(true)) + if len(query.Ids) > 0 { + sql.WriteString(` OR alert_notification.id IN (?` + strings.Repeat(",?", len(query.Ids)-1) + ")") + for _, v := range query.Ids { + params = append(params, v) + } + } + sql.WriteString(`)`) + + results := make([]*m.AlertNotification, 0) + if err := x.Sql(sql.String(), params...).Find(&results); err != nil { + return err + } + + query.Result = results + return nil +} + +func getAlertNotificationInternal(query *m.GetAlertNotificationsQuery, sess *xorm.Session) error { + var sql bytes.Buffer + params := make([]interface{}, 0) + + sql.WriteString(`SELECT + alert_notification.id, + alert_notification.org_id, + alert_notification.name, + alert_notification.type, + alert_notification.created, + alert_notification.updated, + alert_notification.settings, + alert_notification.is_default + FROM alert_notification + `) + + sql.WriteString(` WHERE alert_notification.org_id = ?`) + params = append(params, query.OrgId) + + if query.Name != "" || query.Id != 0 { + if query.Name != "" { + sql.WriteString(` AND alert_notification.name = ?`) + params = append(params, query.Name) + } + + if query.Id != 0 { + sql.WriteString(` AND alert_notification.id = ?`) + params = append(params, query.Id) + } + } + + results := make([]*m.AlertNotification, 0) + if err := sess.Sql(sql.String(), params...).Find(&results); err != nil { + return err + } + + if len(results) == 0 { + query.Result = nil + } else { + query.Result = results[0] + } + + return nil +} + +func CreateAlertNotificationCommand(cmd *m.CreateAlertNotificationCommand) error { + return inTransaction(func(sess *xorm.Session) error { + existingQuery := &m.GetAlertNotificationsQuery{OrgId: cmd.OrgId, Name: cmd.Name} + err := getAlertNotificationInternal(existingQuery, sess) + + if err != nil { + return err + } + + if existingQuery.Result != nil { + return fmt.Errorf("Alert notification name %s already exists", cmd.Name) + } + + alertNotification := &m.AlertNotification{ + OrgId: cmd.OrgId, + Name: cmd.Name, + Type: cmd.Type, + Settings: cmd.Settings, + Created: time.Now(), + Updated: time.Now(), + IsDefault: cmd.IsDefault, + } + + if _, err = sess.Insert(alertNotification); err != nil { + return err + } + + cmd.Result = alertNotification + return nil + }) +} + +func UpdateAlertNotification(cmd *m.UpdateAlertNotificationCommand) error { + return inTransaction(func(sess *xorm.Session) (err error) { + current := m.AlertNotification{} + + if _, err = sess.Id(cmd.Id).Get(¤t); err != nil { + return err + } + + // check if name exists + sameNameQuery := &m.GetAlertNotificationsQuery{OrgId: cmd.OrgId, Name: cmd.Name} + if err := getAlertNotificationInternal(sameNameQuery, sess); err != nil { + return err + } + + if sameNameQuery.Result != nil && sameNameQuery.Result.Id != current.Id { + return fmt.Errorf("Alert notification name %s already exists", cmd.Name) + } + + current.Updated = time.Now() + current.Settings = cmd.Settings + current.Name = cmd.Name + current.Type = cmd.Type + current.IsDefault = cmd.IsDefault + + sess.UseBool("is_default") + + if affected, err := sess.Id(cmd.Id).Update(current); err != nil { + return err + } else if affected == 0 { + return fmt.Errorf("Could not find alert notification") + } + + cmd.Result = ¤t + return nil + }) +} diff --git a/pkg/services/sqlstore/alert_notification_test.go b/pkg/services/sqlstore/alert_notification_test.go new file mode 100644 index 00000000000..d37062fb58f --- /dev/null +++ b/pkg/services/sqlstore/alert_notification_test.go @@ -0,0 +1,98 @@ +package sqlstore + +import ( + "fmt" + "testing" + + "github.com/grafana/grafana/pkg/components/simplejson" + m "github.com/grafana/grafana/pkg/models" + . "github.com/smartystreets/goconvey/convey" +) + +func TestAlertNotificationSQLAccess(t *testing.T) { + Convey("Testing Alert notification sql access", t, func() { + InitTestDB(t) + var err error + + Convey("Alert notifications should be empty", func() { + cmd := &m.GetAlertNotificationsQuery{ + OrgId: 2, + Name: "email", + } + + err := GetAlertNotifications(cmd) + fmt.Printf("errror %v", err) + So(err, ShouldBeNil) + So(cmd.Result, ShouldBeNil) + }) + + Convey("Can save Alert Notification", func() { + cmd := &m.CreateAlertNotificationCommand{ + Name: "ops", + Type: "email", + OrgId: 1, + Settings: simplejson.New(), + } + + err = CreateAlertNotificationCommand(cmd) + So(err, ShouldBeNil) + So(cmd.Result.Id, ShouldNotEqual, 0) + So(cmd.Result.OrgId, ShouldNotEqual, 0) + So(cmd.Result.Type, ShouldEqual, "email") + + Convey("Cannot save Alert Notification with the same name", func() { + err = CreateAlertNotificationCommand(cmd) + So(err, ShouldNotBeNil) + }) + + Convey("Can update alert notification", func() { + newCmd := &m.UpdateAlertNotificationCommand{ + Name: "NewName", + Type: "webhook", + OrgId: cmd.Result.OrgId, + Settings: simplejson.New(), + Id: cmd.Result.Id, + } + err := UpdateAlertNotification(newCmd) + So(err, ShouldBeNil) + So(newCmd.Result.Name, ShouldEqual, "NewName") + }) + }) + + Convey("Can search using an array of ids", func() { + cmd1 := m.CreateAlertNotificationCommand{Name: "nagios", Type: "webhook", OrgId: 1, Settings: simplejson.New()} + cmd2 := m.CreateAlertNotificationCommand{Name: "slack", Type: "webhook", OrgId: 1, Settings: simplejson.New()} + cmd3 := m.CreateAlertNotificationCommand{Name: "ops2", Type: "email", OrgId: 1, Settings: simplejson.New()} + cmd4 := m.CreateAlertNotificationCommand{IsDefault: true, Name: "default", Type: "email", OrgId: 1, Settings: simplejson.New()} + + otherOrg := m.CreateAlertNotificationCommand{Name: "default", Type: "email", OrgId: 2, Settings: simplejson.New()} + + So(CreateAlertNotificationCommand(&cmd1), ShouldBeNil) + So(CreateAlertNotificationCommand(&cmd2), ShouldBeNil) + So(CreateAlertNotificationCommand(&cmd3), ShouldBeNil) + So(CreateAlertNotificationCommand(&cmd4), ShouldBeNil) + So(CreateAlertNotificationCommand(&otherOrg), ShouldBeNil) + + Convey("search", func() { + query := &m.GetAlertNotificationsToSendQuery{ + Ids: []int64{cmd1.Result.Id, cmd2.Result.Id, 112341231}, + OrgId: 1, + } + + err := GetAlertNotificationsToSend(query) + So(err, ShouldBeNil) + So(len(query.Result), ShouldEqual, 3) + }) + + Convey("all", func() { + query := &m.GetAllAlertNotificationsQuery{ + OrgId: 1, + } + + err := GetAllAlertNotifications(query) + So(err, ShouldBeNil) + So(len(query.Result), ShouldEqual, 4) + }) + }) + }) +} diff --git a/pkg/services/sqlstore/alert_test.go b/pkg/services/sqlstore/alert_test.go new file mode 100644 index 00000000000..daf4f774717 --- /dev/null +++ b/pkg/services/sqlstore/alert_test.go @@ -0,0 +1,210 @@ +package sqlstore + +import ( + "testing" + + "github.com/grafana/grafana/pkg/components/simplejson" + m "github.com/grafana/grafana/pkg/models" + . "github.com/smartystreets/goconvey/convey" +) + +func TestAlertingDataAccess(t *testing.T) { + Convey("Testing Alerting data access", t, func() { + InitTestDB(t) + + testDash := insertTestDashboard("dashboard with alerts", 1, "alert") + + items := []*m.Alert{ + { + PanelId: 1, + DashboardId: testDash.Id, + OrgId: testDash.OrgId, + Name: "Alerting title", + Message: "Alerting message", + Settings: simplejson.New(), + Frequency: 1, + }, + } + + cmd := m.SaveAlertsCommand{ + Alerts: items, + DashboardId: testDash.Id, + OrgId: 1, + UserId: 1, + } + + err := SaveAlerts(&cmd) + + Convey("Can create one alert", func() { + So(err, ShouldBeNil) + }) + + Convey("Can set new states", func() { + Convey("new state ok", func() { + cmd := &m.SetAlertStateCommand{ + AlertId: 1, + State: m.AlertStateOK, + } + + err = SetAlertState(cmd) + So(err, ShouldBeNil) + }) + + Convey("can pause alert", func() { + cmd := &m.PauseAllAlertCommand{ + Paused: true, + } + + err = PauseAllAlerts(cmd) + So(err, ShouldBeNil) + + Convey("cannot updated paused alert", func() { + cmd := &m.SetAlertStateCommand{ + AlertId: 1, + State: m.AlertStateOK, + } + + err = SetAlertState(cmd) + So(err, ShouldNotBeNil) + }) + }) + }) + + Convey("Can read properties", func() { + alertQuery := m.GetAlertsQuery{DashboardId: testDash.Id, PanelId: 1, OrgId: 1} + err2 := HandleAlertsQuery(&alertQuery) + + alert := alertQuery.Result[0] + So(err2, ShouldBeNil) + So(alert.Name, ShouldEqual, "Alerting title") + So(alert.Message, ShouldEqual, "Alerting message") + So(alert.State, ShouldEqual, "pending") + So(alert.Frequency, ShouldEqual, 1) + }) + + Convey("Alerts with same dashboard id and panel id should update", func() { + modifiedItems := items + modifiedItems[0].Name = "Name" + + modifiedCmd := m.SaveAlertsCommand{ + DashboardId: testDash.Id, + OrgId: 1, + UserId: 1, + Alerts: modifiedItems, + } + + err := SaveAlerts(&modifiedCmd) + + Convey("Can save alerts with same dashboard and panel id", func() { + So(err, ShouldBeNil) + }) + + Convey("Alerts should be updated", func() { + query := m.GetAlertsQuery{DashboardId: testDash.Id, OrgId: 1} + err2 := HandleAlertsQuery(&query) + + So(err2, ShouldBeNil) + So(len(query.Result), ShouldEqual, 1) + So(query.Result[0].Name, ShouldEqual, "Name") + + Convey("Alert state should not be updated", func() { + So(query.Result[0].State, ShouldEqual, "pending") + }) + }) + + Convey("Updates without changes should be ignored", func() { + err3 := SaveAlerts(&modifiedCmd) + So(err3, ShouldBeNil) + }) + }) + + Convey("Multiple alerts per dashboard", func() { + multipleItems := []*m.Alert{ + { + DashboardId: testDash.Id, + PanelId: 1, + Name: "1", + OrgId: 1, + Settings: simplejson.New(), + }, + { + DashboardId: testDash.Id, + PanelId: 2, + Name: "2", + OrgId: 1, + Settings: simplejson.New(), + }, + { + DashboardId: testDash.Id, + PanelId: 3, + Name: "3", + OrgId: 1, + Settings: simplejson.New(), + }, + } + + cmd.Alerts = multipleItems + err = SaveAlerts(&cmd) + + Convey("Should save 3 dashboards", func() { + So(err, ShouldBeNil) + + queryForDashboard := m.GetAlertsQuery{DashboardId: testDash.Id, OrgId: 1} + err2 := HandleAlertsQuery(&queryForDashboard) + + So(err2, ShouldBeNil) + So(len(queryForDashboard.Result), ShouldEqual, 3) + }) + + Convey("should updated two dashboards and delete one", func() { + missingOneAlert := multipleItems[:2] + + cmd.Alerts = missingOneAlert + err = SaveAlerts(&cmd) + + Convey("should delete the missing alert", func() { + query := m.GetAlertsQuery{DashboardId: testDash.Id, OrgId: 1} + err2 := HandleAlertsQuery(&query) + So(err2, ShouldBeNil) + So(len(query.Result), ShouldEqual, 2) + }) + }) + }) + + Convey("When dashboard is removed", func() { + items := []*m.Alert{ + { + PanelId: 1, + DashboardId: testDash.Id, + Name: "Alerting title", + Message: "Alerting message", + }, + } + + cmd := m.SaveAlertsCommand{ + Alerts: items, + DashboardId: testDash.Id, + OrgId: 1, + UserId: 1, + } + + SaveAlerts(&cmd) + + err = DeleteDashboard(&m.DeleteDashboardCommand{ + OrgId: 1, + Slug: testDash.Slug, + }) + + So(err, ShouldBeNil) + + Convey("Alerts should be removed", func() { + query := m.GetAlertsQuery{DashboardId: testDash.Id, OrgId: 1} + err2 := HandleAlertsQuery(&query) + + So(testDash.Id, ShouldEqual, 1) + So(err2, ShouldBeNil) + So(len(query.Result), ShouldEqual, 0) + }) + }) + }) +} diff --git a/pkg/services/sqlstore/annotation.go b/pkg/services/sqlstore/annotation.go new file mode 100644 index 00000000000..e219f48d2fe --- /dev/null +++ b/pkg/services/sqlstore/annotation.go @@ -0,0 +1,100 @@ +package sqlstore + +import ( + "bytes" + "fmt" + "strings" + + "github.com/go-xorm/xorm" + "github.com/grafana/grafana/pkg/services/annotations" +) + +type SqlAnnotationRepo struct { +} + +func (r *SqlAnnotationRepo) Save(item *annotations.Item) error { + return inTransaction(func(sess *xorm.Session) error { + + if _, err := sess.Table("annotation").Insert(item); err != nil { + return err + } + + return nil + }) +} + +func (r *SqlAnnotationRepo) Find(query *annotations.ItemQuery) ([]*annotations.Item, error) { + var sql bytes.Buffer + params := make([]interface{}, 0) + + sql.WriteString(`SELECT * + from annotation + `) + + sql.WriteString(`WHERE org_id = ?`) + params = append(params, query.OrgId) + + if query.AlertId != 0 { + sql.WriteString(` AND alert_id = ?`) + params = append(params, query.AlertId) + } + + if query.AlertId != 0 { + sql.WriteString(` AND alert_id = ?`) + params = append(params, query.AlertId) + } + + if query.DashboardId != 0 { + sql.WriteString(` AND dashboard_id = ?`) + params = append(params, query.DashboardId) + } + + if query.PanelId != 0 { + sql.WriteString(` AND panel_id = ?`) + params = append(params, query.PanelId) + } + + if query.From > 0 && query.To > 0 { + sql.WriteString(` AND epoch BETWEEN ? AND ?`) + params = append(params, query.From, query.To) + } + + if query.Type != "" { + sql.WriteString(` AND type = ?`) + params = append(params, string(query.Type)) + } + + if len(query.NewState) > 0 { + sql.WriteString(` AND new_state IN (?` + strings.Repeat(",?", len(query.NewState)-1) + ")") + for _, v := range query.NewState { + params = append(params, v) + } + } + + if query.Limit == 0 { + query.Limit = 10 + } + + sql.WriteString(fmt.Sprintf(" ORDER BY epoch DESC LIMIT %v", query.Limit)) + + items := make([]*annotations.Item, 0) + if err := x.Sql(sql.String(), params...).Find(&items); err != nil { + return nil, err + } + + return items, nil +} + +func (r *SqlAnnotationRepo) Delete(params *annotations.DeleteParams) error { + return inTransaction(func(sess *xorm.Session) error { + + sql := "DELETE FROM annotation WHERE dashboard_id = ? AND panel_id = ?" + + _, err := sess.Exec(sql, params.DashboardId, params.PanelId) + if err != nil { + return err + } + + return nil + }) +} diff --git a/pkg/services/sqlstore/dashboard.go b/pkg/services/sqlstore/dashboard.go index 396d507cfd2..7bd65ac4da8 100644 --- a/pkg/services/sqlstore/dashboard.go +++ b/pkg/services/sqlstore/dashboard.go @@ -18,6 +18,8 @@ func init() { bus.AddHandler("sql", DeleteDashboard) bus.AddHandler("sql", SearchDashboards) bus.AddHandler("sql", GetDashboardTags) + bus.AddHandler("sql", GetDashboardSlugById) + bus.AddHandler("sql", GetDashboardsByPluginId) } func SaveDashboard(cmd *m.SaveDashboardCommand) error { @@ -44,6 +46,11 @@ func SaveDashboard(cmd *m.SaveDashboardCommand) error { return m.ErrDashboardVersionMismatch } } + + // do not allow plugin dashboard updates without overwrite flag + if existing.PluginId != "" && cmd.Overwrite == false { + return m.UpdatePluginDashboardError{PluginId: existing.PluginId} + } } sameTitleExists, err := sess.Where("org_id=? AND slug=?", dash.OrgId, dash.Slug).Get(&sameTitle) @@ -215,7 +222,7 @@ func GetDashboardTags(query *m.GetDashboardTagsQuery) error { func DeleteDashboard(cmd *m.DeleteDashboardCommand) error { return inTransaction2(func(sess *session) error { dashboard := m.Dashboard{Slug: cmd.Slug, OrgId: cmd.OrgId} - has, err := x.Get(&dashboard) + has, err := sess.Get(&dashboard) if err != nil { return err } else if has == false { @@ -226,6 +233,7 @@ func DeleteDashboard(cmd *m.DeleteDashboardCommand) error { "DELETE FROM dashboard_tag WHERE dashboard_id = ? ", "DELETE FROM star WHERE dashboard_id = ? ", "DELETE FROM dashboard WHERE id = ?", + "DELETE FROM playlist_item WHERE type = 'dashboard_by_id' AND value = ?", } for _, sql := range deletes { @@ -235,6 +243,10 @@ func DeleteDashboard(cmd *m.DeleteDashboardCommand) error { } } + if err := DeleteAlertDefinition(dashboard.Id, sess.Session); err != nil { + return nil + } + return nil }) } @@ -244,10 +256,10 @@ func GetDashboards(query *m.GetDashboardsQuery) error { return m.ErrCommandValidationFailed } - var dashboards = make([]m.Dashboard, 0) + var dashboards = make([]*m.Dashboard, 0) err := x.In("id", query.DashboardIds).Find(&dashboards) - query.Result = &dashboards + query.Result = dashboards if err != nil { return err @@ -255,3 +267,36 @@ func GetDashboards(query *m.GetDashboardsQuery) error { return nil } + +func GetDashboardsByPluginId(query *m.GetDashboardsByPluginIdQuery) error { + var dashboards = make([]*m.Dashboard, 0) + + err := x.Where("org_id=? AND plugin_id=?", query.OrgId, query.PluginId).Find(&dashboards) + query.Result = dashboards + + if err != nil { + return err + } + + return nil +} + +type DashboardSlugDTO struct { + Slug string +} + +func GetDashboardSlugById(query *m.GetDashboardSlugByIdQuery) error { + var rawSql = `SELECT slug from dashboard WHERE Id=?` + var slug = DashboardSlugDTO{} + + exists, err := x.Sql(rawSql, query.Id).Get(&slug) + + if err != nil { + return err + } else if exists == false { + return m.ErrDashboardNotFound + } + + query.Result = slug.Slug + return nil +} diff --git a/pkg/services/sqlstore/dashboard_snapshot.go b/pkg/services/sqlstore/dashboard_snapshot.go index fc94a91cce5..bb3a4f8f57e 100644 --- a/pkg/services/sqlstore/dashboard_snapshot.go +++ b/pkg/services/sqlstore/dashboard_snapshot.go @@ -6,6 +6,7 @@ import ( "github.com/go-xorm/xorm" "github.com/grafana/grafana/pkg/bus" m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/setting" ) func init() { @@ -13,6 +14,25 @@ func init() { bus.AddHandler("sql", GetDashboardSnapshot) bus.AddHandler("sql", DeleteDashboardSnapshot) bus.AddHandler("sql", SearchDashboardSnapshots) + bus.AddHandler("sql", DeleteExpiredSnapshots) +} + +func DeleteExpiredSnapshots(cmd *m.DeleteExpiredSnapshotsCommand) error { + return inTransaction(func(sess *xorm.Session) error { + var expiredCount int64 = 0 + + if setting.SnapShotRemoveExpired { + deleteExpiredSql := "DELETE FROM dashboard_snapshot WHERE expires < ?" + expiredResponse, err := x.Exec(deleteExpiredSql, time.Now) + if err != nil { + return err + } + expiredCount, _ = expiredResponse.RowsAffected() + } + + sqlog.Debug("Deleted old/expired snaphots", "expired", expiredCount) + return nil + }) } func CreateDashboardSnapshot(cmd *m.CreateDashboardSnapshotCommand) error { diff --git a/pkg/services/sqlstore/dashboard_test.go b/pkg/services/sqlstore/dashboard_test.go index 609639f7788..a055500592b 100644 --- a/pkg/services/sqlstore/dashboard_test.go +++ b/pkg/services/sqlstore/dashboard_test.go @@ -5,6 +5,7 @@ import ( . "github.com/smartystreets/goconvey/convey" + "github.com/gosimple/slug" "github.com/grafana/grafana/pkg/components/simplejson" m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/search" @@ -55,6 +56,19 @@ func TestDashboardDataAccess(t *testing.T) { So(query.Result.Slug, ShouldEqual, "test-dash-23") }) + Convey("Should be able to delete dashboard", func() { + insertTestDashboard("delete me", 1, "delete this") + + dashboardSlug := slug.Make("delete me") + + err := DeleteDashboard(&m.DeleteDashboardCommand{ + Slug: dashboardSlug, + OrgId: 1, + }) + + So(err, ShouldBeNil) + }) + Convey("Should return error if no dashboard is updated", func() { cmd := m.SaveDashboardCommand{ OrgId: 1, diff --git a/pkg/services/sqlstore/datasource.go b/pkg/services/sqlstore/datasource.go index 55a95413640..57abaf35083 100644 --- a/pkg/services/sqlstore/datasource.go +++ b/pkg/services/sqlstore/datasource.go @@ -4,6 +4,7 @@ import ( "time" "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/components/securejsondata" m "github.com/grafana/grafana/pkg/models" "github.com/go-xorm/xorm" @@ -19,27 +20,31 @@ func init() { } func GetDataSourceById(query *m.GetDataSourceByIdQuery) error { - sess := x.Limit(100, 0).Where("org_id=? AND id=?", query.OrgId, query.Id) - has, err := sess.Get(&query.Result) + datasource := m.DataSource{OrgId: query.OrgId, Id: query.Id} + has, err := x.Get(&datasource) if !has { return m.ErrDataSourceNotFound } + + query.Result = &datasource return err } func GetDataSourceByName(query *m.GetDataSourceByNameQuery) error { - sess := x.Limit(100, 0).Where("org_id=? AND name=?", query.OrgId, query.Name) - has, err := sess.Get(&query.Result) + datasource := m.DataSource{OrgId: query.OrgId, Name: query.Name} + has, err := x.Get(&datasource) if !has { return m.ErrDataSourceNotFound } + + query.Result = &datasource return err } func GetDataSources(query *m.GetDataSourcesQuery) error { - sess := x.Limit(100, 0).Where("org_id=?", query.OrgId).Asc("name") + sess := x.Limit(1000, 0).Where("org_id=?", query.OrgId).Asc("name") query.Result = make([]*m.DataSource, 0) return sess.Find(&query.Result) @@ -56,6 +61,13 @@ func DeleteDataSource(cmd *m.DeleteDataSourceCommand) error { func AddDataSource(cmd *m.AddDataSourceCommand) error { return inTransaction(func(sess *xorm.Session) error { + existing := m.DataSource{OrgId: cmd.OrgId, Name: cmd.Name} + has, _ := sess.Get(&existing) + + if has { + return m.ErrDataSourceNameExists + } + ds := &m.DataSource{ OrgId: cmd.OrgId, Name: cmd.Name, @@ -71,6 +83,7 @@ func AddDataSource(cmd *m.AddDataSourceCommand) error { BasicAuthPassword: cmd.BasicAuthPassword, WithCredentials: cmd.WithCredentials, JsonData: cmd.JsonData, + SecureJsonData: securejsondata.GetEncryptedJsonData(cmd.SecureJsonData), Created: time.Now(), Updated: time.Now(), } @@ -117,6 +130,7 @@ func UpdateDataSource(cmd *m.UpdateDataSourceCommand) error { BasicAuthPassword: cmd.BasicAuthPassword, WithCredentials: cmd.WithCredentials, JsonData: cmd.JsonData, + SecureJsonData: securejsondata.GetEncryptedJsonData(cmd.SecureJsonData), Updated: time.Now(), } diff --git a/pkg/services/sqlstore/datasource_test.go b/pkg/services/sqlstore/datasource_test.go index 4142602c472..35752eeaafc 100644 --- a/pkg/services/sqlstore/datasource_test.go +++ b/pkg/services/sqlstore/datasource_test.go @@ -12,8 +12,6 @@ import ( ) func InitTestDB(t *testing.T) { - - t.Log("InitTestDB") x, err := xorm.NewEngine(sqlutil.TestDB_Sqlite3.DriverName, sqlutil.TestDB_Sqlite3.ConnStr) //x, err := xorm.NewEngine(sqlutil.TestDB_Mysql.DriverName, sqlutil.TestDB_Mysql.ConnStr) //x, err := xorm.NewEngine(sqlutil.TestDB_Postgres.DriverName, sqlutil.TestDB_Postgres.ConnStr) @@ -24,7 +22,7 @@ func InitTestDB(t *testing.T) { sqlutil.CleanDB(x) - if err := SetEngine(x, false); err != nil { + if err := SetEngine(x); err != nil { t.Fatal(err) } } @@ -43,6 +41,7 @@ func TestDataAccess(t *testing.T) { err := AddDataSource(&m.AddDataSourceCommand{ OrgId: 10, + Name: "laban", Type: m.DS_INFLUXDB, Access: m.DS_ACCESS_DIRECT, Url: "http://test", @@ -65,15 +64,19 @@ func TestDataAccess(t *testing.T) { Convey("Given a datasource", func() { - AddDataSource(&m.AddDataSourceCommand{ + err := AddDataSource(&m.AddDataSourceCommand{ OrgId: 10, + Name: "nisse", Type: m.DS_GRAPHITE, Access: m.DS_ACCESS_DIRECT, Url: "http://test", }) + So(err, ShouldBeNil) query := m.GetDataSourcesQuery{OrgId: 10} - GetDataSources(&query) + err = GetDataSources(&query) + So(err, ShouldBeNil) + ds := query.Result[0] Convey("Can delete datasource", func() { diff --git a/pkg/services/sqlstore/migrations/alert_mig.go b/pkg/services/sqlstore/migrations/alert_mig.go new file mode 100644 index 00000000000..b6956be41c7 --- /dev/null +++ b/pkg/services/sqlstore/migrations/alert_mig.go @@ -0,0 +1,70 @@ +package migrations + +import ( + . "github.com/grafana/grafana/pkg/services/sqlstore/migrator" +) + +func addAlertMigrations(mg *Migrator) { + + alertV1 := Table{ + Name: "alert", + Columns: []*Column{ + {Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true}, + {Name: "version", Type: DB_BigInt, Nullable: false}, + {Name: "dashboard_id", Type: DB_BigInt, Nullable: false}, + {Name: "panel_id", Type: DB_BigInt, Nullable: false}, + {Name: "org_id", Type: DB_BigInt, Nullable: false}, + {Name: "name", Type: DB_NVarchar, Length: 255, Nullable: false}, + {Name: "message", Type: DB_Text, Nullable: false}, + {Name: "state", Type: DB_NVarchar, Length: 255, Nullable: false}, + {Name: "settings", Type: DB_Text, Nullable: false}, + {Name: "frequency", Type: DB_BigInt, Nullable: false}, + {Name: "handler", Type: DB_BigInt, Nullable: false}, + {Name: "severity", Type: DB_Text, Nullable: false}, + {Name: "silenced", Type: DB_Bool, Nullable: false}, + {Name: "execution_error", Type: DB_Text, Nullable: false}, + {Name: "eval_data", Type: DB_Text, Nullable: true}, + {Name: "eval_date", Type: DB_DateTime, Nullable: true}, + {Name: "new_state_date", Type: DB_DateTime, Nullable: false}, + {Name: "state_changes", Type: DB_Int, Nullable: false}, + {Name: "created", Type: DB_DateTime, Nullable: false}, + {Name: "updated", Type: DB_DateTime, Nullable: false}, + }, + Indices: []*Index{ + {Cols: []string{"org_id", "id"}, Type: IndexType}, + {Cols: []string{"state"}, Type: IndexType}, + {Cols: []string{"dashboard_id"}, Type: IndexType}, + }, + } + + // create table + mg.AddMigration("create alert table v1", NewAddTableMigration(alertV1)) + + // create indices + mg.AddMigration("add index alert org_id & id ", NewAddIndexMigration(alertV1, alertV1.Indices[0])) + mg.AddMigration("add index alert state", NewAddIndexMigration(alertV1, alertV1.Indices[1])) + mg.AddMigration("add index alert dashboard_id", NewAddIndexMigration(alertV1, alertV1.Indices[2])) + + alert_notification := Table{ + Name: "alert_notification", + Columns: []*Column{ + {Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true}, + {Name: "org_id", Type: DB_BigInt, Nullable: false}, + {Name: "name", Type: DB_NVarchar, Length: 255, Nullable: false}, + {Name: "type", Type: DB_NVarchar, Length: 255, Nullable: false}, + {Name: "settings", Type: DB_Text, Nullable: false}, + {Name: "created", Type: DB_DateTime, Nullable: false}, + {Name: "updated", Type: DB_DateTime, Nullable: false}, + }, + Indices: []*Index{ + {Cols: []string{"org_id", "name"}, Type: UniqueIndex}, + }, + } + + mg.AddMigration("create alert_notification table v1", NewAddTableMigration(alert_notification)) + mg.AddMigration("Add column is_default", NewAddColumnMigration(alert_notification, &Column{ + Name: "is_default", Type: DB_Bool, Nullable: false, Default: "0", + })) + mg.AddMigration("add index alert_notification org_id & name", NewAddIndexMigration(alert_notification, alert_notification.Indices[0])) + +} diff --git a/pkg/services/sqlstore/migrations/annotation_mig.go b/pkg/services/sqlstore/migrations/annotation_mig.go new file mode 100644 index 00000000000..a307100ad3c --- /dev/null +++ b/pkg/services/sqlstore/migrations/annotation_mig.go @@ -0,0 +1,47 @@ +package migrations + +import ( + . "github.com/grafana/grafana/pkg/services/sqlstore/migrator" +) + +func addAnnotationMig(mg *Migrator) { + + table := Table{ + Name: "annotation", + Columns: []*Column{ + {Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true}, + {Name: "org_id", Type: DB_BigInt, Nullable: false}, + {Name: "alert_id", Type: DB_BigInt, Nullable: true}, + {Name: "user_id", Type: DB_BigInt, Nullable: true}, + {Name: "dashboard_id", Type: DB_BigInt, Nullable: true}, + {Name: "panel_id", Type: DB_BigInt, Nullable: true}, + {Name: "category_id", Type: DB_BigInt, Nullable: true}, + {Name: "type", Type: DB_NVarchar, Length: 25, Nullable: false}, + {Name: "title", Type: DB_Text, Nullable: false}, + {Name: "text", Type: DB_Text, Nullable: false}, + {Name: "metric", Type: DB_NVarchar, Length: 255, Nullable: true}, + {Name: "prev_state", Type: DB_NVarchar, Length: 25, Nullable: false}, + {Name: "new_state", Type: DB_NVarchar, Length: 25, Nullable: false}, + {Name: "data", Type: DB_Text, Nullable: false}, + {Name: "epoch", Type: DB_BigInt, Nullable: false}, + }, + Indices: []*Index{ + {Cols: []string{"org_id", "alert_id"}, Type: IndexType}, + {Cols: []string{"org_id", "type"}, Type: IndexType}, + {Cols: []string{"org_id", "category_id"}, Type: IndexType}, + {Cols: []string{"org_id", "dashboard_id", "panel_id", "epoch"}, Type: IndexType}, + {Cols: []string{"org_id", "epoch"}, Type: IndexType}, + }, + } + + mg.AddMigration("Drop old annotation table v4", NewDropTableMigration("annotation")) + + mg.AddMigration("create annotation table v5", NewAddTableMigration(table)) + + // create indices + mg.AddMigration("add index annotation 0 v3", NewAddIndexMigration(table, table.Indices[0])) + mg.AddMigration("add index annotation 1 v3", NewAddIndexMigration(table, table.Indices[1])) + mg.AddMigration("add index annotation 2 v3", NewAddIndexMigration(table, table.Indices[2])) + mg.AddMigration("add index annotation 3 v3", NewAddIndexMigration(table, table.Indices[3])) + mg.AddMigration("add index annotation 4 v3", NewAddIndexMigration(table, table.Indices[4])) +} diff --git a/pkg/services/sqlstore/migrations/dashboard_mig.go b/pkg/services/sqlstore/migrations/dashboard_mig.go index a4a8629b331..283501d366f 100644 --- a/pkg/services/sqlstore/migrations/dashboard_mig.go +++ b/pkg/services/sqlstore/migrations/dashboard_mig.go @@ -102,4 +102,27 @@ func addDashboardMigration(mg *Migrator) { mg.AddMigration("Add column created_by in dashboard - v2", NewAddColumnMigration(dashboardV2, &Column{ Name: "created_by", Type: DB_Int, Nullable: true, })) + + // add column to store gnetId + mg.AddMigration("Add column gnetId in dashboard", NewAddColumnMigration(dashboardV2, &Column{ + Name: "gnet_id", Type: DB_BigInt, Nullable: true, + })) + + mg.AddMigration("Add index for gnetId in dashboard", NewAddIndexMigration(dashboardV2, &Index{ + Cols: []string{"gnet_id"}, Type: IndexType, + })) + + // add column to store plugin_id + mg.AddMigration("Add column plugin_id in dashboard", NewAddColumnMigration(dashboardV2, &Column{ + Name: "plugin_id", Type: DB_NVarchar, Nullable: true, Length: 255, + })) + + mg.AddMigration("Add index for plugin_id in dashboard", NewAddIndexMigration(dashboardV2, &Index{ + Cols: []string{"org_id", "plugin_id"}, Type: IndexType, + })) + + // dashboard_id index for dashboard_tag table + mg.AddMigration("Add index for dashboard_id in dashboard_tag", NewAddIndexMigration(dashboardTagV1, &Index{ + Cols: []string{"dashboard_id"}, Type: IndexType, + })) } diff --git a/pkg/services/sqlstore/migrations/datasource_mig.go b/pkg/services/sqlstore/migrations/datasource_mig.go index 90f7dac85e6..396f80df99f 100644 --- a/pkg/services/sqlstore/migrations/datasource_mig.go +++ b/pkg/services/sqlstore/migrations/datasource_mig.go @@ -101,4 +101,9 @@ func addDataSourceMigration(mg *Migrator) { mg.AddMigration("Add column with_credentials", NewAddColumnMigration(tableV2, &Column{ Name: "with_credentials", Type: DB_Bool, Nullable: false, Default: "0", })) + + // add column that can store TLS client auth data + mg.AddMigration("Add secure json data column", NewAddColumnMigration(tableV2, &Column{ + Name: "secure_json_data", Type: DB_Text, Nullable: true, + })) } diff --git a/pkg/services/sqlstore/migrations/heartbeat_mig.go b/pkg/services/sqlstore/migrations/heartbeat_mig.go new file mode 100644 index 00000000000..e0ee7a5f88f --- /dev/null +++ b/pkg/services/sqlstore/migrations/heartbeat_mig.go @@ -0,0 +1,18 @@ +package migrations + +// // create table +// mg.AddMigration("create alert table v1", NewAddTableMigration(alertV1)) +// +// alert_heartbeat := Table{ +// Name: "alert_heartbeat", +// Columns: []*Column{ +// {Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true}, +// {Name: "server_id", Type: DB_NVarchar, Length: 50, Nullable: false}, +// {Name: "created", Type: DB_DateTime, Nullable: false}, +// {Name: "updated", Type: DB_DateTime, Nullable: false}, +// }, +// } +// +// mg.AddMigration("create alert_heartbeat table v1", NewAddTableMigration(alert_heartbeat)) +// +// diff --git a/pkg/services/sqlstore/migrations/migrations.go b/pkg/services/sqlstore/migrations/migrations.go index 7a6ba554246..f0f69ee0e23 100644 --- a/pkg/services/sqlstore/migrations/migrations.go +++ b/pkg/services/sqlstore/migrations/migrations.go @@ -22,6 +22,8 @@ func AddMigrations(mg *Migrator) { addSessionMigration(mg) addPlaylistMigrations(mg) addPreferencesMigrations(mg) + addAlertMigrations(mg) + addAnnotationMig(mg) } func addMigrationLogMigrations(mg *Migrator) { diff --git a/pkg/services/sqlstore/migrations/migrations_test.go b/pkg/services/sqlstore/migrations/migrations_test.go index 0278ea6632b..5bddf6ff605 100644 --- a/pkg/services/sqlstore/migrations/migrations_test.go +++ b/pkg/services/sqlstore/migrations/migrations_test.go @@ -8,6 +8,7 @@ import ( "github.com/grafana/grafana/pkg/services/sqlstore/sqlutil" . "github.com/smartystreets/goconvey/convey" + //"github.com/grafana/grafana/pkg/log" ) var indexTypes = []string{"Unknown", "INDEX", "UNIQUE INDEX"} @@ -28,7 +29,6 @@ func TestMigrations(t *testing.T) { sqlutil.CleanDB(x) mg := NewMigrator(x) - //mg.LogLevel = log.DEBUG AddMigrations(mg) err = mg.Start() diff --git a/pkg/services/sqlstore/migrations/plugin_setting.go b/pkg/services/sqlstore/migrations/plugin_setting.go index 4a8729691d3..0700ab67d2f 100644 --- a/pkg/services/sqlstore/migrations/plugin_setting.go +++ b/pkg/services/sqlstore/migrations/plugin_setting.go @@ -26,4 +26,10 @@ func addAppSettingsMigration(mg *Migrator) { //------- indexes ------------------ addTableIndicesMigrations(mg, "v1", pluginSettingTable) + + // add column to store installed version + mg.AddMigration("Add column plugin_version to plugin_settings", NewAddColumnMigration(pluginSettingTable, &Column{ + Name: "plugin_version", Type: DB_NVarchar, Nullable: true, Length: 50, + })) + } diff --git a/pkg/services/sqlstore/migrations/preferences_mig.go b/pkg/services/sqlstore/migrations/preferences_mig.go index 0ce01857b75..67a8169a7a8 100644 --- a/pkg/services/sqlstore/migrations/preferences_mig.go +++ b/pkg/services/sqlstore/migrations/preferences_mig.go @@ -4,17 +4,29 @@ import . "github.com/grafana/grafana/pkg/services/sqlstore/migrator" func addPreferencesMigrations(mg *Migrator) { - preferencesV1 := Table{ + mg.AddMigration("drop preferences table v2", NewDropTableMigration("preferences")) + + preferencesV2 := Table{ Name: "preferences", Columns: []*Column{ {Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true}, - {Name: "pref_id", Type: DB_Int, Nullable: false}, - {Name: "pref_type", Type: DB_NVarchar, Length: 255, Nullable: false}, - {Name: "pref_data", Type: DB_Text, Nullable: false}, + {Name: "org_id", Type: DB_BigInt, Nullable: false}, + {Name: "user_id", Type: DB_BigInt, Nullable: false}, + {Name: "version", Type: DB_Int, Nullable: false}, + {Name: "home_dashboard_id", Type: DB_BigInt, Nullable: false}, + {Name: "timezone", Type: DB_NVarchar, Length: 50, Nullable: false}, + {Name: "theme", Type: DB_NVarchar, Length: 20, Nullable: false}, + {Name: "created", Type: DB_DateTime, Nullable: false}, + {Name: "updated", Type: DB_DateTime, Nullable: false}, + }, + Indices: []*Index{ + {Cols: []string{"org_id"}}, + {Cols: []string{"user_id"}}, }, } - // create table - mg.AddMigration("create preferences table v1", NewAddTableMigration(preferencesV1)) + mg.AddMigration("drop preferences table v3", NewDropTableMigration("preferences")) + // create table + mg.AddMigration("create preferences table v3", NewAddTableMigration(preferencesV2)) } diff --git a/pkg/services/sqlstore/migrations/user_mig.go b/pkg/services/sqlstore/migrations/user_mig.go index 51db4d74857..67446f64d1a 100644 --- a/pkg/services/sqlstore/migrations/user_mig.go +++ b/pkg/services/sqlstore/migrations/user_mig.go @@ -88,4 +88,8 @@ func addUserMigrations(mg *Migrator) { })) mg.AddMigration("Drop old table user_v1", NewDropTableMigration("user_v1")) + + mg.AddMigration("Add column help_flags1 to user table", NewAddColumnMigration(userV2, &Column{ + Name: "help_flags1", Type: DB_BigInt, Nullable: false, Default: "0", + })) } diff --git a/pkg/services/sqlstore/migrator/dialect.go b/pkg/services/sqlstore/migrator/dialect.go index 0c94eb82234..4473b560428 100644 --- a/pkg/services/sqlstore/migrator/dialect.go +++ b/pkg/services/sqlstore/migrator/dialect.go @@ -18,6 +18,7 @@ type Dialect interface { SupportEngine() bool LikeStr() string Default(col *Column) string + BooleanStr(bool) string CreateIndexSql(tableName string, index *Index) string CreateTableSql(table *Table) string diff --git a/pkg/services/sqlstore/migrator/migrator.go b/pkg/services/sqlstore/migrator/migrator.go index 48000e34ca2..64831ee46b4 100644 --- a/pkg/services/sqlstore/migrator/migrator.go +++ b/pkg/services/sqlstore/migrator/migrator.go @@ -11,11 +11,10 @@ import ( ) type Migrator struct { - LogLevel log.LogLevel - x *xorm.Engine dialect Dialect migrations []Migration + Logger log.Logger } type MigrationLog struct { @@ -30,7 +29,7 @@ type MigrationLog struct { func NewMigrator(engine *xorm.Engine) *Migrator { mg := &Migrator{} mg.x = engine - mg.LogLevel = log.WARN + mg.Logger = log.New("migrator") mg.migrations = make([]Migration, 0) mg.dialect = NewDialect(mg.x.DriverName()) return mg @@ -69,9 +68,7 @@ func (mg *Migrator) GetMigrationLog() (map[string]MigrationLog, error) { } func (mg *Migrator) Start() error { - if mg.LogLevel <= log.INFO { - log.Info("Migrator: Starting DB migration") - } + mg.Logger.Info("Starting DB migration") logMap, err := mg.GetMigrationLog() if err != nil { @@ -81,9 +78,7 @@ func (mg *Migrator) Start() error { for _, m := range mg.migrations { _, exists := logMap[m.Id()] if exists { - if mg.LogLevel <= log.DEBUG { - log.Debug("Migrator: Skipping migration: %v, Already executed", m.Id()) - } + mg.Logger.Debug("Skipping migration: Already executed", "id", m.Id()) continue } @@ -95,50 +90,47 @@ func (mg *Migrator) Start() error { Timestamp: time.Now(), } - if mg.LogLevel <= log.DEBUG { - log.Debug("Migrator: Executing SQL: \n %v \n", sql) - } + mg.Logger.Debug("Executing", "sql", sql) - if err := mg.exec(m); err != nil { - log.Error(3, "Migrator: error: \n%s:\n%s", err, sql) - record.Error = err.Error() - mg.x.Insert(&record) + err := mg.inTransaction(func(sess *xorm.Session) error { + + if err := mg.exec(m, sess); err != nil { + mg.Logger.Error("Exec failed", "error", err, "sql", sql) + record.Error = err.Error() + sess.Insert(&record) + return err + } else { + record.Success = true + sess.Insert(&record) + } + + return nil + }) + + if err != nil { return err - } else { - record.Success = true - mg.x.Insert(&record) } } return nil } -func (mg *Migrator) exec(m Migration) error { - if mg.LogLevel <= log.INFO { - log.Info("Migrator: exec migration id: %v", m.Id()) +func (mg *Migrator) exec(m Migration, sess *xorm.Session) error { + mg.Logger.Info("Executing migration", "id", m.Id()) + + condition := m.GetCondition() + if condition != nil { + sql, args := condition.Sql(mg.dialect) + results, err := sess.Query(sql, args...) + if err != nil || len(results) == 0 { + mg.Logger.Info("Skipping migration condition not fulfilled", "id", m.Id()) + return sess.Rollback() + } } - err := mg.inTransaction(func(sess *xorm.Session) error { - - condition := m.GetCondition() - if condition != nil { - sql, args := condition.Sql(mg.dialect) - results, err := sess.Query(sql, args...) - if err != nil || len(results) == 0 { - log.Info("Migrator: skipping migration id: %v, condition not fulfilled", m.Id()) - return sess.Rollback() - } - } - - _, err := sess.Exec(m.Sql(mg.dialect)) - if err != nil { - log.Error(3, "Migrator: exec FAILED migration id: %v, err: %v", m.Id(), err) - return err - } - return nil - }) - + _, err := sess.Exec(m.Sql(mg.dialect)) if err != nil { + mg.Logger.Error("Executing migration failed", "id", m.Id(), "error", err) return err } diff --git a/pkg/services/sqlstore/migrator/mysql_dialect.go b/pkg/services/sqlstore/migrator/mysql_dialect.go index 195d52d1934..48c2cd3ea55 100644 --- a/pkg/services/sqlstore/migrator/mysql_dialect.go +++ b/pkg/services/sqlstore/migrator/mysql_dialect.go @@ -29,6 +29,13 @@ func (db *Mysql) AutoIncrStr() string { return "AUTO_INCREMENT" } +func (db *Mysql) BooleanStr(value bool) string { + if value { + return "1" + } + return "0" +} + func (db *Mysql) SqlType(c *Column) string { var res string switch c.Type { diff --git a/pkg/services/sqlstore/migrator/postgres_dialect.go b/pkg/services/sqlstore/migrator/postgres_dialect.go index 826a00a1410..5500b9f1684 100644 --- a/pkg/services/sqlstore/migrator/postgres_dialect.go +++ b/pkg/services/sqlstore/migrator/postgres_dialect.go @@ -36,6 +36,10 @@ func (db *Postgres) AutoIncrStr() string { return "" } +func (db *Postgres) BooleanStr(value bool) string { + return strconv.FormatBool(value) +} + func (b *Postgres) Default(col *Column) string { if col.Type == DB_Bool { if col.Default == "0" { diff --git a/pkg/services/sqlstore/migrator/sqlite_dialect.go b/pkg/services/sqlstore/migrator/sqlite_dialect.go index 8555754ab92..fe1e781c8df 100644 --- a/pkg/services/sqlstore/migrator/sqlite_dialect.go +++ b/pkg/services/sqlstore/migrator/sqlite_dialect.go @@ -29,6 +29,13 @@ func (db *Sqlite3) AutoIncrStr() string { return "AUTOINCREMENT" } +func (db *Sqlite3) BooleanStr(value bool) string { + if value { + return "1" + } + return "0" +} + func (db *Sqlite3) SqlType(c *Column) string { switch c.Type { case DB_Date, DB_DateTime, DB_TimeStamp, DB_Time: diff --git a/pkg/services/sqlstore/org.go b/pkg/services/sqlstore/org.go index 6ac171127c9..919bb6fd026 100644 --- a/pkg/services/sqlstore/org.go +++ b/pkg/services/sqlstore/org.go @@ -133,10 +133,16 @@ func UpdateOrg(cmd *m.UpdateOrgCommand) error { Updated: time.Now(), } - if _, err := sess.Id(cmd.OrgId).Update(&org); err != nil { + affectedRows, err := sess.Id(cmd.OrgId).Update(&org) + + if err != nil { return err } + if affectedRows == 0 { + return m.ErrOrgNotFound + } + sess.publishAfterCommit(&events.OrgUpdated{ Timestamp: org.Updated, Id: org.Id, @@ -176,6 +182,11 @@ func UpdateOrgAddress(cmd *m.UpdateOrgAddressCommand) error { func DeleteOrg(cmd *m.DeleteOrgCommand) error { return inTransaction2(func(sess *session) error { + if res, err := sess.Query("SELECT 1 from org WHERE id=?", cmd.Id); err != nil { + return err + } else if len(res) != 1 { + return m.ErrOrgNotFound + } deletes := []string{ "DELETE FROM star WHERE EXISTS (SELECT 1 FROM dashboard WHERE org_id = ? AND star.dashboard_id = dashboard.id)", diff --git a/pkg/services/sqlstore/org_users.go b/pkg/services/sqlstore/org_users.go index fdd671d0bfe..11ea558b0ce 100644 --- a/pkg/services/sqlstore/org_users.go +++ b/pkg/services/sqlstore/org_users.go @@ -26,6 +26,12 @@ func AddOrgUser(cmd *m.AddOrgUserCommand) error { return m.ErrOrgUserAlreadyAdded } + if res, err := sess.Query("SELECT 1 from org WHERE id=?", cmd.OrgId); err != nil { + return err + } else if len(res) != 1 { + return m.ErrOrgNotFound + } + entity := m.OrgUser{ OrgId: cmd.OrgId, UserId: cmd.UserId, diff --git a/pkg/services/sqlstore/plugin_setting.go b/pkg/services/sqlstore/plugin_setting.go index b3285e905cf..8121b8c7b4b 100644 --- a/pkg/services/sqlstore/plugin_setting.go +++ b/pkg/services/sqlstore/plugin_setting.go @@ -13,14 +13,20 @@ func init() { bus.AddHandler("sql", GetPluginSettings) bus.AddHandler("sql", GetPluginSettingById) bus.AddHandler("sql", UpdatePluginSetting) + bus.AddHandler("sql", UpdatePluginSettingVersion) } func GetPluginSettings(query *m.GetPluginSettingsQuery) error { - sql := `SELECT org_id, plugin_id, enabled, pinned - FROM plugin_setting - WHERE org_id=?` + sql := `SELECT org_id, plugin_id, enabled, pinned, plugin_version + FROM plugin_setting ` + params := make([]interface{}, 0) - sess := x.Sql(sql, query.OrgId) + if query.OrgId != 0 { + sql += "WHERE org_id=?" + params = append(params, query.OrgId) + } + + sess := x.Sql(sql, params...) query.Result = make([]*m.PluginSettingInfoDTO, 0) return sess.Find(&query.Result) } @@ -51,23 +57,52 @@ func UpdatePluginSetting(cmd *m.UpdatePluginSettingCmd) error { Enabled: cmd.Enabled, Pinned: cmd.Pinned, JsonData: cmd.JsonData, + PluginVersion: cmd.PluginVersion, SecureJsonData: cmd.GetEncryptedJsonData(), Created: time.Now(), Updated: time.Now(), } + + // add state change event on commit success + sess.events = append(sess.events, &m.PluginStateChangedEvent{ + PluginId: cmd.PluginId, + OrgId: cmd.OrgId, + Enabled: cmd.Enabled, + }) + _, err = sess.Insert(&pluginSetting) return err } else { for key, data := range cmd.SecureJsonData { pluginSetting.SecureJsonData[key] = util.Encrypt([]byte(data), setting.SecretKey) } - pluginSetting.SecureJsonData = cmd.GetEncryptedJsonData() + + // add state change event on commit success + if pluginSetting.Enabled != cmd.Enabled { + sess.events = append(sess.events, &m.PluginStateChangedEvent{ + PluginId: cmd.PluginId, + OrgId: cmd.OrgId, + Enabled: cmd.Enabled, + }) + } + pluginSetting.Updated = time.Now() pluginSetting.Enabled = cmd.Enabled pluginSetting.JsonData = cmd.JsonData pluginSetting.Pinned = cmd.Pinned + pluginSetting.PluginVersion = cmd.PluginVersion + _, err = sess.Id(pluginSetting.Id).Update(&pluginSetting) return err } }) } + +func UpdatePluginSettingVersion(cmd *m.UpdatePluginSettingVersionCmd) error { + return inTransaction2(func(sess *session) error { + + _, err := sess.Exec("UPDATE plugin_setting SET plugin_version=? WHERE org_id=? AND plugin_id=?", cmd.PluginVersion, cmd.OrgId, cmd.PluginId) + return err + + }) +} diff --git a/pkg/services/sqlstore/preferences.go b/pkg/services/sqlstore/preferences.go new file mode 100644 index 00000000000..65609a9c57c --- /dev/null +++ b/pkg/services/sqlstore/preferences.go @@ -0,0 +1,98 @@ +package sqlstore + +import ( + "time" + + "github.com/grafana/grafana/pkg/bus" + m "github.com/grafana/grafana/pkg/models" + + "github.com/grafana/grafana/pkg/setting" +) + +func init() { + bus.AddHandler("sql", GetPreferences) + bus.AddHandler("sql", GetPreferencesWithDefaults) + bus.AddHandler("sql", SavePreferences) +} + +func GetPreferencesWithDefaults(query *m.GetPreferencesWithDefaultsQuery) error { + + prefs := make([]*m.Preferences, 0) + filter := "(org_id=? AND user_id=?) OR (org_id=? AND user_id=0)" + err := x.Where(filter, query.OrgId, query.UserId, query.OrgId). + OrderBy("user_id ASC"). + Find(&prefs) + + if err != nil { + return err + } + + res := &m.Preferences{ + Theme: setting.DefaultTheme, + Timezone: "browser", + HomeDashboardId: 0, + } + + for _, p := range prefs { + if p.Theme != "" { + res.Theme = p.Theme + } + if p.Timezone != "" { + res.Timezone = p.Timezone + } + if p.HomeDashboardId != 0 { + res.HomeDashboardId = p.HomeDashboardId + } + } + + query.Result = res + return nil +} + +func GetPreferences(query *m.GetPreferencesQuery) error { + + var prefs m.Preferences + exists, err := x.Where("org_id=? AND user_id=?", query.OrgId, query.UserId).Get(&prefs) + + if err != nil { + return err + } + + if exists { + query.Result = &prefs + } else { + query.Result = new(m.Preferences) + } + + return nil +} + +func SavePreferences(cmd *m.SavePreferencesCommand) error { + return inTransaction2(func(sess *session) error { + + var prefs m.Preferences + exists, err := sess.Where("org_id=? AND user_id=?", cmd.OrgId, cmd.UserId).Get(&prefs) + + if !exists { + prefs = m.Preferences{ + UserId: cmd.UserId, + OrgId: cmd.OrgId, + HomeDashboardId: cmd.HomeDashboardId, + Timezone: cmd.Timezone, + Theme: cmd.Theme, + Created: time.Now(), + Updated: time.Now(), + } + _, err = sess.Insert(&prefs) + return err + } else { + prefs.HomeDashboardId = cmd.HomeDashboardId + prefs.Timezone = cmd.Timezone + prefs.Theme = cmd.Theme + prefs.Updated = time.Now() + prefs.Version += 1 + _, err := sess.Id(prefs.Id).AllCols().Update(&prefs) + return err + } + }) +} diff --git a/pkg/services/sqlstore/sqlstore.go b/pkg/services/sqlstore/sqlstore.go index 8dae7247a39..5c44fe85f50 100644 --- a/pkg/services/sqlstore/sqlstore.go +++ b/pkg/services/sqlstore/sqlstore.go @@ -2,6 +2,7 @@ package sqlstore import ( "fmt" + "net/url" "os" "path" "path/filepath" @@ -10,6 +11,7 @@ import ( "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/log" m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/annotations" "github.com/grafana/grafana/pkg/services/sqlstore/migrations" "github.com/grafana/grafana/pkg/services/sqlstore/migrator" "github.com/grafana/grafana/pkg/setting" @@ -21,12 +23,12 @@ import ( _ "github.com/mattn/go-sqlite3" ) -type MySQLConfig struct { - SslMode string - CaCertPath string - ClientKeyPath string - ClientCertPath string - ServerCertName string +type DatabaseConfig struct { + Type, Host, Name, User, Pwd, Path, SslMode string + CaCertPath string + ClientKeyPath string + ClientCertPath string + ServerCertName string } var ( @@ -35,13 +37,10 @@ var ( HasEngine bool - DbCfg struct { - Type, Host, Name, User, Pwd, Path, SslMode string - } - - mysqlConfig MySQLConfig + DbCfg DatabaseConfig UseSQLite3 bool + sqlog log.Logger = log.New("sqlstore") ) func EnsureAdminUser() { @@ -74,38 +73,30 @@ func NewEngine() { x, err := getEngine() if err != nil { - log.Fatal(3, "Sqlstore: Fail to connect to database: %v", err) + sqlog.Crit("Fail to connect to database", "error", err) + os.Exit(1) } - err = SetEngine(x, setting.Env == setting.DEV) + err = SetEngine(x) if err != nil { - log.Fatal(3, "fail to initialize orm engine: %v", err) + sqlog.Error("Fail to initialize orm engine", "error", err) + os.Exit(1) } } -func SetEngine(engine *xorm.Engine, enableLog bool) (err error) { +func SetEngine(engine *xorm.Engine) (err error) { x = engine dialect = migrator.NewDialect(x.DriverName()) migrator := migrator.NewMigrator(x) - migrator.LogLevel = log.INFO migrations.AddMigrations(migrator) if err := migrator.Start(); err != nil { return fmt.Errorf("Sqlstore::Migration failed err: %v\n", err) } - if enableLog { - logPath := path.Join(setting.LogsPath, "xorm.log") - os.MkdirAll(path.Dir(logPath), os.ModePerm) - - f, err := os.Create(logPath) - if err != nil { - return fmt.Errorf("sqlstore.init(fail to create xorm.log): %v", err) - } - x.Logger = xorm.NewSimpleLogger(f) - } + annotations.SetRepository(&SqlAnnotationRepo{}) return nil } @@ -124,8 +115,8 @@ func getEngine() (*xorm.Engine, error) { cnnstr = fmt.Sprintf("%s:%s@%s(%s)/%s?charset=utf8", DbCfg.User, DbCfg.Pwd, protocol, DbCfg.Host, DbCfg.Name) - if mysqlConfig.SslMode == "true" || mysqlConfig.SslMode == "skip-verify" { - tlsCert, err := makeCert("custom", mysqlConfig) + if DbCfg.SslMode == "true" || DbCfg.SslMode == "skip-verify" { + tlsCert, err := makeCert("custom", DbCfg) if err != nil { return nil, err } @@ -147,7 +138,7 @@ func getEngine() (*xorm.Engine, error) { if DbCfg.User == "" { DbCfg.User = "''" } - cnnstr = fmt.Sprintf("user=%s password=%s host=%s port=%s dbname=%s sslmode=%s", DbCfg.User, DbCfg.Pwd, host, port, DbCfg.Name, DbCfg.SslMode) + cnnstr = fmt.Sprintf("user=%s password=%s host=%s port=%s dbname=%s sslmode=%s sslcert=%s sslkey=%s sslrootcert=%s", DbCfg.User, DbCfg.Pwd, host, port, DbCfg.Name, DbCfg.SslMode, DbCfg.ClientCertPath, DbCfg.ClientKeyPath, DbCfg.CaCertPath) case "sqlite3": if !filepath.IsAbs(DbCfg.Path) { DbCfg.Path = filepath.Join(setting.DataPath, DbCfg.Path) @@ -158,32 +149,46 @@ func getEngine() (*xorm.Engine, error) { return nil, fmt.Errorf("Unknown database type: %s", DbCfg.Type) } - log.Info("Database: %v", DbCfg.Type) - + sqlog.Info("Initializing DB", "dbtype", DbCfg.Type) return xorm.NewEngine(DbCfg.Type, cnnstr) } func LoadConfig() { sec := setting.Cfg.Section("database") - DbCfg.Type = sec.Key("type").String() + cfgURL := sec.Key("url").String() + if len(cfgURL) != 0 { + dbURL, _ := url.Parse(cfgURL) + DbCfg.Type = dbURL.Scheme + DbCfg.Host = dbURL.Host + + pathSplit := strings.Split(dbURL.Path, "/") + if len(pathSplit) > 1 { + DbCfg.Name = pathSplit[1] + } + + userInfo := dbURL.User + if userInfo != nil { + DbCfg.User = userInfo.Username() + DbCfg.Pwd, _ = userInfo.Password() + } + } else { + DbCfg.Type = sec.Key("type").String() + DbCfg.Host = sec.Key("host").String() + DbCfg.Name = sec.Key("name").String() + DbCfg.User = sec.Key("user").String() + if len(DbCfg.Pwd) == 0 { + DbCfg.Pwd = sec.Key("password").String() + } + } + if DbCfg.Type == "sqlite3" { UseSQLite3 = true } - DbCfg.Host = sec.Key("host").String() - DbCfg.Name = sec.Key("name").String() - DbCfg.User = sec.Key("user").String() - if len(DbCfg.Pwd) == 0 { - DbCfg.Pwd = sec.Key("password").String() - } DbCfg.SslMode = sec.Key("ssl_mode").String() + DbCfg.CaCertPath = sec.Key("ca_cert_path").String() + DbCfg.ClientKeyPath = sec.Key("client_key_path").String() + DbCfg.ClientCertPath = sec.Key("client_cert_path").String() + DbCfg.ServerCertName = sec.Key("server_cert_name").String() DbCfg.Path = sec.Key("path").MustString("data/grafana.db") - - if DbCfg.Type == "mysql" { - mysqlConfig.SslMode = DbCfg.SslMode - mysqlConfig.CaCertPath = sec.Key("ca_cert_path").String() - mysqlConfig.ClientKeyPath = sec.Key("client_key_path").String() - mysqlConfig.ClientCertPath = sec.Key("client_cert_path").String() - mysqlConfig.ServerCertName = sec.Key("server_cert_name").String() - } } diff --git a/pkg/services/sqlstore/stats.go b/pkg/services/sqlstore/stats.go index 92efab2015d..dd1a8111332 100644 --- a/pkg/services/sqlstore/stats.go +++ b/pkg/services/sqlstore/stats.go @@ -39,7 +39,11 @@ func GetSystemStats(query *m.GetSystemStatsQuery) error { ( SELECT COUNT(*) FROM ` + dialect.Quote("playlist") + ` - ) AS playlist_count + ) AS playlist_count, + ( + SELECT COUNT(*) + FROM ` + dialect.Quote("alert") + ` + ) AS alert_count ` var stats m.SystemStats @@ -88,9 +92,8 @@ func GetAdminStats(query *m.GetAdminStatsQuery) error { ) AS starred_db_count, ( SELECT COUNT(*) - FROM ` + dialect.Quote("user") + ` - WHERE ` + dialect.Quote("is_admin") + ` = 1 - ) AS grafana_admin_count + FROM ` + dialect.Quote("alert") + ` + ) AS alert_count ` var stats m.AdminStats diff --git a/pkg/services/sqlstore/tls_mysql.go b/pkg/services/sqlstore/tls_mysql.go index fb55eb401c9..3c9475e19a0 100644 --- a/pkg/services/sqlstore/tls_mysql.go +++ b/pkg/services/sqlstore/tls_mysql.go @@ -7,7 +7,7 @@ import ( "io/ioutil" ) -func makeCert(tlsPoolName string, config MySQLConfig) (*tls.Config, error) { +func makeCert(tlsPoolName string, config DatabaseConfig) (*tls.Config, error) { rootCertPool := x509.NewCertPool() pem, err := ioutil.ReadFile(config.CaCertPath) if err != nil { diff --git a/pkg/services/sqlstore/user.go b/pkg/services/sqlstore/user.go index 96b8c24b8fc..b26a9153f55 100644 --- a/pkg/services/sqlstore/user.go +++ b/pkg/services/sqlstore/user.go @@ -19,6 +19,7 @@ func init() { bus.AddHandler("sql", UpdateUser) bus.AddHandler("sql", ChangeUserPassword) bus.AddHandler("sql", GetUserByLogin) + bus.AddHandler("sql", GetUserByEmail) bus.AddHandler("sql", SetUsingOrg) bus.AddHandler("sql", GetUserProfile) bus.AddHandler("sql", GetSignedInUser) @@ -27,6 +28,7 @@ func init() { bus.AddHandler("sql", DeleteUser) bus.AddHandler("sql", SetUsingOrg) bus.AddHandler("sql", UpdateUserPermissions) + bus.AddHandler("sql", SetUserHelpFlag) } func getOrgIdForNewUser(cmd *m.CreateUserCommand, sess *session) (int64, error) { @@ -128,7 +130,11 @@ func CreateUser(cmd *m.CreateUserCommand) error { } if setting.AutoAssignOrg && !user.IsAdmin { - orgUser.Role = m.RoleType(setting.AutoAssignOrgRole) + if len(cmd.DefaultOrgRole) > 0 { + orgUser.Role = m.RoleType(cmd.DefaultOrgRole) + } else { + orgUser.Role = m.RoleType(setting.AutoAssignOrgRole) + } } if _, err = sess.Insert(&orgUser); err != nil { @@ -161,12 +167,42 @@ func GetUserByLogin(query *m.GetUserByLoginQuery) error { } user := new(m.User) - if strings.Contains(query.LoginOrEmail, "@") { - user = &m.User{Email: query.LoginOrEmail} - } else { - user = &m.User{Login: query.LoginOrEmail} + + // Try and find the user by login first. + // It's not sufficient to assume that a LoginOrEmail with an "@" is an email. + user = &m.User{Login: query.LoginOrEmail} + has, err := x.Get(user) + + if err != nil { + return err } + if has == false && strings.Contains(query.LoginOrEmail, "@") { + // If the user wasn't found, and it contains an "@" fallback to finding the + // user by email. + user = &m.User{Email: query.LoginOrEmail} + has, err = x.Get(user) + } + + if err != nil { + return err + } else if has == false { + return m.ErrUserNotFound + } + + query.Result = user + + return nil +} + +func GetUserByEmail(query *m.GetUserByEmailQuery) error { + if query.Email == "" { + return m.ErrUserNotFound + } + + user := new(m.User) + + user = &m.User{Email: query.Email} has, err := x.Get(user) if err != nil { @@ -273,7 +309,7 @@ func GetSignedInUser(query *m.GetSignedInUserQuery) error { u.email as email, u.login as login, u.name as name, - u.theme as theme, + u.help_flags1 as help_flags1, org.name as org_name, org_user.role as org_role, org.id as org_id @@ -346,3 +382,20 @@ func UpdateUserPermissions(cmd *m.UpdateUserPermissionsCommand) error { return err }) } + +func SetUserHelpFlag(cmd *m.SetUserHelpFlagCommand) error { + return inTransaction2(func(sess *session) error { + + user := m.User{ + Id: cmd.UserId, + HelpFlags1: cmd.HelpFlags1, + Updated: time.Now(), + } + + if _, err := sess.Id(cmd.UserId).Cols("help_flags1").Update(&user); err != nil { + return err + } + + return nil + }) +} diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index b8e8d7f7fcf..0de7b87b164 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -5,7 +5,6 @@ package setting import ( "bytes" - "encoding/json" "fmt" "net/url" "os" @@ -25,8 +24,9 @@ import ( type Scheme string const ( - HTTP Scheme = "http" - HTTPS Scheme = "https" + HTTP Scheme = "http" + HTTPS Scheme = "https" + DEFAULT_HTTP_ADDR string = "0.0.0.0" ) const ( @@ -37,9 +37,10 @@ const ( var ( // App settings. - Env string = DEV - AppUrl string - AppSubUrl string + Env string = DEV + AppUrl string + AppSubUrl string + InstanceName string // build BuildVersion string @@ -47,10 +48,11 @@ var ( BuildStamp int64 // Paths - LogsPath string - HomePath string - DataPath string - PluginsPath string + LogsPath string + HomePath string + DataPath string + PluginsPath string + CustomInitPath = "conf/custom.ini" // Log settings. LogModes []string @@ -77,9 +79,11 @@ var ( DataProxyWhiteList map[string]bool // Snapshots - ExternalSnapshotUrl string - ExternalSnapshotName string - ExternalEnabled bool + ExternalSnapshotUrl string + ExternalSnapshotName string + ExternalEnabled bool + SnapShotTTLDays int + SnapShotRemoveExpired bool // User settings AllowUserSignUp bool @@ -88,6 +92,8 @@ var ( AutoAssignOrgRole string VerifyEmailEnabled bool LoginHint string + DefaultTheme string + DisableLoginForm bool // Http auth AdminUser string @@ -102,6 +108,8 @@ var ( AuthProxyHeaderName string AuthProxyHeaderProperty string AuthProxyAutoSignUp bool + AuthProxyLdapSyncTtl int + AuthProxyWhitelist string // Basic Auth BasicAuthEnabled bool @@ -124,18 +132,36 @@ var ( appliedEnvOverrides []string ReportingEnabled bool + CheckForUpdates bool GoogleAnalyticsId string GoogleTagManagerId string // LDAP - LdapEnabled bool - LdapConfigFile string + LdapEnabled bool + LdapConfigFile string + LdapAllowSignup bool = true // SMTP email settings Smtp SmtpSettings // QUOTA Quota QuotaSettings + + // Alerting + ExecuteAlerts bool + + // logger + logger log.Logger + + // Grafana.NET URL + GrafanaNetUrl string + + // S3 temp image store + S3TempImageStoreBucketUrl string + S3TempImageStoreAccessKey string + S3TempImageStoreSecretKey string + + ImageUploadProvider string ) type CommandLineArgs struct { @@ -146,7 +172,7 @@ type CommandLineArgs struct { func init() { IsWindows = runtime.GOOS == "windows" - log.NewLogger(0, "console", `{"level": 0, "formatting":true}`) + logger = log.New("settings") } func parseAppUrlAndSubUrl(section *ini.Section) (string, string) { @@ -171,7 +197,12 @@ func ToAbsUrl(relativeUrl string) string { func shouldRedactKey(s string) bool { uppercased := strings.ToUpper(s) - return strings.Contains(uppercased, "PASSWORD") || strings.Contains(uppercased, "SECRET") + return strings.Contains(uppercased, "PASSWORD") || strings.Contains(uppercased, "SECRET") || strings.Contains(uppercased, "PROVIDER_CONFIG") +} + +func shouldRedactURLKey(s string) bool { + uppercased := strings.ToUpper(s) + return strings.Contains(uppercased, "DATABASE_URL") } func applyEnvVariableOverrides() { @@ -188,6 +219,17 @@ func applyEnvVariableOverrides() { if shouldRedactKey(envKey) { envValue = "*********" } + if shouldRedactURLKey(envKey) { + u, _ := url.Parse(envValue) + ui := u.User + if ui != nil { + _, exists := ui.Password() + if exists { + u.User = url.UserPassword(ui.Username(), "-redacted-") + envValue = u.String() + } + } + } appliedEnvOverrides = append(appliedEnvOverrides, fmt.Sprintf("%s=%s", envKey, envValue)) } } @@ -257,6 +299,12 @@ func evalEnvVarExpression(value string) string { envVar = strings.TrimPrefix(envVar, "${") envVar = strings.TrimSuffix(envVar, "}") envValue := os.Getenv(envVar) + + // if env variable is hostname and it is emtpy use os.Hostname as default + if envVar == "HOSTNAME" && envValue == "" { + envValue, _ = os.Hostname() + } + return envValue }) } @@ -269,21 +317,22 @@ func evalConfigValues() { } } -func loadSpecifedConfigFile(configFile string) { +func loadSpecifedConfigFile(configFile string) error { if configFile == "" { - configFile = filepath.Join(HomePath, "conf/custom.ini") + configFile = filepath.Join(HomePath, CustomInitPath) // return without error if custom file does not exist if !pathExists(configFile) { - return + return nil } } userConfig, err := ini.Load(configFile) - userConfig.BlockMode = false if err != nil { - log.Fatal(3, "Failed to parse %v, %v", configFile, err) + return fmt.Errorf("Failed to parse %v, %v", configFile, err) } + userConfig.BlockMode = false + for _, section := range userConfig.Sections() { for _, key := range section.Keys() { if key.Value() == "" { @@ -303,6 +352,7 @@ func loadSpecifedConfigFile(configFile string) { } configFiles = append(configFiles, configFile) + return nil } func loadConfiguration(args *CommandLineArgs) { @@ -312,24 +362,33 @@ func loadConfiguration(args *CommandLineArgs) { defaultConfigFile := path.Join(HomePath, "conf/defaults.ini") configFiles = append(configFiles, defaultConfigFile) - Cfg, err = ini.Load(defaultConfigFile) - Cfg.BlockMode = false - - if err != nil { - log.Fatal(3, "Failed to parse defaults.ini, %v", err) + // check if config file exists + if _, err := os.Stat(defaultConfigFile); os.IsNotExist(err) { + fmt.Println("Grafana-server Init Failed: Could not find config defaults, make sure homepath command line parameter is set or working directory is homepath") + os.Exit(1) } + // load defaults + Cfg, err = ini.Load(defaultConfigFile) + if err != nil { + fmt.Println(fmt.Sprintf("Failed to parse defaults.ini, %v", err)) + os.Exit(1) + return + } + + Cfg.BlockMode = false + // command line props commandLineProps := getCommandLineProperties(args.Args) // load default overrides applyCommandLineDefaultProperties(commandLineProps) - // init logging before specific config so we can log errors from here on - DataPath = makeAbsolute(Cfg.Section("paths").Key("data").String(), HomePath) - initLogging(args) - // load specified config file - loadSpecifedConfigFile(args.Config) + err = loadSpecifedConfigFile(args.Config) + if err != nil { + initLogging() + log.Fatal(3, err.Error()) + } // apply environment overrides applyEnvVariableOverrides() @@ -342,7 +401,7 @@ func loadConfiguration(args *CommandLineArgs) { // update data path and logging config DataPath = makeAbsolute(Cfg.Section("paths").Key("data").String(), HomePath) - initLogging(args) + initLogging() } func pathExists(path string) bool { @@ -393,12 +452,29 @@ func validateStaticRootPath() error { return fmt.Errorf("Failed to detect generated css or javascript files in static root (%s), have you executed default grunt task?", StaticRootPath) } +// func readInstanceName() string { +// hostname, _ := os.Hostname() +// if hostname == "" { +// hostname = "hostname_unknown" +// } +// +// instanceName := Cfg.Section("").Key("instance_name").MustString("") +// if instanceName = "" { +// // set value as it might be used in other places +// Cfg.Section("").Key("instance_name").SetValue(hostname) +// instanceName = hostname +// } +// +// return +// } + func NewConfigContext(args *CommandLineArgs) error { setHomePath(args) loadConfiguration(args) Env = Cfg.Section("").Key("app_mode").MustString("development") - PluginsPath = Cfg.Section("paths").Key("plugins").String() + InstanceName = Cfg.Section("").Key("instance_name").MustString("unknown_instance_name") + PluginsPath = makeAbsolute(Cfg.Section("paths").Key("plugins").String(), HomePath) server := Cfg.Section("server") AppUrl, AppSubUrl = parseAppUrlAndSubUrl(server) @@ -411,7 +487,7 @@ func NewConfigContext(args *CommandLineArgs) error { } Domain = server.Key("domain").MustString("localhost") - HttpAddr = server.Key("http_addr").MustString("0.0.0.0") + HttpAddr = server.Key("http_addr").MustString(DEFAULT_HTTP_ADDR) HttpPort = server.Key("http_port").MustString("3000") RouterLogging = server.Key("router_logging").MustBool(false) EnableGzip = server.Key("enable_gzip").MustBool(false) @@ -435,6 +511,8 @@ func NewConfigContext(args *CommandLineArgs) error { ExternalSnapshotUrl = snapshots.Key("external_snapshot_url").String() ExternalSnapshotName = snapshots.Key("external_snapshot_name").String() ExternalEnabled = snapshots.Key("external_enabled").MustBool(true) + SnapShotRemoveExpired = snapshots.Key("snapshot_remove_expired").MustBool(true) + SnapShotTTLDays = snapshots.Key("snapshot_TTL_days").MustInt(90) // read data source proxy white list DataProxyWhiteList = make(map[string]bool) @@ -453,6 +531,11 @@ func NewConfigContext(args *CommandLineArgs) error { AutoAssignOrgRole = users.Key("auto_assign_org_role").In("Editor", []string{"Editor", "Admin", "Read Only Editor", "Viewer"}) VerifyEmailEnabled = users.Key("verify_email_enabled").MustBool(false) LoginHint = users.Key("login_hint").String() + DefaultTheme = users.Key("default_theme").String() + + // auth + auth := Cfg.Section("auth") + DisableLoginForm = auth.Key("disable_login_form").MustBool(false) // anonymous access AnonymousEnabled = Cfg.Section("auth.anonymous").Key("enabled").MustBool(false) @@ -465,7 +548,10 @@ func NewConfigContext(args *CommandLineArgs) error { AuthProxyHeaderName = authProxy.Key("header_name").String() AuthProxyHeaderProperty = authProxy.Key("header_property").String() AuthProxyAutoSignUp = authProxy.Key("auto_sign_up").MustBool(true) + AuthProxyLdapSyncTtl = authProxy.Key("ldap_sync_ttl").MustInt() + AuthProxyWhitelist = authProxy.Key("whitelist").String() + // basic auth authBasic := Cfg.Section("auth.basic") BasicAuthEnabled = authBasic.Key("enabled").MustBool(true) @@ -475,12 +561,17 @@ func NewConfigContext(args *CommandLineArgs) error { analytics := Cfg.Section("analytics") ReportingEnabled = analytics.Key("reporting_enabled").MustBool(true) + CheckForUpdates = analytics.Key("check_for_updates").MustBool(true) GoogleAnalyticsId = analytics.Key("google_analytics_ua_id").String() GoogleTagManagerId = analytics.Key("google_tag_manager_id").String() ldapSec := Cfg.Section("auth.ldap") LdapEnabled = ldapSec.Key("enabled").MustBool(false) LdapConfigFile = ldapSec.Key("config_file").String() + LdapAllowSignup = ldapSec.Key("allow_sign_up").MustBool(true) + + alerting := Cfg.Section("alerting") + ExecuteAlerts = alerting.Key("execute_alerts").MustBool(true) readSessionConfig() readSmtpSettings() @@ -490,6 +581,10 @@ func NewConfigContext(args *CommandLineArgs) error { log.Warn("require_email_validation is enabled but smpt is disabled") } + GrafanaNetUrl = Cfg.Section("grafana_net").Key("url").MustString("https://grafana.net") + + imageUploadingSection := Cfg.Section("external_image_storage") + ImageUploadProvider = imageUploadingSection.Key("provider").MustString("internal") return nil } @@ -515,124 +610,39 @@ func readSessionConfig() { } } -var logLevels = map[string]int{ - "Trace": 0, - "Debug": 1, - "Info": 2, - "Warn": 3, - "Error": 4, - "Critical": 5, -} - -func initLogging(args *CommandLineArgs) { - //close any existing log handlers. - log.Close() - // Get and check log mode. +func initLogging() { + // split on comma LogModes = strings.Split(Cfg.Section("log").Key("mode").MustString("console"), ",") - LogsPath = makeAbsolute(Cfg.Section("paths").Key("logs").String(), HomePath) - - LogConfigs = make([]util.DynMap, len(LogModes)) - for i, mode := range LogModes { - mode = strings.TrimSpace(mode) - sec, err := Cfg.GetSection("log." + mode) - if err != nil { - log.Fatal(4, "Unknown log mode: %s", mode) - } - - // Log level. - levelName := Cfg.Section("log."+mode).Key("level").In("Trace", - []string{"Trace", "Debug", "Info", "Warn", "Error", "Critical"}) - level, ok := logLevels[levelName] - if !ok { - log.Fatal(4, "Unknown log level: %s", levelName) - } - - // Generate log configuration. - switch mode { - case "console": - formatting := sec.Key("formatting").MustBool(true) - LogConfigs[i] = util.DynMap{ - "level": level, - "formatting": formatting, - } - case "file": - logPath := sec.Key("file_name").MustString(filepath.Join(LogsPath, "grafana.log")) - os.MkdirAll(filepath.Dir(logPath), os.ModePerm) - LogConfigs[i] = util.DynMap{ - "level": level, - "filename": logPath, - "rotate": sec.Key("log_rotate").MustBool(true), - "maxlines": sec.Key("max_lines").MustInt(1000000), - "maxsize": 1 << uint(sec.Key("max_size_shift").MustInt(28)), - "daily": sec.Key("daily_rotate").MustBool(true), - "maxdays": sec.Key("max_days").MustInt(7), - } - case "conn": - LogConfigs[i] = util.DynMap{ - "level": level, - "reconnectOnMsg": sec.Key("reconnect_on_msg").MustBool(), - "reconnect": sec.Key("reconnect").MustBool(), - "net": sec.Key("protocol").In("tcp", []string{"tcp", "unix", "udp"}), - "addr": sec.Key("addr").MustString(":7020"), - } - case "smtp": - LogConfigs[i] = util.DynMap{ - "level": level, - "user": sec.Key("user").MustString("example@example.com"), - "passwd": sec.Key("passwd").MustString("******"), - "host": sec.Key("host").MustString("127.0.0.1:25"), - "receivers": sec.Key("receivers").MustString("[]"), - "subject": sec.Key("subject").MustString("Diagnostic message from serve"), - } - case "database": - LogConfigs[i] = util.DynMap{ - "level": level, - "driver": sec.Key("driver").String(), - "conn": sec.Key("conn").String(), - } - case "syslog": - LogConfigs[i] = util.DynMap{ - "level": level, - "network": sec.Key("network").MustString(""), - "address": sec.Key("address").MustString(""), - "facility": sec.Key("facility").MustString("local7"), - "tag": sec.Key("tag").MustString(""), - } - } - - cfgJsonBytes, _ := json.Marshal(LogConfigs[i]) - log.NewLogger(Cfg.Section("log").Key("buffer_len").MustInt64(10000), mode, string(cfgJsonBytes)) + // also try space + if len(LogModes) == 1 { + LogModes = strings.Split(Cfg.Section("log").Key("mode").MustString("console"), " ") } + LogsPath = makeAbsolute(Cfg.Section("paths").Key("logs").String(), HomePath) + log.ReadLoggingConfig(LogModes, LogsPath, Cfg) } func LogConfigurationInfo() { var text bytes.Buffer - text.WriteString("Configuration Info\n") - text.WriteString("Config files:\n") - for i, file := range configFiles { - text.WriteString(fmt.Sprintf(" [%d]: %s\n", i, file)) + for _, file := range configFiles { + logger.Info("Config loaded from", "file", file) } if len(appliedCommandLineProperties) > 0 { - text.WriteString("Command lines overrides:\n") - for i, prop := range appliedCommandLineProperties { - text.WriteString(fmt.Sprintf(" [%d]: %s\n", i, prop)) + for _, prop := range appliedCommandLineProperties { + logger.Info("Config overriden from command line", "arg", prop) } } if len(appliedEnvOverrides) > 0 { text.WriteString("\tEnvironment variables used:\n") - for i, prop := range appliedEnvOverrides { - text.WriteString(fmt.Sprintf(" [%d]: %s\n", i, prop)) + for _, prop := range appliedEnvOverrides { + logger.Info("Config overriden from Environment variable", "var", prop) } } - text.WriteString("Paths:\n") - text.WriteString(fmt.Sprintf(" home: %s\n", HomePath)) - text.WriteString(fmt.Sprintf(" data: %s\n", DataPath)) - text.WriteString(fmt.Sprintf(" logs: %s\n", LogsPath)) - text.WriteString(fmt.Sprintf(" plugins: %s\n", PluginsPath)) - - log.Info(text.String()) + logger.Info("Path Home", "path", HomePath) + logger.Info("Path Data", "path", DataPath) + logger.Info("Path Logs", "path", LogsPath) + logger.Info("Path Plugins", "path", PluginsPath) } diff --git a/pkg/setting/setting_oauth.go b/pkg/setting/setting_oauth.go index db2f0fb3802..bc52d2336c3 100644 --- a/pkg/setting/setting_oauth.go +++ b/pkg/setting/setting_oauth.go @@ -6,13 +6,17 @@ type OAuthInfo struct { AuthUrl, TokenUrl string Enabled bool AllowedDomains []string + HostedDomain string ApiUrl string AllowSignup bool + Name string + TlsClientCert string + TlsClientKey string + TlsClientCa string } type OAuther struct { - GitHub, Google, Twitter bool - OAuthInfos map[string]*OAuthInfo + OAuthInfos map[string]*OAuthInfo } var OAuthService *OAuther diff --git a/pkg/setting/setting_test.go b/pkg/setting/setting_test.go index ef44f55551c..586cd8ff61d 100644 --- a/pkg/setting/setting_test.go +++ b/pkg/setting/setting_test.go @@ -29,6 +29,20 @@ func TestLoadingSettings(t *testing.T) { So(LogsPath, ShouldEqual, filepath.Join(DataPath, "log")) }) + Convey("Should replace password when defined in environment", func() { + os.Setenv("GF_SECURITY_ADMIN_PASSWORD", "supersecret") + NewConfigContext(&CommandLineArgs{HomePath: "../../"}) + + So(appliedEnvOverrides, ShouldContain, "GF_SECURITY_ADMIN_PASSWORD=*********") + }) + + Convey("Should replace password in URL when url environment is defined", func() { + os.Setenv("GF_DATABASE_URL", "mysql://user:secret@localhost:3306/database") + NewConfigContext(&CommandLineArgs{HomePath: "../../"}) + + So(appliedEnvOverrides, ShouldContain, "GF_DATABASE_URL=mysql://user:-redacted-@localhost:3306/database") + }) + Convey("Should get property map from command line args array", func() { props := getCommandLineProperties([]string{"cfg:test=value", "cfg:map.test=1"}) @@ -89,5 +103,14 @@ func TestLoadingSettings(t *testing.T) { So(DataPath, ShouldEqual, "/tmp/env_override") }) + Convey("instance_name default to hostname even if hostname env is emtpy", func() { + NewConfigContext(&CommandLineArgs{ + HomePath: "../../", + }) + + hostname, _ := os.Hostname() + So(InstanceName, ShouldEqual, hostname) + }) + }) } diff --git a/pkg/social/common.go b/pkg/social/common.go new file mode 100644 index 00000000000..7bce5d2ae8f --- /dev/null +++ b/pkg/social/common.go @@ -0,0 +1,20 @@ +package social + +import ( + "fmt" + "strings" +) + +func isEmailAllowed(email string, allowedDomains []string) bool { + if len(allowedDomains) == 0 { + return true + } + + valid := false + for _, domain := range allowedDomains { + emailSuffix := fmt.Sprintf("@%s", domain) + valid = valid || strings.HasSuffix(email, emailSuffix) + } + + return valid +} diff --git a/pkg/social/generic_oauth.go b/pkg/social/generic_oauth.go new file mode 100644 index 00000000000..f0e36ac064c --- /dev/null +++ b/pkg/social/generic_oauth.go @@ -0,0 +1,217 @@ +package social + +import ( + "encoding/json" + "errors" + "fmt" + "net/http" + + "github.com/grafana/grafana/pkg/models" + + "golang.org/x/oauth2" +) + +type GenericOAuth struct { + *oauth2.Config + allowedDomains []string + allowedOrganizations []string + apiUrl string + allowSignup bool + teamIds []int +} + +func (s *GenericOAuth) Type() int { + return int(models.GENERIC) +} + +func (s *GenericOAuth) IsEmailAllowed(email string) bool { + return isEmailAllowed(email, s.allowedDomains) +} + +func (s *GenericOAuth) IsSignupAllowed() bool { + return s.allowSignup +} + +func (s *GenericOAuth) IsTeamMember(client *http.Client) bool { + if len(s.teamIds) == 0 { + return true + } + + teamMemberships, err := s.FetchTeamMemberships(client) + if err != nil { + return false + } + + for _, teamId := range s.teamIds { + for _, membershipId := range teamMemberships { + if teamId == membershipId { + return true + } + } + } + + return false +} + +func (s *GenericOAuth) IsOrganizationMember(client *http.Client) bool { + if len(s.allowedOrganizations) == 0 { + return true + } + + organizations, err := s.FetchOrganizations(client) + if err != nil { + return false + } + + for _, allowedOrganization := range s.allowedOrganizations { + for _, organization := range organizations { + if organization == allowedOrganization { + return true + } + } + } + + return false +} + +func (s *GenericOAuth) FetchPrivateEmail(client *http.Client) (string, error) { + type Record struct { + Email string `json:"email"` + Primary bool `json:"primary"` + Verified bool `json:"verified"` + } + + emailsUrl := fmt.Sprintf(s.apiUrl + "/emails") + r, err := client.Get(emailsUrl) + if err != nil { + return "", err + } + + defer r.Body.Close() + + var records []Record + + if err = json.NewDecoder(r.Body).Decode(&records); err != nil { + return "", err + } + + var email = "" + for _, record := range records { + if record.Primary { + email = record.Email + } + } + + return email, nil +} + +func (s *GenericOAuth) FetchTeamMemberships(client *http.Client) ([]int, error) { + type Record struct { + Id int `json:"id"` + } + + membershipUrl := fmt.Sprintf(s.apiUrl + "/teams") + r, err := client.Get(membershipUrl) + if err != nil { + return nil, err + } + + defer r.Body.Close() + + var records []Record + + if err = json.NewDecoder(r.Body).Decode(&records); err != nil { + return nil, err + } + + var ids = make([]int, len(records)) + for i, record := range records { + ids[i] = record.Id + } + + return ids, nil +} + +func (s *GenericOAuth) FetchOrganizations(client *http.Client) ([]string, error) { + type Record struct { + Login string `json:"login"` + } + + url := fmt.Sprintf(s.apiUrl + "/orgs") + r, err := client.Get(url) + if err != nil { + return nil, err + } + + defer r.Body.Close() + + var records []Record + + if err = json.NewDecoder(r.Body).Decode(&records); err != nil { + return nil, err + } + + var logins = make([]string, len(records)) + for i, record := range records { + logins[i] = record.Login + } + + return logins, nil +} + +func (s *GenericOAuth) UserInfo(client *http.Client) (*BasicUserInfo, error) { + var data struct { + Name string `json:"name"` + Login string `json:"login"` + Username string `json:"username"` + Email string `json:"email"` + Attributes map[string][]string `json:"attributes"` + } + + var err error + r, err := client.Get(s.apiUrl) + if err != nil { + return nil, err + } + + defer r.Body.Close() + + if err = json.NewDecoder(r.Body).Decode(&data); err != nil { + return nil, err + } + + userInfo := &BasicUserInfo{ + Name: data.Name, + Login: data.Login, + Email: data.Email, + } + + if userInfo.Email == "" && data.Attributes["email:primary"] != nil { + userInfo.Email = data.Attributes["email:primary"][0] + } + + if userInfo.Email == "" { + userInfo.Email, err = s.FetchPrivateEmail(client) + if err != nil { + return nil, err + } + } + + if userInfo.Login == "" && data.Username != "" { + userInfo.Login = data.Username + } + + if userInfo.Login == "" { + userInfo.Login = data.Email + } + + if !s.IsTeamMember(client) { + return nil, errors.New("User not a member of one of the required teams") + } + + if !s.IsOrganizationMember(client) { + return nil, errors.New("User not a member of one of the required organizations") + } + + return userInfo, nil +} diff --git a/pkg/social/github_oauth.go b/pkg/social/github_oauth.go new file mode 100644 index 00000000000..64ff1d86851 --- /dev/null +++ b/pkg/social/github_oauth.go @@ -0,0 +1,211 @@ +package social + +import ( + "encoding/json" + "errors" + "fmt" + "net/http" + + "github.com/grafana/grafana/pkg/models" + + "golang.org/x/oauth2" +) + +type SocialGithub struct { + *oauth2.Config + allowedDomains []string + allowedOrganizations []string + apiUrl string + allowSignup bool + teamIds []int +} + +var ( + ErrMissingTeamMembership = errors.New("User not a member of one of the required teams") +) + +var ( + ErrMissingOrganizationMembership = errors.New("User not a member of one of the required organizations") +) + +func (s *SocialGithub) Type() int { + return int(models.GITHUB) +} + +func (s *SocialGithub) IsEmailAllowed(email string) bool { + return isEmailAllowed(email, s.allowedDomains) +} + +func (s *SocialGithub) IsSignupAllowed() bool { + return s.allowSignup +} + +func (s *SocialGithub) IsTeamMember(client *http.Client) bool { + if len(s.teamIds) == 0 { + return true + } + + teamMemberships, err := s.FetchTeamMemberships(client) + if err != nil { + return false + } + + for _, teamId := range s.teamIds { + for _, membershipId := range teamMemberships { + if teamId == membershipId { + return true + } + } + } + + return false +} + +func (s *SocialGithub) IsOrganizationMember(client *http.Client) bool { + if len(s.allowedOrganizations) == 0 { + return true + } + + organizations, err := s.FetchOrganizations(client) + if err != nil { + return false + } + + for _, allowedOrganization := range s.allowedOrganizations { + for _, organization := range organizations { + if organization == allowedOrganization { + return true + } + } + } + + return false +} + +func (s *SocialGithub) FetchPrivateEmail(client *http.Client) (string, error) { + type Record struct { + Email string `json:"email"` + Primary bool `json:"primary"` + Verified bool `json:"verified"` + } + + emailsUrl := fmt.Sprintf(s.apiUrl + "/emails") + r, err := client.Get(emailsUrl) + if err != nil { + return "", err + } + + defer r.Body.Close() + + var records []Record + + if err = json.NewDecoder(r.Body).Decode(&records); err != nil { + return "", err + } + + var email = "" + for _, record := range records { + if record.Primary { + email = record.Email + } + } + + return email, nil +} + +func (s *SocialGithub) FetchTeamMemberships(client *http.Client) ([]int, error) { + type Record struct { + Id int `json:"id"` + } + + membershipUrl := fmt.Sprintf(s.apiUrl + "/teams") + r, err := client.Get(membershipUrl) + if err != nil { + return nil, err + } + + defer r.Body.Close() + + var records []Record + + if err = json.NewDecoder(r.Body).Decode(&records); err != nil { + return nil, err + } + + var ids = make([]int, len(records)) + for i, record := range records { + ids[i] = record.Id + } + + return ids, nil +} + +func (s *SocialGithub) FetchOrganizations(client *http.Client) ([]string, error) { + type Record struct { + Login string `json:"login"` + } + + url := fmt.Sprintf(s.apiUrl + "/orgs") + r, err := client.Get(url) + if err != nil { + return nil, err + } + + defer r.Body.Close() + + var records []Record + + if err = json.NewDecoder(r.Body).Decode(&records); err != nil { + return nil, err + } + + var logins = make([]string, len(records)) + for i, record := range records { + logins[i] = record.Login + } + + return logins, nil +} + +func (s *SocialGithub) UserInfo(client *http.Client) (*BasicUserInfo, error) { + var data struct { + Id int `json:"id"` + Login string `json:"login"` + Email string `json:"email"` + } + + var err error + r, err := client.Get(s.apiUrl) + if err != nil { + return nil, err + } + + defer r.Body.Close() + + if err = json.NewDecoder(r.Body).Decode(&data); err != nil { + return nil, err + } + + userInfo := &BasicUserInfo{ + Name: data.Login, + Login: data.Login, + Email: data.Email, + } + + if !s.IsTeamMember(client) { + return nil, ErrMissingTeamMembership + } + + if !s.IsOrganizationMember(client) { + return nil, ErrMissingOrganizationMembership + } + + if userInfo.Email == "" { + userInfo.Email, err = s.FetchPrivateEmail(client) + if err != nil { + return nil, err + } + } + + return userInfo, nil +} diff --git a/pkg/social/google_oauth.go b/pkg/social/google_oauth.go new file mode 100644 index 00000000000..d140f385b66 --- /dev/null +++ b/pkg/social/google_oauth.go @@ -0,0 +1,52 @@ +package social + +import ( + "encoding/json" + "net/http" + + "github.com/grafana/grafana/pkg/models" + + "golang.org/x/oauth2" +) + +type SocialGoogle struct { + *oauth2.Config + allowedDomains []string + hostedDomain string + apiUrl string + allowSignup bool +} + +func (s *SocialGoogle) Type() int { + return int(models.GOOGLE) +} + +func (s *SocialGoogle) IsEmailAllowed(email string) bool { + return isEmailAllowed(email, s.allowedDomains) +} + +func (s *SocialGoogle) IsSignupAllowed() bool { + return s.allowSignup +} + +func (s *SocialGoogle) UserInfo(client *http.Client) (*BasicUserInfo, error) { + var data struct { + Name string `json:"name"` + Email string `json:"email"` + } + var err error + + r, err := client.Get(s.apiUrl) + if err != nil { + return nil, err + } + defer r.Body.Close() + if err = json.NewDecoder(r.Body).Decode(&data); err != nil { + return nil, err + } + return &BasicUserInfo{ + Name: data.Name, + Email: data.Email, + Login: data.Email, + }, nil +} diff --git a/pkg/social/grafananet_oauth.go b/pkg/social/grafananet_oauth.go new file mode 100644 index 00000000000..83c6d147b70 --- /dev/null +++ b/pkg/social/grafananet_oauth.go @@ -0,0 +1,84 @@ +package social + +import ( + "encoding/json" + "net/http" + + "github.com/grafana/grafana/pkg/models" + + "golang.org/x/oauth2" +) + +type SocialGrafanaNet struct { + *oauth2.Config + url string + allowedOrganizations []string + allowSignup bool +} + +type OrgRecord struct { + Login string `json:"login"` +} + +func (s *SocialGrafanaNet) Type() int { + return int(models.GRAFANANET) +} + +func (s *SocialGrafanaNet) IsEmailAllowed(email string) bool { + return true +} + +func (s *SocialGrafanaNet) IsSignupAllowed() bool { + return s.allowSignup +} + +func (s *SocialGrafanaNet) IsOrganizationMember(organizations []OrgRecord) bool { + if len(s.allowedOrganizations) == 0 { + return true + } + + for _, allowedOrganization := range s.allowedOrganizations { + for _, organization := range organizations { + if organization.Login == allowedOrganization { + return true + } + } + } + + return false +} + +func (s *SocialGrafanaNet) UserInfo(client *http.Client) (*BasicUserInfo, error) { + var data struct { + Name string `json:"name"` + Login string `json:"username"` + Email string `json:"email"` + Role string `json:"role"` + Orgs []OrgRecord `json:"orgs"` + } + + var err error + r, err := client.Get(s.url + "/api/oauth2/user") + if err != nil { + return nil, err + } + + defer r.Body.Close() + + if err = json.NewDecoder(r.Body).Decode(&data); err != nil { + return nil, err + } + + userInfo := &BasicUserInfo{ + Name: data.Name, + Login: data.Login, + Email: data.Email, + Role: data.Role, + } + + if !s.IsOrganizationMember(data.Orgs) { + return nil, ErrMissingOrganizationMembership + } + + return userInfo, nil +} diff --git a/pkg/social/social.go b/pkg/social/social.go index 4a8cb8bac5d..860d068957e 100644 --- a/pkg/social/social.go +++ b/pkg/social/social.go @@ -1,36 +1,32 @@ package social import ( - "encoding/json" - "errors" - "fmt" "net/http" - "strconv" "strings" - "github.com/grafana/grafana/pkg/models" - "github.com/grafana/grafana/pkg/setting" "golang.org/x/net/context" - "golang.org/x/oauth2" + + "github.com/grafana/grafana/pkg/setting" ) type BasicUserInfo struct { - Identity string - Name string - Email string - Login string - Company string + Name string + Email string + Login string + Company string + Role string } type SocialConnector interface { Type() int - UserInfo(token *oauth2.Token) (*BasicUserInfo, error) + UserInfo(client *http.Client) (*BasicUserInfo, error) IsEmailAllowed(email string) bool IsSignupAllowed() bool AuthCodeURL(state string, opts ...oauth2.AuthCodeOption) string Exchange(ctx context.Context, code string) (*oauth2.Token, error) + Client(ctx context.Context, t *oauth2.Token) *http.Client } var ( @@ -42,7 +38,7 @@ func NewOAuthService() { setting.OAuthService = &setting.OAuther{} setting.OAuthService.OAuthInfos = make(map[string]*setting.OAuthInfo) - allOauthes := []string{"github", "google"} + allOauthes := []string{"github", "google", "generic_oauth", "grafananet"} for _, name := range allOauthes { sec := setting.Cfg.Section("auth." + name) @@ -55,7 +51,12 @@ func NewOAuthService() { ApiUrl: sec.Key("api_url").String(), Enabled: sec.Key("enabled").MustBool(), AllowedDomains: sec.Key("allowed_domains").Strings(" "), + HostedDomain: sec.Key("hosted_domain").String(), AllowSignup: sec.Key("allow_sign_up").MustBool(), + Name: sec.Key("name").MustString(name), + TlsClientCert: sec.Key("tls_client_cert").String(), + TlsClientKey: sec.Key("tls_client_key").String(), + TlsClientCa: sec.Key("tls_client_ca").String(), } if !info.Enabled { @@ -63,6 +64,7 @@ func NewOAuthService() { } setting.OAuthService.OAuthInfos[name] = info + config := oauth2.Config{ ClientID: info.ClientId, ClientSecret: info.ClientSecret, @@ -76,291 +78,57 @@ func NewOAuthService() { // GitHub. if name == "github" { - setting.OAuthService.GitHub = true - teamIds := sec.Key("team_ids").Ints(",") - allowedOrganizations := sec.Key("allowed_organizations").Strings(" ") SocialMap["github"] = &SocialGithub{ Config: &config, allowedDomains: info.AllowedDomains, apiUrl: info.ApiUrl, allowSignup: info.AllowSignup, - teamIds: teamIds, - allowedOrganizations: allowedOrganizations, + teamIds: sec.Key("team_ids").Ints(","), + allowedOrganizations: sec.Key("allowed_organizations").Strings(" "), } } // Google. if name == "google" { - setting.OAuthService.Google = true SocialMap["google"] = &SocialGoogle{ - Config: &config, allowedDomains: info.AllowedDomains, - apiUrl: info.ApiUrl, - allowSignup: info.AllowSignup, + Config: &config, + allowedDomains: info.AllowedDomains, + hostedDomain: info.HostedDomain, + apiUrl: info.ApiUrl, + allowSignup: info.AllowSignup, + } + } + + // Generic - Uses the same scheme as Github. + if name == "generic_oauth" { + SocialMap["generic_oauth"] = &GenericOAuth{ + Config: &config, + allowedDomains: info.AllowedDomains, + apiUrl: info.ApiUrl, + allowSignup: info.AllowSignup, + teamIds: sec.Key("team_ids").Ints(","), + allowedOrganizations: sec.Key("allowed_organizations").Strings(" "), + } + } + + if name == "grafananet" { + config = oauth2.Config{ + ClientID: info.ClientId, + ClientSecret: info.ClientSecret, + Endpoint: oauth2.Endpoint{ + AuthURL: setting.GrafanaNetUrl + "/oauth2/authorize", + TokenURL: setting.GrafanaNetUrl + "/api/oauth2/token", + }, + RedirectURL: strings.TrimSuffix(setting.AppUrl, "/") + SocialBaseUrl + name, + Scopes: info.Scopes, + } + + SocialMap["grafananet"] = &SocialGrafanaNet{ + Config: &config, + url: setting.GrafanaNetUrl, + allowSignup: info.AllowSignup, + allowedOrganizations: sec.Key("allowed_organizations").Strings(" "), } } } } - -func isEmailAllowed(email string, allowedDomains []string) bool { - if len(allowedDomains) == 0 { - return true - } - - valid := false - for _, domain := range allowedDomains { - emailSuffix := fmt.Sprintf("@%s", domain) - valid = valid || strings.HasSuffix(email, emailSuffix) - } - - return valid -} - -type SocialGithub struct { - *oauth2.Config - allowedDomains []string - allowedOrganizations []string - apiUrl string - allowSignup bool - teamIds []int -} - -var ( - ErrMissingTeamMembership = errors.New("User not a member of one of the required teams") -) - -var ( - ErrMissingOrganizationMembership = errors.New("User not a member of one of the required organizations") -) - -func (s *SocialGithub) Type() int { - return int(models.GITHUB) -} - -func (s *SocialGithub) IsEmailAllowed(email string) bool { - return isEmailAllowed(email, s.allowedDomains) -} - -func (s *SocialGithub) IsSignupAllowed() bool { - return s.allowSignup -} - -func (s *SocialGithub) IsTeamMember(client *http.Client) bool { - if len(s.teamIds) == 0 { - return true - } - - teamMemberships, err := s.FetchTeamMemberships(client) - if err != nil { - return false - } - - for _, teamId := range s.teamIds { - for _, membershipId := range teamMemberships { - if teamId == membershipId { - return true - } - } - } - - return false -} - -func (s *SocialGithub) IsOrganizationMember(client *http.Client) bool { - if len(s.allowedOrganizations) == 0 { - return true - } - - organizations, err := s.FetchOrganizations(client) - if err != nil { - return false - } - - for _, allowedOrganization := range s.allowedOrganizations { - for _, organization := range organizations { - if organization == allowedOrganization { - return true - } - } - } - - return false -} - -func (s *SocialGithub) FetchPrivateEmail(client *http.Client) (string, error) { - type Record struct { - Email string `json:"email"` - Primary bool `json:"primary"` - Verified bool `json:"verified"` - } - - emailsUrl := fmt.Sprintf(s.apiUrl + "/emails") - r, err := client.Get(emailsUrl) - if err != nil { - return "", err - } - - defer r.Body.Close() - - var records []Record - - if err = json.NewDecoder(r.Body).Decode(&records); err != nil { - return "", err - } - - var email = "" - for _, record := range records { - if record.Primary { - email = record.Email - } - } - - return email, nil -} - -func (s *SocialGithub) FetchTeamMemberships(client *http.Client) ([]int, error) { - type Record struct { - Id int `json:"id"` - } - - membershipUrl := fmt.Sprintf(s.apiUrl + "/teams") - r, err := client.Get(membershipUrl) - if err != nil { - return nil, err - } - - defer r.Body.Close() - - var records []Record - - if err = json.NewDecoder(r.Body).Decode(&records); err != nil { - return nil, err - } - - var ids = make([]int, len(records)) - for i, record := range records { - ids[i] = record.Id - } - - return ids, nil -} - -func (s *SocialGithub) FetchOrganizations(client *http.Client) ([]string, error) { - type Record struct { - Login string `json:"login"` - } - - url := fmt.Sprintf(s.apiUrl + "/orgs") - r, err := client.Get(url) - if err != nil { - return nil, err - } - - defer r.Body.Close() - - var records []Record - - if err = json.NewDecoder(r.Body).Decode(&records); err != nil { - return nil, err - } - - var logins = make([]string, len(records)) - for i, record := range records { - logins[i] = record.Login - } - - return logins, nil -} - -func (s *SocialGithub) UserInfo(token *oauth2.Token) (*BasicUserInfo, error) { - var data struct { - Id int `json:"id"` - Name string `json:"login"` - Email string `json:"email"` - } - - var err error - client := s.Client(oauth2.NoContext, token) - r, err := client.Get(s.apiUrl) - if err != nil { - return nil, err - } - - defer r.Body.Close() - - if err = json.NewDecoder(r.Body).Decode(&data); err != nil { - return nil, err - } - - userInfo := &BasicUserInfo{ - Identity: strconv.Itoa(data.Id), - Name: data.Name, - Email: data.Email, - } - - if !s.IsTeamMember(client) { - return nil, ErrMissingTeamMembership - } - - if !s.IsOrganizationMember(client) { - return nil, ErrMissingOrganizationMembership - } - - if userInfo.Email == "" { - userInfo.Email, err = s.FetchPrivateEmail(client) - if err != nil { - return nil, err - } - } - - return userInfo, nil -} - -// ________ .__ -// / _____/ ____ ____ ____ | | ____ -// / \ ___ / _ \ / _ \ / ___\| | _/ __ \ -// \ \_\ ( <_> | <_> ) /_/ > |_\ ___/ -// \______ /\____/ \____/\___ /|____/\___ > -// \/ /_____/ \/ - -type SocialGoogle struct { - *oauth2.Config - allowedDomains []string - apiUrl string - allowSignup bool -} - -func (s *SocialGoogle) Type() int { - return int(models.GOOGLE) -} - -func (s *SocialGoogle) IsEmailAllowed(email string) bool { - return isEmailAllowed(email, s.allowedDomains) -} - -func (s *SocialGoogle) IsSignupAllowed() bool { - return s.allowSignup -} - -func (s *SocialGoogle) UserInfo(token *oauth2.Token) (*BasicUserInfo, error) { - var data struct { - Id string `json:"id"` - Name string `json:"name"` - Email string `json:"email"` - } - var err error - - client := s.Client(oauth2.NoContext, token) - r, err := client.Get(s.apiUrl) - if err != nil { - return nil, err - } - defer r.Body.Close() - if err = json.NewDecoder(r.Body).Decode(&data); err != nil { - return nil, err - } - return &BasicUserInfo{ - Identity: data.Id, - Name: data.Name, - Email: data.Email, - }, nil -} diff --git a/pkg/tsdb/batch.go b/pkg/tsdb/batch.go new file mode 100644 index 00000000000..8130ac94b0d --- /dev/null +++ b/pkg/tsdb/batch.go @@ -0,0 +1,90 @@ +package tsdb + +import "context" + +type Batch struct { + DataSourceId int64 + Queries QuerySlice + Depends map[string]bool + Done bool + Started bool +} + +type BatchSlice []*Batch + +func newBatch(dsId int64, queries QuerySlice) *Batch { + return &Batch{ + DataSourceId: dsId, + Queries: queries, + Depends: make(map[string]bool), + } +} + +func (bg *Batch) process(ctx context.Context, queryContext *QueryContext) { + executor, err := getExecutorFor(bg.Queries[0].DataSource) + + if err != nil { + bg.Done = true + result := &BatchResult{ + Error: err, + QueryResults: make(map[string]*QueryResult), + } + for _, query := range bg.Queries { + result.QueryResults[query.RefId] = &QueryResult{Error: result.Error} + } + queryContext.ResultsChan <- result + return + } + + res := executor.Execute(ctx, bg.Queries, queryContext) + bg.Done = true + queryContext.ResultsChan <- res +} + +func (bg *Batch) addQuery(query *Query) { + bg.Queries = append(bg.Queries, query) +} + +func (bg *Batch) allDependenciesAreIn(context *QueryContext) bool { + for key := range bg.Depends { + if _, exists := context.Results[key]; !exists { + return false + } + } + + return true +} + +func getBatches(req *Request) (BatchSlice, error) { + batches := make(BatchSlice, 0) + + for _, query := range req.Queries { + if foundBatch := findMatchingBatchGroup(query, batches); foundBatch != nil { + foundBatch.addQuery(query) + } else { + newBatch := newBatch(query.DataSource.Id, QuerySlice{query}) + batches = append(batches, newBatch) + + for _, refId := range query.Depends { + for _, batch := range batches { + for _, batchQuery := range batch.Queries { + if batchQuery.RefId == refId { + newBatch.Depends[refId] = true + } + } + } + } + } + } + + return batches, nil +} + +func findMatchingBatchGroup(query *Query, batches BatchSlice) *Batch { + for _, batch := range batches { + if batch.DataSourceId == query.DataSource.Id { + return batch + } + } + return nil +} diff --git a/pkg/tsdb/executor.go b/pkg/tsdb/executor.go new file mode 100644 index 00000000000..251b3dc947a --- /dev/null +++ b/pkg/tsdb/executor.go @@ -0,0 +1,36 @@ +package tsdb + +import ( + "context" + "fmt" + + "github.com/grafana/grafana/pkg/models" +) + +type Executor interface { + Execute(ctx context.Context, queries QuerySlice, query *QueryContext) *BatchResult +} + +var registry map[string]GetExecutorFn + +type GetExecutorFn func(dsInfo *models.DataSource) (Executor, error) + +func init() { + registry = make(map[string]GetExecutorFn) +} + +func getExecutorFor(dsInfo *models.DataSource) (Executor, error) { + if fn, exists := registry[dsInfo.Type]; exists { + executor, err := fn(dsInfo) + if err != nil { + return nil, err + } + + return executor, nil + } + return nil, fmt.Errorf("Could not find executor for data source type: %s", dsInfo.Type) +} + +func RegisterExecutor(pluginId string, fn GetExecutorFn) { + registry[pluginId] = fn +} diff --git a/pkg/tsdb/fake_test.go b/pkg/tsdb/fake_test.go new file mode 100644 index 00000000000..3c773971240 --- /dev/null +++ b/pkg/tsdb/fake_test.go @@ -0,0 +1,45 @@ +package tsdb + +import ( + "context" + + "github.com/grafana/grafana/pkg/models" +) + +type FakeExecutor struct { + results map[string]*QueryResult + resultsFn map[string]ResultsFn +} + +type ResultsFn func(context *QueryContext) *QueryResult + +func NewFakeExecutor(dsInfo *models.DataSource) (*FakeExecutor, error) { + return &FakeExecutor{ + results: make(map[string]*QueryResult), + resultsFn: make(map[string]ResultsFn), + }, nil +} + +func (e *FakeExecutor) Execute(ctx context.Context, queries QuerySlice, context *QueryContext) *BatchResult { + result := &BatchResult{QueryResults: make(map[string]*QueryResult)} + for _, query := range queries { + if results, has := e.results[query.RefId]; has { + result.QueryResults[query.RefId] = results + } + if testFunc, has := e.resultsFn[query.RefId]; has { + result.QueryResults[query.RefId] = testFunc(context) + } + } + + return result +} + +func (e *FakeExecutor) Return(refId string, series TimeSeriesSlice) { + e.results[refId] = &QueryResult{ + RefId: refId, Series: series, + } +} + +func (e *FakeExecutor) HandleQuery(refId string, fn ResultsFn) { + e.resultsFn[refId] = fn +} diff --git a/pkg/tsdb/graphite/graphite.go b/pkg/tsdb/graphite/graphite.go new file mode 100644 index 00000000000..a467e839b82 --- /dev/null +++ b/pkg/tsdb/graphite/graphite.go @@ -0,0 +1,166 @@ +package graphite + +import ( + "context" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "net/url" + "path" + "regexp" + "strings" + + "golang.org/x/net/context/ctxhttp" + + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/setting" + "github.com/grafana/grafana/pkg/tsdb" +) + +type GraphiteExecutor struct { + *models.DataSource + HttpClient *http.Client +} + +func NewGraphiteExecutor(datasource *models.DataSource) (tsdb.Executor, error) { + httpClient, err := datasource.GetHttpClient() + + if err != nil { + return nil, err + } + + return &GraphiteExecutor{ + DataSource: datasource, + HttpClient: httpClient, + }, nil +} + +var ( + glog log.Logger +) + +func init() { + glog = log.New("tsdb.graphite") + tsdb.RegisterExecutor("graphite", NewGraphiteExecutor) +} + +func (e *GraphiteExecutor) Execute(ctx context.Context, queries tsdb.QuerySlice, context *tsdb.QueryContext) *tsdb.BatchResult { + result := &tsdb.BatchResult{} + + formData := url.Values{ + "from": []string{"-" + formatTimeRange(context.TimeRange.From)}, + "until": []string{formatTimeRange(context.TimeRange.To)}, + "format": []string{"json"}, + "maxDataPoints": []string{"500"}, + } + + for _, query := range queries { + if fullTarget, err := query.Model.Get("targetFull").String(); err == nil { + formData["target"] = []string{fixIntervalFormat(fullTarget)} + } else { + formData["target"] = []string{fixIntervalFormat(query.Model.Get("target").MustString())} + } + } + + if setting.Env == setting.DEV { + glog.Debug("Graphite request", "params", formData) + } + + req, err := e.createRequest(formData) + if err != nil { + result.Error = err + return result + } + + res, err := ctxhttp.Do(ctx, e.HttpClient, req) + if err != nil { + result.Error = err + return result + } + + data, err := e.parseResponse(res) + if err != nil { + result.Error = err + return result + } + + result.QueryResults = make(map[string]*tsdb.QueryResult) + queryRes := tsdb.NewQueryResult() + + for _, series := range data { + queryRes.Series = append(queryRes.Series, &tsdb.TimeSeries{ + Name: series.Target, + Points: series.DataPoints, + }) + + if setting.Env == setting.DEV { + glog.Debug("Graphite response", "target", series.Target, "datapoints", len(series.DataPoints)) + } + } + + result.QueryResults["A"] = queryRes + return result +} + +func (e *GraphiteExecutor) parseResponse(res *http.Response) ([]TargetResponseDTO, error) { + body, err := ioutil.ReadAll(res.Body) + defer res.Body.Close() + if err != nil { + return nil, err + } + + if res.StatusCode/100 != 2 { + glog.Info("Request failed", "status", res.Status, "body", string(body)) + return nil, fmt.Errorf("Request failed status: %v", res.Status) + } + + var data []TargetResponseDTO + err = json.Unmarshal(body, &data) + if err != nil { + glog.Info("Failed to unmarshal graphite response", "error", err, "status", res.Status, "body", string(body)) + return nil, err + } + + return data, nil +} + +func (e *GraphiteExecutor) createRequest(data url.Values) (*http.Request, error) { + u, _ := url.Parse(e.Url) + u.Path = path.Join(u.Path, "render") + + req, err := http.NewRequest(http.MethodPost, u.String(), strings.NewReader(data.Encode())) + if err != nil { + glog.Info("Failed to create request", "error", err) + return nil, fmt.Errorf("Failed to create request. error: %v", err) + } + + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + if e.BasicAuth { + req.SetBasicAuth(e.BasicAuthUser, e.BasicAuthPassword) + } + + return req, err +} + +func formatTimeRange(input string) string { + if input == "now" { + return input + } + return strings.Replace(strings.Replace(input, "m", "min", -1), "M", "mon", -1) +} + +func fixIntervalFormat(target string) string { + rMinute := regexp.MustCompile(`'(\d+)m'`) + rMin := regexp.MustCompile("m") + target = rMinute.ReplaceAllStringFunc(target, func(m string) string { + return rMin.ReplaceAllString(m, "min") + }) + rMonth := regexp.MustCompile(`'(\d+)M'`) + rMon := regexp.MustCompile("M") + target = rMonth.ReplaceAllStringFunc(target, func(M string) string { + return rMon.ReplaceAllString(M, "mon") + }) + return target +} diff --git a/pkg/tsdb/graphite/graphite_test.go b/pkg/tsdb/graphite/graphite_test.go new file mode 100644 index 00000000000..c1a2736293b --- /dev/null +++ b/pkg/tsdb/graphite/graphite_test.go @@ -0,0 +1,61 @@ +package graphite + +import ( + . "github.com/smartystreets/goconvey/convey" + "testing" +) + +func TestGraphiteFunctions(t *testing.T) { + Convey("Testing Graphite Functions", t, func() { + + Convey("formatting time range for now", func() { + + timeRange := formatTimeRange("now") + So(timeRange, ShouldEqual, "now") + + }) + + Convey("formatting time range for now-1m", func() { + + timeRange := formatTimeRange("now-1m") + So(timeRange, ShouldEqual, "now-1min") + + }) + + Convey("formatting time range for now-1M", func() { + + timeRange := formatTimeRange("now-1M") + So(timeRange, ShouldEqual, "now-1mon") + + }) + + Convey("fix interval format in query for 1m", func() { + + timeRange := fixIntervalFormat("aliasByNode(hitcount(averageSeries(app.grafana.*.dashboards.views.count), '1m'), 4)") + So(timeRange, ShouldEqual, "aliasByNode(hitcount(averageSeries(app.grafana.*.dashboards.views.count), '1min'), 4)") + + }) + + Convey("fix interval format in query for 1M", func() { + + timeRange := fixIntervalFormat("aliasByNode(hitcount(averageSeries(app.grafana.*.dashboards.views.count), '1M'), 4)") + So(timeRange, ShouldEqual, "aliasByNode(hitcount(averageSeries(app.grafana.*.dashboards.views.count), '1mon'), 4)") + + }) + + Convey("should not override query for 1M", func() { + + timeRange := fixIntervalFormat("app.grafana.*.dashboards.views.1M.count") + So(timeRange, ShouldEqual, "app.grafana.*.dashboards.views.1M.count") + + }) + + Convey("should not override query for 1m", func() { + + timeRange := fixIntervalFormat("app.grafana.*.dashboards.views.1m.count") + So(timeRange, ShouldEqual, "app.grafana.*.dashboards.views.1m.count") + + }) + + }) +} diff --git a/pkg/tsdb/graphite/types.go b/pkg/tsdb/graphite/types.go new file mode 100644 index 00000000000..8bd13aec4f2 --- /dev/null +++ b/pkg/tsdb/graphite/types.go @@ -0,0 +1,8 @@ +package graphite + +import "github.com/grafana/grafana/pkg/tsdb" + +type TargetResponseDTO struct { + Target string `json:"target"` + DataPoints tsdb.TimeSeriesPoints `json:"datapoints"` +} diff --git a/pkg/tsdb/influxdb/influxdb.go b/pkg/tsdb/influxdb/influxdb.go new file mode 100644 index 00000000000..21d359d24bf --- /dev/null +++ b/pkg/tsdb/influxdb/influxdb.go @@ -0,0 +1,142 @@ +package influxdb + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "net/url" + "path" + + "golang.org/x/net/context/ctxhttp" + + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/setting" + "github.com/grafana/grafana/pkg/tsdb" +) + +type InfluxDBExecutor struct { + *models.DataSource + QueryParser *InfluxdbQueryParser + ResponseParser *ResponseParser + HttpClient *http.Client +} + +func NewInfluxDBExecutor(datasource *models.DataSource) (tsdb.Executor, error) { + httpClient, err := datasource.GetHttpClient() + + if err != nil { + return nil, err + } + + return &InfluxDBExecutor{ + DataSource: datasource, + QueryParser: &InfluxdbQueryParser{}, + ResponseParser: &ResponseParser{}, + HttpClient: httpClient, + }, nil +} + +var ( + glog log.Logger +) + +func init() { + glog = log.New("tsdb.influxdb") + tsdb.RegisterExecutor("influxdb", NewInfluxDBExecutor) +} + +func (e *InfluxDBExecutor) Execute(ctx context.Context, queries tsdb.QuerySlice, context *tsdb.QueryContext) *tsdb.BatchResult { + result := &tsdb.BatchResult{} + + query, err := e.getQuery(queries, context) + if err != nil { + return result.WithError(err) + } + + rawQuery, err := query.Build(context) + if err != nil { + return result.WithError(err) + } + + if setting.Env == setting.DEV { + glog.Debug("Influxdb query", "raw query", rawQuery) + } + + req, err := e.createRequest(rawQuery) + if err != nil { + return result.WithError(err) + } + + resp, err := ctxhttp.Do(ctx, e.HttpClient, req) + if err != nil { + return result.WithError(err) + } + + if resp.StatusCode/100 != 2 { + return result.WithError(fmt.Errorf("Influxdb returned statuscode invalid status code: %v", resp.Status)) + } + + var response Response + dec := json.NewDecoder(resp.Body) + defer resp.Body.Close() + dec.UseNumber() + err = dec.Decode(&response) + + if err != nil { + return result.WithError(err) + } + + if response.Err != nil { + return result.WithError(response.Err) + } + + result.QueryResults = make(map[string]*tsdb.QueryResult) + result.QueryResults["A"] = e.ResponseParser.Parse(&response, query) + + return result +} + +func (e *InfluxDBExecutor) getQuery(queries tsdb.QuerySlice, context *tsdb.QueryContext) (*Query, error) { + for _, v := range queries { + + query, err := e.QueryParser.Parse(v.Model, e.DataSource) + if err != nil { + return nil, err + } + + return query, nil + } + + return nil, fmt.Errorf("query request contains no queries") +} + +func (e *InfluxDBExecutor) createRequest(query string) (*http.Request, error) { + u, _ := url.Parse(e.Url) + u.Path = path.Join(u.Path, "query") + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + return nil, err + } + + params := req.URL.Query() + params.Set("q", query) + params.Set("db", e.Database) + params.Set("epoch", "s") + req.URL.RawQuery = params.Encode() + + req.Header.Set("User-Agent", "Grafana") + + if e.BasicAuth { + req.SetBasicAuth(e.BasicAuthUser, e.BasicAuthPassword) + } + + if !e.BasicAuth && e.User != "" { + req.SetBasicAuth(e.User, e.Password) + } + + glog.Debug("Influxdb request", "url", req.URL.String()) + return req, nil +} diff --git a/pkg/tsdb/influxdb/model_parser.go b/pkg/tsdb/influxdb/model_parser.go new file mode 100644 index 00000000000..f3d87739e5b --- /dev/null +++ b/pkg/tsdb/influxdb/model_parser.go @@ -0,0 +1,166 @@ +package influxdb + +import ( + "strconv" + + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/models" +) + +type InfluxdbQueryParser struct{} + +func (qp *InfluxdbQueryParser) Parse(model *simplejson.Json, dsInfo *models.DataSource) (*Query, error) { + policy := model.Get("policy").MustString("default") + rawQuery := model.Get("query").MustString("") + useRawQuery := model.Get("rawQuery").MustBool(false) + alias := model.Get("alias").MustString("") + + measurement := model.Get("measurement").MustString("") + + resultFormat, err := model.Get("resultFormat").String() + if err != nil { + return nil, err + } + + tags, err := qp.parseTags(model) + if err != nil { + return nil, err + } + + groupBys, err := qp.parseGroupBy(model) + if err != nil { + return nil, err + } + + selects, err := qp.parseSelects(model) + if err != nil { + return nil, err + } + + interval := model.Get("interval").MustString("") + if interval == "" && dsInfo.JsonData != nil { + dsInterval := dsInfo.JsonData.Get("timeInterval").MustString("") + if dsInterval != "" { + interval = dsInterval + } + } + + return &Query{ + Measurement: measurement, + Policy: policy, + ResultFormat: resultFormat, + GroupBy: groupBys, + Tags: tags, + Selects: selects, + RawQuery: rawQuery, + Interval: interval, + Alias: alias, + UseRawQuery: useRawQuery, + }, nil +} + +func (qp *InfluxdbQueryParser) parseSelects(model *simplejson.Json) ([]*Select, error) { + var result []*Select + + for _, selectObj := range model.Get("select").MustArray() { + selectJson := simplejson.NewFromAny(selectObj) + var parts Select + + for _, partObj := range selectJson.MustArray() { + part := simplejson.NewFromAny(partObj) + queryPart, err := qp.parseQueryPart(part) + if err != nil { + return nil, err + } + + parts = append(parts, *queryPart) + } + + result = append(result, &parts) + } + + return result, nil +} + +func (*InfluxdbQueryParser) parseTags(model *simplejson.Json) ([]*Tag, error) { + var result []*Tag + for _, t := range model.Get("tags").MustArray() { + tagJson := simplejson.NewFromAny(t) + tag := &Tag{} + var err error + + tag.Key, err = tagJson.Get("key").String() + if err != nil { + return nil, err + } + + tag.Value, err = tagJson.Get("value").String() + if err != nil { + return nil, err + } + + operator, err := tagJson.Get("operator").String() + if err == nil { + tag.Operator = operator + } + + condition, err := tagJson.Get("condition").String() + if err == nil { + tag.Condition = condition + } + + result = append(result, tag) + } + + return result, nil +} + +func (*InfluxdbQueryParser) parseQueryPart(model *simplejson.Json) (*QueryPart, error) { + typ, err := model.Get("type").String() + if err != nil { + return nil, err + } + + var params []string + for _, paramObj := range model.Get("params").MustArray() { + param := simplejson.NewFromAny(paramObj) + + stringParam, err := param.String() + if err == nil { + params = append(params, stringParam) + continue + } + + intParam, err := param.Int() + if err == nil { + params = append(params, strconv.Itoa(intParam)) + continue + } + + return nil, err + + } + + qp, err := NewQueryPart(typ, params) + if err != nil { + return nil, err + } + + return qp, nil +} + +func (qp *InfluxdbQueryParser) parseGroupBy(model *simplejson.Json) ([]*QueryPart, error) { + var result []*QueryPart + + for _, groupObj := range model.Get("groupBy").MustArray() { + groupJson := simplejson.NewFromAny(groupObj) + queryPart, err := qp.parseQueryPart(groupJson) + + if err != nil { + return nil, err + } + result = append(result, queryPart) + } + + return result, nil +} diff --git a/pkg/tsdb/influxdb/model_parser_test.go b/pkg/tsdb/influxdb/model_parser_test.go new file mode 100644 index 00000000000..f7049efb9a7 --- /dev/null +++ b/pkg/tsdb/influxdb/model_parser_test.go @@ -0,0 +1,180 @@ +package influxdb + +import ( + "testing" + + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/models" + . "github.com/smartystreets/goconvey/convey" +) + +func TestInfluxdbQueryParser(t *testing.T) { + Convey("Influxdb query parser", t, func() { + + parser := &InfluxdbQueryParser{} + dsInfo := &models.DataSource{ + JsonData: simplejson.New(), + } + + Convey("can parse influxdb json model", func() { + json := ` + { + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "datacenter" + ], + "type": "tag" + }, + { + "params": [ + "none" + ], + "type": "fill" + } + ], + "measurement": "logins.count", + "policy": "default", + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "type": "field", + "params": [ + "value" + ] + }, + { + "type": "count", + "params": [] + } + ], + [ + { + "type": "field", + "params": [ + "value" + ] + }, + { + "type": "bottom", + "params": [ + 3 + ] + } + ], + [ + { + "type": "field", + "params": [ + "value" + ] + }, + { + "type": "mean", + "params": [] + }, + { + "type": "math", + "params": [ + " / 100" + ] + } + ] + ], + "alias": "serie alias", + "tags": [ + { + "key": "datacenter", + "operator": "=", + "value": "America" + }, + { + "condition": "OR", + "key": "hostname", + "operator": "=", + "value": "server1" + } + ] + } + ` + dsInfo.JsonData.Set("timeInterval", ">20s") + modelJson, err := simplejson.NewJson([]byte(json)) + So(err, ShouldBeNil) + + res, err := parser.Parse(modelJson, dsInfo) + So(err, ShouldBeNil) + So(len(res.GroupBy), ShouldEqual, 3) + So(len(res.Selects), ShouldEqual, 3) + So(len(res.Tags), ShouldEqual, 2) + So(res.Interval, ShouldEqual, ">20s") + So(res.Alias, ShouldEqual, "serie alias") + }) + + Convey("can part raw query json model", func() { + json := ` + { + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "interval": ">10s", + "policy": "default", + "query": "RawDummieQuery", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [ + + ], + "type": "mean" + } + ] + ], + "tags": [ + + ] + } + ` + + modelJson, err := simplejson.NewJson([]byte(json)) + So(err, ShouldBeNil) + + res, err := parser.Parse(modelJson, dsInfo) + So(err, ShouldBeNil) + So(res.RawQuery, ShouldEqual, "RawDummieQuery") + So(len(res.GroupBy), ShouldEqual, 2) + So(len(res.Selects), ShouldEqual, 1) + So(len(res.Tags), ShouldEqual, 0) + So(res.Interval, ShouldEqual, ">10s") + }) + }) +} diff --git a/pkg/tsdb/influxdb/models.go b/pkg/tsdb/influxdb/models.go new file mode 100644 index 00000000000..44e05608290 --- /dev/null +++ b/pkg/tsdb/influxdb/models.go @@ -0,0 +1,51 @@ +package influxdb + +type Query struct { + Measurement string + Policy string + ResultFormat string + Tags []*Tag + GroupBy []*QueryPart + Selects []*Select + RawQuery string + UseRawQuery bool + Alias string + + Interval string +} + +type Tag struct { + Key string + Operator string + Value string + Condition string +} + +type Select []QueryPart + +type InfluxDbSelect struct { + Type string +} + +type Response struct { + Results []Result + Err error +} + +type Result struct { + Series []Row + Messages []*Message + Err error +} + +type Message struct { + Level string `json:"level,omitempty"` + Text string `json:"text,omitempty"` +} + +type Row struct { + Name string `json:"name,omitempty"` + Tags map[string]string `json:"tags,omitempty"` + Columns []string `json:"columns,omitempty"` + Values [][]interface{} `json:"values,omitempty"` +} diff --git a/pkg/tsdb/influxdb/query.go b/pkg/tsdb/influxdb/query.go new file mode 100644 index 00000000000..094f98cbe53 --- /dev/null +++ b/pkg/tsdb/influxdb/query.go @@ -0,0 +1,148 @@ +package influxdb + +import ( + "fmt" + "strings" + + "regexp" + + "github.com/grafana/grafana/pkg/tsdb" +) + +var ( + regexpOperatorPattern *regexp.Regexp = regexp.MustCompile(`^\/.*\/$`) + regexpMeasurementPattern *regexp.Regexp = regexp.MustCompile(`^\/.*\/$`) +) + +func (query *Query) Build(queryContext *tsdb.QueryContext) (string, error) { + if query.UseRawQuery && query.RawQuery != "" { + q := query.RawQuery + + q = strings.Replace(q, "$timeFilter", query.renderTimeFilter(queryContext), 1) + q = strings.Replace(q, "$interval", tsdb.CalculateInterval(queryContext.TimeRange), 1) + + return q, nil + } + + res := query.renderSelectors(queryContext) + res += query.renderMeasurement() + res += query.renderWhereClause() + res += query.renderTimeFilter(queryContext) + res += query.renderGroupBy(queryContext) + + return res, nil +} + +func (query *Query) renderTags() []string { + var res []string + for i, tag := range query.Tags { + str := "" + + if i > 0 { + if tag.Condition == "" { + str += "AND" + } else { + str += tag.Condition + } + str += " " + } + + //If the operator is missing we fall back to sensible defaults + if tag.Operator == "" { + if regexpOperatorPattern.Match([]byte(tag.Value)) { + tag.Operator = "=~" + } else { + tag.Operator = "=" + } + } + + textValue := "" + + // quote value unless regex or number + if tag.Operator == "=~" || tag.Operator == "!~" { + textValue = tag.Value + } else if tag.Operator == "<" || tag.Operator == ">" { + textValue = tag.Value + } else { + textValue = fmt.Sprintf("'%s'", tag.Value) + } + + res = append(res, fmt.Sprintf(`%s"%s" %s %s`, str, tag.Key, tag.Operator, textValue)) + } + + return res +} + +func (query *Query) renderTimeFilter(queryContext *tsdb.QueryContext) string { + from := "now() - " + queryContext.TimeRange.From + to := "" + + if queryContext.TimeRange.To != "now" && queryContext.TimeRange.To != "" { + to = " and time < now() - " + strings.Replace(queryContext.TimeRange.To, "now-", "", 1) + } + + return fmt.Sprintf("time > %s%s", from, to) +} + +func (query *Query) renderSelectors(queryContext *tsdb.QueryContext) string { + res := "SELECT " + + var selectors []string + for _, sel := range query.Selects { + + stk := "" + for _, s := range *sel { + stk = s.Render(query, queryContext, stk) + } + selectors = append(selectors, stk) + } + + return res + strings.Join(selectors, ", ") +} + +func (query *Query) renderMeasurement() string { + policy := "" + if query.Policy == "" || query.Policy == "default" { + policy = "" + } else { + policy = `"` + query.Policy + `".` + } + + measurement := query.Measurement + + if !regexpMeasurementPattern.Match([]byte(measurement)) { + measurement = fmt.Sprintf(`"%s"`, measurement) + } + + return fmt.Sprintf(` FROM %s%s`, policy, measurement) +} + +func (query *Query) renderWhereClause() string { + res := " WHERE " + conditions := query.renderTags() + res += strings.Join(conditions, " ") + if len(conditions) > 0 { + res += " AND " + } + + return res +} + +func (query *Query) renderGroupBy(queryContext *tsdb.QueryContext) string { + groupBy := "" + for i, group := range query.GroupBy { + if i == 0 { + groupBy += " GROUP BY" + } + + if i > 0 && group.Type != "fill" { + groupBy += ", " //fill is so very special. fill is a creep, fill is a weirdo + } else { + groupBy += " " + } + + groupBy += group.Render(query, queryContext, "") + } + + return groupBy +} diff --git a/pkg/tsdb/influxdb/query_part.go b/pkg/tsdb/influxdb/query_part.go new file mode 100644 index 00000000000..222e0b054ee --- /dev/null +++ b/pkg/tsdb/influxdb/query_part.go @@ -0,0 +1,166 @@ +package influxdb + +import ( + "fmt" + "strings" + "time" + + "github.com/grafana/grafana/pkg/tsdb" +) + +var renders map[string]QueryDefinition + +type DefinitionParameters struct { + Name string + Type string +} + +type QueryDefinition struct { + Renderer func(query *Query, queryContext *tsdb.QueryContext, part *QueryPart, innerExpr string) string + Params []DefinitionParameters +} + +func init() { + renders = make(map[string]QueryDefinition) + + renders["field"] = QueryDefinition{Renderer: fieldRenderer} + + renders["spread"] = QueryDefinition{Renderer: functionRenderer} + renders["count"] = QueryDefinition{Renderer: functionRenderer} + renders["distinct"] = QueryDefinition{Renderer: functionRenderer} + renders["integral"] = QueryDefinition{Renderer: functionRenderer} + renders["mean"] = QueryDefinition{Renderer: functionRenderer} + renders["median"] = QueryDefinition{Renderer: functionRenderer} + renders["sum"] = QueryDefinition{Renderer: functionRenderer} + + renders["derivative"] = QueryDefinition{ + Renderer: functionRenderer, + Params: []DefinitionParameters{{Name: "duration", Type: "interval"}}, + } + + renders["non_negative_derivative"] = QueryDefinition{ + Renderer: functionRenderer, + Params: []DefinitionParameters{{Name: "duration", Type: "interval"}}, + } + renders["difference"] = QueryDefinition{Renderer: functionRenderer} + renders["moving_average"] = QueryDefinition{ + Renderer: functionRenderer, + Params: []DefinitionParameters{{Name: "window", Type: "number"}}, + } + renders["stddev"] = QueryDefinition{Renderer: functionRenderer} + renders["time"] = QueryDefinition{ + Renderer: functionRenderer, + Params: []DefinitionParameters{{Name: "interval", Type: "time"}}, + } + renders["fill"] = QueryDefinition{ + Renderer: functionRenderer, + Params: []DefinitionParameters{{Name: "fill", Type: "string"}}, + } + renders["elapsed"] = QueryDefinition{ + Renderer: functionRenderer, + Params: []DefinitionParameters{{Name: "duration", Type: "interval"}}, + } + renders["bottom"] = QueryDefinition{ + Renderer: functionRenderer, + Params: []DefinitionParameters{{Name: "count", Type: "int"}}, + } + + renders["first"] = QueryDefinition{Renderer: functionRenderer} + renders["last"] = QueryDefinition{Renderer: functionRenderer} + renders["max"] = QueryDefinition{Renderer: functionRenderer} + renders["min"] = QueryDefinition{Renderer: functionRenderer} + renders["percentile"] = QueryDefinition{ + Renderer: functionRenderer, + Params: []DefinitionParameters{{Name: "nth", Type: "int"}}, + } + renders["top"] = QueryDefinition{ + Renderer: functionRenderer, + Params: []DefinitionParameters{{Name: "count", Type: "int"}}, + } + renders["tag"] = QueryDefinition{ + Renderer: fieldRenderer, + Params: []DefinitionParameters{{Name: "tag", Type: "string"}}, + } + + renders["math"] = QueryDefinition{Renderer: suffixRenderer} + renders["alias"] = QueryDefinition{Renderer: aliasRenderer} +} + +func fieldRenderer(query *Query, queryContext *tsdb.QueryContext, part *QueryPart, innerExpr string) string { + if part.Params[0] == "*" { + return "*" + } + return fmt.Sprintf(`"%s"`, part.Params[0]) +} + +func getDefinedInterval(query *Query, queryContext *tsdb.QueryContext) string { + setInterval := strings.Replace(strings.Replace(query.Interval, "<", "", 1), ">", "", 1) + defaultInterval := tsdb.CalculateInterval(queryContext.TimeRange) + + if strings.Contains(query.Interval, ">") { + parsedDefaultInterval, err := time.ParseDuration(defaultInterval) + parsedSetInterval, err2 := time.ParseDuration(setInterval) + + if err == nil && err2 == nil && parsedDefaultInterval > parsedSetInterval { + return defaultInterval + } + } + + return setInterval +} + +func functionRenderer(query *Query, queryContext *tsdb.QueryContext, part *QueryPart, innerExpr string) string { + for i, param := range part.Params { + if param == "$interval" || param == "auto" { + if query.Interval != "" { + part.Params[i] = getDefinedInterval(query, queryContext) + } else { + part.Params[i] = tsdb.CalculateInterval(queryContext.TimeRange) + } + } + } + + if innerExpr != "" { + part.Params = append([]string{innerExpr}, part.Params...) + } + + params := strings.Join(part.Params, ", ") + + return fmt.Sprintf("%s(%s)", part.Type, params) +} + +func suffixRenderer(query *Query, queryContext *tsdb.QueryContext, part *QueryPart, innerExpr string) string { + return fmt.Sprintf("%s %s", innerExpr, part.Params[0]) +} + +func aliasRenderer(query *Query, queryContext *tsdb.QueryContext, part *QueryPart, innerExpr string) string { + return fmt.Sprintf(`%s AS "%s"`, innerExpr, part.Params[0]) +} + +func (r QueryDefinition) Render(query *Query, queryContext *tsdb.QueryContext, part *QueryPart, innerExpr string) string { + return r.Renderer(query, queryContext, part, innerExpr) +} + +func NewQueryPart(typ string, params []string) (*QueryPart, error) { + def, exist := renders[typ] + + if !exist { + return nil, fmt.Errorf("Missing query definition for %s", typ) + } + + return &QueryPart{ + Type: typ, + Params: params, + Def: def, + }, nil +} + +type QueryPart struct { + Def QueryDefinition + Type string + Params []string +} + +func (qp *QueryPart) Render(query *Query, queryContext *tsdb.QueryContext, expr string) string { + return qp.Def.Renderer(query, queryContext, qp, expr) +} diff --git a/pkg/tsdb/influxdb/query_part_test.go b/pkg/tsdb/influxdb/query_part_test.go new file mode 100644 index 00000000000..a083754574a --- /dev/null +++ b/pkg/tsdb/influxdb/query_part_test.go @@ -0,0 +1,101 @@ +package influxdb + +import ( + "testing" + + "github.com/grafana/grafana/pkg/tsdb" + . "github.com/smartystreets/goconvey/convey" +) + +func TestInfluxdbQueryPart(t *testing.T) { + Convey("Influxdb query parts", t, func() { + + queryContext := &tsdb.QueryContext{TimeRange: tsdb.NewTimeRange("5m", "now")} + query := &Query{} + + Convey("render field ", func() { + part, err := NewQueryPart("field", []string{"value"}) + So(err, ShouldBeNil) + + res := part.Render(query, queryContext, "value") + So(res, ShouldEqual, `"value"`) + }) + + Convey("render nested part", func() { + part, err := NewQueryPart("derivative", []string{"10s"}) + So(err, ShouldBeNil) + + res := part.Render(query, queryContext, "mean(value)") + So(res, ShouldEqual, "derivative(mean(value), 10s)") + }) + + Convey("render bottom", func() { + part, err := NewQueryPart("bottom", []string{"3"}) + So(err, ShouldBeNil) + + res := part.Render(query, queryContext, "value") + So(res, ShouldEqual, "bottom(value, 3)") + }) + + Convey("render time with $interval", func() { + part, err := NewQueryPart("time", []string{"$interval"}) + So(err, ShouldBeNil) + + res := part.Render(query, queryContext, "") + So(res, ShouldEqual, "time(200ms)") + }) + + Convey("render time with auto", func() { + part, err := NewQueryPart("time", []string{"auto"}) + So(err, ShouldBeNil) + + res := part.Render(query, queryContext, "") + So(res, ShouldEqual, "time(200ms)") + }) + + Convey("render time interval >10s", func() { + part, err := NewQueryPart("time", []string{"$interval"}) + So(err, ShouldBeNil) + + query.Interval = ">10s" + + res := part.Render(query, queryContext, "") + So(res, ShouldEqual, "time(10s)") + }) + + Convey("render time interval >1s and higher interval calculation", func() { + part, err := NewQueryPart("time", []string{"$interval"}) + queryContext := &tsdb.QueryContext{TimeRange: tsdb.NewTimeRange("1y", "now")} + So(err, ShouldBeNil) + + query.Interval = ">1s" + + res := part.Render(query, queryContext, "") + So(res, ShouldEqual, "time(168h)") + }) + + Convey("render spread", func() { + part, err := NewQueryPart("spread", []string{}) + So(err, ShouldBeNil) + + res := part.Render(query, queryContext, "value") + So(res, ShouldEqual, `spread(value)`) + }) + + Convey("render suffix", func() { + part, err := NewQueryPart("math", []string{"/ 100"}) + So(err, ShouldBeNil) + + res := part.Render(query, queryContext, "mean(value)") + So(res, ShouldEqual, "mean(value) / 100") + }) + + Convey("render alias", func() { + part, err := NewQueryPart("alias", []string{"test"}) + So(err, ShouldBeNil) + + res := part.Render(query, queryContext, "mean(value)") + So(res, ShouldEqual, `mean(value) AS "test"`) + }) + }) +} diff --git a/pkg/tsdb/influxdb/query_test.go b/pkg/tsdb/influxdb/query_test.go new file mode 100644 index 00000000000..b6af67e5e42 --- /dev/null +++ b/pkg/tsdb/influxdb/query_test.go @@ -0,0 +1,142 @@ +package influxdb + +import ( + "testing" + + "strings" + + "github.com/grafana/grafana/pkg/tsdb" + . "github.com/smartystreets/goconvey/convey" +) + +func TestInfluxdbQueryBuilder(t *testing.T) { + + Convey("Influxdb query builder", t, func() { + + qp1, _ := NewQueryPart("field", []string{"value"}) + qp2, _ := NewQueryPart("mean", []string{}) + + groupBy1, _ := NewQueryPart("time", []string{"$interval"}) + groupBy2, _ := NewQueryPart("tag", []string{"datacenter"}) + groupBy3, _ := NewQueryPart("fill", []string{"null"}) + + tag1 := &Tag{Key: "hostname", Value: "server1", Operator: "="} + tag2 := &Tag{Key: "hostname", Value: "server2", Operator: "=", Condition: "OR"} + + queryContext := &tsdb.QueryContext{ + TimeRange: tsdb.NewTimeRange("5m", "now"), + } + + Convey("can build simple query", func() { + query := &Query{ + Selects: []*Select{{*qp1, *qp2}}, + Measurement: "cpu", + Policy: "policy", + GroupBy: []*QueryPart{groupBy1, groupBy3}, + Interval: "10s", + } + + rawQuery, err := query.Build(queryContext) + So(err, ShouldBeNil) + So(rawQuery, ShouldEqual, `SELECT mean("value") FROM "policy"."cpu" WHERE time > now() - 5m GROUP BY time(10s) fill(null)`) + }) + + Convey("can build query with group bys", func() { + query := &Query{ + Selects: []*Select{{*qp1, *qp2}}, + Measurement: "cpu", + GroupBy: []*QueryPart{groupBy1, groupBy2, groupBy3}, + Tags: []*Tag{tag1, tag2}, + Interval: "5s", + } + + rawQuery, err := query.Build(queryContext) + So(err, ShouldBeNil) + So(rawQuery, ShouldEqual, `SELECT mean("value") FROM "cpu" WHERE "hostname" = 'server1' OR "hostname" = 'server2' AND time > now() - 5m GROUP BY time(5s), "datacenter" fill(null)`) + }) + + Convey("can render time range", func() { + query := Query{} + Convey("render from: 2h to now-1h", func() { + query := Query{} + queryContext := &tsdb.QueryContext{TimeRange: tsdb.NewTimeRange("2h", "now-1h")} + So(query.renderTimeFilter(queryContext), ShouldEqual, "time > now() - 2h and time < now() - 1h") + }) + + Convey("render from: 10m", func() { + queryContext := &tsdb.QueryContext{TimeRange: tsdb.NewTimeRange("10m", "now")} + So(query.renderTimeFilter(queryContext), ShouldEqual, "time > now() - 10m") + }) + }) + + Convey("can build query from raw query", func() { + query := &Query{ + Selects: []*Select{{*qp1, *qp2}}, + Measurement: "cpu", + Policy: "policy", + GroupBy: []*QueryPart{groupBy1, groupBy3}, + Interval: "10s", + RawQuery: "Raw query", + UseRawQuery: true, + } + + rawQuery, err := query.Build(queryContext) + So(err, ShouldBeNil) + So(rawQuery, ShouldEqual, `Raw query`) + }) + + Convey("can render normal tags without operator", func() { + query := &Query{Tags: []*Tag{&Tag{Operator: "", Value: `value`, Key: "key"}}} + + So(strings.Join(query.renderTags(), ""), ShouldEqual, `"key" = 'value'`) + }) + + Convey("can render regex tags without operator", func() { + query := &Query{Tags: []*Tag{&Tag{Operator: "", Value: `/value/`, Key: "key"}}} + + So(strings.Join(query.renderTags(), ""), ShouldEqual, `"key" =~ /value/`) + }) + + Convey("can render regex tags", func() { + query := &Query{Tags: []*Tag{&Tag{Operator: "=~", Value: `/value/`, Key: "key"}}} + + So(strings.Join(query.renderTags(), ""), ShouldEqual, `"key" =~ /value/`) + }) + + Convey("can render number tags", func() { + query := &Query{Tags: []*Tag{&Tag{Operator: "=", Value: "10001", Key: "key"}}} + + So(strings.Join(query.renderTags(), ""), ShouldEqual, `"key" = '10001'`) + }) + + Convey("can render numbers less then condition tags", func() { + query := &Query{Tags: []*Tag{&Tag{Operator: "<", Value: "10001", Key: "key"}}} + + So(strings.Join(query.renderTags(), ""), ShouldEqual, `"key" < 10001`) + }) + + Convey("can render number greather then condition tags", func() { + query := &Query{Tags: []*Tag{&Tag{Operator: ">", Value: "10001", Key: "key"}}} + + So(strings.Join(query.renderTags(), ""), ShouldEqual, `"key" > 10001`) + }) + + Convey("can render string tags", func() { + query := &Query{Tags: []*Tag{&Tag{Operator: "=", Value: "value", Key: "key"}}} + + So(strings.Join(query.renderTags(), ""), ShouldEqual, `"key" = 'value'`) + }) + + Convey("can render regular measurement", func() { + query := &Query{Measurement: `apa`, Policy: "policy"} + + So(query.renderMeasurement(), ShouldEqual, ` FROM "policy"."apa"`) + }) + + Convey("can render regexp measurement", func() { + query := &Query{Measurement: `/apa/`, Policy: "policy"} + + So(query.renderMeasurement(), ShouldEqual, ` FROM "policy"./apa/`) + }) + }) +} diff --git a/pkg/tsdb/influxdb/response_parser.go b/pkg/tsdb/influxdb/response_parser.go new file mode 100644 index 00000000000..8e9fa0022c3 --- /dev/null +++ b/pkg/tsdb/influxdb/response_parser.go @@ -0,0 +1,145 @@ +package influxdb + +import ( + "encoding/json" + "fmt" + "regexp" + "strconv" + "strings" + + "github.com/grafana/grafana/pkg/tsdb" + "gopkg.in/guregu/null.v3" +) + +type ResponseParser struct{} + +var ( + legendFormat *regexp.Regexp +) + +func init() { + legendFormat = regexp.MustCompile(`\[\[(\w+?)*\]\]*|\$\s*(\w+?)*`) +} + +func (rp *ResponseParser) Parse(response *Response, query *Query) *tsdb.QueryResult { + queryRes := tsdb.NewQueryResult() + + for _, result := range response.Results { + queryRes.Series = append(queryRes.Series, rp.transformRows(result.Series, queryRes, query)...) + } + + return queryRes +} + +func (rp *ResponseParser) transformRows(rows []Row, queryResult *tsdb.QueryResult, query *Query) tsdb.TimeSeriesSlice { + var result tsdb.TimeSeriesSlice + + for _, row := range rows { + for columnIndex, column := range row.Columns { + if column == "time" { + continue + } + + var points tsdb.TimeSeriesPoints + for _, valuePair := range row.Values { + point, err := rp.parseTimepoint(valuePair, columnIndex) + if err == nil { + points = append(points, point) + } + } + result = append(result, &tsdb.TimeSeries{ + Name: rp.formatSerieName(row, column, query), + Points: points, + }) + } + } + + return result +} + +func (rp *ResponseParser) formatSerieName(row Row, column string, query *Query) string { + if query.Alias == "" { + return rp.buildSerieNameFromQuery(row, column) + } + + nameSegment := strings.Split(row.Name, ".") + + result := legendFormat.ReplaceAllFunc([]byte(query.Alias), func(in []byte) []byte { + aliasFormat := string(in) + aliasFormat = strings.Replace(aliasFormat, "[[", "", 1) + aliasFormat = strings.Replace(aliasFormat, "]]", "", 1) + aliasFormat = strings.Replace(aliasFormat, "$", "", 1) + + if aliasFormat == "m" || aliasFormat == "measurement" { + return []byte(query.Measurement) + } + if aliasFormat == "col" { + return []byte(column) + } + + pos, err := strconv.Atoi(aliasFormat) + if err == nil && len(nameSegment) >= pos { + return []byte(nameSegment[pos]) + } + + if !strings.HasPrefix(aliasFormat, "tag_") { + return in + } + + tagKey := strings.Replace(aliasFormat, "tag_", "", 1) + tagValue, exist := row.Tags[tagKey] + if exist { + return []byte(tagValue) + } + + return in + }) + + return string(result) +} + +func (rp *ResponseParser) buildSerieNameFromQuery(row Row, column string) string { + var tags []string + + for k, v := range row.Tags { + tags = append(tags, fmt.Sprintf("%s: %s", k, v)) + } + + tagText := "" + if len(tags) > 0 { + tagText = fmt.Sprintf(" { %s }", strings.Join(tags, " ")) + } + + return fmt.Sprintf("%s.%s%s", row.Name, column, tagText) +} + +func (rp *ResponseParser) parseTimepoint(valuePair []interface{}, valuePosition int) (tsdb.TimePoint, error) { + var value null.Float = rp.parseValue(valuePair[valuePosition]) + + timestampNumber, _ := valuePair[0].(json.Number) + timestamp, err := timestampNumber.Float64() + if err != nil { + return tsdb.TimePoint{}, err + } + + return tsdb.NewTimePoint(value, timestamp), nil +} + +func (rp *ResponseParser) parseValue(value interface{}) null.Float { + number, ok := value.(json.Number) + if !ok { + return null.FloatFromPtr(nil) + } + + fvalue, err := number.Float64() + if err == nil { + return null.FloatFrom(fvalue) + } + + ivalue, err := number.Int64() + if err == nil { + return null.FloatFrom(float64(ivalue)) + } + + return null.FloatFromPtr(nil) +} diff --git a/pkg/tsdb/influxdb/response_parser_test.go b/pkg/tsdb/influxdb/response_parser_test.go new file mode 100644 index 00000000000..67667f565d5 --- /dev/null +++ b/pkg/tsdb/influxdb/response_parser_test.go @@ -0,0 +1,164 @@ +package influxdb + +import ( + "encoding/json" + "testing" + + "github.com/grafana/grafana/pkg/setting" + . "github.com/smartystreets/goconvey/convey" +) + +func TestInfluxdbResponseParser(t *testing.T) { + Convey("Influxdb response parser", t, func() { + Convey("Response parser", func() { + parser := &ResponseParser{} + + setting.NewConfigContext(&setting.CommandLineArgs{ + HomePath: "../../../", + }) + + response := &Response{ + Results: []Result{ + Result{ + Series: []Row{ + { + Name: "cpu", + Columns: []string{"time", "mean", "sum"}, + Tags: map[string]string{"datacenter": "America"}, + Values: [][]interface{}{ + {json.Number("111"), json.Number("222"), json.Number("333")}, + {json.Number("111"), json.Number("222"), json.Number("333")}, + {json.Number("111"), json.Number("null"), json.Number("333")}, + }, + }, + }, + }, + }, + } + + query := &Query{} + + result := parser.Parse(response, query) + + Convey("can parse all series", func() { + So(len(result.Series), ShouldEqual, 2) + }) + + Convey("can parse all points", func() { + So(len(result.Series[0].Points), ShouldEqual, 3) + So(len(result.Series[1].Points), ShouldEqual, 3) + }) + + Convey("can parse multi row result", func() { + So(result.Series[0].Points[1][0].Float64, ShouldEqual, float64(222)) + So(result.Series[1].Points[1][0].Float64, ShouldEqual, float64(333)) + }) + + Convey("can parse null points", func() { + So(result.Series[0].Points[2][0].Valid, ShouldBeFalse) + }) + + Convey("can format serie names", func() { + So(result.Series[0].Name, ShouldEqual, "cpu.mean { datacenter: America }") + So(result.Series[1].Name, ShouldEqual, "cpu.sum { datacenter: America }") + }) + }) + + Convey("Response parser with alias", func() { + parser := &ResponseParser{} + + response := &Response{ + Results: []Result{ + Result{ + Series: []Row{ + { + Name: "cpu.upc", + Columns: []string{"time", "mean", "sum"}, + Tags: map[string]string{"datacenter": "America"}, + Values: [][]interface{}{ + {json.Number("111"), json.Number("222"), json.Number("333")}, + }, + }, + }, + }, + }, + } + + Convey("$ alias", func() { + Convey("simple alias", func() { + query := &Query{Alias: "serie alias"} + result := parser.Parse(response, query) + + So(result.Series[0].Name, ShouldEqual, "serie alias") + }) + + Convey("measurement alias", func() { + query := &Query{Alias: "alias $m $measurement", Measurement: "10m"} + result := parser.Parse(response, query) + + So(result.Series[0].Name, ShouldEqual, "alias 10m 10m") + }) + + Convey("column alias", func() { + query := &Query{Alias: "alias $col", Measurement: "10m"} + result := parser.Parse(response, query) + + So(result.Series[0].Name, ShouldEqual, "alias mean") + So(result.Series[1].Name, ShouldEqual, "alias sum") + }) + + Convey("tag alias", func() { + query := &Query{Alias: "alias $tag_datacenter"} + result := parser.Parse(response, query) + + So(result.Series[0].Name, ShouldEqual, "alias America") + }) + + Convey("segment alias", func() { + query := &Query{Alias: "alias $1"} + result := parser.Parse(response, query) + + So(result.Series[0].Name, ShouldEqual, "alias upc") + }) + + Convey("segment position out of bound", func() { + query := &Query{Alias: "alias $5"} + result := parser.Parse(response, query) + + So(result.Series[0].Name, ShouldEqual, "alias $5") + }) + }) + + Convey("[[]] alias", func() { + Convey("simple alias", func() { + query := &Query{Alias: "serie alias"} + result := parser.Parse(response, query) + + So(result.Series[0].Name, ShouldEqual, "serie alias") + }) + + Convey("measurement alias", func() { + query := &Query{Alias: "alias [[m]] [[measurement]]", Measurement: "10m"} + result := parser.Parse(response, query) + + So(result.Series[0].Name, ShouldEqual, "alias 10m 10m") + }) + + Convey("column alias", func() { + query := &Query{Alias: "alias [[col]]", Measurement: "10m"} + result := parser.Parse(response, query) + + So(result.Series[0].Name, ShouldEqual, "alias mean") + So(result.Series[1].Name, ShouldEqual, "alias sum") + }) + + Convey("tag alias", func() { + query := &Query{Alias: "alias [[tag_datacenter]]"} + result := parser.Parse(response, query) + + So(result.Series[0].Name, ShouldEqual, "alias America") + }) + }) + }) + }) +} diff --git a/pkg/tsdb/interval.go b/pkg/tsdb/interval.go new file mode 100644 index 00000000000..71caf122c13 --- /dev/null +++ b/pkg/tsdb/interval.go @@ -0,0 +1,145 @@ +package tsdb + +import ( + "fmt" + "time" +) + +var ( + defaultRes int64 = 1500 + minInterval time.Duration = 1 * time.Millisecond + year time.Duration = time.Hour * 24 * 365 + day time.Duration = time.Hour * 24 * 365 +) + +func CalculateInterval(timerange *TimeRange) string { + interval := time.Duration((timerange.MustGetTo().UnixNano() - timerange.MustGetFrom().UnixNano()) / defaultRes) + + if interval < minInterval { + return formatDuration(minInterval) + } + + return formatDuration(roundInterval(interval)) +} + +func formatDuration(inter time.Duration) string { + if inter >= year { + return fmt.Sprintf("%dy", inter/year) + } + + if inter >= day { + return fmt.Sprintf("%dd", inter/day) + } + + if inter >= time.Hour { + return fmt.Sprintf("%dh", inter/time.Hour) + } + + if inter >= time.Minute { + return fmt.Sprintf("%dm", inter/time.Minute) + } + + if inter >= time.Second { + return fmt.Sprintf("%ds", inter/time.Second) + } + + if inter >= time.Millisecond { + return fmt.Sprintf("%dms", inter/time.Millisecond) + } + + return "1ms" +} + +func roundInterval(interval time.Duration) time.Duration { + switch true { + // 0.015s + case interval <= 15*time.Millisecond: + return time.Millisecond * 10 // 0.01s + // 0.035s + case interval <= 35*time.Millisecond: + return time.Millisecond * 20 // 0.02s + // 0.075s + case interval <= 75*time.Millisecond: + return time.Millisecond * 50 // 0.05s + // 0.15s + case interval <= 150*time.Millisecond: + return time.Millisecond * 100 // 0.1s + // 0.35s + case interval <= 350*time.Millisecond: + return time.Millisecond * 200 // 0.2s + // 0.75s + case interval <= 750*time.Millisecond: + return time.Millisecond * 500 // 0.5s + // 1.5s + case interval <= 1500*time.Millisecond: + return time.Millisecond * 1000 // 1s + // 3.5s + case interval <= 3500*time.Millisecond: + return time.Millisecond * 2000 // 2s + // 7.5s + case interval <= 7500*time.Millisecond: + return time.Millisecond * 5000 // 5s + // 12.5s + case interval <= 12500*time.Millisecond: + return time.Millisecond * 10000 // 10s + // 17.5s + case interval <= 17500*time.Millisecond: + return time.Millisecond * 15000 // 15s + // 25s + case interval <= 25000*time.Millisecond: + return time.Millisecond * 20000 // 20s + // 45s + case interval <= 45000*time.Millisecond: + return time.Millisecond * 30000 // 30s + // 1.5m + case interval <= 90000*time.Millisecond: + return time.Millisecond * 60000 // 1m + // 3.5m + case interval <= 210000*time.Millisecond: + return time.Millisecond * 120000 // 2m + // 7.5m + case interval <= 450000*time.Millisecond: + return time.Millisecond * 300000 // 5m + // 12.5m + case interval <= 750000*time.Millisecond: + return time.Millisecond * 600000 // 10m + // 12.5m + case interval <= 1050000*time.Millisecond: + return time.Millisecond * 900000 // 15m + // 25m + case interval <= 1500000*time.Millisecond: + return time.Millisecond * 1200000 // 20m + // 45m + case interval <= 2700000*time.Millisecond: + return time.Millisecond * 1800000 // 30m + // 1.5h + case interval <= 5400000*time.Millisecond: + return time.Millisecond * 3600000 // 1h + // 2.5h + case interval <= 9000000*time.Millisecond: + return time.Millisecond * 7200000 // 2h + // 4.5h + case interval <= 16200000*time.Millisecond: + return time.Millisecond * 10800000 // 3h + // 9h + case interval <= 32400000*time.Millisecond: + return time.Millisecond * 21600000 // 6h + // 24h + case interval <= 86400000*time.Millisecond: + return time.Millisecond * 43200000 // 12h + // 48h + case interval <= 172800000*time.Millisecond: + return time.Millisecond * 86400000 // 24h + // 1w + case interval <= 604800000*time.Millisecond: + return time.Millisecond * 86400000 // 24h + // 3w + case interval <= 1814400000*time.Millisecond: + return time.Millisecond * 604800000 // 1w + // 2y + case interval < 3628800000*time.Millisecond: + return time.Millisecond * 2592000000 // 30d + default: + return time.Millisecond * 31536000000 // 1y + } +} diff --git a/pkg/tsdb/interval_test.go b/pkg/tsdb/interval_test.go new file mode 100644 index 00000000000..c06e1879668 --- /dev/null +++ b/pkg/tsdb/interval_test.go @@ -0,0 +1,57 @@ +package tsdb + +import ( + "testing" + "time" + + "github.com/grafana/grafana/pkg/setting" + . "github.com/smartystreets/goconvey/convey" +) + +func TestInterval(t *testing.T) { + Convey("Default interval ", t, func() { + setting.NewConfigContext(&setting.CommandLineArgs{ + HomePath: "../../", + }) + + Convey("for 5min", func() { + tr := NewTimeRange("5m", "now") + + interval := CalculateInterval(tr) + So(interval, ShouldEqual, "200ms") + }) + + Convey("for 15min", func() { + tr := NewTimeRange("15m", "now") + + interval := CalculateInterval(tr) + So(interval, ShouldEqual, "500ms") + }) + + Convey("for 30min", func() { + tr := NewTimeRange("30m", "now") + + interval := CalculateInterval(tr) + So(interval, ShouldEqual, "1s") + }) + + Convey("for 1h", func() { + tr := NewTimeRange("1h", "now") + + interval := CalculateInterval(tr) + So(interval, ShouldEqual, "2s") + }) + + Convey("Round interval", func() { + So(roundInterval(time.Millisecond*30), ShouldEqual, time.Millisecond*20) + So(roundInterval(time.Millisecond*45), ShouldEqual, time.Millisecond*50) + }) + + Convey("Format value", func() { + So(formatDuration(time.Second*61), ShouldEqual, "1m") + So(formatDuration(time.Millisecond*30), ShouldEqual, "30ms") + So(formatDuration(time.Hour*23), ShouldEqual, "23h") + So(formatDuration(time.Hour*24*367), ShouldEqual, "1y") + }) + }) +} diff --git a/pkg/tsdb/models.go b/pkg/tsdb/models.go new file mode 100644 index 00000000000..e95713e7077 --- /dev/null +++ b/pkg/tsdb/models.go @@ -0,0 +1,87 @@ +package tsdb + +import ( + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/models" + "gopkg.in/guregu/null.v3" +) + +type Query struct { + RefId string + Model *simplejson.Json + Depends []string + DataSource *models.DataSource + Results []*TimeSeries + Exclude bool + MaxDataPoints int64 + IntervalMs int64 +} + +type QuerySlice []*Query + +type Request struct { + TimeRange *TimeRange + Queries QuerySlice +} + +type Response struct { + BatchTimings []*BatchTiming `json:"timings"` + Results map[string]*QueryResult `json:"results"` +} + +type BatchTiming struct { + TimeElapsed int64 +} + +type BatchResult struct { + Error error + QueryResults map[string]*QueryResult + Timings *BatchTiming +} + +func (br *BatchResult) WithError(err error) *BatchResult { + br.Error = err + return br +} + +type QueryResult struct { + Error error `json:"error"` + RefId string `json:"refId"` + Series TimeSeriesSlice `json:"series"` +} + +type TimeSeries struct { + Name string `json:"name"` + Points TimeSeriesPoints `json:"points"` +} + +type TimePoint [2]null.Float +type TimeSeriesPoints []TimePoint +type TimeSeriesSlice []*TimeSeries + +func NewQueryResult() *QueryResult { + return &QueryResult{ + Series: make(TimeSeriesSlice, 0), + } +} + +func NewTimePoint(value null.Float, timestamp float64) TimePoint { + return TimePoint{value, null.FloatFrom(timestamp)} +} + +func NewTimeSeriesPointsFromArgs(values ...float64) TimeSeriesPoints { + points := make(TimeSeriesPoints, 0) + + for i := 0; i < len(values); i += 2 { + points = append(points, NewTimePoint(null.FloatFrom(values[i]), values[i+1])) + } + + return points +} + +func NewTimeSeries(name string, points TimeSeriesPoints) *TimeSeries { + return &TimeSeries{ + Name: name, + Points: points, + } +} diff --git a/pkg/tsdb/mqe/httpClient.go b/pkg/tsdb/mqe/httpClient.go new file mode 100644 index 00000000000..c4a7807f9cb --- /dev/null +++ b/pkg/tsdb/mqe/httpClient.go @@ -0,0 +1,129 @@ +package mqe + +import ( + "context" + "net/http" + "net/url" + "path" + "strings" + + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/setting" + "github.com/grafana/grafana/pkg/tsdb" + + "golang.org/x/net/context/ctxhttp" +) + +var ( + MaxWorker int = 4 +) + +type apiClient struct { + *models.DataSource + log log.Logger + httpClient *http.Client + responseParser *ResponseParser +} + +func NewApiClient(httpClient *http.Client, datasource *models.DataSource) *apiClient { + return &apiClient{ + DataSource: datasource, + log: log.New("tsdb.mqe"), + httpClient: httpClient, + responseParser: NewResponseParser(), + } +} + +func (e *apiClient) PerformRequests(ctx context.Context, queries []QueryToSend) (*tsdb.QueryResult, error) { + queryResult := &tsdb.QueryResult{} + + queryCount := len(queries) + jobsChan := make(chan QueryToSend, queryCount) + resultChan := make(chan []*tsdb.TimeSeries, queryCount) + errorsChan := make(chan error, 1) + for w := 1; w <= MaxWorker; w++ { + go e.spawnWorker(ctx, w, jobsChan, resultChan, errorsChan) + } + + for _, v := range queries { + jobsChan <- v + } + close(jobsChan) + + resultCounter := 0 + for { + select { + case timeseries := <-resultChan: + queryResult.Series = append(queryResult.Series, timeseries...) + resultCounter++ + + if resultCounter == queryCount { + close(resultChan) + return queryResult, nil + } + case err := <-errorsChan: + return nil, err + case <-ctx.Done(): + return nil, ctx.Err() + } + } +} + +func (e *apiClient) spawnWorker(ctx context.Context, id int, jobs chan QueryToSend, results chan []*tsdb.TimeSeries, errors chan error) { + e.log.Debug("Spawning worker", "id", id) + for query := range jobs { + if setting.Env == setting.DEV { + e.log.Debug("Sending request", "query", query.RawQuery) + } + + req, err := e.createRequest(query.RawQuery) + + resp, err := ctxhttp.Do(ctx, e.httpClient, req) + if err != nil { + errors <- err + return + } + + series, err := e.responseParser.Parse(resp, query.QueryRef) + if err != nil { + errors <- err + return + } + + results <- series + } + e.log.Debug("Worker is complete", "id", id) +} + +func (e *apiClient) createRequest(query string) (*http.Request, error) { + u, err := url.Parse(e.Url) + if err != nil { + return nil, err + } + + u.Path = path.Join(u.Path, "query") + + payload := simplejson.New() + payload.Set("query", query) + + jsonPayload, err := payload.MarshalJSON() + if err != nil { + return nil, err + } + + req, err := http.NewRequest(http.MethodPost, u.String(), strings.NewReader(string(jsonPayload))) + if err != nil { + return nil, err + } + + req.Header.Set("User-Agent", "Grafana") + req.Header.Set("Content-Type", "application/json") + + if e.BasicAuth { + req.SetBasicAuth(e.BasicAuthUser, e.BasicAuthPassword) + } + + return req, nil +} diff --git a/pkg/tsdb/mqe/model_parser.go b/pkg/tsdb/mqe/model_parser.go new file mode 100644 index 00000000000..d139bea9c15 --- /dev/null +++ b/pkg/tsdb/mqe/model_parser.go @@ -0,0 +1,60 @@ +package mqe + +import ( + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/tsdb" +) + +func NewQueryParser() *QueryParser { + return &QueryParser{} +} + +type QueryParser struct{} + +func (qp *QueryParser) Parse(model *simplejson.Json, dsInfo *models.DataSource, queryContext *tsdb.QueryContext) (*Query, error) { + query := &Query{TimeRange: queryContext.TimeRange} + query.AddClusterToAlias = model.Get("addClusterToAlias").MustBool(false) + query.AddHostToAlias = model.Get("addHostToAlias").MustBool(false) + query.UseRawQuery = model.Get("rawQuery").MustBool(false) + query.RawQuery = model.Get("query").MustString("") + + query.Cluster = model.Get("cluster").MustStringArray([]string{}) + query.Hosts = model.Get("hosts").MustStringArray([]string{}) + + var metrics []Metric + var err error + for _, metricsObj := range model.Get("metrics").MustArray() { + metricJson := simplejson.NewFromAny(metricsObj) + var m Metric + + m.Alias = metricJson.Get("alias").MustString("") + m.Metric, err = metricJson.Get("metric").String() + if err != nil { + return nil, err + } + + metrics = append(metrics, m) + } + + query.Metrics = metrics + + var functions []Function + for _, functionListObj := range model.Get("functionList").MustArray() { + functionListJson := simplejson.NewFromAny(functionListObj) + var f Function + + f.Func = functionListJson.Get("func").MustString("") + if err != nil { + return nil, err + } + + if f.Func != "" { + functions = append(functions, f) + } + } + + query.FunctionList = functions + + return query, nil +} diff --git a/pkg/tsdb/mqe/model_parser_test.go b/pkg/tsdb/mqe/model_parser_test.go new file mode 100644 index 00000000000..58e7b7eb28d --- /dev/null +++ b/pkg/tsdb/mqe/model_parser_test.go @@ -0,0 +1,127 @@ +package mqe + +import ( + "testing" + + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/tsdb" + . "github.com/smartystreets/goconvey/convey" +) + +func TestMQEQueryParser(t *testing.T) { + Convey("MQE query parser", t, func() { + parser := &QueryParser{} + + dsInfo := &models.DataSource{JsonData: simplejson.New()} + queryContext := &tsdb.QueryContext{} + + Convey("can parse simple mqe model", func() { + json := ` + { + "cluster": [], + "hosts": [ + "staples-lab-1" + ], + "metrics": [ + { + "metric": "os.cpu.all*" + } + ], + "rawQuery": "", + "refId": "A" + } + ` + modelJson, err := simplejson.NewJson([]byte(json)) + So(err, ShouldBeNil) + + query, err := parser.Parse(modelJson, dsInfo, queryContext) + So(err, ShouldBeNil) + So(query.UseRawQuery, ShouldBeFalse) + + So(len(query.Cluster), ShouldEqual, 0) + So(query.Hosts[0], ShouldEqual, "staples-lab-1") + So(query.Metrics[0].Metric, ShouldEqual, "os.cpu.all*") + }) + + Convey("can parse multi serie mqe model", func() { + json := ` + { + "cluster": [ + "demoapp" + ], + "hosts": [ + "staples-lab-1" + ], + "metrics": [ + { + "metric": "os.cpu.all.active_percentage" + }, + { + "metric": "os.disk.sda.io_time" + } + ], + "functionList": [ + { + "func": "aggregate.min" + }, + { + "func": "aggregate.max" + } + ], + "rawQuery": "", + "refId": "A", + "addClusterToAlias": true, + "addHostToAlias": true + } + ` + modelJson, err := simplejson.NewJson([]byte(json)) + So(err, ShouldBeNil) + + query, err := parser.Parse(modelJson, dsInfo, queryContext) + So(err, ShouldBeNil) + So(query.UseRawQuery, ShouldBeFalse) + So(query.Cluster[0], ShouldEqual, "demoapp") + So(query.Metrics[0].Metric, ShouldEqual, "os.cpu.all.active_percentage") + So(query.Metrics[1].Metric, ShouldEqual, "os.disk.sda.io_time") + So(query.FunctionList[0].Func, ShouldEqual, "aggregate.min") + So(query.FunctionList[1].Func, ShouldEqual, "aggregate.max") + }) + + Convey("can parse raw query", func() { + json := ` + { + "addClusterToAlias": true, + "addHostToAlias": true, + "cluster": [], + "hosts": [ + "staples-lab-1" + ], + "metrics": [ + { + "alias": "cpu active", + "metric": "os.cpu.all.active_percentage" + }, + { + "alias": "disk sda time", + "metric": "os.disk.sda.io_time" + } + ], + "rawQuery": true, + "query": "raw-query", + "refId": "A" + } + ` + modelJson, err := simplejson.NewJson([]byte(json)) + So(err, ShouldBeNil) + + query, err := parser.Parse(modelJson, dsInfo, queryContext) + So(err, ShouldBeNil) + + So(query.UseRawQuery, ShouldBeTrue) + So(query.RawQuery, ShouldEqual, "raw-query") + So(query.AddClusterToAlias, ShouldBeTrue) + So(query.AddHostToAlias, ShouldBeTrue) + }) + }) +} diff --git a/pkg/tsdb/mqe/mqe.go b/pkg/tsdb/mqe/mqe.go new file mode 100644 index 00000000000..5d5f0950de5 --- /dev/null +++ b/pkg/tsdb/mqe/mqe.go @@ -0,0 +1,84 @@ +package mqe + +import ( + "context" + "net/http" + + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/tsdb" +) + +type MQEExecutor struct { + *models.DataSource + queryParser *QueryParser + apiClient *apiClient + httpClient *http.Client + log log.Logger + tokenClient *TokenClient +} + +func NewMQEExecutor(dsInfo *models.DataSource) (tsdb.Executor, error) { + httpclient, err := dsInfo.GetHttpClient() + if err != nil { + return nil, err + } + + return &MQEExecutor{ + DataSource: dsInfo, + httpClient: httpclient, + log: log.New("tsdb.mqe"), + queryParser: NewQueryParser(), + apiClient: NewApiClient(httpclient, dsInfo), + tokenClient: NewTokenClient(dsInfo), + }, nil +} + +func init() { + tsdb.RegisterExecutor("mqe-datasource", NewMQEExecutor) +} + +type QueryToSend struct { + RawQuery string + QueryRef *Query +} + +func (e *MQEExecutor) Execute(ctx context.Context, queries tsdb.QuerySlice, queryContext *tsdb.QueryContext) *tsdb.BatchResult { + result := &tsdb.BatchResult{} + + availableSeries, err := e.tokenClient.GetTokenData(ctx) + if err != nil { + return result.WithError(err) + } + + var mqeQueries []*Query + for _, v := range queries { + q, err := e.queryParser.Parse(v.Model, e.DataSource, queryContext) + if err != nil { + return result.WithError(err) + } + mqeQueries = append(mqeQueries, q) + } + + var rawQueries []QueryToSend + for _, v := range mqeQueries { + queries, err := v.Build(availableSeries.Metrics) + if err != nil { + return result.WithError(err) + } + + rawQueries = append(rawQueries, queries...) + } + + e.log.Debug("Sending request", "url", e.DataSource.Url) + + queryResult, err := e.apiClient.PerformRequests(ctx, rawQueries) + if err != nil { + return result.WithError(err) + } + + result.QueryResults = make(map[string]*tsdb.QueryResult) + result.QueryResults["A"] = queryResult + + return result +} diff --git a/pkg/tsdb/mqe/response_parser.go b/pkg/tsdb/mqe/response_parser.go new file mode 100644 index 00000000000..283098e74f3 --- /dev/null +++ b/pkg/tsdb/mqe/response_parser.go @@ -0,0 +1,103 @@ +package mqe + +import ( + "encoding/json" + "io/ioutil" + "net/http" + + null "gopkg.in/guregu/null.v3" + + "fmt" + + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/tsdb" +) + +func NewResponseParser() *ResponseParser { + return &ResponseParser{ + log: log.New("tsdb.mqe"), + } +} + +type MQEResponse struct { + Success bool `json:"success"` + Name string `json:"name"` + Body []MQEResponseSerie `json:"body"` +} + +type ResponseTimeRange struct { + Start int64 `json:"start"` + End int64 `json:"end"` + Resolution int64 `json:"Resolution"` +} + +type MQEResponseSerie struct { + Query string `json:"query"` + Name string `json:"name"` + Type string `json:"type"` + Series []MQESerie `json:"series"` + TimeRange ResponseTimeRange `json:"timerange"` +} + +type MQESerie struct { + Values []null.Float `json:"values"` + Tagset map[string]string `json:"tagset"` +} + +type ResponseParser struct { + log log.Logger +} + +func (parser *ResponseParser) Parse(res *http.Response, queryRef *Query) ([]*tsdb.TimeSeries, error) { + body, err := ioutil.ReadAll(res.Body) + defer res.Body.Close() + if err != nil { + return nil, err + } + + if res.StatusCode/100 != 2 { + parser.log.Error("Request failed", "status code", res.StatusCode, "body", string(body)) + return nil, fmt.Errorf("Returned invalid statuscode") + } + + var data *MQEResponse = &MQEResponse{} + err = json.Unmarshal(body, data) + if err != nil { + parser.log.Info("Failed to unmarshal response", "error", err, "status", res.Status, "body", string(body)) + return nil, err + } + + if !data.Success { + return nil, fmt.Errorf("Request failed.") + } + + var series []*tsdb.TimeSeries + for _, body := range data.Body { + for _, mqeSerie := range body.Series { + namePrefix := "" + + //append predefined tags to seriename + for key, value := range mqeSerie.Tagset { + if key == "cluster" && queryRef.AddClusterToAlias { + namePrefix += value + " " + } + } + for key, value := range mqeSerie.Tagset { + if key == "host" && queryRef.AddHostToAlias { + namePrefix += value + " " + } + } + + serie := &tsdb.TimeSeries{Name: namePrefix + body.Name} + + for i, value := range mqeSerie.Values { + timestamp := body.TimeRange.Start + int64(i)*body.TimeRange.Resolution + serie.Points = append(serie.Points, tsdb.NewTimePoint(value, float64(timestamp))) + } + + series = append(series, serie) + } + } + + return series, nil +} diff --git a/pkg/tsdb/mqe/response_parser_test.go b/pkg/tsdb/mqe/response_parser_test.go new file mode 100644 index 00000000000..63761841d97 --- /dev/null +++ b/pkg/tsdb/mqe/response_parser_test.go @@ -0,0 +1,131 @@ +package mqe + +import ( + "testing" + + "net/http" + "strings" + + "io/ioutil" + + . "github.com/smartystreets/goconvey/convey" +) + +var ( + dummieJson string +) + +func TestMQEResponseParser(t *testing.T) { + Convey("MQE response parser", t, func() { + parser := NewResponseParser() + + Convey("Can parse response", func() { + queryRef := &Query{ + AddClusterToAlias: true, + AddHostToAlias: true, + } + + response := &http.Response{ + StatusCode: 200, + Body: ioutil.NopCloser(strings.NewReader(dummieJson)), + } + res, err := parser.Parse(response, queryRef) + So(err, ShouldBeNil) + So(len(res), ShouldEqual, 2) + So(len(res[0].Points), ShouldEqual, 14) + So(res[0].Name, ShouldEqual, "demoapp staples-lab-1 os.disk.sda3.weighted_io_time") + startTime := 1479287280000 + for i := 0; i < 11; i++ { + So(res[0].Points[i][0].Float64, ShouldEqual, i+1) + So(res[0].Points[i][1].Float64, ShouldEqual, startTime+(i*30000)) + } + }) + }) +} + +func init() { + dummieJson = `{ + "success": true, + "name": "select", + "body": [ + { + "query": "os.disk.sda3.weighted_io_time", + "name": "os.disk.sda3.weighted_io_time", + "type": "series", + "series": [ + { + "tagset": { + "cluster": "demoapp", + "host": "staples-lab-1" + }, + "values": [1,2,3,4,5,6,7,8,9,10,11, null, null, null] + }, + { + "tagset": { + "cluster": "demoapp", + "host": "staples-lab-2" + }, + "values": [11,10,9,8,7,6,5,4,3,2,1] + } + ], + "timerange": { + "start": 1479287280000, + "end": 1479287580000, + "resolution": 30000 + } + } + ], + "metadata": { + "description": { + "cluster": [ + "demoapp" + ], + "host": [ + "staples-lab-1", + "staples-lab-2" + ] + }, + "notes": null, + "profile": [ + { + "name": "Parsing Query", + "start": "2016-11-16T04:16:21.874354721-05:00", + "finish": "2016-11-16T04:16:21.874762291-05:00" + }, + { + "name": "Cassandra GetAllTags", + "start": "2016-11-16T04:16:21.874907171-05:00", + "finish": "2016-11-16T04:16:21.876401922-05:00" + }, + { + "name": "CachedMetricMetadataAPI_GetAllTags_Expired", + "start": "2016-11-16T04:16:21.874904751-05:00", + "finish": "2016-11-16T04:16:21.876407852-05:00" + }, + { + "name": "CachedMetricMetadataAPI_GetAllTags", + "start": "2016-11-16T04:16:21.874899491-05:00", + "finish": "2016-11-16T04:16:21.876410382-05:00" + }, + { + "name": "Blueflood FetchSingleTimeseries Resolution", + "description": "os.disk.sda3.weighted_io_time [app=demoapp,host=staples-lab-1]\n at 30s", + "start": "2016-11-16T04:16:21.876623312-05:00", + "finish": "2016-11-16T04:16:21.881763444-05:00" + }, + { + "name": "Blueflood FetchSingleTimeseries Resolution", + "description": "os.disk.sda3.weighted_io_time [app=demoapp,host=staples-lab-2]\n at 30s", + "start": "2016-11-16T04:16:21.876642682-05:00", + "finish": "2016-11-16T04:16:21.881895914-05:00" + }, + { + "name": "Blueflood FetchMultipleTimeseries", + "start": "2016-11-16T04:16:21.876418022-05:00", + "finish": "2016-11-16T04:16:21.881921474-05:00" + } + ] + } + } + ` +} diff --git a/pkg/tsdb/mqe/token_client.go b/pkg/tsdb/mqe/token_client.go new file mode 100644 index 00000000000..df136738ab6 --- /dev/null +++ b/pkg/tsdb/mqe/token_client.go @@ -0,0 +1,101 @@ +package mqe + +import ( + "context" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "net/url" + "path" + "time" + + "golang.org/x/net/context/ctxhttp" + + "strconv" + + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/models" + "github.com/patrickmn/go-cache" +) + +var tokenCache *cache.Cache + +func init() { + tokenCache = cache.New(5*time.Minute, 30*time.Second) +} + +type TokenClient struct { + log log.Logger + Datasource *models.DataSource + HttpClient *http.Client +} + +func NewTokenClient(datasource *models.DataSource) *TokenClient { + httpClient, _ := datasource.GetHttpClient() + + return &TokenClient{ + log: log.New("tsdb.mqe.tokenclient"), + Datasource: datasource, + HttpClient: httpClient, + } +} + +func (client *TokenClient) GetTokenData(ctx context.Context) (*TokenBody, error) { + key := strconv.FormatInt(client.Datasource.Id, 10) + + item, found := tokenCache.Get(key) + if found { + if result, ok := item.(*TokenBody); ok { + return result, nil + } + } + + b, err := client.RequestTokenData(ctx) + if err != nil { + return nil, err + } + + tokenCache.Set(key, b, cache.DefaultExpiration) + + return b, nil +} + +func (client *TokenClient) RequestTokenData(ctx context.Context) (*TokenBody, error) { + u, _ := url.Parse(client.Datasource.Url) + u.Path = path.Join(u.Path, "token") + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + client.log.Info("Failed to create request", "error", err) + } + + res, err := ctxhttp.Do(ctx, client.HttpClient, req) + if err != nil { + return nil, err + } + + body, err := ioutil.ReadAll(res.Body) + defer res.Body.Close() + if err != nil { + return nil, err + } + + if res.StatusCode/100 != 2 { + client.log.Info("Request failed", "status", res.Status, "body", string(body)) + return nil, fmt.Errorf("Request failed status: %v", res.Status) + } + + var result *TokenResponse + err = json.Unmarshal(body, &result) + if err != nil { + client.log.Info("Failed to unmarshal response", "error", err, "status", res.Status, "body", string(body)) + return nil, err + } + + if !result.Success { + return nil, fmt.Errorf("Request failed for unknown reason.") + } + + return &result.Body, nil +} diff --git a/pkg/tsdb/mqe/token_client_test.go b/pkg/tsdb/mqe/token_client_test.go new file mode 100644 index 00000000000..f940f798b36 --- /dev/null +++ b/pkg/tsdb/mqe/token_client_test.go @@ -0,0 +1,27 @@ +package mqe + +import ( + "context" + "testing" + + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/models" + . "github.com/smartystreets/goconvey/convey" +) + +func TestTokenClient(t *testing.T) { + SkipConvey("Token client", t, func() { + dsInfo := &models.DataSource{ + JsonData: simplejson.New(), + Url: "", + } + + client := NewTokenClient(dsInfo) + + body, err := client.RequestTokenData(context.TODO()) + + So(err, ShouldBeNil) + //So(len(body.Functions), ShouldBeGreaterThan, 1) + So(len(body.Metrics), ShouldBeGreaterThan, 1) + }) +} diff --git a/pkg/tsdb/mqe/types.go b/pkg/tsdb/mqe/types.go new file mode 100644 index 00000000000..4fa2c1d4e7f --- /dev/null +++ b/pkg/tsdb/mqe/types.go @@ -0,0 +1,135 @@ +package mqe + +import ( + "fmt" + + "strings" + + "regexp" + + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/tsdb" +) + +type Metric struct { + Metric string + Alias string +} + +type Function struct { + Func string +} + +type Query struct { + Metrics []Metric + Hosts []string + Cluster []string + FunctionList []Function + AddClusterToAlias bool + AddHostToAlias bool + + TimeRange *tsdb.TimeRange + UseRawQuery bool + RawQuery string +} + +var ( + containsWildcardPattern *regexp.Regexp = regexp.MustCompile(`\*`) +) + +func (q *Query) Build(availableSeries []string) ([]QueryToSend, error) { + var queriesToSend []QueryToSend + where := q.buildWhereClause() + functions := q.buildFunctionList() + + for _, metric := range q.Metrics { + alias := "" + if metric.Alias != "" { + alias = fmt.Sprintf(" {%s}", metric.Alias) + } + + if !containsWildcardPattern.Match([]byte(metric.Metric)) { + rawQuery := q.renderQuerystring(metric.Metric, functions, alias, where, q.TimeRange) + queriesToSend = append(queriesToSend, QueryToSend{ + RawQuery: rawQuery, + QueryRef: q, + }) + } else { + m := strings.Replace(metric.Metric, "*", ".*", -1) + mp, err := regexp.Compile(m) + + if err != nil { + log.Error2("failed to compile regex for ", "metric", m) + continue + } + + //TODO: this lookup should be cached + for _, wildcardMatch := range availableSeries { + if mp.Match([]byte(wildcardMatch)) { + rawQuery := q.renderQuerystring(wildcardMatch, functions, alias, where, q.TimeRange) + queriesToSend = append(queriesToSend, QueryToSend{ + RawQuery: rawQuery, + QueryRef: q, + }) + } + } + } + } + + return queriesToSend, nil +} + +func (q *Query) renderQuerystring(path, functions, alias, where string, timerange *tsdb.TimeRange) string { + return fmt.Sprintf( + "`%s`%s%s %s from %v to %v", + path, + functions, + alias, + where, + q.TimeRange.GetFromAsMsEpoch(), + q.TimeRange.GetToAsMsEpoch()) +} + +func (q *Query) buildFunctionList() string { + functions := "" + for _, v := range q.FunctionList { + functions = fmt.Sprintf("%s|%s", functions, v.Func) + } + + return functions +} + +func (q *Query) buildWhereClause() string { + hasApps := len(q.Cluster) > 0 + hasHosts := len(q.Hosts) > 0 + + where := "" + if hasHosts || hasApps { + where += "where " + } + + if hasApps { + apps := strings.Join(q.Cluster, "', '") + where += fmt.Sprintf("cluster in ('%s')", apps) + } + + if hasHosts && hasApps { + where += " and " + } + + if hasHosts { + hosts := strings.Join(q.Hosts, "', '") + where += fmt.Sprintf("host in ('%s')", hosts) + } + + return where +} + +type TokenBody struct { + Metrics []string +} + +type TokenResponse struct { + Success bool + Body TokenBody +} diff --git a/pkg/tsdb/mqe/types_test.go b/pkg/tsdb/mqe/types_test.go new file mode 100644 index 00000000000..1138e0599e7 --- /dev/null +++ b/pkg/tsdb/mqe/types_test.go @@ -0,0 +1,95 @@ +package mqe + +import ( + "testing" + + "time" + + "fmt" + + "github.com/grafana/grafana/pkg/tsdb" + . "github.com/smartystreets/goconvey/convey" +) + +func TestWildcardExpansion(t *testing.T) { + availableMetrics := []string{ + "os.cpu.all.idle", + "os.cpu.1.idle", + "os.cpu.2.idle", + "os.cpu.3.idle", + } + + now := time.Now() + from := now.Add((time.Minute*5)*-1).UnixNano() / int64(time.Millisecond) + to := now.UnixNano() / int64(time.Millisecond) + + Convey("Can expanding query", t, func() { + Convey("Without wildcard series", func() { + query := &Query{ + Metrics: []Metric{ + Metric{Metric: "os.cpu.3.idle", Alias: ""}, + Metric{Metric: "os.cpu.2.idle", Alias: ""}, + Metric{Metric: "os.cpu.1.idle", Alias: "cpu"}, + }, + Hosts: []string{"staples-lab-1", "staples-lab-2"}, + Cluster: []string{"demoapp-1", "demoapp-2"}, + AddClusterToAlias: false, + AddHostToAlias: false, + FunctionList: []Function{ + Function{Func: "aggregate.min"}, + }, + TimeRange: &tsdb.TimeRange{Now: now, From: "5m", To: "now"}, + } + + expandeQueries, err := query.Build(availableMetrics) + So(err, ShouldBeNil) + So(len(expandeQueries), ShouldEqual, 3) + So(expandeQueries[0].RawQuery, ShouldEqual, fmt.Sprintf("`os.cpu.3.idle`|aggregate.min where cluster in ('demoapp-1', 'demoapp-2') and host in ('staples-lab-1', 'staples-lab-2') from %v to %v", from, to)) + So(expandeQueries[1].RawQuery, ShouldEqual, fmt.Sprintf("`os.cpu.2.idle`|aggregate.min where cluster in ('demoapp-1', 'demoapp-2') and host in ('staples-lab-1', 'staples-lab-2') from %v to %v", from, to)) + So(expandeQueries[2].RawQuery, ShouldEqual, fmt.Sprintf("`os.cpu.1.idle`|aggregate.min {cpu} where cluster in ('demoapp-1', 'demoapp-2') and host in ('staples-lab-1', 'staples-lab-2') from %v to %v", from, to)) + }) + + Convey("With two aggregate functions", func() { + query := &Query{ + Metrics: []Metric{ + Metric{Metric: "os.cpu.3.idle", Alias: ""}, + }, + Hosts: []string{"staples-lab-1", "staples-lab-2"}, + Cluster: []string{"demoapp-1", "demoapp-2"}, + AddClusterToAlias: false, + AddHostToAlias: false, + FunctionList: []Function{ + Function{Func: "aggregate.min"}, + Function{Func: "aggregate.max"}, + }, + TimeRange: &tsdb.TimeRange{Now: now, From: "5m", To: "now"}, + } + + expandeQueries, err := query.Build(availableMetrics) + So(err, ShouldBeNil) + So(len(expandeQueries), ShouldEqual, 1) + So(expandeQueries[0].RawQuery, ShouldEqual, fmt.Sprintf("`os.cpu.3.idle`|aggregate.min|aggregate.max where cluster in ('demoapp-1', 'demoapp-2') and host in ('staples-lab-1', 'staples-lab-2') from %v to %v", from, to)) + }) + + Convey("Containg wildcard series", func() { + query := &Query{ + Metrics: []Metric{ + Metric{Metric: "os.cpu*", Alias: ""}, + }, + Hosts: []string{"staples-lab-1"}, + AddClusterToAlias: false, + AddHostToAlias: false, + TimeRange: &tsdb.TimeRange{Now: now, From: "5m", To: "now"}, + } + + expandeQueries, err := query.Build(availableMetrics) + So(err, ShouldBeNil) + So(len(expandeQueries), ShouldEqual, 4) + + So(expandeQueries[0].RawQuery, ShouldEqual, fmt.Sprintf("`os.cpu.all.idle` where host in ('staples-lab-1') from %v to %v", from, to)) + So(expandeQueries[1].RawQuery, ShouldEqual, fmt.Sprintf("`os.cpu.1.idle` where host in ('staples-lab-1') from %v to %v", from, to)) + So(expandeQueries[2].RawQuery, ShouldEqual, fmt.Sprintf("`os.cpu.2.idle` where host in ('staples-lab-1') from %v to %v", from, to)) + So(expandeQueries[3].RawQuery, ShouldEqual, fmt.Sprintf("`os.cpu.3.idle` where host in ('staples-lab-1') from %v to %v", from, to)) + }) + }) +} diff --git a/pkg/tsdb/opentsdb/opentsdb.go b/pkg/tsdb/opentsdb/opentsdb.go new file mode 100644 index 00000000000..f5b6ffda7d2 --- /dev/null +++ b/pkg/tsdb/opentsdb/opentsdb.go @@ -0,0 +1,211 @@ +package opentsdb + +import ( + "context" + "fmt" + "path" + "strconv" + "strings" + + "golang.org/x/net/context/ctxhttp" + + "encoding/json" + "io/ioutil" + "net/http" + "net/url" + + "gopkg.in/guregu/null.v3" + + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/setting" + "github.com/grafana/grafana/pkg/tsdb" +) + +type OpenTsdbExecutor struct { + *models.DataSource + httpClient *http.Client +} + +func NewOpenTsdbExecutor(datasource *models.DataSource) (tsdb.Executor, error) { + httpClient, err := datasource.GetHttpClient() + + if err != nil { + return nil, err + } + + return &OpenTsdbExecutor{ + DataSource: datasource, + httpClient: httpClient, + }, nil +} + +var ( + plog log.Logger +) + +func init() { + plog = log.New("tsdb.opentsdb") + tsdb.RegisterExecutor("opentsdb", NewOpenTsdbExecutor) +} + +func (e *OpenTsdbExecutor) Execute(ctx context.Context, queries tsdb.QuerySlice, queryContext *tsdb.QueryContext) *tsdb.BatchResult { + result := &tsdb.BatchResult{} + + var tsdbQuery OpenTsdbQuery + + tsdbQuery.Start = queryContext.TimeRange.GetFromAsMsEpoch() + tsdbQuery.End = queryContext.TimeRange.GetToAsMsEpoch() + + for _, query := range queries { + metric := e.buildMetric(query) + tsdbQuery.Queries = append(tsdbQuery.Queries, metric) + } + + if setting.Env == setting.DEV { + plog.Debug("OpenTsdb request", "params", tsdbQuery) + } + + req, err := e.createRequest(tsdbQuery) + if err != nil { + result.Error = err + return result + } + + res, err := ctxhttp.Do(ctx, e.httpClient, req) + if err != nil { + result.Error = err + return result + } + + queryResult, err := e.parseResponse(tsdbQuery, res) + if err != nil { + return result.WithError(err) + } + + result.QueryResults = queryResult + return result +} + +func (e *OpenTsdbExecutor) createRequest(data OpenTsdbQuery) (*http.Request, error) { + u, _ := url.Parse(e.Url) + u.Path = path.Join(u.Path, "api/query") + + postData, err := json.Marshal(data) + + req, err := http.NewRequest(http.MethodPost, u.String(), strings.NewReader(string(postData))) + if err != nil { + plog.Info("Failed to create request", "error", err) + return nil, fmt.Errorf("Failed to create request. error: %v", err) + } + + req.Header.Set("Content-Type", "application/json") + if e.BasicAuth { + req.SetBasicAuth(e.BasicAuthUser, e.BasicAuthPassword) + } + + return req, err +} + +func (e *OpenTsdbExecutor) parseResponse(query OpenTsdbQuery, res *http.Response) (map[string]*tsdb.QueryResult, error) { + + queryResults := make(map[string]*tsdb.QueryResult) + queryRes := tsdb.NewQueryResult() + + body, err := ioutil.ReadAll(res.Body) + defer res.Body.Close() + if err != nil { + return nil, err + } + + if res.StatusCode/100 != 2 { + plog.Info("Request failed", "status", res.Status, "body", string(body)) + return nil, fmt.Errorf("Request failed status: %v", res.Status) + } + + var data []OpenTsdbResponse + err = json.Unmarshal(body, &data) + if err != nil { + plog.Info("Failed to unmarshal opentsdb response", "error", err, "status", res.Status, "body", string(body)) + return nil, err + } + + for _, val := range data { + series := tsdb.TimeSeries{ + Name: val.Metric, + } + + for timeString, value := range val.DataPoints { + timestamp, err := strconv.ParseFloat(timeString, 64) + if err != nil { + plog.Info("Failed to unmarshal opentsdb timestamp", "timestamp", timeString) + return nil, err + } + series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFrom(value), timestamp)) + } + + queryRes.Series = append(queryRes.Series, &series) + } + + queryResults["A"] = queryRes + return queryResults, nil +} + +func (e *OpenTsdbExecutor) buildMetric(query *tsdb.Query) map[string]interface{} { + + metric := make(map[string]interface{}) + + // Setting metric and aggregator + metric["metric"] = query.Model.Get("metric").MustString() + metric["aggregator"] = query.Model.Get("aggregator").MustString() + + // Setting downsampling options + disableDownsampling := query.Model.Get("disableDownsampling").MustBool() + if !disableDownsampling { + downsampleInterval := query.Model.Get("downsampleInterval").MustString() + if downsampleInterval == "" { + downsampleInterval = "1m" //default value for blank + } + downsample := downsampleInterval + "-" + query.Model.Get("downsampleAggregator").MustString() + if query.Model.Get("downsampleFillPolicy").MustString() != "none" { + metric["downsample"] = downsample + "-" + query.Model.Get("downsampleFillPolicy").MustString() + } else { + metric["downsample"] = downsample + } + } + + // Setting rate options + if query.Model.Get("shouldComputeRate").MustBool() { + + metric["rate"] = true + rateOptions := make(map[string]interface{}) + rateOptions["counter"] = query.Model.Get("isCounter").MustBool() + + counterMax, counterMaxCheck := query.Model.CheckGet("counterMax") + if counterMaxCheck { + rateOptions["counterMax"] = counterMax.MustFloat64() + } + + resetValue, resetValueCheck := query.Model.CheckGet("counterResetValue") + if resetValueCheck { + rateOptions["resetValue"] = resetValue.MustFloat64() + } + + metric["rateOptions"] = rateOptions + } + + // Setting tags + tags, tagsCheck := query.Model.CheckGet("tags") + if tagsCheck && len(tags.MustMap()) > 0 { + metric["tags"] = tags.MustMap() + } + + // Setting filters + filters, filtersCheck := query.Model.CheckGet("filters") + if filtersCheck && len(filters.MustArray()) > 0 { + metric["filters"] = filters.MustArray() + } + + return metric + +} diff --git a/pkg/tsdb/opentsdb/opentsdb_test.go b/pkg/tsdb/opentsdb/opentsdb_test.go new file mode 100644 index 00000000000..094deb9e8ec --- /dev/null +++ b/pkg/tsdb/opentsdb/opentsdb_test.go @@ -0,0 +1,176 @@ +package opentsdb + +import ( + "testing" + + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/tsdb" + . "github.com/smartystreets/goconvey/convey" +) + +func TestOpenTsdbExecutor(t *testing.T) { + Convey("OpenTsdb query testing", t, func() { + + exec := &OpenTsdbExecutor{} + + Convey("Build metric with downsampling enabled", func() { + + query := &tsdb.Query{ + Model: simplejson.New(), + } + + query.Model.Set("metric", "cpu.average.percent") + query.Model.Set("aggregator", "avg") + query.Model.Set("disableDownsampling", false) + query.Model.Set("downsampleInterval", "") + query.Model.Set("downsampleAggregator", "avg") + query.Model.Set("downsampleFillPolicy", "none") + + metric := exec.buildMetric(query) + + So(len(metric), ShouldEqual, 3) + So(metric["metric"], ShouldEqual, "cpu.average.percent") + So(metric["aggregator"], ShouldEqual, "avg") + So(metric["downsample"], ShouldEqual, "1m-avg") + + }) + + Convey("Build metric with downsampling diabled", func() { + + query := &tsdb.Query{ + Model: simplejson.New(), + } + + query.Model.Set("metric", "cpu.average.percent") + query.Model.Set("aggregator", "avg") + query.Model.Set("disableDownsampling", true) + query.Model.Set("downsampleInterval", "") + query.Model.Set("downsampleAggregator", "avg") + query.Model.Set("downsampleFillPolicy", "none") + + metric := exec.buildMetric(query) + + So(len(metric), ShouldEqual, 2) + So(metric["metric"], ShouldEqual, "cpu.average.percent") + So(metric["aggregator"], ShouldEqual, "avg") + + }) + + Convey("Build metric with downsampling enabled with params", func() { + + query := &tsdb.Query{ + Model: simplejson.New(), + } + + query.Model.Set("metric", "cpu.average.percent") + query.Model.Set("aggregator", "avg") + query.Model.Set("disableDownsampling", false) + query.Model.Set("downsampleInterval", "5m") + query.Model.Set("downsampleAggregator", "sum") + query.Model.Set("downsampleFillPolicy", "null") + + metric := exec.buildMetric(query) + + So(len(metric), ShouldEqual, 3) + So(metric["metric"], ShouldEqual, "cpu.average.percent") + So(metric["aggregator"], ShouldEqual, "avg") + So(metric["downsample"], ShouldEqual, "5m-sum-null") + }) + + Convey("Build metric with tags with downsampling disabled", func() { + + query := &tsdb.Query{ + Model: simplejson.New(), + } + + query.Model.Set("metric", "cpu.average.percent") + query.Model.Set("aggregator", "avg") + query.Model.Set("disableDownsampling", true) + query.Model.Set("downsampleInterval", "5m") + query.Model.Set("downsampleAggregator", "sum") + query.Model.Set("downsampleFillPolicy", "null") + + tags := simplejson.New() + tags.Set("env", "prod") + tags.Set("app", "grafana") + query.Model.Set("tags", tags.MustMap()) + + metric := exec.buildMetric(query) + + So(len(metric), ShouldEqual, 3) + So(metric["metric"], ShouldEqual, "cpu.average.percent") + So(metric["aggregator"], ShouldEqual, "avg") + So(metric["downsample"], ShouldEqual, nil) + So(len(metric["tags"].(map[string]interface{})), ShouldEqual, 2) + So(metric["tags"].(map[string]interface{})["env"], ShouldEqual, "prod") + So(metric["tags"].(map[string]interface{})["app"], ShouldEqual, "grafana") + So(metric["tags"].(map[string]interface{})["ip"], ShouldEqual, nil) + }) + + Convey("Build metric with rate enabled but counter disabled", func() { + + query := &tsdb.Query{ + Model: simplejson.New(), + } + + query.Model.Set("metric", "cpu.average.percent") + query.Model.Set("aggregator", "avg") + query.Model.Set("disableDownsampling", true) + query.Model.Set("shouldComputeRate", true) + query.Model.Set("isCounter", false) + + tags := simplejson.New() + tags.Set("env", "prod") + tags.Set("app", "grafana") + query.Model.Set("tags", tags.MustMap()) + + metric := exec.buildMetric(query) + + So(len(metric), ShouldEqual, 5) + So(metric["metric"], ShouldEqual, "cpu.average.percent") + So(metric["aggregator"], ShouldEqual, "avg") + So(len(metric["tags"].(map[string]interface{})), ShouldEqual, 2) + So(metric["tags"].(map[string]interface{})["env"], ShouldEqual, "prod") + So(metric["tags"].(map[string]interface{})["app"], ShouldEqual, "grafana") + So(metric["tags"].(map[string]interface{})["ip"], ShouldEqual, nil) + So(metric["rate"], ShouldEqual, true) + So(metric["rateOptions"].(map[string]interface{})["counter"], ShouldEqual, false) + }) + + Convey("Build metric with rate and counter enabled", func() { + + query := &tsdb.Query{ + Model: simplejson.New(), + } + + query.Model.Set("metric", "cpu.average.percent") + query.Model.Set("aggregator", "avg") + query.Model.Set("disableDownsampling", true) + query.Model.Set("shouldComputeRate", true) + query.Model.Set("isCounter", true) + query.Model.Set("counterMax", 45) + query.Model.Set("counterResetValue", 60) + + tags := simplejson.New() + tags.Set("env", "prod") + tags.Set("app", "grafana") + query.Model.Set("tags", tags.MustMap()) + + metric := exec.buildMetric(query) + + So(len(metric), ShouldEqual, 5) + So(metric["metric"], ShouldEqual, "cpu.average.percent") + So(metric["aggregator"], ShouldEqual, "avg") + So(len(metric["tags"].(map[string]interface{})), ShouldEqual, 2) + So(metric["tags"].(map[string]interface{})["env"], ShouldEqual, "prod") + So(metric["tags"].(map[string]interface{})["app"], ShouldEqual, "grafana") + So(metric["tags"].(map[string]interface{})["ip"], ShouldEqual, nil) + So(metric["rate"], ShouldEqual, true) + So(len(metric["rateOptions"].(map[string]interface{})), ShouldEqual, 3) + So(metric["rateOptions"].(map[string]interface{})["counter"], ShouldEqual, true) + So(metric["rateOptions"].(map[string]interface{})["counterMax"], ShouldEqual, 45) + So(metric["rateOptions"].(map[string]interface{})["resetValue"], ShouldEqual, 60) + }) + + }) +} diff --git a/pkg/tsdb/opentsdb/types.go b/pkg/tsdb/opentsdb/types.go new file mode 100644 index 00000000000..752dee0fb3b --- /dev/null +++ b/pkg/tsdb/opentsdb/types.go @@ -0,0 +1,12 @@ +package opentsdb + +type OpenTsdbQuery struct { + Start int64 `json:"start"` + End int64 `json:"end"` + Queries []map[string]interface{} `json:"queries"` +} + +type OpenTsdbResponse struct { + Metric string `json:"metric"` + DataPoints map[string]float64 `json:"dps"` +} diff --git a/pkg/tsdb/prometheus/prometheus.go b/pkg/tsdb/prometheus/prometheus.go new file mode 100644 index 00000000000..c391f00920a --- /dev/null +++ b/pkg/tsdb/prometheus/prometheus.go @@ -0,0 +1,172 @@ +package prometheus + +import ( + "context" + "fmt" + "regexp" + "strings" + "time" + + "gopkg.in/guregu/null.v3" + + "net/http" + + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/tsdb" + "github.com/prometheus/client_golang/api/prometheus" + pmodel "github.com/prometheus/common/model" +) + +type PrometheusExecutor struct { + *models.DataSource + Transport *http.Transport +} + +func NewPrometheusExecutor(dsInfo *models.DataSource) (tsdb.Executor, error) { + transport, err := dsInfo.GetHttpTransport() + if err != nil { + return nil, err + } + + return &PrometheusExecutor{ + DataSource: dsInfo, + Transport: transport, + }, nil +} + +var ( + plog log.Logger + legendFormat *regexp.Regexp +) + +func init() { + plog = log.New("tsdb.prometheus") + tsdb.RegisterExecutor("prometheus", NewPrometheusExecutor) + legendFormat = regexp.MustCompile(`\{\{\s*(.+?)\s*\}\}`) +} + +func (e *PrometheusExecutor) getClient() (prometheus.QueryAPI, error) { + cfg := prometheus.Config{ + Address: e.DataSource.Url, + Transport: e.Transport, + } + + client, err := prometheus.New(cfg) + if err != nil { + return nil, err + } + + return prometheus.NewQueryAPI(client), nil +} + +func (e *PrometheusExecutor) Execute(ctx context.Context, queries tsdb.QuerySlice, queryContext *tsdb.QueryContext) *tsdb.BatchResult { + result := &tsdb.BatchResult{} + + client, err := e.getClient() + if err != nil { + return result.WithError(err) + } + + query, err := parseQuery(queries, queryContext) + if err != nil { + return result.WithError(err) + } + + timeRange := prometheus.Range{ + Start: query.Start, + End: query.End, + Step: query.Step, + } + + value, err := client.QueryRange(ctx, query.Expr, timeRange) + + if err != nil { + return result.WithError(err) + } + + queryResult, err := parseResponse(value, query) + if err != nil { + return result.WithError(err) + } + result.QueryResults = queryResult + return result +} + +func formatLegend(metric pmodel.Metric, query *PrometheusQuery) string { + if query.LegendFormat == "" { + return metric.String() + } + + result := legendFormat.ReplaceAllFunc([]byte(query.LegendFormat), func(in []byte) []byte { + labelName := strings.Replace(string(in), "{{", "", 1) + labelName = strings.Replace(labelName, "}}", "", 1) + labelName = strings.TrimSpace(labelName) + if val, exists := metric[pmodel.LabelName(labelName)]; exists { + return []byte(val) + } + + return in + }) + + return string(result) +} + +func parseQuery(queries tsdb.QuerySlice, queryContext *tsdb.QueryContext) (*PrometheusQuery, error) { + queryModel := queries[0] + + expr, err := queryModel.Model.Get("expr").String() + if err != nil { + return nil, err + } + + step, err := queryModel.Model.Get("step").Int64() + if err != nil { + return nil, err + } + + format := queryModel.Model.Get("legendFormat").MustString("") + + start, err := queryContext.TimeRange.ParseFrom() + if err != nil { + return nil, err + } + + end, err := queryContext.TimeRange.ParseTo() + if err != nil { + return nil, err + } + + return &PrometheusQuery{ + Expr: expr, + Step: time.Second * time.Duration(step), + LegendFormat: format, + Start: start, + End: end, + }, nil +} + +func parseResponse(value pmodel.Value, query *PrometheusQuery) (map[string]*tsdb.QueryResult, error) { + queryResults := make(map[string]*tsdb.QueryResult) + queryRes := tsdb.NewQueryResult() + + data, ok := value.(pmodel.Matrix) + if !ok { + return queryResults, fmt.Errorf("Unsupported result format: %s", value.Type().String()) + } + + for _, v := range data { + series := tsdb.TimeSeries{ + Name: formatLegend(v.Metric, query), + } + + for _, k := range v.Values { + series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFrom(float64(k.Value)), float64(k.Timestamp.Unix()*1000))) + } + + queryRes.Series = append(queryRes.Series, &series) + } + + queryResults["A"] = queryRes + return queryResults, nil +} diff --git a/pkg/tsdb/prometheus/prometheus_test.go b/pkg/tsdb/prometheus/prometheus_test.go new file mode 100644 index 00000000000..d66ef75e479 --- /dev/null +++ b/pkg/tsdb/prometheus/prometheus_test.go @@ -0,0 +1,40 @@ +package prometheus + +import ( + "testing" + + p "github.com/prometheus/common/model" + . "github.com/smartystreets/goconvey/convey" +) + +func TestPrometheus(t *testing.T) { + Convey("Prometheus", t, func() { + + Convey("converting metric name", func() { + metric := map[p.LabelName]p.LabelValue{ + p.LabelName("app"): p.LabelValue("backend"), + p.LabelName("device"): p.LabelValue("mobile"), + } + + query := &PrometheusQuery{ + LegendFormat: "legend {{app}} {{ device }} {{broken}}", + } + + So(formatLegend(metric, query), ShouldEqual, "legend backend mobile {{broken}}") + }) + + Convey("build full serie name", func() { + metric := map[p.LabelName]p.LabelValue{ + p.LabelName(p.MetricNameLabel): p.LabelValue("http_request_total"), + p.LabelName("app"): p.LabelValue("backend"), + p.LabelName("device"): p.LabelValue("mobile"), + } + + query := &PrometheusQuery{ + LegendFormat: "", + } + + So(formatLegend(metric, query), ShouldEqual, `http_request_total{app="backend", device="mobile"}`) + }) + }) +} diff --git a/pkg/tsdb/prometheus/types.go b/pkg/tsdb/prometheus/types.go new file mode 100644 index 00000000000..8ed665d0123 --- /dev/null +++ b/pkg/tsdb/prometheus/types.go @@ -0,0 +1,11 @@ +package prometheus + +import "time" + +type PrometheusQuery struct { + Expr string + Step time.Duration + LegendFormat string + Start time.Time + End time.Time +} diff --git a/pkg/tsdb/query_context.go b/pkg/tsdb/query_context.go new file mode 100644 index 00000000000..db40ba6253c --- /dev/null +++ b/pkg/tsdb/query_context.go @@ -0,0 +1,21 @@ +package tsdb + +import "sync" + +type QueryContext struct { + TimeRange *TimeRange + Queries QuerySlice + Results map[string]*QueryResult + ResultsChan chan *BatchResult + Lock sync.RWMutex + BatchWaits sync.WaitGroup +} + +func NewQueryContext(queries QuerySlice, timeRange *TimeRange) *QueryContext { + return &QueryContext{ + TimeRange: timeRange, + Queries: queries, + ResultsChan: make(chan *BatchResult), + Results: make(map[string]*QueryResult), + } +} diff --git a/pkg/tsdb/request.go b/pkg/tsdb/request.go new file mode 100644 index 00000000000..2934443bc53 --- /dev/null +++ b/pkg/tsdb/request.go @@ -0,0 +1,61 @@ +package tsdb + +import "context" + +type HandleRequestFunc func(ctx context.Context, req *Request) (*Response, error) + +func HandleRequest(ctx context.Context, req *Request) (*Response, error) { + context := NewQueryContext(req.Queries, req.TimeRange) + + batches, err := getBatches(req) + if err != nil { + return nil, err + } + + currentlyExecuting := 0 + + for _, batch := range batches { + if len(batch.Depends) == 0 { + currentlyExecuting += 1 + batch.Started = true + go batch.process(ctx, context) + } + } + + response := &Response{} + + for currentlyExecuting != 0 { + select { + case batchResult := <-context.ResultsChan: + currentlyExecuting -= 1 + + response.BatchTimings = append(response.BatchTimings, batchResult.Timings) + + if batchResult.Error != nil { + return nil, batchResult.Error + } + + for refId, result := range batchResult.QueryResults { + context.Results[refId] = result + } + + for _, batch := range batches { + // not interested in started batches + if batch.Started { + continue + } + + if batch.allDependenciesAreIn(context) { + currentlyExecuting += 1 + batch.Started = true + go batch.process(ctx, context) + } + } + case <-ctx.Done(): + return nil, ctx.Err() + } + } + + response.Results = context.Results + return response, nil +} diff --git a/pkg/tsdb/testdata/scenarios.go b/pkg/tsdb/testdata/scenarios.go new file mode 100644 index 00000000000..667b7fffcba --- /dev/null +++ b/pkg/tsdb/testdata/scenarios.go @@ -0,0 +1,137 @@ +package testdata + +import ( + "math/rand" + "strconv" + "strings" + "time" + + "gopkg.in/guregu/null.v3" + + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/tsdb" +) + +type ScenarioHandler func(query *tsdb.Query, context *tsdb.QueryContext) *tsdb.QueryResult + +type Scenario struct { + Id string `json:"id"` + Name string `json:"name"` + StringInput string `json:"stringOption"` + Description string `json:"description"` + Handler ScenarioHandler `json:"-"` +} + +var ScenarioRegistry map[string]*Scenario + +func init() { + ScenarioRegistry = make(map[string]*Scenario) + logger := log.New("tsdb.testdata") + + logger.Debug("Initializing TestData Scenario") + + registerScenario(&Scenario{ + Id: "random_walk", + Name: "Random Walk", + + Handler: func(query *tsdb.Query, context *tsdb.QueryContext) *tsdb.QueryResult { + timeWalkerMs := context.TimeRange.GetFromAsMsEpoch() + to := context.TimeRange.GetToAsMsEpoch() + + series := newSeriesForQuery(query) + + points := make(tsdb.TimeSeriesPoints, 0) + walker := rand.Float64() * 100 + + for i := int64(0); i < 10000 && timeWalkerMs < to; i++ { + points = append(points, tsdb.NewTimePoint(null.FloatFrom(walker), float64(timeWalkerMs))) + + walker += rand.Float64() - 0.5 + timeWalkerMs += query.IntervalMs + } + + series.Points = points + + queryRes := tsdb.NewQueryResult() + queryRes.Series = append(queryRes.Series, series) + return queryRes + }, + }) + + registerScenario(&Scenario{ + Id: "no_data_points", + Name: "No Data Points", + Handler: func(query *tsdb.Query, context *tsdb.QueryContext) *tsdb.QueryResult { + return tsdb.NewQueryResult() + }, + }) + + registerScenario(&Scenario{ + Id: "datapoints_outside_range", + Name: "Datapoints Outside Range", + Handler: func(query *tsdb.Query, context *tsdb.QueryContext) *tsdb.QueryResult { + queryRes := tsdb.NewQueryResult() + + series := newSeriesForQuery(query) + outsideTime := context.TimeRange.MustGetFrom().Add(-1*time.Hour).Unix() * 1000 + + series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFrom(10), float64(outsideTime))) + queryRes.Series = append(queryRes.Series, series) + + return queryRes + }, + }) + + registerScenario(&Scenario{ + Id: "csv_metric_values", + Name: "CSV Metric Values", + StringInput: "1,20,90,30,5,0", + Handler: func(query *tsdb.Query, context *tsdb.QueryContext) *tsdb.QueryResult { + queryRes := tsdb.NewQueryResult() + + stringInput := query.Model.Get("stringInput").MustString() + stringInput = strings.Replace(stringInput, " ", "", -1) + + values := []null.Float{} + for _, strVal := range strings.Split(stringInput, ",") { + if strVal == "null" { + values = append(values, null.FloatFromPtr(nil)) + } + if val, err := strconv.ParseFloat(strVal, 64); err == nil { + values = append(values, null.FloatFrom(val)) + } + } + + if len(values) == 0 { + return queryRes + } + + series := newSeriesForQuery(query) + startTime := context.TimeRange.GetFromAsMsEpoch() + endTime := context.TimeRange.GetToAsMsEpoch() + step := (endTime - startTime) / int64(len(values)-1) + + for _, val := range values { + series.Points = append(series.Points, tsdb.TimePoint{val, null.FloatFrom(float64(startTime))}) + startTime += step + } + + queryRes.Series = append(queryRes.Series, series) + + return queryRes + }, + }) +} + +func registerScenario(scenario *Scenario) { + ScenarioRegistry[scenario.Id] = scenario +} + +func newSeriesForQuery(query *tsdb.Query) *tsdb.TimeSeries { + alias := query.Model.Get("alias").MustString("") + if alias == "" { + alias = query.RefId + "-series" + } + + return &tsdb.TimeSeries{Name: alias} +} diff --git a/pkg/tsdb/testdata/testdata.go b/pkg/tsdb/testdata/testdata.go new file mode 100644 index 00000000000..6aefd8686d8 --- /dev/null +++ b/pkg/tsdb/testdata/testdata.go @@ -0,0 +1,42 @@ +package testdata + +import ( + "context" + + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/tsdb" +) + +type TestDataExecutor struct { + *models.DataSource + log log.Logger +} + +func NewTestDataExecutor(dsInfo *models.DataSource) (tsdb.Executor, error) { + return &TestDataExecutor{ + DataSource: dsInfo, + log: log.New("tsdb.testdata"), + }, nil +} + +func init() { + tsdb.RegisterExecutor("grafana-testdata-datasource", NewTestDataExecutor) +} + +func (e *TestDataExecutor) Execute(ctx context.Context, queries tsdb.QuerySlice, context *tsdb.QueryContext) *tsdb.BatchResult { + result := &tsdb.BatchResult{} + result.QueryResults = make(map[string]*tsdb.QueryResult) + + for _, query := range queries { + scenarioId := query.Model.Get("scenarioId").MustString("random_walk") + if scenario, exist := ScenarioRegistry[scenarioId]; exist { + result.QueryResults[query.RefId] = scenario.Handler(query, context) + result.QueryResults[query.RefId].RefId = query.RefId + } else { + e.log.Error("Scenario not found", "scenarioId", scenarioId) + } + } + + return result +} diff --git a/pkg/tsdb/time_range.go b/pkg/tsdb/time_range.go new file mode 100644 index 00000000000..cf6bc6a5048 --- /dev/null +++ b/pkg/tsdb/time_range.go @@ -0,0 +1,90 @@ +package tsdb + +import ( + "fmt" + "strconv" + "strings" + "time" +) + +func NewTimeRange(from, to string) *TimeRange { + return &TimeRange{ + From: from, + To: to, + Now: time.Now(), + } +} + +type TimeRange struct { + From string + To string + Now time.Time +} + +func (tr *TimeRange) GetFromAsMsEpoch() int64 { + return tr.MustGetFrom().UnixNano() / int64(time.Millisecond) +} + +func (tr *TimeRange) GetToAsMsEpoch() int64 { + return tr.MustGetTo().UnixNano() / int64(time.Millisecond) +} + +func (tr *TimeRange) MustGetFrom() time.Time { + if res, err := tr.ParseFrom(); err != nil { + return time.Unix(0, 0) + } else { + return res + } +} + +func (tr *TimeRange) MustGetTo() time.Time { + if res, err := tr.ParseTo(); err != nil { + return time.Unix(0, 0) + } else { + return res + } +} + +func tryParseUnixMsEpoch(val string) (time.Time, bool) { + if val, err := strconv.ParseInt(val, 10, 64); err == nil { + seconds := val / 1000 + nano := (val - seconds*1000) * 1000000 + return time.Unix(seconds, nano), true + } + return time.Time{}, false +} + +func (tr *TimeRange) ParseFrom() (time.Time, error) { + if res, ok := tryParseUnixMsEpoch(tr.From); ok { + return res, nil + } + + fromRaw := strings.Replace(tr.From, "now-", "", 1) + diff, err := time.ParseDuration("-" + fromRaw) + if err != nil { + return time.Time{}, err + } + + return tr.Now.Add(diff), nil +} + +func (tr *TimeRange) ParseTo() (time.Time, error) { + if tr.To == "now" { + return tr.Now, nil + } else if strings.HasPrefix(tr.To, "now-") { + withoutNow := strings.Replace(tr.To, "now-", "", 1) + + diff, err := time.ParseDuration("-" + withoutNow) + if err != nil { + return time.Time{}, nil + } + + return tr.Now.Add(diff), nil + } + + if res, ok := tryParseUnixMsEpoch(tr.To); ok { + return res, nil + } + + return time.Time{}, fmt.Errorf("cannot parse to value %s", tr.To) +} diff --git a/pkg/tsdb/time_range_test.go b/pkg/tsdb/time_range_test.go new file mode 100644 index 00000000000..5412d0d05f3 --- /dev/null +++ b/pkg/tsdb/time_range_test.go @@ -0,0 +1,95 @@ +package tsdb + +import ( + "testing" + "time" + + . "github.com/smartystreets/goconvey/convey" +) + +func TestTimeRange(t *testing.T) { + Convey("Time range", t, func() { + + now := time.Now() + + Convey("Can parse 5m, now", func() { + tr := TimeRange{ + From: "5m", + To: "now", + Now: now, + } + + Convey("5m ago ", func() { + fiveMinAgo, _ := time.ParseDuration("-5m") + expected := now.Add(fiveMinAgo) + + res, err := tr.ParseFrom() + So(err, ShouldBeNil) + So(res.Unix(), ShouldEqual, expected.Unix()) + }) + + Convey("now ", func() { + res, err := tr.ParseTo() + So(err, ShouldBeNil) + So(res.Unix(), ShouldEqual, now.Unix()) + }) + }) + + Convey("Can parse 5h, now-10m", func() { + tr := TimeRange{ + From: "5h", + To: "now-10m", + Now: now, + } + + Convey("5h ago ", func() { + fiveHourAgo, _ := time.ParseDuration("-5h") + expected := now.Add(fiveHourAgo) + + res, err := tr.ParseFrom() + So(err, ShouldBeNil) + So(res.Unix(), ShouldEqual, expected.Unix()) + }) + + Convey("now-10m ", func() { + fiveMinAgo, _ := time.ParseDuration("-10m") + expected := now.Add(fiveMinAgo) + res, err := tr.ParseTo() + So(err, ShouldBeNil) + So(res.Unix(), ShouldEqual, expected.Unix()) + }) + }) + + Convey("can parse unix epocs", func() { + var err error + tr := TimeRange{ + From: "1474973725473", + To: "1474975757930", + Now: now, + } + + res, err := tr.ParseFrom() + So(err, ShouldBeNil) + So(res.UnixNano()/int64(time.Millisecond), ShouldEqual, 1474973725473) + + res, err = tr.ParseTo() + So(err, ShouldBeNil) + So(res.UnixNano()/int64(time.Millisecond), ShouldEqual, 1474975757930) + }) + + Convey("Cannot parse asdf", func() { + var err error + tr := TimeRange{ + From: "asdf", + To: "asdf", + Now: now, + } + + _, err = tr.ParseFrom() + So(err, ShouldNotBeNil) + + _, err = tr.ParseTo() + So(err, ShouldNotBeNil) + }) + }) +} diff --git a/pkg/tsdb/tsdb_test.go b/pkg/tsdb/tsdb_test.go new file mode 100644 index 00000000000..2b1a2372cd6 --- /dev/null +++ b/pkg/tsdb/tsdb_test.go @@ -0,0 +1,177 @@ +package tsdb + +import ( + "context" + "testing" + "time" + + "github.com/grafana/grafana/pkg/models" + . "github.com/smartystreets/goconvey/convey" +) + +func TestMetricQuery(t *testing.T) { + + Convey("When batches groups for query", t, func() { + + Convey("Given 3 queries for 2 data sources", func() { + request := &Request{ + Queries: QuerySlice{ + {RefId: "A", DataSource: &models.DataSource{Id: 1}}, + {RefId: "B", DataSource: &models.DataSource{Id: 1}}, + {RefId: "C", DataSource: &models.DataSource{Id: 2}}, + }, + } + + batches, err := getBatches(request) + So(err, ShouldBeNil) + + Convey("Should group into two batches", func() { + So(len(batches), ShouldEqual, 2) + }) + }) + + Convey("Given query 2 depends on query 1", func() { + request := &Request{ + Queries: QuerySlice{ + {RefId: "A", DataSource: &models.DataSource{Id: 1}}, + {RefId: "B", DataSource: &models.DataSource{Id: 2}}, + {RefId: "C", DataSource: &models.DataSource{Id: 3}, Depends: []string{"A", "B"}}, + }, + } + + batches, err := getBatches(request) + So(err, ShouldBeNil) + + Convey("Should return three batch groups", func() { + So(len(batches), ShouldEqual, 3) + }) + + Convey("Group 3 should have group 1 and 2 as dependencies", func() { + So(batches[2].Depends["A"], ShouldEqual, true) + So(batches[2].Depends["B"], ShouldEqual, true) + }) + + }) + }) + + Convey("When executing request with one query", t, func() { + req := &Request{ + Queries: QuerySlice{ + {RefId: "A", DataSource: &models.DataSource{Id: 1, Type: "test"}}, + }, + } + + fakeExecutor := registerFakeExecutor() + fakeExecutor.Return("A", TimeSeriesSlice{&TimeSeries{Name: "argh"}}) + + res, err := HandleRequest(context.TODO(), req) + So(err, ShouldBeNil) + + Convey("Should return query results", func() { + So(res.Results["A"].Series, ShouldNotBeEmpty) + So(res.Results["A"].Series[0].Name, ShouldEqual, "argh") + }) + }) + + Convey("When executing one request with two queries from same data source", t, func() { + req := &Request{ + Queries: QuerySlice{ + {RefId: "A", DataSource: &models.DataSource{Id: 1, Type: "test"}}, + {RefId: "B", DataSource: &models.DataSource{Id: 1, Type: "test"}}, + }, + } + + fakeExecutor := registerFakeExecutor() + fakeExecutor.Return("A", TimeSeriesSlice{&TimeSeries{Name: "argh"}}) + fakeExecutor.Return("B", TimeSeriesSlice{&TimeSeries{Name: "barg"}}) + + res, err := HandleRequest(context.TODO(), req) + So(err, ShouldBeNil) + + Convey("Should return query results", func() { + So(len(res.Results), ShouldEqual, 2) + So(res.Results["B"].Series[0].Name, ShouldEqual, "barg") + }) + + Convey("Should have been batched in one request", func() { + So(len(res.BatchTimings), ShouldEqual, 1) + }) + + }) + + Convey("When executing one request with three queries from different datasources", t, func() { + req := &Request{ + Queries: QuerySlice{ + {RefId: "A", DataSource: &models.DataSource{Id: 1, Type: "test"}}, + {RefId: "B", DataSource: &models.DataSource{Id: 1, Type: "test"}}, + {RefId: "C", DataSource: &models.DataSource{Id: 2, Type: "test"}}, + }, + } + + res, err := HandleRequest(context.TODO(), req) + So(err, ShouldBeNil) + + Convey("Should have been batched in two requests", func() { + So(len(res.BatchTimings), ShouldEqual, 2) + }) + }) + + Convey("When query uses data source of unknown type", t, func() { + req := &Request{ + Queries: QuerySlice{ + {RefId: "A", DataSource: &models.DataSource{Id: 1, Type: "asdasdas"}}, + }, + } + + _, err := HandleRequest(context.TODO(), req) + So(err, ShouldNotBeNil) + }) + + Convey("When executing request that depend on other query", t, func() { + req := &Request{ + Queries: QuerySlice{ + { + RefId: "A", DataSource: &models.DataSource{Id: 1, Type: "test"}, + }, + { + RefId: "B", DataSource: &models.DataSource{Id: 2, Type: "test"}, Depends: []string{"A"}, + }, + }, + } + + fakeExecutor := registerFakeExecutor() + fakeExecutor.HandleQuery("A", func(c *QueryContext) *QueryResult { + time.Sleep(10 * time.Millisecond) + return &QueryResult{ + Series: TimeSeriesSlice{ + &TimeSeries{Name: "Ares"}, + }} + }) + fakeExecutor.HandleQuery("B", func(c *QueryContext) *QueryResult { + return &QueryResult{ + Series: TimeSeriesSlice{ + &TimeSeries{Name: "Bres+" + c.Results["A"].Series[0].Name}, + }} + }) + + res, err := HandleRequest(context.TODO(), req) + So(err, ShouldBeNil) + + Convey("Should have been batched in two requests", func() { + So(len(res.BatchTimings), ShouldEqual, 2) + }) + + Convey("Query B should have access to Query A results", func() { + So(res.Results["B"].Series[0].Name, ShouldEqual, "Bres+Ares") + }) + }) +} + +func registerFakeExecutor() *FakeExecutor { + executor, _ := NewFakeExecutor(nil) + RegisterExecutor("test", func(dsInfo *models.DataSource) (Executor, error) { + return executor, nil + }) + + return executor +} diff --git a/pkg/util/strings.go b/pkg/util/strings.go index 7e503a99118..8598949c2cb 100644 --- a/pkg/util/strings.go +++ b/pkg/util/strings.go @@ -1,18 +1,18 @@ package util func StringsFallback2(val1 string, val2 string) string { - if val1 != "" { - return val1 - } - return val2 + return stringsFallback(val1, val2) } func StringsFallback3(val1 string, val2 string, val3 string) string { - if val1 != "" { - return val1 + return stringsFallback(val1, val2, val3) +} + +func stringsFallback(vals ...string) string { + for _, v := range vals { + if v != "" { + return v + } } - if val2 != "" { - return val2 - } - return val3 + return "" } diff --git a/pkg/util/strings_test.go b/pkg/util/strings_test.go new file mode 100644 index 00000000000..c959dfd1d54 --- /dev/null +++ b/pkg/util/strings_test.go @@ -0,0 +1,15 @@ +package util + +import ( + "testing" + + . "github.com/smartystreets/goconvey/convey" +) + +func TestStringsUtil(t *testing.T) { + Convey("Falling back until none empty string", t, func() { + So(StringsFallback2("1", "2"), ShouldEqual, "1") + So(StringsFallback2("", "2"), ShouldEqual, "2") + So(StringsFallback3("", "", "3"), ShouldEqual, "3") + }) +} diff --git a/public/app/app.ts b/public/app/app.ts index b30b75a0ca3..22431a5110c 100644 --- a/public/app/app.ts +++ b/public/app/app.ts @@ -14,6 +14,7 @@ import $ from 'jquery'; import angular from 'angular'; import config from 'app/core/config'; import _ from 'lodash'; +import moment from 'moment'; import {coreModule} from './core/core'; export class GrafanaApp { @@ -39,9 +40,17 @@ export class GrafanaApp { init() { var app = angular.module('grafana', []); - app.constant('grafanaVersion', "@grafanaVersion@"); - app.config(($locationProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) => { + moment.locale(config.bootData.user.locale); + + app.config(($locationProvider, $controllerProvider, $compileProvider, $filterProvider, $httpProvider, $provide) => { + + if (config.buildInfo.env !== 'development') { + $compileProvider.debugInfoEnabled(false); + } + + $httpProvider.useApplyAsync(true); + this.registerFunctions.controller = $controllerProvider.register; this.registerFunctions.directive = $compileProvider.directive; this.registerFunctions.factory = $provide.factory; diff --git a/public/app/core/components/colorpicker.ts b/public/app/core/components/colorpicker.ts index 7c35ac7e4ac..1834a1eb8a1 100644 --- a/public/app/core/components/colorpicker.ts +++ b/public/app/core/components/colorpicker.ts @@ -7,10 +7,6 @@ import coreModule from 'app/core/core_module'; var template = `
    - - - -
    `; @@ -51,21 +46,17 @@ export class ColorPickerCtrl { toggleAxis(yaxis) { this.$scope.toggleAxis(); - if (!this.$scope.autoClose) { + if (this.$scope.autoClose) { this.$scope.dismiss(); } } colorSelected(color) { this.$scope.colorSelected(color); - if (!this.$scope.autoClose) { + if (this.$scope.autoClose) { this.$scope.dismiss(); } } - - close() { - this.$scope.dismiss(); - } } export function colorPicker() { diff --git a/public/app/core/components/dashboard_selector.ts b/public/app/core/components/dashboard_selector.ts new file mode 100644 index 00000000000..4209ff3f8dc --- /dev/null +++ b/public/app/core/components/dashboard_selector.ts @@ -0,0 +1,47 @@ +/// + +import config from 'app/core/config'; +import _ from 'lodash'; +import $ from 'jquery'; +import coreModule from 'app/core/core_module'; + +var template = ` + + + Not finding dashboard you want? Star it first, then it should appear in this select box. + +`; + +export class DashboardSelectorCtrl { + model: any; + options: any; + + /** @ngInject */ + constructor(private backendSrv) { + } + + $onInit() { + this.options = [{value: 0, text: 'Default'}]; + + return this.backendSrv.search({starred: true}).then(res => { + res.forEach(dash => { + this.options.push({value: dash.id, text: dash.title}); + }); + }); + } +} + +export function dashboardSelector() { + return { + restrict: 'E', + controller: DashboardSelectorCtrl, + bindToController: true, + controllerAs: 'ctrl', + template: template, + scope: { + model: '=' + } + }; +} + +coreModule.directive('dashboardSelector', dashboardSelector); diff --git a/public/app/core/components/grafana_app.ts b/public/app/core/components/grafana_app.ts index 0a2e49e5d72..83b55ac476f 100644 --- a/public/app/core/components/grafana_app.ts +++ b/public/app/core/components/grafana_app.ts @@ -5,7 +5,10 @@ import store from 'app/core/store'; import _ from 'lodash'; import angular from 'angular'; import $ from 'jquery'; + import coreModule from 'app/core/core_module'; +import {profiler} from 'app/core/profiler'; +import appEvents from 'app/core/app_events'; export class GrafanaCtrl { @@ -15,14 +18,10 @@ export class GrafanaCtrl { $scope.init = function() { $scope.contextSrv = contextSrv; + $rootScope.appSubUrl = config.appSubUrl; $scope._ = _; - $rootScope.profilingEnabled = store.getBool('profilingEnabled'); - $rootScope.performance = { loadStart: new Date().getTime() }; - $rootScope.appSubUrl = config.appSubUrl; - - if ($rootScope.profilingEnabled) { $scope.initProfiling(); } - + profiler.init(config, $rootScope); alertSrv.init(); utilSrv.init(); @@ -30,6 +29,7 @@ export class GrafanaCtrl { }; $scope.initDashboard = function(dashboardData, viewScope) { + $scope.appEvent("dashboard-fetch-end", dashboardData); $controller('DashboardCtrl', { $scope: viewScope }).init(dashboardData); }; @@ -47,6 +47,7 @@ export class GrafanaCtrl { $rootScope.appEvent = function(name, payload) { $rootScope.$emit(name, payload); + appEvents.emit(name, payload); }; $rootScope.colors = [ @@ -59,82 +60,6 @@ export class GrafanaCtrl { "#E0F9D7","#FCEACA","#CFFAFF","#F9E2D2","#FCE2DE","#BADFF4","#F9D9F9","#DEDAF7" ]; - $scope.getTotalWatcherCount = function() { - var count = 0; - var scopes = 0; - var root = $(document.getElementsByTagName('body')); - - var f = function (element) { - if (element.data().hasOwnProperty('$scope')) { - scopes++; - angular.forEach(element.data().$scope.$$watchers, function () { - count++; - }); - } - - angular.forEach(element.children(), function (childElement) { - f($(childElement)); - }); - }; - - f(root); - $rootScope.performance.scopeCount = scopes; - return count; - }; - - $scope.initProfiling = function() { - var count = 0; - - $scope.$watch(function digestCounter() { - count++; - }, function() { - // something - }); - - $rootScope.performance.panels = []; - - $scope.$on('refresh', function() { - if ($rootScope.performance.panels.length > 0) { - var totalRender = 0; - var totalQuery = 0; - - _.each($rootScope.performance.panels, function(panelTiming: any) { - totalRender += panelTiming.render; - totalQuery += panelTiming.query; - }); - - console.log('total query: ' + totalQuery); - console.log('total render: ' + totalRender); - console.log('avg render: ' + totalRender / $rootScope.performance.panels.length); - } - - $rootScope.performance.panels = []; - }); - - $scope.onAppEvent('dashboard-loaded', function() { - count = 0; - - setTimeout(function() { - console.log("Dashboard::Performance Total Digests: " + count); - console.log("Dashboard::Performance Total Watchers: " + $scope.getTotalWatcherCount()); - console.log("Dashboard::Performance Total ScopeCount: " + $rootScope.performance.scopeCount); - - var timeTaken = $rootScope.performance.allPanelsInitialized - $rootScope.performance.dashboardLoadStart; - console.log("Dashboard::Performance - All panels initialized in " + timeTaken + " ms"); - - // measure digest performance - var rootDigestStart = window.performance.now(); - for (var i = 0; i < 30; i++) { - $rootScope.$apply(); - } - console.log("Dashboard::Performance Root Digest " + ((window.performance.now() - rootDigestStart) / 30)); - - }, 3000); - - }); - - }; - $scope.init(); } } @@ -182,6 +107,58 @@ export function grafanaAppDirective(playlistSrv, contextSrv) { body.addClass(pageClass); } $("#tooltip, .tooltip").remove(); + + // check for kiosk url param + if (data.params.kiosk) { + appEvents.emit('toggle-kiosk-mode'); + } + }); + + // handle kiosk mode + appEvents.on('toggle-kiosk-mode', () => { + body.toggleClass('page-kiosk-mode'); + }); + + // handle in active view state class + var lastActivity = new Date().getTime(); + var activeUser = true; + var inActiveTimeLimit = 60 * 1000; + + function checkForInActiveUser() { + if (!activeUser) { + return; + } + // only go to activity low mode on dashboard page + if (!body.hasClass('page-dashboard')) { + return; + } + + if ((new Date().getTime() - lastActivity) > inActiveTimeLimit) { + activeUser = false; + body.addClass('user-activity-low'); + } + } + + function userActivityDetected() { + lastActivity = new Date().getTime(); + if (!activeUser) { + activeUser = true; + body.removeClass('user-activity-low'); + } + } + + // mouse and keyboard is user activity + body.mousemove(userActivityDetected); + body.keydown(userActivityDetected); + // treat tab change as activity + document.addEventListener('visibilitychange', userActivityDetected); + + // check every 2 seconds + setInterval(checkForInActiveUser, 2000); + + appEvents.on('toggle-view-mode', () => { + lastActivity = 0; + checkForInActiveUser(); }); // handle document clicks that should hide things @@ -191,6 +168,17 @@ export function grafanaAppDirective(playlistSrv, contextSrv) { return; } + // for stuff that animates, slides out etc, clicking it needs to + // hide it right away + var clickAutoHide = target.closest('[data-click-hide]'); + if (clickAutoHide.length) { + var clickAutoHideParent = clickAutoHide.parent(); + clickAutoHide.detach(); + setTimeout(function() { + clickAutoHideParent.append(clickAutoHide); + }, 100); + } + if (target.parents('.dash-playlist-actions').length === 0) { playlistSrv.stop(); } diff --git a/public/app/core/components/help/help.html b/public/app/core/components/help/help.html new file mode 100644 index 00000000000..3356f21d452 --- /dev/null +++ b/public/app/core/components/help/help.html @@ -0,0 +1,48 @@ + diff --git a/public/app/core/components/help/help.ts b/public/app/core/components/help/help.ts new file mode 100644 index 00000000000..3bc9b57077a --- /dev/null +++ b/public/app/core/components/help/help.ts @@ -0,0 +1,66 @@ +/// + +import coreModule from '../../core_module'; +import appEvents from 'app/core/app_events'; + +export class HelpCtrl { + tabIndex: any; + shortcuts: any; + + /** @ngInject */ + constructor(private $scope, $sce) { + this.tabIndex = 0; + this.shortcuts = { + 'Global': [ + {keys: ['g', 'h'], description: 'Go to Home Dashboard'}, + {keys: ['g', 'p'], description: 'Go to Profile'}, + {keys: ['s', 'o'], description: 'Open search'}, + {keys: ['s', 's'], description: 'Open search with starred filter'}, + {keys: ['s', 't'], description: 'Open search in tags view'}, + {keys: ['esc'], description: 'Exit edit/setting views'}, + ], + 'Dashboard': [ + {keys: ['mod+s'], description: 'Save dashboard'}, + {keys: ['mod+h'], description: 'Hide row controls'}, + {keys: ['d', 'r'], description: 'Refresh all panels'}, + {keys: ['d', 's'], description: 'Dashboard settings'}, + {keys: ['d', 'v'], description: 'Toggle in-active / view mode'}, + {keys: ['d', 'k'], description: 'Toggle kiosk mode (hides top nav)'}, + {keys: ['mod+o'], description: 'Toggle shared graph crosshair'}, + ], + 'Focused Panel': [ + {keys: ['e'], description: 'Toggle panel edit view'}, + {keys: ['v'], description: 'Toggle panel fullscreen view'}, + {keys: ['p', 's'], description: 'Open Panel Share Modal'}, + {keys: ['p', 'r'], description: 'Remove Panel'}, + ], + 'Focused Row': [ + {keys: ['r', 'c'], description: 'Collapse Row'}, + {keys: ['r', 'r'], description: 'Remove Row'}, + ], + 'Time Range': [ + {keys: ['t', 'z'], description: 'Zoom out time range'}, + {keys: ['t', ''], description: 'Move time range back'}, + {keys: ['t', ''], description: 'Move time range forward'}, + ], + }; + } + + dismiss() { + appEvents.emit('hide-modal'); + } +} + +export function helpModal() { + return { + restrict: 'E', + templateUrl: 'public/app/core/components/help/help.html', + controller: HelpCtrl, + bindToController: true, + transclude: true, + controllerAs: 'ctrl', + scope: {}, + }; +} + +coreModule.directive('helpModal', helpModal); diff --git a/public/app/core/components/info_popover.ts b/public/app/core/components/info_popover.ts index cc49ecbc4ab..6b2a300551e 100644 --- a/public/app/core/components/info_popover.ts +++ b/public/app/core/components/info_popover.ts @@ -8,21 +8,24 @@ import Drop from 'tether-drop'; export function infoPopover() { return { restrict: 'E', + template: '', transclude: true, link: function(scope, elem, attrs, ctrl, transclude) { - var inputElem = elem.prev(); - if (inputElem.length === 0) { - console.log('Failed to find input element for popover'); - return; - } - var offset = attrs.offset || '0 -10px'; var position = attrs.position || 'right middle'; var classes = 'drop-help drop-hide-out-of-bounds'; + var openOn = 'hover'; + + elem.addClass('gf-form-help-icon'); + if (attrs.wide) { classes += ' drop-wide'; } + if (attrs.mode) { + elem.addClass('gf-form-help-icon--' + attrs.mode); + } + transclude(function(clone, newScope) { var content = document.createElement("div"); _.each(clone, (node) => { @@ -30,18 +33,20 @@ export function infoPopover() { }); var drop = new Drop({ - target: inputElem[0], + target: elem[0], content: content, position: position, classes: classes, - openOn: 'click', + openOn: openOn, + hoverOpenDelay: 400, tetherOptions: { offset: offset } }); - scope.$on('$destroy', function() { + var unbind = scope.$on('$destroy', function() { drop.destroy(); + unbind(); }); }); diff --git a/public/app/core/components/jsontree/jsontree.ts b/public/app/core/components/jsontree/jsontree.ts new file mode 100644 index 00000000000..14f6012ce12 --- /dev/null +++ b/public/app/core/components/jsontree/jsontree.ts @@ -0,0 +1,200 @@ + +/** Created by: Alex Wendland (me@alexwendland.com), 2014-08-06 + * + * angular-json-tree + * + * Directive for creating a tree-view out of a JS Object. Only loads + * sub-nodes on demand in order to improve performance of rendering large + * objects. + * + * Attributes: + * - object (Object, 2-way): JS object to build the tree from + * - start-expanded (Boolean, 1-way, ?=true): should the tree default to expanded + * + * Usage: + * // In the controller + * scope.someObject = { + * test: 'hello', + * array: [1,1,2,3,5,8] + * }; + * // In the html + * + * + * Dependencies: + * - utils (json-tree.js) + * - ajsRecursiveDirectiveHelper (json-tree.js) + * + * Test: json-tree-test.js + */ + +import angular from 'angular'; +import coreModule from 'app/core/core_module'; + +var utils = { + /* See link for possible type values to check against. + * http://stackoverflow.com/questions/4622952/json-object-containing-array + * + * Value Class Type + * ------------------------------------- + * "foo" String string + * new String("foo") String object + * 1.2 Number number + * new Number(1.2) Number object + * true Boolean boolean + * new Boolean(true) Boolean object + * new Date() Date object + * new Error() Error object + * [1,2,3] Array object + * new Array(1, 2, 3) Array object + * new Function("") Function function + * /abc/g RegExp object (function in Nitro/V8) + * new RegExp("meow") RegExp object (function in Nitro/V8) + * {} Object object + * new Object() Object object + */ + is: function is(obj, clazz) { + return Object.prototype.toString.call(obj).slice(8, -1) === clazz; + }, + + // See above for possible values + whatClass: function whatClass(obj) { + return Object.prototype.toString.call(obj).slice(8, -1); + }, + + // Iterate over an objects keyset + forKeys: function forKeys(obj, f) { + for (var key in obj) { + if (obj.hasOwnProperty(key) && typeof obj[key] !== 'function') { + if (f(key, obj[key])) { + break; + } + } + } + } +}; + +coreModule.directive('jsonTree', [function jsonTreeDirective() { + return { + restrict: 'E', + scope: { + object: '=', + startExpanded: '@', + rootName: '@', + }, + template: '' + }; +}]); + +coreModule.directive('jsonNode', ['ajsRecursiveDirectiveHelper', function jsonNodeDirective(ajsRecursiveDirectiveHelper) { + return { + restrict: 'E', + scope: { + key: '=', + value: '=', + startExpanded: '@' + }, + compile: function jsonNodeDirectiveCompile(elem) { + return ajsRecursiveDirectiveHelper.compile(elem, this); + }, + template: ' {{key}}' + + ' {{value}}' + + ' ' + + ' {{preview}}' + + '
      ' + + '
    • ' + + ' ' + + '
    • ' + + '
    ', + pre: function jsonNodeDirectiveLink(scope, elem, attrs) { + // Set value's type as Class for CSS styling + elem.addClass(utils.whatClass(scope.value).toLowerCase()); + // If the value is an Array or Object, use expandable view type + if (utils.is(scope.value, 'Object') || utils.is(scope.value, 'Array')) { + scope.isExpandable = true; + // Add expandable class for CSS usage + elem.addClass('expandable'); + // Setup preview text + var isArray = utils.is(scope.value, 'Array'); + scope.preview = isArray ? '[ ' : '{ '; + utils.forKeys(scope.value, function jsonNodeDirectiveLinkForKeys(key, value) { + if (isArray) { + scope.preview += value + ', '; + } else { + scope.preview += key + ': ' + value + ', '; + } + }); + scope.preview = scope.preview.substring(0, scope.preview.length - (scope.preview.length > 2 ? 2 : 0)) + (isArray ? ' ]' : ' }'); + // If directive initially has isExpanded set, also set shouldRender to true + if (scope.startExpanded) { + scope.shouldRender = true; + elem.addClass('expanded'); + } + // Setup isExpanded state handling + scope.isExpanded = scope.startExpanded; + scope.toggleExpanded = function jsonNodeDirectiveToggleExpanded() { + scope.isExpanded = !scope.isExpanded; + if (scope.isExpanded) { + elem.addClass('expanded'); + } else { + elem.removeClass('expanded'); + } + // For delaying subnode render until requested + scope.shouldRender = true; + }; + } else { + scope.isExpandable = false; + // Add expandable class for CSS usage + elem.addClass('not-expandable'); + } + } + }; +}]); + +/** Added by: Alex Wendland (me@alexwendland.com), 2014-08-09 + * Source: http://stackoverflow.com/questions/14430655/recursion-in-angular-directives + * + * Used to allow for recursion within directives + */ +coreModule.factory('ajsRecursiveDirectiveHelper', ['$compile', function RecursiveDirectiveHelper($compile) { + return { + /** + * Manually compiles the element, fixing the recursion loop. + * @param element + * @param [link] A post-link function, or an object with function(s) registered via pre and post properties. + * @returns An object containing the linking functions. + */ + compile: function RecursiveDirectiveHelperCompile(element, link) { + // Normalize the link parameter + if (angular.isFunction(link)) { + link = { + post: link + }; + } + + // Break the recursion loop by removing the contents + var contents = element.contents().remove(); + var compiledContents; + return { + pre: (link && link.pre) ? link.pre : null, + /** + * Compiles and re-adds the contents + */ + post: function RecursiveDirectiveHelperCompilePost(scope, element) { + // Compile the contents + if (!compiledContents) { + compiledContents = $compile(contents); + } + // Re-add the compiled contents to the element + compiledContents(scope, function (clone) { + element.append(clone); + }); + + // Call the post-linking function, if any + if (link && link.post) { + link.post.apply(null, arguments); + } + } + }; + } + }; +}]); diff --git a/public/app/core/components/query_part/query_part.ts b/public/app/core/components/query_part/query_part.ts new file mode 100644 index 00000000000..fcd337a0a26 --- /dev/null +++ b/public/app/core/components/query_part/query_part.ts @@ -0,0 +1,123 @@ +/// + +import _ from 'lodash'; + +export class QueryPartDef { + type: string; + params: any[]; + defaultParams: any[]; + renderer: any; + category: any; + addStrategy: any; + + constructor(options: any) { + this.type = options.type; + this.params = options.params; + this.defaultParams = options.defaultParams; + this.renderer = options.renderer; + this.category = options.category; + this.addStrategy = options.addStrategy; + } +} + +export class QueryPart { + part: any; + def: QueryPartDef; + params: any[]; + text: string; + + constructor(part: any, def: any) { + this.part = part; + this.def = def; + if (!this.def) { + throw {message: 'Could not find query part ' + part.type}; + } + + part.params = part.params || _.clone(this.def.defaultParams); + this.params = part.params; + this.updateText(); + } + + render(innerExpr: string) { + return this.def.renderer(this, innerExpr); + } + + hasMultipleParamsInString (strValue, index) { + if (strValue.indexOf(',') === -1) { + return false; + } + + return this.def.params[index + 1] && this.def.params[index + 1].optional; + } + + updateParam (strValue, index) { + // handle optional parameters + // if string contains ',' and next param is optional, split and update both + if (this.hasMultipleParamsInString(strValue, index)) { + _.each(strValue.split(','), (partVal, idx) => { + this.updateParam(partVal.trim(), idx); + }); + return; + } + + if (strValue === '' && this.def.params[index].optional) { + this.params.splice(index, 1); + } else { + this.params[index] = strValue; + } + + this.part.params = this.params; + this.updateText(); + } + + updateText() { + if (this.params.length === 0) { + this.text = this.def.type + '()'; + return; + } + + var text = this.def.type + '('; + text += this.params.join(', '); + text += ')'; + this.text = text; + } +} + +export function functionRenderer(part, innerExpr) { + var str = part.def.type + '('; + var parameters = _.map(part.params, (value, index) => { + var paramType = part.def.params[index]; + if (paramType.type === 'time') { + if (value === 'auto') { + value = '$interval'; + } + } + if (paramType.quote === 'single') { + return "'" + value + "'"; + } else if (paramType.quote === 'double') { + return '"' + value + '"'; + } + + return value; + }); + + if (innerExpr) { + parameters.unshift(innerExpr); + } + return str + parameters.join(', ') + ')'; +} + + +export function suffixRenderer(part, innerExpr) { + return innerExpr + ' ' + part.params[0]; +} + +export function identityRenderer(part, innerExpr) { + return part.params[0]; +} + +export function quotedIdentityRenderer(part, innerExpr) { + return '"' + part.params[0] + '"'; +} + + diff --git a/public/app/core/components/query_part/query_part_editor.ts b/public/app/core/components/query_part/query_part_editor.ts new file mode 100644 index 00000000000..ae53eb31001 --- /dev/null +++ b/public/app/core/components/query_part/query_part_editor.ts @@ -0,0 +1,176 @@ +/// + +import _ from 'lodash'; +import $ from 'jquery'; +import coreModule from 'app/core/core_module'; + +var template = ` +
    diff --git a/public/app/core/components/search/search.ts b/public/app/core/components/search/search.ts index e296acf56e1..bff6d3149f2 100644 --- a/public/app/core/components/search/search.ts +++ b/public/app/core/components/search/search.ts @@ -5,6 +5,7 @@ import config from 'app/core/config'; import _ from 'lodash'; import $ from 'jquery'; import coreModule from '../../core_module'; +import appEvents from 'app/core/app_events'; export class SearchCtrl { isOpen: boolean; @@ -28,7 +29,7 @@ export class SearchCtrl { this.isOpen = this.ignoreClose; } - openSearch() { + openSearch(evt, payload) { if (this.isOpen) { this.isOpen = false; return; @@ -42,10 +43,21 @@ export class SearchCtrl { this.currentSearchId = 0; this.ignoreClose = true; + if (payload && payload.starred) { + this.query.starred = true; + } + + if (payload && payload.tagsMode) { + return this.$timeout(() => { + this.ignoreClose = false; + this.giveSearchFocus = this.giveSearchFocus + 1; + this.getTags(); + }, 100); + } + this.$timeout(() => { this.ignoreClose = false; this.giveSearchFocus = this.giveSearchFocus + 1; - this.query.query = ''; this.search(); }, 100); } @@ -148,9 +160,6 @@ export class SearchCtrl { this.searchDashboards(); }; - newDashboard() { - this.$location.url('dashboard/new'); - }; } export function searchDirective() { diff --git a/public/app/core/components/sidemenu/sidemenu.html b/public/app/core/components/sidemenu/sidemenu.html index 4ff30c92f47..8aa3c6ae571 100644 --- a/public/app/core/components/sidemenu/sidemenu.html +++ b/public/app/core/components/sidemenu/sidemenu.html @@ -21,9 +21,15 @@ {{::menuItem.text}} - - - {{::menuItem.text}} + +
  • + Max shown : {{::ctrl.maxShownOrgs}} + +
  • +
  • + + + {{::orgItem.text}}
  • @@ -49,7 +55,7 @@
  • - + Sign in diff --git a/public/app/core/components/sidemenu/sidemenu.ts b/public/app/core/components/sidemenu/sidemenu.ts index a47704f9d7d..c6d721e0977 100644 --- a/public/app/core/components/sidemenu/sidemenu.ts +++ b/public/app/core/components/sidemenu/sidemenu.ts @@ -12,6 +12,11 @@ export class SideMenuCtrl { mainLinks: any; orgMenu: any; appSubUrl: string; + loginUrl: string; + orgFilter: string; + orgItems: any; + orgs: any; + maxShownOrgs: number; /** @ngInject */ constructor(private $scope, private $location, private contextSrv, private backendSrv, private $element) { @@ -19,16 +24,20 @@ export class SideMenuCtrl { this.user = contextSrv.user; this.appSubUrl = config.appSubUrl; this.showSignout = this.contextSrv.isSignedIn && !config['authProxyEnabled']; + this.maxShownOrgs = 10; this.mainLinks = config.bootData.mainNavLinks; this.openUserDropdown(); + this.loginUrl = 'login?redirect=' + encodeURIComponent(this.$location.path()); this.$scope.$on('$routeChangeSuccess', () => { if (!this.contextSrv.pinned) { this.contextSrv.sidemenu = false; } + this.loginUrl = 'login?redirect=' + encodeURIComponent(this.$location.path()); }); + this.orgFilter = ''; } getUrl(url) { @@ -49,46 +58,45 @@ export class SideMenuCtrl { this.orgMenu.push({section: this.user.orgName, cssClass: 'dropdown-menu-title'}); this.orgMenu.push({ text: "Preferences", - url: this.getUrl("/org"), + url: this.getUrl("/org") }); this.orgMenu.push({ text: "Users", - url: this.getUrl("/org/users"), + url: this.getUrl("/org/users") }); this.orgMenu.push({ text: "API Keys", - url: this.getUrl("/org/apikeys"), + url: this.getUrl("/org/apikeys") }); } this.orgMenu.push({cssClass: "divider"}); - this.backendSrv.get('/api/user/orgs').then(orgs => { - orgs.forEach(org => { - if (org.orgId === this.contextSrv.user.orgId) { - return; - } - - this.orgMenu.push({ - text: "Switch to " + org.name, - icon: "fa fa-fw fa-random", - click: () => { - this.switchOrg(org.orgId); - } - }); - }); - - if (config.allowOrgCreate) { - this.orgMenu.push({text: "New organization", icon: "fa fa-fw fa-plus", url: this.getUrl('/org/new')}); - } + this.orgs = orgs; + this.loadOrgsItems(); }); } - switchOrg(orgId) { - this.backendSrv.post('/api/user/using/' + orgId).then(() => { - window.location.href = `${config.appSubUrl}/`; + loadOrgsItems(){ + this.orgItems = []; + this.orgs.forEach(org => { + if (org.orgId === this.contextSrv.user.orgId) { + return; + } + + if (this.orgItems.length < this.maxShownOrgs && (this.orgFilter === '' || org.name.indexOf(this.orgFilter) !== -1)){ + this.orgItems.push({ + text: "Switch to " + org.name, + icon: "fa fa-fw fa-random", + url: this.getUrl('/profile/switch-org/' + org.orgId), + target: '_self' + }); + } }); - }; + if (config.allowOrgCreate) { + this.orgItems.push({text: "New organization", icon: "fa fa-fw fa-plus", url: this.getUrl('/org/new')}); + } + } } export function sideMenuDirective() { diff --git a/public/app/core/components/switch.ts b/public/app/core/components/switch.ts index 1dddae20d49..2a64ec487f7 100644 --- a/public/app/core/components/switch.ts +++ b/public/app/core/components/switch.ts @@ -7,7 +7,12 @@ import coreModule from 'app/core/core_module'; import Drop from 'tether-drop'; var template = ` - +
    @@ -21,17 +26,14 @@ export class SwitchCtrl { id: any; /** @ngInject */ - constructor($scope) { + constructor($scope, private $timeout) { this.show = true; this.id = $scope.$id; } internalOnChange() { - return new Promise(resolve => { - setTimeout(() => { - this.onChange(); - resolve(); - }); + return this.$timeout(() => { + return this.onChange(); }); } @@ -52,22 +54,6 @@ export function switchDirective() { onChange: "&", }, template: template, - link: (scope, elem) => { - if (scope.ctrl.tooltip) { - var drop = new Drop({ - target: elem[0], - content: scope.ctrl.tooltip, - position: "right middle", - classes: 'drop-help', - openOn: 'hover', - hoverOpenDelay: 400, - }); - - scope.$on('$destroy', function() { - drop.destroy(); - }); - } - } }; } diff --git a/public/app/core/components/wizard/wizard.html b/public/app/core/components/wizard/wizard.html new file mode 100644 index 00000000000..9d3f680649a --- /dev/null +++ b/public/app/core/components/wizard/wizard.html @@ -0,0 +1,32 @@ + + diff --git a/public/app/core/components/wizard/wizard.ts b/public/app/core/components/wizard/wizard.ts new file mode 100644 index 00000000000..2ae38cf9e03 --- /dev/null +++ b/public/app/core/components/wizard/wizard.ts @@ -0,0 +1,73 @@ +/// + +import config from 'app/core/config'; +import _ from 'lodash'; +import $ from 'jquery'; + +import coreModule from 'app/core/core_module'; +import appEvents from 'app/core/app_events'; + +export class WizardSrv { + /** @ngInject */ + constructor() { + } +} + +export interface WizardStep { + name: string; + type: string; + process: any; +} + +export class SelectOptionStep { + type: string; + name: string; + fulfill: any; + + constructor() { + this.type = 'select'; + } + + process() { + return new Promise((fulfill, reject) => { + + }); + } +} + +export class WizardFlow { + name: string; + steps: WizardStep[]; + + constructor(name) { + this.name = name; + this.steps = []; + } + + addStep(step) { + this.steps.push(step); + } + + next(index) { + var step = this.steps[0]; + + return step.process().then(() => { + if (this.steps.length === index+1) { + return; + } + + return this.next(index+1); + }); + } + + start() { + appEvents.emit('show-modal', { + src: 'public/app/core/components/wizard/wizard.html', + model: this + }); + + return this.next(0); + } +} + +coreModule.service('wizardSrv', WizardSrv); diff --git a/public/app/core/controllers/inspect_ctrl.js b/public/app/core/controllers/inspect_ctrl.js index 2adc62f0039..39d550658f1 100644 --- a/public/app/core/controllers/inspect_ctrl.js +++ b/public/app/core/controllers/inspect_ctrl.js @@ -7,7 +7,7 @@ define([ function (angular, _, $, coreModule) { 'use strict'; - coreModule.default.controller('InspectCtrl', function($scope) { + coreModule.default.controller('InspectCtrl', function($scope, $sanitize) { var model = $scope.inspector; function getParametersFromQueryString(queryString) { @@ -32,7 +32,11 @@ function (angular, _, $, coreModule) { if (_.isString(model.error.data)) { $scope.response = $("
    " + model.error.data + "
    ").text(); } else if (model.error.data) { - $scope.response = angular.toJson(model.error.data, true); + if (model.error.data.response) { + $scope.response = $sanitize(model.error.data.response); + } else { + $scope.response = angular.toJson(model.error.data, true); + } } else if (model.error.message) { $scope.message = model.error.message; } @@ -44,13 +48,13 @@ function (angular, _, $, coreModule) { } if (model.error.stack) { - $scope.editor.index = 2; + $scope.editor.index = 3; $scope.stack_trace = model.error.stack; $scope.message = model.error.message; } if (model.error.config && model.error.config.data) { - $scope.editor.index = 1; + $scope.editor.index = 2; if (_.isString(model.error.config.data)) { $scope.request_parameters = getParametersFromQueryString(model.error.config.data); diff --git a/public/app/core/controllers/login_ctrl.js b/public/app/core/controllers/login_ctrl.js index 89757c3d141..fa3af3d10f0 100644 --- a/public/app/core/controllers/login_ctrl.js +++ b/public/app/core/controllers/login_ctrl.js @@ -1,11 +1,19 @@ define([ 'angular', + 'lodash', '../core_module', 'app/core/config', ], -function (angular, coreModule, config) { +function (angular, _, coreModule, config) { 'use strict'; + var failCodes = { + "1000": "Required team membership not fulfilled", + "1001": "Required organization membership not fulfilled", + "1002": "Required email domain not fulfilled", + "1003": "Login provider denied login request", + }; + coreModule.default.controller('LoginCtrl', function($scope, backendSrv, contextSrv, $location) { $scope.formModel = { user: '', @@ -15,9 +23,10 @@ function (angular, coreModule, config) { contextSrv.sidemenu = false; - $scope.googleAuthEnabled = config.googleAuthEnabled; - $scope.githubAuthEnabled = config.githubAuthEnabled; - $scope.oauthEnabled = config.githubAuthEnabled || config.googleAuthEnabled; + $scope.oauth = config.oauth; + $scope.oauthEnabled = _.keys(config.oauth).length > 0; + + $scope.disableLoginForm = config.disableLoginForm; $scope.disableUserSignUp = config.disableUserSignUp; $scope.loginHint = config.loginHint; @@ -28,20 +37,13 @@ function (angular, coreModule, config) { $scope.$watch("loginMode", $scope.loginModeChanged); var params = $location.search(); - if (params.failedMsg) { - $scope.appEvent('alert-warning', ['Login Failed', params.failedMsg]); + if (params.failCode) { + $scope.appEvent('alert-warning', ['Login Failed', failCodes[params.failCode]]); delete params.failedMsg; $location.search(params); } }; - // build info view model - $scope.buildInfo = { - version: config.buildInfo.version, - commit: config.buildInfo.commit, - buildstamp: new Date(config.buildInfo.buildstamp * 1000) - }; - $scope.submit = function() { if ($scope.loginMode) { $scope.login(); @@ -76,7 +78,12 @@ function (angular, coreModule, config) { } backendSrv.post('/login', $scope.formModel).then(function(result) { - if (result.redirectUrl) { + var params = $location.search(); + + if (params.redirect && params.redirect[0] === '/') { + window.location.href = config.appSubUrl + params.redirect; + } + else if (result.redirectUrl) { window.location.href = result.redirectUrl; } else { window.location.href = config.appSubUrl + '/'; diff --git a/public/app/core/core.ts b/public/app/core/core.ts index 279f54d4e45..4aa2e7eb64a 100644 --- a/public/app/core/core.ts +++ b/public/app/core/core.ts @@ -5,13 +5,11 @@ import "./directives/annotation_tooltip"; import "./directives/dash_class"; import "./directives/confirm_click"; import "./directives/dash_edit_link"; -import "./directives/dash_upload"; import "./directives/dropdown_typeahead"; -import "./directives/grafana_version_check"; import "./directives/metric_segment"; import "./directives/misc"; import "./directives/ng_model_on_blur"; -import "./directives/password_strenght"; +import "./directives/password_strength"; import "./directives/spectrum_picker"; import "./directives/tags"; import "./directives/value_select_dropdown"; @@ -20,6 +18,7 @@ import "./directives/rebuild_on_change"; import "./directives/give_focus"; import './jquery_extended'; import './partials'; +import './components/jsontree/jsontree'; import {grafanaAppDirective} from './components/grafana_app'; import {sideMenuDirective} from './components/sidemenu/sidemenu'; @@ -32,12 +31,20 @@ import {liveSrv} from './live/live_srv'; import {Emitter} from './utils/emitter'; import {layoutSelector} from './components/layout_selector/layout_selector'; import {switchDirective} from './components/switch'; +import {dashboardSelector} from './components/dashboard_selector'; +import {queryPartEditorDirective} from './components/query_part/query_part_editor'; +import {WizardFlow} from './components/wizard/wizard'; import 'app/core/controllers/all'; import 'app/core/services/all'; import 'app/core/routes/routes'; import './filters/filters'; import coreModule from './core_module'; import appEvents from './app_events'; +import colors from './utils/colors'; +import {assignModelProperties} from './utils/model_utils'; +import {contextSrv} from './services/context_srv'; +import {KeybindingSrv} from './services/keybindingSrv'; +import {helpModal} from './components/help/help'; export { @@ -54,4 +61,12 @@ export { infoPopover, Emitter, appEvents, + dashboardSelector, + queryPartEditorDirective, + WizardFlow, + colors, + assignModelProperties, + contextSrv, + KeybindingSrv, + helpModal, }; diff --git a/public/app/core/directives/dash_class.js b/public/app/core/directives/dash_class.js index 013c267fc0f..7ac13a552ec 100644 --- a/public/app/core/directives/dash_class.js +++ b/public/app/core/directives/dash_class.js @@ -10,8 +10,6 @@ function (_, $, coreModule) { return { link: function($scope, elem) { - var lastHideControlsVal; - $scope.onAppEvent('panel-fullscreen-enter', function() { elem.toggleClass('panel-in-fullscreen', true); }); @@ -20,13 +18,13 @@ function (_, $, coreModule) { elem.toggleClass('panel-in-fullscreen', false); }); + var lastHideControlsVal; $scope.$watch('dashboard.hideControls', function() { if (!$scope.dashboard) { return; } - var hideControls = $scope.dashboard.hideControls || $scope.playlist_active; - + var hideControls = $scope.dashboard.hideControls; if (lastHideControlsVal !== hideControls) { elem.toggleClass('hide-controls', hideControls); lastHideControlsVal = hideControls; diff --git a/public/app/core/directives/dash_edit_link.js b/public/app/core/directives/dash_edit_link.js index 23855925541..7486d0ada18 100644 --- a/public/app/core/directives/dash_edit_link.js +++ b/public/app/core/directives/dash_edit_link.js @@ -6,28 +6,13 @@ function ($, coreModule) { 'use strict'; var editViewMap = { - 'settings': { src: 'public/app/features/dashboard/partials/settings.html', title: "Settings" }, - 'annotations': { src: 'public/app/features/annotations/partials/editor.html', title: "Annotations" }, - 'templating': { src: 'public/app/features/templating/partials/editor.html', title: "Templating" } + 'settings': { src: 'public/app/features/dashboard/partials/settings.html'}, + 'annotations': { src: 'public/app/features/annotations/partials/editor.html'}, + 'templating': { src: 'public/app/features/templating/partials/editor.html'}, + 'import': { src: '' } }; - coreModule.default.directive('dashEditorLink', function($timeout) { - return { - restrict: 'A', - link: function(scope, elem, attrs) { - var partial = attrs.dashEditorLink; - - elem.bind('click',function() { - $timeout(function() { - var editorScope = attrs.editorScope === 'isolated' ? null : scope; - scope.appEvent('show-dash-editor', { src: partial, scope: editorScope }); - }); - }); - } - }; - }); - - coreModule.default.directive('dashEditorView', function($compile, $location) { + coreModule.default.directive('dashEditorView', function($compile, $location, $rootScope) { return { restrict: 'A', link: function(scope, elem) { @@ -72,8 +57,25 @@ function ($, coreModule) { } }; - var src = "'" + payload.src + "'"; - var view = $('
    '); + if (editview === 'import') { + var modalScope = $rootScope.$new(); + modalScope.$on("$destroy", function() { + editorScope.dismiss(); + }); + + $rootScope.appEvent('show-modal', { + templateHtml: '', + scope: modalScope, + backdrop: 'static' + }); + + return; + } + + var view = payload.src; + if (view.indexOf('.html') > 0) { + view = $('
    '); + } elem.append(view); $compile(elem.contents())(editorScope); diff --git a/public/app/core/directives/dash_upload.js b/public/app/core/directives/dash_upload.js deleted file mode 100644 index b03bc201e83..00000000000 --- a/public/app/core/directives/dash_upload.js +++ /dev/null @@ -1,46 +0,0 @@ -define([ - '../core_module', - 'app/core/utils/kbn', -], -function (coreModule, kbn) { - 'use strict'; - - coreModule.default.directive('dashUpload', function(timer, alertSrv, $location) { - return { - restrict: 'A', - link: function(scope) { - function file_selected(evt) { - var files = evt.target.files; // FileList object - var readerOnload = function() { - return function(e) { - scope.$apply(function() { - try { - window.grafanaImportDashboard = JSON.parse(e.target.result); - } catch (err) { - console.log(err); - scope.appEvent('alert-error', ['Import failed', 'JSON -> JS Serialization failed: ' + err.message]); - return; - } - var title = kbn.slugifyForUrl(window.grafanaImportDashboard.title); - window.grafanaImportDashboard.id = null; - $location.path('/dashboard-import/' + title); - }); - }; - }; - for (var i = 0, f; f = files[i]; i++) { - var reader = new FileReader(); - reader.onload = (readerOnload)(f); - reader.readAsText(f); - } - } - // Check for the various File API support. - if (window.File && window.FileReader && window.FileList && window.Blob) { - // Something - document.getElementById('dashupload').addEventListener('change', file_selected, false); - } else { - alertSrv.set('Oops','Sorry, the HTML5 File APIs are not fully supported in this browser.','error'); - } - } - }; - }); -}); diff --git a/public/app/core/directives/dropdown_typeahead.js b/public/app/core/directives/dropdown_typeahead.js index 2dc5111874e..b44e953785e 100644 --- a/public/app/core/directives/dropdown_typeahead.js +++ b/public/app/core/directives/dropdown_typeahead.js @@ -9,10 +9,10 @@ function (_, $, coreModule) { coreModule.default.directive('dropdownTypeahead', function($compile) { var inputTemplate = ''; - var buttonTemplate = ''; diff --git a/public/app/core/directives/grafana_version_check.js b/public/app/core/directives/grafana_version_check.js deleted file mode 100644 index bee437b8183..00000000000 --- a/public/app/core/directives/grafana_version_check.js +++ /dev/null @@ -1,31 +0,0 @@ -define([ - '../core_module', -], -function (coreModule) { - 'use strict'; - - coreModule.default.directive('grafanaVersionCheck', function($http, contextSrv) { - return { - restrict: 'A', - link: function(scope, elem) { - if (contextSrv.version === 'master') { - return; - } - - $http({ method: 'GET', url: 'https://grafanarel.s3.amazonaws.com/latest.json' }) - .then(function(response) { - if (!response.data || !response.data.version) { - return; - } - - if (contextSrv.version !== response.data.version) { - elem.append(' ' + - ' ' + - 'New version available: ' + response.data.version + - ''); - } - }); - } - }; - }); -}); diff --git a/public/app/core/directives/metric_segment.js b/public/app/core/directives/metric_segment.js index 56dc1fd935a..c3e51dc7a0c 100644 --- a/public/app/core/directives/metric_segment.js +++ b/public/app/core/directives/metric_segment.js @@ -8,10 +8,13 @@ function (_, $, coreModule) { coreModule.default.directive('metricSegment', function($compile, $sce) { var inputTemplate = ''; - var buttonTemplate = ''; + + var selectTemplate = ''; return { @@ -22,8 +25,8 @@ function (_, $, coreModule) { }, link: function($scope, elem) { var $input = $(inputTemplate); - var $button = $(buttonTemplate); var segment = $scope.segment; + var $button = $(segment.selectMode ? selectTemplate : linkTemplate); var options = null; var cancelBlur = null; var linkMode = true; @@ -37,10 +40,10 @@ function (_, $, coreModule) { } $scope.$apply(function() { - var selected = _.findWhere($scope.altSegments, { value: value }); + var selected = _.find($scope.altSegments, {value: value}); if (selected) { segment.value = selected.value; - segment.html = selected.html; + segment.html = selected.html || selected.value; segment.fake = false; segment.expandable = selected.expandable; } @@ -73,10 +76,8 @@ function (_, $, coreModule) { }; $scope.source = function(query, callback) { - if (options) { return options; } - $scope.$apply(function() { - $scope.getOptions().then(function(altSegments) { + $scope.getOptions({ measurementFilter: query }).then(function(altSegments) { $scope.altSegments = altSegments; options = _.map($scope.altSegments, function(alt) { return alt.value; }); @@ -110,7 +111,7 @@ function (_, $, coreModule) { if (str[0] === '/') { str = str.substring(1); } if (str[str.length - 1] === '/') { str = str.substring(0, str.length-1); } try { - return item.toLowerCase().match(str); + return item.toLowerCase().match(str.toLowerCase()); } catch(e) { return false; } @@ -135,7 +136,7 @@ function (_, $, coreModule) { $button.click(function() { options = null; - $input.css('width', ($button.width() + 16) + 'px'); + $input.css('width', (Math.max($button.width(), 80) + 16) + 'px'); $button.hide(); $input.show(); @@ -169,31 +170,42 @@ function (_, $, coreModule) { }, link: { pre: function postLink($scope, elem, attrs) { + var cachedOptions; $scope.valueToSegment = function(value) { - var option = _.findWhere($scope.options, {value: value}); + var option = _.find($scope.options, {value: value}); var segment = { cssClass: attrs.cssClass, custom: attrs.custom, value: option ? option.text : value, + selectMode: attrs.selectMode, }; + return uiSegmentSrv.newSegment(segment); }; $scope.getOptionsInternal = function() { if ($scope.options) { - var optionSegments = _.map($scope.options, function(option) { - return uiSegmentSrv.newSegment({value: option.text}); - }); - return $q.when(optionSegments); + cachedOptions = $scope.options; + return $q.when(_.map($scope.options, function(option) { + return {value: option.text}; + })); } else { - return $scope.getOptions(); + return $scope.getOptions().then(function(options) { + cachedOptions = options; + return _.map(options, function(option) { + if (option.html) { + return option; + } + return {value: option.text}; + }); + }); } }; $scope.onSegmentChange = function() { - if ($scope.options) { - var option = _.findWhere($scope.options, {text: $scope.segment.value}); + if (cachedOptions) { + var option = _.find(cachedOptions, {text: $scope.segment.value}); if (option && option.value !== $scope.property) { $scope.property = option.value; } else if (attrs.custom !== 'false') { @@ -206,7 +218,9 @@ function (_, $, coreModule) { // needs to call this after digest so // property is synced with outerscope $scope.$$postDigest(function() { - $scope.onChange(); + $scope.$apply(function() { + $scope.onChange(); + }); }); }; diff --git a/public/app/core/directives/ng_model_on_blur.js b/public/app/core/directives/ng_model_on_blur.js index 6f4a55b53f0..09c87f5fabe 100644 --- a/public/app/core/directives/ng_model_on_blur.js +++ b/public/app/core/directives/ng_model_on_blur.js @@ -47,7 +47,7 @@ function (coreModule, kbn, rangeUtil) { if (ctrl.$isEmpty(modelValue)) { return true; } - if (viewValue.indexOf('$') === 0) { + if (viewValue.indexOf('$') === 0 || viewValue.indexOf('+$') === 0) { return true; // allow template variable } var info = rangeUtil.describeTextRange(viewValue); diff --git a/public/app/core/directives/password_strenght.js b/public/app/core/directives/password_strength.js similarity index 100% rename from public/app/core/directives/password_strenght.js rename to public/app/core/directives/password_strength.js diff --git a/public/app/core/directives/plugin_component.ts b/public/app/core/directives/plugin_component.ts index 4f87a94573e..83c030cb317 100644 --- a/public/app/core/directives/plugin_component.ts +++ b/public/app/core/directives/plugin_component.ts @@ -58,7 +58,7 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $ var componentInfo: any = { name: 'panel-plugin-' + scope.panel.type, bindings: {dashboard: "=", panel: "=", row: "="}, - attrs: {dashboard: "dashboard", panel: "panel", row: "row"}, + attrs: {dashboard: "ctrl.dashboard", panel: "panel", row: "ctrl.row"}, }; var panelElemName = 'panel-' + scope.panel.type; @@ -136,12 +136,12 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $ } // Annotations case "annotations-query-ctrl": { - return System.import(scope.currentDatasource.meta.module).then(function(dsModule) { + return System.import(scope.ctrl.currentDatasource.meta.module).then(function(dsModule) { return { - baseUrl: scope.currentDatasource.meta.baseUrl, - name: 'annotations-query-ctrl-' + scope.currentDatasource.meta.id, + baseUrl: scope.ctrl.currentDatasource.meta.baseUrl, + name: 'annotations-query-ctrl-' + scope.ctrl.currentDatasource.meta.id, bindings: {annotation: "=", datasource: "="}, - attrs: {"annotation": "currentAnnotation", datasource: "currentDatasource"}, + attrs: {"annotation": "ctrl.currentAnnotation", datasource: "ctrl.currentDatasource"}, Component: dsModule.AnnotationsQueryCtrl, }; }); @@ -169,7 +169,7 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $ return System.import(model.module).then(function(appModule) { return { baseUrl: model.baseUrl, - name: 'app-config-' + model.pluginId, + name: 'app-config-' + model.id, bindings: {appModel: "=", appEditCtrl: "="}, attrs: {"app-model": "ctrl.model", "app-edit-ctrl": "ctrl"}, Component: appModule.ConfigCtrl, @@ -206,9 +206,15 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $ }); $compile(child)(scope); - elem.empty(); - elem.append(child); + + // let a binding digest cycle complete before adding to dom + setTimeout(function() { + elem.append(child); + scope.$applyAsync(function() { + scope.$broadcast('refresh'); + }); + }); } function registerPluginComponent(scope, elem, attrs, componentInfo) { @@ -238,7 +244,7 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $ registerPluginComponent(scope, elem, attrs, componentInfo); }).catch(err => { $rootScope.appEvent('alert-error', ['Plugin Error', err.message || err]); - console.log('Plugin componnet error', err); + console.log('Plugin component error', err); }); } }; diff --git a/public/app/core/directives/value_select_dropdown.js b/public/app/core/directives/value_select_dropdown.js index 60d257d6fa8..8b1719c669d 100644 --- a/public/app/core/directives/value_select_dropdown.js +++ b/public/app/core/directives/value_select_dropdown.js @@ -51,7 +51,7 @@ function (angular, _, coreModule) { }); // convert values to text - var currentTexts = _.pluck(selectedAndNotInTag, 'text'); + var currentTexts = _.map(selectedAndNotInTag, 'text'); // join texts vm.linkText = currentTexts.join(' + '); @@ -75,7 +75,7 @@ function (angular, _, coreModule) { tag.selected = !tag.selected; var tagValuesPromise; if (!tag.values) { - tagValuesPromise = vm.getValuesForTag({tagKey: tag.text}); + tagValuesPromise = vm.variable.getValuesForTag(tag.text); } else { tagValuesPromise = $q.when(tag.values); } @@ -167,7 +167,7 @@ function (angular, _, coreModule) { _.each(vm.tags, function(tag) { if (tag.selected) { _.each(tag.values, function(value) { - if (!_.findWhere(vm.selectedValues, {value: value})) { + if (!_.find(vm.selectedValues, {value: value})) { tag.selected = false; } }); @@ -175,8 +175,8 @@ function (angular, _, coreModule) { }); vm.selectedTags = _.filter(vm.tags, {selected: true}); - vm.variable.current.value = _.pluck(vm.selectedValues, 'value'); - vm.variable.current.text = _.pluck(vm.selectedValues, 'text').join(' + '); + vm.variable.current.value = _.map(vm.selectedValues, 'value'); + vm.variable.current.text = _.map(vm.selectedValues, 'text').join(' + '); vm.variable.current.tags = vm.selectedTags; if (!vm.variable.multi) { @@ -225,7 +225,7 @@ function (angular, _, coreModule) { coreModule.default.directive('valueSelectDropdown', function($compile, $window, $timeout, $rootScope) { return { - scope: { variable: "=", onUpdated: "&", getValuesForTag: "&" }, + scope: { variable: "=", onUpdated: "&"}, templateUrl: 'public/app/partials/valueSelectDropdown.html', controller: 'ValueSelectDropdownCtrl', controllerAs: 'vm', @@ -236,7 +236,7 @@ function (angular, _, coreModule) { var inputEl = elem.find('input'); function openDropdown() { - inputEl.css('width', Math.max(linkEl.width(), 30) + 'px'); + inputEl.css('width', Math.max(linkEl.width(), 80) + 'px'); inputEl.show(); linkEl.hide(); diff --git a/public/app/core/filters/filters.ts b/public/app/core/filters/filters.ts index 6122a010182..63f2bf28bc3 100644 --- a/public/app/core/filters/filters.ts +++ b/public/app/core/filters/filters.ts @@ -60,8 +60,8 @@ coreModule.filter('noXml', function() { coreModule.filter('interpolateTemplateVars', function (templateSrv) { var filterFunc: any = function(text, scope) { var scopedVars; - if (scope.ctrl && scope.ctrl.panel) { - scopedVars = scope.ctrl.panel.scopedVars; + if (scope.ctrl) { + scopedVars = (scope.ctrl.panel || scope.ctrl.row).scopedVars; } else { scopedVars = scope.row.scopedVars; } diff --git a/public/app/core/lodash_extended.js b/public/app/core/lodash_extended.js index 4edae35f02d..6487b19193e 100644 --- a/public/app/core/lodash_extended.js +++ b/public/app/core/lodash_extended.js @@ -19,7 +19,7 @@ function () { return variable === value ? alt : value; }, toggleInOut: function(array,value) { - if(_.contains(array,value)) { + if(_.includes(array,value)) { array = _.without(array,value); } else { array.push(value); diff --git a/public/app/core/profiler.ts b/public/app/core/profiler.ts new file mode 100644 index 00000000000..9b07a1b379d --- /dev/null +++ b/public/app/core/profiler.ts @@ -0,0 +1,126 @@ +/// + +import $ from 'jquery'; +import _ from 'lodash'; +import angular from 'angular'; + +export class Profiler { + panelsRendered: number; + enabled: boolean; + panelsInitCount: any; + timings: any; + digestCounter: any; + $rootScope: any; + scopeCount: any; + + init(config, $rootScope) { + this.enabled = config.buildInfo.env === 'development'; + this.timings = {}; + this.timings.appStart = { loadStart: new Date().getTime() }; + this.$rootScope = $rootScope; + + if (!this.enabled) { + return; + } + + $rootScope.$watch(() => { + this.digestCounter++; + return false; + }, () => {}); + + $rootScope.onAppEvent('refresh', this.refresh.bind(this), $rootScope); + $rootScope.onAppEvent('dashboard-fetch-end', this.dashboardFetched.bind(this), $rootScope); + $rootScope.onAppEvent('dashboard-initialized', this.dashboardInitialized.bind(this), $rootScope); + $rootScope.onAppEvent('panel-initialized', this.panelInitialized.bind(this), $rootScope); + } + + refresh() { + this.timings.query = 0; + this.timings.render = 0; + + setTimeout(() => { + console.log('panel count: ' + this.panelsInitCount); + console.log('total query: ' + this.timings.query); + console.log('total render: ' + this.timings.render); + console.log('avg render: ' + this.timings.render / this.panelsInitCount); + }, 5000); + } + + dashboardFetched() { + this.timings.dashboardLoadStart = new Date().getTime(); + this.panelsInitCount = 0; + this.digestCounter = 0; + this.panelsInitCount = 0; + this.panelsRendered = 0; + this.timings.query = 0; + this.timings.render = 0; + } + + dashboardInitialized() { + setTimeout(() => { + console.log("Dashboard::Performance Total Digests: " + this.digestCounter); + console.log("Dashboard::Performance Total Watchers: " + this.getTotalWatcherCount()); + console.log("Dashboard::Performance Total ScopeCount: " + this.scopeCount); + + var timeTaken = this.timings.lastPanelInitializedAt - this.timings.dashboardLoadStart; + console.log("Dashboard::Performance All panels initialized in " + timeTaken + " ms"); + + // measure digest performance + var rootDigestStart = window.performance.now(); + for (var i = 0; i < 30; i++) { + this.$rootScope.$apply(); + } + + console.log("Dashboard::Performance Root Digest " + ((window.performance.now() - rootDigestStart) / 30)); + }, 3000); + } + + getTotalWatcherCount() { + var count = 0; + var scopes = 0; + var root = $(document.getElementsByTagName('body')); + + var f = function (element) { + if (element.data().hasOwnProperty('$scope')) { + scopes++; + angular.forEach(element.data().$scope.$$watchers, function () { + count++; + }); + } + + angular.forEach(element.children(), function (childElement) { + f($(childElement)); + }); + }; + + f(root); + this.scopeCount = scopes; + return count; + } + + renderingCompleted(panelId, panelTimings) { + // add render counter to root scope + // used by phantomjs render.js to know when panel has rendered + this.panelsRendered = (this.panelsRendered || 0) + 1; + this.$rootScope.panelsRendered = this.panelsRendered; + + if (this.enabled) { + panelTimings.renderEnd = new Date().getTime(); + this.timings.query += panelTimings.queryEnd - panelTimings.queryStart; + this.timings.render += panelTimings.renderEnd - panelTimings.renderStart; + } + } + + panelInitialized() { + if (!this.enabled) { + return; + } + + this.panelsInitCount++; + this.timings.lastPanelInitializedAt = new Date().getTime(); + } + +} + +var profiler = new Profiler(); +export {profiler}; diff --git a/public/app/core/routes/bundle_loader.ts b/public/app/core/routes/bundle_loader.ts index 3d275aeda36..473ac66b4b9 100644 --- a/public/app/core/routes/bundle_loader.ts +++ b/public/app/core/routes/bundle_loader.ts @@ -2,21 +2,22 @@ export class BundleLoader { lazy: any; - loadingDefer: any; constructor(bundleName) { + var defer = null; + this.lazy = ["$q", "$route", "$rootScope", ($q, $route, $rootScope) => { - if (this.loadingDefer) { - return this.loadingDefer.promise; + if (defer) { + return defer.promise; } - this.loadingDefer = $q.defer(); + defer = $q.defer(); System.import(bundleName).then(() => { - this.loadingDefer.resolve(); + defer.resolve(); }); - return this.loadingDefer.promise; + return defer.promise; }]; } diff --git a/public/app/core/routes/dashboard_loaders.js b/public/app/core/routes/dashboard_loaders.js index 8e2157ad84b..728b7e0092f 100644 --- a/public/app/core/routes/dashboard_loaders.js +++ b/public/app/core/routes/dashboard_loaders.js @@ -4,13 +4,18 @@ define([ function (coreModule) { "use strict"; - coreModule.default.controller('LoadDashboardCtrl', function($scope, $routeParams, dashboardLoaderSrv, backendSrv) { + coreModule.default.controller('LoadDashboardCtrl', function($scope, $routeParams, dashboardLoaderSrv, backendSrv, $location) { + $scope.appEvent("dashboard-fetch-start"); if (!$routeParams.slug) { - backendSrv.get('/api/dashboards/home').then(function(result) { - var meta = result.meta; - meta.canSave = meta.canShare = meta.canStar = false; - $scope.initDashboard(result, $scope); + backendSrv.get('/api/dashboards/home').then(function(homeDash) { + if (homeDash.redirectUri) { + $location.path('dashboard/' + homeDash.redirectUri); + } else { + var meta = homeDash.meta; + meta.canSave = meta.canShare = meta.canStar = false; + $scope.initDashboard(homeDash, $scope); + } }); return; } @@ -21,24 +26,19 @@ function (coreModule) { }); - coreModule.default.controller('DashFromImportCtrl', function($scope, $location, alertSrv) { - if (!window.grafanaImportDashboard) { - alertSrv.set('Not found', 'Cannot reload page with unsaved imported dashboard', 'warning', 7000); - $location.path(''); - return; - } - $scope.initDashboard({ - meta: { canShare: false, canStar: false }, - dashboard: window.grafanaImportDashboard - }, $scope); - }); - coreModule.default.controller('NewDashboardCtrl', function($scope) { $scope.initDashboard({ - meta: { canStar: false, canShare: false }, + meta: { canStar: false, canShare: false, isNew: true }, dashboard: { title: "New dashboard", - rows: [{ height: '250px', panels:[] }] + rows: [ + { + title: 'Dashboard Row', + height: '250px', + panels:[], + isNew: true, + } + ] }, }, $scope); }); diff --git a/public/app/core/routes/routes.ts b/public/app/core/routes/routes.ts index 92cf32448a1..28e1dcf1cd1 100644 --- a/public/app/core/routes/routes.ts +++ b/public/app/core/routes/routes.ts @@ -13,6 +13,7 @@ function setupAngularRoutes($routeProvider, $locationProvider) { var loadOrgBundle = new BundleLoader('app/features/org/all'); var loadPluginsBundle = new BundleLoader('app/features/plugins/all'); var loadAdminBundle = new BundleLoader('app/features/admin/admin'); + var loadAlertingBundle = new BundleLoader('app/features/alerting/all'); $routeProvider .when('/', { @@ -30,11 +31,6 @@ function setupAngularRoutes($routeProvider, $locationProvider) { .when('/dashboard-solo/:type/:slug', { templateUrl: 'public/app/features/panel/partials/soloPanel.html', controller : 'SoloPanelCtrl', - pageClass: 'page-dashboard', - }) - .when('/dashboard-import/:file', { - templateUrl: 'public/app/partials/dashboard.html', - controller : 'DashFromImportCtrl', reloadOnSearch: false, pageClass: 'page-dashboard', }) @@ -44,9 +40,9 @@ function setupAngularRoutes($routeProvider, $locationProvider) { reloadOnSearch: false, pageClass: 'page-dashboard', }) - .when('/import/dashboard', { - templateUrl: 'public/app/features/dashboard/partials/import.html', - controller : 'DashboardImportCtrl', + .when('/dashboards/list', { + templateUrl: 'public/app/features/dashboard/partials/dash_list.html', + controller : 'DashListCtrl', }) .when('/datasources', { templateUrl: 'public/app/features/plugins/partials/ds_list.html', @@ -88,16 +84,20 @@ function setupAngularRoutes($routeProvider, $locationProvider) { resolve: loadOrgBundle, }) .when('/profile', { - templateUrl: 'public/app/features/profile/partials/profile.html', + templateUrl: 'public/app/features/org/partials/profile.html', controller : 'ProfileCtrl', + controllerAs: 'ctrl', + resolve: loadOrgBundle, }) .when('/profile/password', { - templateUrl: 'public/app/features/profile/partials/password.html', + templateUrl: 'public/app/features/org/partials/change_password.html', controller : 'ChangePasswordCtrl', + resolve: loadOrgBundle, }) .when('/profile/select-org', { - templateUrl: 'public/app/features/profile/partials/select_org.html', + templateUrl: 'public/app/features/org/partials/select_org.html', controller : 'SelectOrgCtrl', + resolve: loadOrgBundle, }) // ADMIN .when('/admin', { @@ -185,14 +185,38 @@ function setupAngularRoutes($routeProvider, $locationProvider) { controllerAs: 'ctrl', resolve: loadPluginsBundle, }) - .when('/global-alerts', { - templateUrl: 'public/app/features/dashboard/partials/globalAlerts.html', - }) .when('/styleguide/:page?', { controller: 'StyleGuideCtrl', controllerAs: 'ctrl', templateUrl: 'public/app/features/styleguide/styleguide.html', }) + .when('/alerting', { + redirectTo: '/alerting/list' + }) + .when('/alerting/list', { + templateUrl: 'public/app/features/alerting/partials/alert_list.html', + controller: 'AlertListCtrl', + controllerAs: 'ctrl', + resolve: loadAlertingBundle, + }) + .when('/alerting/notifications', { + templateUrl: 'public/app/features/alerting/partials/notifications_list.html', + controller: 'AlertNotificationsListCtrl', + controllerAs: 'ctrl', + resolve: loadAlertingBundle, + }) + .when('/alerting/notification/new', { + templateUrl: 'public/app/features/alerting/partials/notification_edit.html', + controller: 'AlertNotificationEditCtrl', + controllerAs: 'ctrl', + resolve: loadAlertingBundle, + }) + .when('/alerting/notification/:id/edit', { + templateUrl: 'public/app/features/alerting/partials/notification_edit.html', + controller: 'AlertNotificationEditCtrl', + controllerAs: 'ctrl', + resolve: loadAlertingBundle, + }) .otherwise({ templateUrl: 'public/app/partials/error.html', controller: 'ErrorCtrl' diff --git a/public/app/core/services/alert_srv.ts b/public/app/core/services/alert_srv.ts index 971743b7285..286f03db5f5 100644 --- a/public/app/core/services/alert_srv.ts +++ b/public/app/core/services/alert_srv.ts @@ -16,7 +16,7 @@ export class AlertSrv { init() { this.$rootScope.onAppEvent('alert-error', (e, alert) => { - this.set(alert[0], alert[1], 'error', 0); + this.set(alert[0], alert[1], 'error', 7000); }, this.$rootScope); this.$rootScope.onAppEvent('alert-warning', (e, alert) => { @@ -27,14 +27,21 @@ export class AlertSrv { this.set(alert[0], alert[1], 'success', 3000); }, this.$rootScope); - appEvents.on('confirm-modal', this.showConfirmModal.bind(this)); + appEvents.on('alert-error', options => { + this.set(options[0], options[1], 'error', 7000); + }); - this.$rootScope.onAppEvent('confirm-modal', (e, data) => { - this.showConfirmModal(data); - }, this.$rootScope); + appEvents.on('confirm-modal', this.showConfirmModal.bind(this)); } set(title, text, severity, timeout) { + if (_.isObject(text)) { + console.log('alert error', text); + if (text.statusText) { + text = `HTTP Error (${text.status}) ${text.statusText}`; + } + } + var newAlert = { title: title || '', text: text || '', @@ -73,13 +80,27 @@ export class AlertSrv { showConfirmModal(payload) { var scope = this.$rootScope.$new(); + scope.onConfirm = function() { + payload.onConfirm(); + scope.dismiss(); + }; + + scope.updateConfirmText = function(value) { + scope.confirmTextValid = payload.confirmText.toLowerCase() === value.toLowerCase(); + }; + scope.title = payload.title; scope.text = payload.text; scope.text2 = payload.text2; + scope.confirmText = payload.confirmText; + scope.onConfirm = payload.onConfirm; + scope.onAltAction = payload.onAltAction; + scope.altActionText = payload.altActionText; scope.icon = payload.icon || "fa-check"; scope.yesText = payload.yesText || "Yes"; scope.noText = payload.noText || "Cancel"; + scope.confirmTextValid = scope.confirmText ? false : true; var confirmModal = this.$modal({ template: 'public/app/partials/confirm_modal.html', diff --git a/public/app/core/services/backend_srv.js b/public/app/core/services/backend_srv.js deleted file mode 100644 index ff3784ab45e..00000000000 --- a/public/app/core/services/backend_srv.js +++ /dev/null @@ -1,142 +0,0 @@ -define([ - 'angular', - 'lodash', - '../core_module', - 'app/core/config', -], -function (angular, _, coreModule, config) { - 'use strict'; - - coreModule.default.service('backendSrv', function($http, alertSrv, $timeout) { - var self = this; - - this.get = function(url, params) { - return this.request({ method: 'GET', url: url, params: params }); - }; - - this.delete = function(url) { - return this.request({ method: 'DELETE', url: url }); - }; - - this.post = function(url, data) { - return this.request({ method: 'POST', url: url, data: data }); - }; - - this.patch = function(url, data) { - return this.request({ method: 'PATCH', url: url, data: data }); - }; - - this.put = function(url, data) { - return this.request({ method: 'PUT', url: url, data: data }); - }; - - this._handleError = function(err) { - return function() { - if (err.isHandled) { - return; - } - - var data = err.data || { message: 'Unexpected error' }; - if (_.isString(data)) { - data = { message: data }; - } - - if (err.status === 422) { - alertSrv.set("Validation failed", data.message, "warning", 4000); - throw data; - } - - data.severity = 'error'; - - if (err.status < 500) { - data.severity = "warning"; - } - - if (data.message) { - alertSrv.set("Problem!", data.message, data.severity, 10000); - } - - throw data; - }; - }; - - this.request = function(options) { - options.retry = options.retry || 0; - var requestIsLocal = options.url.indexOf('/') === 0; - var firstAttempt = options.retry === 0; - - if (requestIsLocal && !options.hasSubUrl) { - options.url = config.appSubUrl + options.url; - options.hasSubUrl = true; - } - - return $http(options).then(function(results) { - if (options.method !== 'GET') { - if (results && results.data.message) { - alertSrv.set(results.data.message, '', 'success', 3000); - } - } - return results.data; - }, function(err) { - // handle unauthorized - if (err.status === 401 && firstAttempt) { - return self.loginPing().then(function() { - options.retry = 1; - return self.request(options); - }); - } - - $timeout(self._handleError(err), 50); - throw err; - }); - }; - - this.datasourceRequest = function(options) { - options.retry = options.retry || 0; - var requestIsLocal = options.url.indexOf('/') === 0; - var firstAttempt = options.retry === 0; - - return $http(options).then(null, function(err) { - // handle unauthorized for backend requests - if (requestIsLocal && firstAttempt && err.status === 401) { - return self.loginPing().then(function() { - options.retry = 1; - return self.datasourceRequest(options); - }); - } - - //populate error obj on Internal Error - if (_.isString(err.data) && err.status === 500) { - err.data = { - error: err.statusText - }; - } - - // for Prometheus - if (!err.data.message && _.isString(err.data.error)) { - err.data.message = err.data.error; - } - - throw err; - }); - }; - - this.loginPing = function() { - return this.request({url: '/api/login/ping', method: 'GET', retry: 1 }); - }; - - this.search = function(query) { - return this.get('/api/search', query); - }; - - this.getDashboard = function(type, slug) { - return this.get('/api/dashboards/' + type + '/' + slug); - }; - - this.saveDashboard = function(dash, options) { - options = (options || {}); - return this.post('/api/dashboards/db/', {dashboard: dash, overwrite: options.overwrite === true}); - }; - - }); -}); diff --git a/public/app/core/services/backend_srv.ts b/public/app/core/services/backend_srv.ts new file mode 100644 index 00000000000..9a5ec5d219b --- /dev/null +++ b/public/app/core/services/backend_srv.ts @@ -0,0 +1,184 @@ +/// + +import angular from 'angular'; +import _ from 'lodash'; +import config from 'app/core/config'; +import coreModule from 'app/core/core_module'; + +export class BackendSrv { + inFlightRequests = {}; + HTTP_REQUEST_CANCELLED = -1; + + /** @ngInject */ + constructor(private $http, private alertSrv, private $rootScope, private $q, private $timeout) { + } + + get(url, params?) { + return this.request({ method: 'GET', url: url, params: params }); + } + + delete(url) { + return this.request({ method: 'DELETE', url: url }); + } + + post(url, data) { + return this.request({ method: 'POST', url: url, data: data }); + }; + + patch(url, data) { + return this.request({ method: 'PATCH', url: url, data: data }); + } + + put(url, data) { + return this.request({ method: 'PUT', url: url, data: data }); + } + + requestErrorHandler(err) { + if (err.isHandled) { + return; + } + + var data = err.data || { message: 'Unexpected error' }; + if (_.isString(data)) { + data = { message: data }; + } + + if (err.status === 422) { + this.alertSrv.set("Validation failed", data.message, "warning", 4000); + throw data; + } + + data.severity = 'error'; + + if (err.status < 500) { + data.severity = "warning"; + } + + if (data.message) { + this.alertSrv.set("Problem!", data.message, data.severity, 10000); + } + + throw data; + } + + request(options) { + options.retry = options.retry || 0; + var requestIsLocal = options.url.indexOf('/') === 0; + var firstAttempt = options.retry === 0; + + if (requestIsLocal && !options.hasSubUrl) { + options.url = config.appSubUrl + options.url; + options.hasSubUrl = true; + } + + return this.$http(options).then(results => { + if (options.method !== 'GET') { + if (results && results.data.message) { + if (options.showSuccessAlert !== false) { + this.alertSrv.set(results.data.message, '', 'success', 3000); + } + } + } + return results.data; + }, err => { + // handle unauthorized + if (err.status === 401 && firstAttempt) { + return this.loginPing().then(() => { + options.retry = 1; + return this.request(options); + }); + } + + this.$timeout(this.requestErrorHandler.bind(this, err), 50); + throw err; + }); + }; + + datasourceRequest(options) { + options.retry = options.retry || 0; + + // A requestID is provided by the datasource as a unique identifier for a + // particular query. If the requestID exists, the promise it is keyed to + // is canceled, canceling the previous datasource request if it is still + // in-flight. + var canceler; + if (options.requestId) { + canceler = this.inFlightRequests[options.requestId]; + if (canceler) { + canceler.resolve(); + } + // create new canceler + canceler = this.$q.defer(); + options.timeout = canceler.promise; + this.inFlightRequests[options.requestId] = canceler; + } + + var requestIsLocal = options.url.indexOf('/') === 0; + var firstAttempt = options.retry === 0; + + if (requestIsLocal && !options.hasSubUrl && options.retry === 0) { + options.url = config.appSubUrl + options.url; + } + + if (requestIsLocal && options.headers && options.headers.Authorization) { + options.headers['X-DS-Authorization'] = options.headers.Authorization; + delete options.headers.Authorization; + } + + return this.$http(options).catch(err => { + if (err.status === this.HTTP_REQUEST_CANCELLED) { + throw {err, cancelled: true}; + } + + // handle unauthorized for backend requests + if (requestIsLocal && firstAttempt && err.status === 401) { + return this.loginPing().then(() => { + options.retry = 1; + if (canceler) { + canceler.resolve(); + } + return this.datasourceRequest(options); + }); + } + + //populate error obj on Internal Error + if (_.isString(err.data) && err.status === 500) { + err.data = { + error: err.statusText, + response: err.data, + }; + } + + // for Prometheus + if (!err.data.message && _.isString(err.data.error)) { + err.data.message = err.data.error; + } + + throw err; + }).finally(() => { + // clean up + if (options.requestId) { + delete this.inFlightRequests[options.requestId]; + } + }); + }; + + loginPing() { + return this.request({url: '/api/login/ping', method: 'GET', retry: 1 }); + } + + search(query) { + return this.get('/api/search', query); + } + + getDashboard(type, slug) { + return this.get('/api/dashboards/' + type + '/' + slug); + } + + saveDashboard(dash, options) { + options = (options || {}); + return this.post('/api/dashboards/db/', {dashboard: dash, overwrite: options.overwrite === true}); + } +} + +coreModule.service('backendSrv', BackendSrv); diff --git a/public/app/core/services/context_srv.js b/public/app/core/services/context_srv.js deleted file mode 100644 index b4a133afea3..00000000000 --- a/public/app/core/services/context_srv.js +++ /dev/null @@ -1,47 +0,0 @@ -define([ - 'angular', - 'lodash', - '../core_module', - 'app/core/store', - 'app/core/config', -], -function (angular, _, coreModule, store, config) { - 'use strict'; - - coreModule.default.service('contextSrv', function() { - - function User() { - if (config.bootData.user) { - _.extend(this, config.bootData.user); - } - } - - this.hasRole = function(role) { - return this.user.orgRole === role; - }; - - this.setPinnedState = function(val) { - this.pinned = val; - store.set('grafana.sidemenu.pinned', val); - }; - - this.toggleSideMenu = function() { - this.sidemenu = !this.sidemenu; - if (!this.sidemenu) { - this.setPinnedState(false); - } - }; - - this.pinned = store.getBool('grafana.sidemenu.pinned', false); - if (this.pinned) { - this.sidemenu = true; - } - - this.version = config.buildInfo.version; - this.lightTheme = false; - this.user = new User(); - this.isSignedIn = this.user.isSignedIn; - this.isGrafanaAdmin = this.user.isGrafanaAdmin; - this.isEditor = this.hasRole('Editor') || this.hasRole('Admin'); - }); -}); diff --git a/public/app/core/services/context_srv.ts b/public/app/core/services/context_srv.ts new file mode 100644 index 00000000000..3d048e4f869 --- /dev/null +++ b/public/app/core/services/context_srv.ts @@ -0,0 +1,73 @@ +/// + +import config from 'app/core/config'; +import _ from 'lodash'; +import coreModule from 'app/core/core_module'; +import store from 'app/core/store'; + +export class User { + isGrafanaAdmin: any; + isSignedIn: any; + orgRole: any; + timezone: string; + helpFlags1: number; + + constructor() { + if (config.bootData.user) { + _.extend(this, config.bootData.user); + } + } +} + +export class ContextSrv { + pinned: any; + version: any; + user: User; + isSignedIn: any; + isGrafanaAdmin: any; + isEditor: any; + sidemenu: any; + + constructor() { + this.pinned = store.getBool('grafana.sidemenu.pinned', false); + if (this.pinned) { + this.sidemenu = true; + } + + if (!config.buildInfo) { + config.buildInfo = {}; + } + if (!config.bootData) { + config.bootData = {user: {}, settings: {}}; + } + + this.version = config.buildInfo.version; + this.user = new User(); + this.isSignedIn = this.user.isSignedIn; + this.isGrafanaAdmin = this.user.isGrafanaAdmin; + this.isEditor = this.hasRole('Editor') || this.hasRole('Admin'); + } + + hasRole(role) { + return this.user.orgRole === role; + } + + setPinnedState(val) { + this.pinned = val; + store.set('grafana.sidemenu.pinned', val); + } + + toggleSideMenu() { + this.sidemenu = !this.sidemenu; + if (!this.sidemenu) { + this.setPinnedState(false); + } + } +} + +var contextSrv = new ContextSrv(); +export {contextSrv}; + +coreModule.factory('contextSrv', function() { + return contextSrv; +}); diff --git a/public/app/core/services/datasource_srv.js b/public/app/core/services/datasource_srv.js index 07e3f004d45..b8b94cd286d 100644 --- a/public/app/core/services/datasource_srv.js +++ b/public/app/core/services/datasource_srv.js @@ -7,36 +7,11 @@ define([ function (angular, _, coreModule, config) { 'use strict'; - coreModule.default.service('datasourceSrv', function($q, $injector, $rootScope) { + coreModule.default.service('datasourceSrv', function($q, $injector, $rootScope, templateSrv) { var self = this; this.init = function() { this.datasources = {}; - this.metricSources = []; - this.annotationSources = []; - - _.each(config.datasources, function(value, key) { - if (value.meta && value.meta.metrics) { - self.metricSources.push({ - value: key === config.defaultDatasource ? null : key, - name: key, - meta: value.meta, - }); - } - if (value.meta && value.meta.annotations) { - self.annotationSources.push(value); - } - }); - - this.metricSources.sort(function(a, b) { - if (a.meta.builtIn || a.name > b.name) { - return 1; - } - if (a.name < b.name) { - return -1; - } - return 0; - }); }; this.get = function(name) { @@ -44,6 +19,8 @@ function (angular, _, coreModule, config) { return this.get(config.defaultDatasource); } + name = templateSrv.replace(name); + if (this.datasources[name]) { return $q.when(this.datasources[name]); } @@ -89,11 +66,68 @@ function (angular, _, coreModule, config) { }; this.getAnnotationSources = function() { - return this.annotationSources; + var sources = []; + + this.addDataSourceVariables(sources); + + _.each(config.datasources, function(value) { + if (value.meta && value.meta.annotations) { + sources.push(value); + } + }); + + return sources; }; - this.getMetricSources = function() { - return this.metricSources; + this.getMetricSources = function(options) { + var metricSources = []; + + _.each(config.datasources, function(value, key) { + if (value.meta && value.meta.metrics) { + metricSources.push({value: key, name: key, meta: value.meta}); + + if (key === config.defaultDatasource) { + metricSources.push({value: null, name: 'default', meta: value.meta}); + } + } + }); + + if (!options || !options.skipVariables) { + this.addDataSourceVariables(metricSources); + } + + metricSources.sort(function(a, b) { + if (a.meta.builtIn || a.name > b.name) { + return 1; + } + if (a.name < b.name) { + return -1; + } + return 0; + }); + + return metricSources; + }; + + this.addDataSourceVariables = function(list) { + // look for data source variables + for (var i = 0; i < templateSrv.variables.length; i++) { + var variable = templateSrv.variables[i]; + if (variable.type !== 'datasource') { + continue; + } + + var first = variable.current.value; + var ds = config.datasources[first]; + + if (ds) { + list.push({ + name: '$' + variable.name, + value: '$' + variable.name, + meta: ds.meta, + }); + } + } }; this.init(); diff --git a/public/app/core/services/keybindingSrv.ts b/public/app/core/services/keybindingSrv.ts new file mode 100644 index 00000000000..7cff30ee903 --- /dev/null +++ b/public/app/core/services/keybindingSrv.ts @@ -0,0 +1,223 @@ +/// + +import $ from 'jquery'; +import _ from 'lodash'; + +import coreModule from 'app/core/core_module'; +import appEvents from 'app/core/app_events'; + +import Mousetrap from 'mousetrap'; + +export class KeybindingSrv { + helpModal: boolean; + + /** @ngInject */ + constructor( + private $rootScope, + private $modal, + private $location, + private contextSrv, + private $timeout) { + + // clear out all shortcuts on route change + $rootScope.$on('$routeChangeSuccess', () => { + Mousetrap.reset(); + // rebind global shortcuts + this.setupGlobal(); + }); + + this.setupGlobal(); + } + + setupGlobal() { + this.bind(['?', 'h'], this.showHelpModal); + this.bind("g h", this.goToHome); + this.bind("g a", this.openAlerting); + this.bind("g p", this.goToProfile); + this.bind("s s", this.openSearchStarred); + this.bind('s o', this.openSearch); + this.bind('s t', this.openSearchTags); + this.bind('f', this.openSearch); + } + + openSearchStarred() { + this.$rootScope.appEvent('show-dash-search', {starred: true}); + } + + openSearchTags() { + this.$rootScope.appEvent('show-dash-search', {tagsMode: true}); + } + + openSearch() { + this.$rootScope.appEvent('show-dash-search'); + } + + openAlerting() { + this.$location.url("/alerting"); + } + + goToHome() { + this.$location.url("/"); + } + + goToProfile() { + this.$location.url("/profile"); + } + + showHelpModal() { + appEvents.emit('show-modal', {templateHtml: ''}); + } + + bind(keyArg, fn) { + Mousetrap.bind(keyArg, evt => { + evt.preventDefault(); + evt.stopPropagation(); + evt.returnValue = false; + return this.$rootScope.$apply(fn.bind(this)); + }); + } + + showDashEditView(view) { + var search = _.extend(this.$location.search(), {editview: view}); + this.$location.search(search); + } + + setupDashboardBindings(scope, dashboard) { + // this.bind('b', () => { + // dashboard.toggleEditMode(); + // }); + + this.bind('mod+o', () => { + dashboard.graphTooltip = (dashboard.graphTooltip + 1) % 3; + appEvents.emit('graph-hover-clear'); + scope.broadcastRefresh(); + }); + + this.bind('mod+h', () => { + dashboard.hideControls = !dashboard.hideControls; + }); + + this.bind('mod+s', e => { + scope.appEvent('save-dashboard'); + }); + + this.bind('t z', () => { + scope.appEvent('zoom-out', 2); + }); + + this.bind('ctrl+z', () => { + scope.appEvent('zoom-out', 2); + }); + + this.bind('t left', () => { + scope.appEvent('shift-time-backward'); + }); + + this.bind('t right', () => { + scope.appEvent('shift-time-forward'); + }); + + this.bind('mod+i', () => { + scope.appEvent('quick-snapshot'); + }); + + // edit panel + this.bind('e', () => { + if (dashboard.meta.focusPanelId && dashboard.meta.canEdit) { + this.$rootScope.appEvent('panel-change-view', { + fullscreen: true, + edit: true, + panelId: dashboard.meta.focusPanelId, + toggle: true + }); + } + }); + + // view panel + this.bind('v', () => { + if (dashboard.meta.focusPanelId) { + this.$rootScope.appEvent('panel-change-view', { + fullscreen: true, + edit: null, + panelId: dashboard.meta.focusPanelId, + toggle: true, + }); + } + }); + + // delete panel + this.bind('p r', () => { + if (dashboard.meta.focusPanelId && dashboard.meta.canEdit) { + var panelInfo = dashboard.getPanelInfoById(dashboard.meta.focusPanelId); + panelInfo.row.removePanel(panelInfo.panel); + dashboard.meta.focusPanelId = 0; + } + }); + + // share panel + this.bind('p s', () => { + if (dashboard.meta.focusPanelId) { + var shareScope = scope.$new(); + var panelInfo = dashboard.getPanelInfoById(dashboard.meta.focusPanelId); + shareScope.panel = panelInfo.panel; + shareScope.dashboard = dashboard; + + appEvents.emit('show-modal', { + src: 'public/app/features/dashboard/partials/shareModal.html', + scope: shareScope + }); + } + }); + + // delete row + this.bind('r r', () => { + if (dashboard.meta.focusPanelId && dashboard.meta.canEdit) { + var panelInfo = dashboard.getPanelInfoById(dashboard.meta.focusPanelId); + dashboard.removeRow(panelInfo.row); + dashboard.meta.focusPanelId = 0; + } + }); + + // collapse row + this.bind('r c', () => { + if (dashboard.meta.focusPanelId) { + var panelInfo = dashboard.getPanelInfoById(dashboard.meta.focusPanelId); + panelInfo.row.toggleCollapse(); + dashboard.meta.focusPanelId = 0; + } + }); + + this.bind('d r', () => { + scope.broadcastRefresh(); + }); + + this.bind('d s', () => { + this.showDashEditView('settings'); + }); + + this.bind('d k', () => { + appEvents.emit('toggle-kiosk-mode'); + }); + + this.bind('d v', () => { + appEvents.emit('toggle-view-mode'); + }); + + this.bind('esc', () => { + var popups = $('.popover.in'); + if (popups.length > 0) { + return; + } + // close modals + var modalData = $(".modal").data(); + if (modalData && modalData.$scope && modalData.$scope.dismiss) { + modalData.$scope.dismiss(); + } + + scope.appEvent('hide-dash-editor'); + scope.exitFullscreen(); + }); + } +} + +coreModule.service('keybindingSrv', KeybindingSrv); diff --git a/public/app/core/services/keyboard_manager.js b/public/app/core/services/keyboard_manager.js index d8cab869ec0..b5eefda81a6 100644 --- a/public/app/core/services/keyboard_manager.js +++ b/public/app/core/services/keyboard_manager.js @@ -175,17 +175,17 @@ function (angular, _, coreModule) { // Foreach keys in label (split on +) for (var i = 0, l = keys.length; k = keys[i], i < l; i++) { switch (k) { - case 'ctrl': - case 'control': - kp++; - modifiers.ctrl.wanted = true; - break; - case 'shift': - case 'alt': - case 'meta': - kp++; - modifiers[k].wanted = true; - break; + case 'ctrl': + case 'control': + kp++; + modifiers.ctrl.wanted = true; + break; + case 'shift': + case 'alt': + case 'meta': + kp++; + modifiers[k].wanted = true; + break; } if (k.length > 1) { // If it is a special key diff --git a/public/app/core/services/popover_srv.ts b/public/app/core/services/popover_srv.ts index 4711dc1b23c..73249a67b5b 100644 --- a/public/app/core/services/popover_srv.ts +++ b/public/app/core/services/popover_srv.ts @@ -46,9 +46,12 @@ function popoverSrv($compile, $rootScope) { drop.on('close', () => { popoverScope.dismiss({fromDropClose: true}); destroyDrop(); + if (options.onClose) { + options.onClose(); + } }); - drop.open(); + setTimeout(() => { drop.open(); }, 10); }; } diff --git a/public/app/core/services/segment_srv.js b/public/app/core/services/segment_srv.js index a0b85a8bfb2..096697052ce 100644 --- a/public/app/core/services/segment_srv.js +++ b/public/app/core/services/segment_srv.js @@ -19,15 +19,19 @@ function (angular, _, coreModule) { if (_.isString(options)) { this.value = options; - this.html = $sce.trustAsHtml(this.value); + this.html = $sce.trustAsHtml(templateSrv.highlightVariablesAsHtml(this.value)); return; } + // temp hack to work around legacy inconsistency in segment model + this.text = options.value; + this.cssClass = options.cssClass; this.custom = options.custom; this.type = options.type; this.fake = options.fake; this.value = options.value; + this.selectMode = options.selectMode; this.type = options.type; this.expandable = options.expandable; this.html = options.html || $sce.trustAsHtml(templateSrv.highlightVariablesAsHtml(this.value)); @@ -78,7 +82,7 @@ function (angular, _, coreModule) { this.transformToSegments = function(addTemplateVars, variableTypeFilter) { return function(results) { var segments = _.map(results, function(segment) { - return self.newSegment({ value: segment.text, expandable: segment.expandable }); + return self.newSegment({value: segment.text, expandable: segment.expandable}); }); if (addTemplateVars) { diff --git a/public/app/core/services/util_srv.js b/public/app/core/services/util_srv.js deleted file mode 100644 index e6bf3ae08bf..00000000000 --- a/public/app/core/services/util_srv.js +++ /dev/null @@ -1,31 +0,0 @@ -define([ - 'angular', - '../core_module', -], -function (angular, coreModule) { - 'use strict'; - - coreModule.default.service('utilSrv', function($rootScope, $modal, $q) { - - this.init = function() { - $rootScope.onAppEvent('show-modal', this.showModal, $rootScope); - }; - - this.showModal = function(e, options) { - var modal = $modal({ - modalClass: options.modalClass, - template: options.src, - persist: false, - show: false, - scope: options.scope, - keyboard: false - }); - - $q.when(modal).then(function(modalEl) { - modalEl.modal('show'); - }); - }; - - }); - -}); diff --git a/public/app/core/services/util_srv.ts b/public/app/core/services/util_srv.ts new file mode 100644 index 00000000000..c043211cefc --- /dev/null +++ b/public/app/core/services/util_srv.ts @@ -0,0 +1,59 @@ +/// + +import config from 'app/core/config'; +import _ from 'lodash'; +import $ from 'jquery'; + +import coreModule from 'app/core/core_module'; +import appEvents from 'app/core/app_events'; + +export class UtilSrv { + modalScope: any; + + /** @ngInject */ + constructor(private $rootScope, private $modal) { + } + + init() { + appEvents.on('show-modal', this.showModal.bind(this), this.$rootScope); + appEvents.on('hide-modal', this.hideModal.bind(this), this.$rootScope); + } + + hideModal() { + if (this.modalScope && this.modalScope.dismiss) { + this.modalScope.dismiss(); + } + } + + showModal(options) { + if (this.modalScope && this.modalScope.dismiss) { + this.modalScope.dismiss(); + } + + this.modalScope = options.scope; + + if (options.model) { + this.modalScope = this.$rootScope.$new(); + this.modalScope.model = options.model; + } else if (!this.modalScope) { + this.modalScope = this.$rootScope.$new(); + } + + var modal = this.$modal({ + modalClass: options.modalClass, + template: options.src, + templateHtml: options.templateHtml, + persist: false, + show: false, + scope: this.modalScope, + keyboard: false, + backdrop: options.backdrop + }); + + Promise.resolve(modal).then(function(modalEl) { + modalEl.modal('show'); + }); + } +} + +coreModule.service('utilSrv', UtilSrv); diff --git a/public/app/core/table_model.ts b/public/app/core/table_model.ts index fa0aeccc54b..f3d0b81998f 100644 --- a/public/app/core/table_model.ts +++ b/public/app/core/table_model.ts @@ -32,6 +32,8 @@ export default class TableModel { if (options.desc) { this.rows.reverse(); this.columns[options.col].desc = true; + } else { + this.columns[options.col].desc = false; } } } diff --git a/public/app/core/time_series2.ts b/public/app/core/time_series2.ts index f5fcf5bd50c..4503be68710 100644 --- a/public/app/core/time_series2.ts +++ b/public/app/core/time_series2.ts @@ -31,6 +31,8 @@ export default class TimeSeries { allIsZero: boolean; decimals: number; scaledDecimals: number; + hasMsResolution: boolean; + isOutsideRange: boolean; lines: any; bars: any; @@ -42,6 +44,7 @@ export default class TimeSeries { fillBelowTo: any; transform: any; flotpairs: any; + unit: any; constructor(opts) { this.datapoints = opts.datapoints; @@ -52,6 +55,8 @@ export default class TimeSeries { this.valueFormater = kbn.valueFormats.none; this.stats = {}; this.legend = true; + this.unit = opts.unit; + this.hasMsResolution = this.isMsResolutionNeeded(); } applySeriesOverrides(overrides) { @@ -97,6 +102,10 @@ export default class TimeSeries { this.stats.min = Number.MAX_VALUE; this.stats.avg = null; this.stats.current = null; + this.stats.first = null; + this.stats.delta = 0; + this.stats.range = null; + this.stats.timeStep = Number.MAX_VALUE; this.allIsNull = true; this.allIsZero = true; @@ -105,11 +114,24 @@ export default class TimeSeries { var currentTime; var currentValue; var nonNulls = 0; + var previousTime; + var previousValue = 0; + var previousDeltaUp = true; for (var i = 0; i < this.datapoints.length; i++) { currentValue = this.datapoints[i][0]; currentTime = this.datapoints[i][1]; + // Due to missing values we could have different timeStep all along the series + // so we have to find the minimum one (could occur with aggregators such as ZimSum) + if (previousTime !== undefined) { + let timeStep = currentTime - previousTime; + if (timeStep < this.stats.timeStep) { + this.stats.timeStep = timeStep; + } + } + previousTime = currentTime; + if (currentValue === null) { if (ignoreNulls) { continue; } if (nullAsZero) { @@ -131,6 +153,24 @@ export default class TimeSeries { if (currentValue < this.stats.min) { this.stats.min = currentValue; } + if (this.stats.first === null){ + this.stats.first = currentValue; + }else{ + if (previousValue > currentValue) { // counter reset + previousDeltaUp = false; + if (i === this.datapoints.length-1) { // reset on last + this.stats.delta += currentValue; + } + }else{ + if (previousDeltaUp) { + this.stats.delta += currentValue - previousValue; // normal increment + } else { + this.stats.delta += currentValue; // account for counter reset + } + previousDeltaUp = true; + } + } + previousValue = currentValue; } if (currentValue !== 0) { @@ -140,10 +180,6 @@ export default class TimeSeries { result.push([currentTime, currentValue]); } - if (this.datapoints.length >= 2) { - this.stats.timeStep = this.datapoints[1][1] - this.datapoints[0][1]; - } - if (this.stats.max === -Number.MAX_VALUE) { this.stats.max = null; } if (this.stats.min === Number.MAX_VALUE) { this.stats.min = null; } @@ -154,6 +190,9 @@ export default class TimeSeries { this.stats.current = result[result.length-2][1]; } } + if (this.stats.max !== null && this.stats.min !== null) { + this.stats.range = this.stats.max - this.stats.min; + } this.stats.count = result.length; return result; @@ -170,9 +209,9 @@ export default class TimeSeries { } isMsResolutionNeeded() { - for (var i = 0; i -import {Subject} from 'vendor/npm/rxjs/Subject'; +import EventEmitter from 'eventemitter3'; var hasOwnProp = {}.hasOwnProperty; @@ -9,48 +9,32 @@ function createName(name) { } export class Emitter { - subjects: any; + emitter: any; constructor() { - this.subjects = {}; + this.emitter = new EventEmitter(); } emit(name, data?) { - var fnName = createName(name); - this.subjects[fnName] || (this.subjects[fnName] = new Subject()); - this.subjects[fnName].next(data); + this.emitter.emit(name, data); } on(name, handler, scope?) { - var fnName = createName(name); - this.subjects[fnName] || (this.subjects[fnName] = new Subject()); - var subscription = this.subjects[fnName].subscribe(handler); + this.emitter.on(name, handler); if (scope) { - scope.$on('$destroy', function() { - subscription.unsubscribe(); + var unbind = scope.$on('$destroy', () => { + this.emitter.off(name, handler); + unbind(); }); } + } - return subscription; - }; + removeAllListeners(evt?) { + this.emitter.removeAllListeners(evt); + } off(name, handler) { - var fnName = createName(name); - if (this.subjects[fnName]) { - this.subjects[fnName].dispose(); - delete this.subjects[fnName]; - } - } - - dispose() { - var subjects = this.subjects; - for (var prop in subjects) { - if (hasOwnProp.call(subjects, prop)) { - subjects[prop].dispose(); - } - } - - this.subjects = {}; + this.emitter.off(name, handler); } } diff --git a/public/app/core/utils/file_export.ts b/public/app/core/utils/file_export.ts index 944b6ae8a80..0366a76acc2 100644 --- a/public/app/core/utils/file_export.ts +++ b/public/app/core/utils/file_export.ts @@ -5,7 +5,7 @@ import _ from 'lodash'; declare var window: any; export function exportSeriesListToCsv(seriesList) { - var text = 'Series;Time;Value\n'; + var text = 'sep=;\nSeries;Time;Value\n'; _.each(seriesList, function(series) { _.each(series.datapoints, function(dp) { text += series.alias + ';' + new Date(dp[1]).toISOString() + ';' + dp[0] + '\n'; @@ -15,7 +15,7 @@ export function exportSeriesListToCsv(seriesList) { }; export function exportSeriesListToCsvColumns(seriesList) { - var text = 'Time;'; + var text = 'sep=;\nTime;'; // add header _.each(seriesList, function(series) { text += series.alias + ';'; diff --git a/public/app/core/utils/kbn.js b/public/app/core/utils/kbn.js index 11a544d2708..f37137cfbf8 100644 --- a/public/app/core/utils/kbn.js +++ b/public/app/core/utils/kbn.js @@ -1,6 +1,6 @@ define([ 'jquery', - 'lodash', + 'lodash' ], function($, _) { 'use strict'; @@ -8,87 +8,103 @@ function($, _) { var kbn = {}; kbn.valueFormats = {}; + kbn.regexEscape = function(value) { + return value.replace(/[\\^$*+?.()|[\]{}\/]/g, '\\$&'); + }; + ///// HELPER FUNCTIONS ///// kbn.round_interval = function(interval) { switch (true) { - // 0.3s - case (interval <= 300): - return 100; // 0.1s - // 0.75s - case (interval <= 750): - return 500; // 0.5s - // 1.5s - case (interval <= 1500): - return 1000; // 1s - // 3.5s - case (interval <= 3500): - return 2000; // 2s - // 7.5s - case (interval <= 7500): - return 5000; // 5s - // 12.5s - case (interval <= 12500): - return 10000; // 10s - // 17.5s - case (interval <= 17500): - return 15000; // 15s - // 25s - case (interval <= 25000): - return 20000; // 20s - // 45s - case (interval <= 45000): - return 30000; // 30s - // 1.5m - case (interval <= 90000): - return 60000; // 1m - // 3.5m - case (interval <= 210000): - return 120000; // 2m - // 7.5m - case (interval <= 450000): - return 300000; // 5m - // 12.5m - case (interval <= 750000): - return 600000; // 10m - // 12.5m - case (interval <= 1050000): - return 900000; // 15m - // 25m - case (interval <= 1500000): - return 1200000; // 20m - // 45m - case (interval <= 2700000): - return 1800000; // 30m - // 1.5h - case (interval <= 5400000): - return 3600000; // 1h - // 2.5h - case (interval <= 9000000): - return 7200000; // 2h - // 4.5h - case (interval <= 16200000): - return 10800000; // 3h - // 9h - case (interval <= 32400000): - return 21600000; // 6h - // 24h - case (interval <= 86400000): - return 43200000; // 12h - // 48h - case (interval <= 172800000): - return 86400000; // 24h - // 1w - case (interval <= 604800000): - return 86400000; // 24h - // 3w - case (interval <= 1814400000): - return 604800000; // 1w - // 2y - case (interval < 3628800000): - return 2592000000; // 30d - default: - return 31536000000; // 1y + // 0.015s + case (interval <= 15): + return 10; // 0.01s + // 0.035s + case (interval <= 35): + return 20; // 0.02s + // 0.075s + case (interval <= 75): + return 50; // 0.05s + // 0.15s + case (interval <= 150): + return 100; // 0.1s + // 0.35s + case (interval <= 350): + return 200; // 0.2s + // 0.75s + case (interval <= 750): + return 500; // 0.5s + // 1.5s + case (interval <= 1500): + return 1000; // 1s + // 3.5s + case (interval <= 3500): + return 2000; // 2s + // 7.5s + case (interval <= 7500): + return 5000; // 5s + // 12.5s + case (interval <= 12500): + return 10000; // 10s + // 17.5s + case (interval <= 17500): + return 15000; // 15s + // 25s + case (interval <= 25000): + return 20000; // 20s + // 45s + case (interval <= 45000): + return 30000; // 30s + // 1.5m + case (interval <= 90000): + return 60000; // 1m + // 3.5m + case (interval <= 210000): + return 120000; // 2m + // 7.5m + case (interval <= 450000): + return 300000; // 5m + // 12.5m + case (interval <= 750000): + return 600000; // 10m + // 12.5m + case (interval <= 1050000): + return 900000; // 15m + // 25m + case (interval <= 1500000): + return 1200000; // 20m + // 45m + case (interval <= 2700000): + return 1800000; // 30m + // 1.5h + case (interval <= 5400000): + return 3600000; // 1h + // 2.5h + case (interval <= 9000000): + return 7200000; // 2h + // 4.5h + case (interval <= 16200000): + return 10800000; // 3h + // 9h + case (interval <= 32400000): + return 21600000; // 6h + // 24h + case (interval <= 86400000): + return 43200000; // 12h + // 48h + case (interval <= 172800000): + return 86400000; // 24h + // 1w + case (interval <= 604800000): + return 86400000; // 24h + // 3w + case (interval <= 1814400000): + return 604800000; // 1w + // 2y + case (interval < 3628800000): + return 2592000000; // 30d + default: + return 31536000000; // 1y } }; @@ -133,7 +149,7 @@ function($, _) { return str; }; - kbn.interval_regex = /(\d+(?:\.\d+)?)([Mwdhmsy])/; + kbn.interval_regex = /(\d+(?:\.\d+)?)(ms|[Mwdhmsy])/; // histogram & trends kbn.intervals_in_seconds = { @@ -143,7 +159,8 @@ function($, _) { d: 86400, h: 3600, m: 60, - s: 1 + s: 1, + ms: 0.001 }; kbn.calculateInterval = function(range, resolution, userInterval) { @@ -156,7 +173,10 @@ function($, _) { lowLimitMs = kbn.interval_to_ms(lowLimitInterval); } else { - return userInterval; + return { + intervalMs: kbn.interval_to_ms(userInterval), + interval: userInterval, + }; } } @@ -165,7 +185,10 @@ function($, _) { intervalMs = lowLimitMs; } - return kbn.secondsToHms(intervalMs / 1000); + return { + intervalMs: intervalMs, + interval: kbn.secondsToHms(intervalMs / 1000), + }; }; kbn.describe_interval = function (string) { @@ -354,35 +377,63 @@ function($, _) { return kbn.toFixed(100*size, decimals) + '%'; }; + /* Formats the value to hex. Uses float if specified decimals are not 0. + * There are two options, one with 0x, and one without */ + + kbn.valueFormats.hex = function(value, decimals) { + if (value == null) { return ""; } + return parseFloat(kbn.toFixed(value, decimals)).toString(16).toUpperCase(); + }; + + kbn.valueFormats.hex0x = function(value, decimals) { + if (value == null) { return ""; } + var hexString = kbn.valueFormats.hex(value, decimals); + if (hexString.substring(0,1) === "-") { + return "-0x" + hexString.substring(1); + } + return "0x" + hexString; + }; + // Currencies kbn.valueFormats.currencyUSD = kbn.formatBuilders.currency('$'); kbn.valueFormats.currencyGBP = kbn.formatBuilders.currency('£'); kbn.valueFormats.currencyEUR = kbn.formatBuilders.currency('€'); kbn.valueFormats.currencyJPY = kbn.formatBuilders.currency('¥'); + kbn.valueFormats.currencyRUB = kbn.formatBuilders.currency('₽'); - // Data + // Data (Binary) kbn.valueFormats.bits = kbn.formatBuilders.binarySIPrefix('b'); kbn.valueFormats.bytes = kbn.formatBuilders.binarySIPrefix('B'); kbn.valueFormats.kbytes = kbn.formatBuilders.binarySIPrefix('B', 1); kbn.valueFormats.mbytes = kbn.formatBuilders.binarySIPrefix('B', 2); kbn.valueFormats.gbytes = kbn.formatBuilders.binarySIPrefix('B', 3); + // Data (Decimal) + kbn.valueFormats.decbits = kbn.formatBuilders.decimalSIPrefix('b'); + kbn.valueFormats.decbytes = kbn.formatBuilders.decimalSIPrefix('B'); + kbn.valueFormats.deckbytes = kbn.formatBuilders.decimalSIPrefix('B', 1); + kbn.valueFormats.decmbytes = kbn.formatBuilders.decimalSIPrefix('B', 2); + kbn.valueFormats.decgbytes = kbn.formatBuilders.decimalSIPrefix('B', 3); + // Data Rate kbn.valueFormats.pps = kbn.formatBuilders.decimalSIPrefix('pps'); kbn.valueFormats.bps = kbn.formatBuilders.decimalSIPrefix('bps'); kbn.valueFormats.Bps = kbn.formatBuilders.decimalSIPrefix('Bps'); kbn.valueFormats.KBs = kbn.formatBuilders.decimalSIPrefix('Bs', 1); - kbn.valueFormats.Kbits = kbn.formatBuilders.decimalSIPrefix('bits', 1); + kbn.valueFormats.Kbits = kbn.formatBuilders.decimalSIPrefix('bps', 1); kbn.valueFormats.MBs = kbn.formatBuilders.decimalSIPrefix('Bs', 2); - kbn.valueFormats.Mbits = kbn.formatBuilders.decimalSIPrefix('bits', 2); + kbn.valueFormats.Mbits = kbn.formatBuilders.decimalSIPrefix('bps', 2); kbn.valueFormats.GBs = kbn.formatBuilders.decimalSIPrefix('Bs', 3); - kbn.valueFormats.Gbits = kbn.formatBuilders.decimalSIPrefix('bits', 3); + kbn.valueFormats.Gbits = kbn.formatBuilders.decimalSIPrefix('bps', 3); // Throughput kbn.valueFormats.ops = kbn.formatBuilders.simpleCountUnit('ops'); kbn.valueFormats.rps = kbn.formatBuilders.simpleCountUnit('rps'); kbn.valueFormats.wps = kbn.formatBuilders.simpleCountUnit('wps'); kbn.valueFormats.iops = kbn.formatBuilders.simpleCountUnit('iops'); + kbn.valueFormats.opm = kbn.formatBuilders.simpleCountUnit('opm'); + kbn.valueFormats.rpm = kbn.formatBuilders.simpleCountUnit('rpm'); + kbn.valueFormats.wpm = kbn.formatBuilders.simpleCountUnit('wpm'); // Energy kbn.valueFormats.watt = kbn.formatBuilders.decimalSIPrefix('W'); @@ -396,6 +447,7 @@ function($, _) { kbn.valueFormats.ev = kbn.formatBuilders.decimalSIPrefix('eV'); kbn.valueFormats.amp = kbn.formatBuilders.decimalSIPrefix('A'); kbn.valueFormats.volt = kbn.formatBuilders.decimalSIPrefix('V'); + kbn.valueFormats.dBm = kbn.formatBuilders.decimalSIPrefix('dBm'); // Temperature kbn.valueFormats.celsius = kbn.formatBuilders.fixedUnit('°C'); @@ -458,6 +510,19 @@ function($, _) { kbn.valueFormats.s = function(size, decimals, scaledDecimals) { if (size === null) { return ""; } + // Less than 1 µs, devide in ns + if (Math.abs(size) < 0.000001) { + return kbn.toFixedScaled(size * 1.e9, decimals, scaledDecimals - decimals, -9, " ns"); + } + // Less than 1 ms, devide in µs + if (Math.abs(size) < 0.001) { + return kbn.toFixedScaled(size * 1.e6, decimals, scaledDecimals - decimals, -6, " µs"); + } + // Less than 1 second, devide in ms + if (Math.abs(size) < 1) { + return kbn.toFixedScaled(size * 1.e3, decimals, scaledDecimals - decimals, -3, " ms"); + } + if (Math.abs(size) < 60) { return kbn.toFixed(size, decimals) + " s"; } @@ -566,6 +631,52 @@ function($, _) { } }; + kbn.toDuration = function(size, decimals, timeScale) { + if (size === null) { return ""; } + if (size === 0) { return "0 " + timeScale + "s"; } + if (size < 0) { return kbn.toDuration(-size, decimals, timeScale) + " ago"; } + + var units = [ + {short: "y", long: "year"}, + {short: "M", long: "month"}, + {short: "w", long: "week"}, + {short: "d", long: "day"}, + {short: "h", long: "hour"}, + {short: "m", long: "minute"}, + {short: "s", long: "second"}, + {short: "ms", long: "millisecond"} + ]; + // convert $size to milliseconds + // intervals_in_seconds uses seconds (duh), convert them to milliseconds here to minimize floating point errors + size *= kbn.intervals_in_seconds[units.find(function(e) { return e.long === timeScale; }).short] * 1000; + + var string = []; + // after first value >= 1 print only $decimals more + var decrementDecimals = false; + for (var i = 0; i < units.length && decimals >= 0; i++) { + var interval = kbn.intervals_in_seconds[units[i].short] * 1000; + var value = size / interval; + if (value >= 1 || decrementDecimals) { + decrementDecimals = true; + var floor = Math.floor(value); + var unit = units[i].long + (floor !== 1 ? "s" : ""); + string.push(floor + " " + unit); + size = size % interval; + decimals--; + } + } + + return string.join(", "); + }; + + kbn.valueFormats.dtdurationms = function(size, decimals) { + return kbn.toDuration(size, decimals, 'millisecond'); + }; + + kbn.valueFormats.dtdurations = function(size, decimals) { + return kbn.toDuration(size, decimals, 'second'); + }; + ///// FORMAT MENU ///// kbn.getUnitFormats = function() { @@ -580,6 +691,8 @@ function($, _) { {text: 'Humidity (%H)', value: 'humidity' }, {text: 'ppm', value: 'ppm' }, {text: 'decibel', value: 'dB' }, + {text: 'hexadecimal (0x)', value: 'hex0x' }, + {text: 'hexadecimal', value: 'hex' }, ] }, { @@ -589,6 +702,7 @@ function($, _) { {text: 'Pounds (£)', value: 'currencyGBP'}, {text: 'Euro (€)', value: 'currencyEUR'}, {text: 'Yen (¥)', value: 'currencyJPY'}, + {text: 'Rubles (₽)', value: 'currencyRUB'}, ] }, { @@ -602,16 +716,28 @@ function($, _) { {text: 'minutes (m)', value: 'm' }, {text: 'hours (h)', value: 'h' }, {text: 'days (d)', value: 'd' }, + {text: 'duration (ms)', value: 'dtdurationms' }, + {text: 'duration (s)', value: 'dtdurations' } ] }, { - text: 'data', + text: 'data (IEC)', submenu: [ {text: 'bits', value: 'bits' }, {text: 'bytes', value: 'bytes' }, - {text: 'kilobytes', value: 'kbytes'}, - {text: 'megabytes', value: 'mbytes'}, - {text: 'gigabytes', value: 'gbytes'}, + {text: 'kibibytes', value: 'kbytes'}, + {text: 'mebibytes', value: 'mbytes'}, + {text: 'gibibytes', value: 'gbytes'}, + ] + }, + { + text: 'data (Metric)', + submenu: [ + {text: 'bits', value: 'decbits' }, + {text: 'bytes', value: 'decbytes' }, + {text: 'kilobytes', value: 'deckbytes'}, + {text: 'megabytes', value: 'decmbytes'}, + {text: 'gigabytes', value: 'decgbytes'}, ] }, { @@ -635,6 +761,9 @@ function($, _) { {text: 'reads/sec (rps)', value: 'rps' }, {text: 'writes/sec (wps)', value: 'wps' }, {text: 'I/O ops/sec (iops)', value: 'iops'}, + {text: 'ops/min (opm)', value: 'opm' }, + {text: 'reads/min (rpm)', value: 'rpm' }, + {text: 'writes/min (wpm)', value: 'wpm' }, ] }, { @@ -677,6 +806,7 @@ function($, _) { {text: 'electron volt (eV)', value: 'ev' }, {text: 'Ampere (A)', value: 'amp' }, {text: 'Volt (V)', value: 'volt' }, + {text: 'Decibel-milliwatt (dBm)', value: 'dBm' }, ] }, { diff --git a/public/app/core/utils/model_utils.ts b/public/app/core/utils/model_utils.ts new file mode 100644 index 00000000000..dd620aff53d --- /dev/null +++ b/public/app/core/utils/model_utils.ts @@ -0,0 +1,10 @@ +export function assignModelProperties(target, source, defaults, removeDefaults?) { + for (var key in defaults) { + if (!defaults.hasOwnProperty(key)) { + continue; + } + + target[key] = source[key] === undefined ? defaults[key] : source[key]; + } +} + diff --git a/public/app/core/utils/rangeutil.ts b/public/app/core/utils/rangeutil.ts index 7f2f2fd72b1..ea9ad111e8d 100644 --- a/public/app/core/utils/rangeutil.ts +++ b/public/app/core/utils/rangeutil.ts @@ -38,10 +38,10 @@ var rangeOptions = [ { from: 'now-12h', to: 'now', display: 'Last 12 hours', section: 3 }, { from: 'now-24h', to: 'now', display: 'Last 24 hours', section: 3 }, + { from: 'now-2d', to: 'now', display: 'Last 2 days', section: 0 }, { from: 'now-7d', to: 'now', display: 'Last 7 days', section: 0 }, { from: 'now-30d', to: 'now', display: 'Last 30 days', section: 0 }, { from: 'now-60d', to: 'now', display: 'Last 60 days', section: 0 }, - { from: 'now-90d', to: 'now', display: 'Last 90 days', section: 0 }, { from: 'now-6M', to: 'now', display: 'Last 6 months', section: 0 }, { from: 'now-1y', to: 'now', display: 'Last 1 year', section: 0 }, { from: 'now-2y', to: 'now', display: 'Last 2 years', section: 0 }, @@ -82,8 +82,9 @@ function formatDate(date) { // now/d // if no to then to now is assumed export function describeTextRange(expr: any) { + let isLast = (expr.indexOf('+') !== 0); if (expr.indexOf('now') === -1) { - expr = 'now-' + expr; + expr = (isLast ? 'now-' : 'now') + expr; } let opt = rangeIndex[expr + ' to now']; @@ -91,15 +92,20 @@ export function describeTextRange(expr: any) { return opt; } - opt = {from: expr, to: 'now'}; + if (isLast) { + opt = {from: expr, to: 'now'}; + } else { + opt = {from: 'now', to: expr}; + } - let parts = /^now-(\d+)(\w)/.exec(expr); + let parts = /^now([-+])(\d+)(\w)/.exec(expr); if (parts) { - let unit = parts[2]; - let amount = parseInt(parts[1]); + let unit = parts[3]; + let amount = parseInt(parts[2]); let span = spans[unit]; if (span) { - opt.display = 'Last ' + amount + ' ' + span.display; + opt.display = isLast ? 'Last ' : 'Next '; + opt.display += amount + ' ' + span.display; opt.section = span.section; if (amount > 1) { opt.display += 's'; diff --git a/public/app/core/utils/sort_by_keys.ts b/public/app/core/utils/sort_by_keys.ts new file mode 100644 index 00000000000..9dff252576a --- /dev/null +++ b/public/app/core/utils/sort_by_keys.ts @@ -0,0 +1,17 @@ +import _ from 'lodash'; + +export default function sortByKeys(input) { + if (_.isArray(input)) { + return input.map(sortByKeys); + } + + if (_.isPlainObject(input)) { + var sortedObject = {}; + for (let key of _.keys(input).sort()) { + sortedObject[key] = sortByKeys(input[key]); + } + return sortedObject; + } + + return input; +} diff --git a/public/app/features/admin/adminEditUserCtrl.js b/public/app/features/admin/adminEditUserCtrl.js index d8500a845d3..104ccff99cd 100644 --- a/public/app/features/admin/adminEditUserCtrl.js +++ b/public/app/features/admin/adminEditUserCtrl.js @@ -81,20 +81,20 @@ function (angular, _) { $scope.searchOrgs = function(queryStr, callback) { if ($scope.orgsSearchCache.length > 0) { - callback(_.pluck($scope.orgsSearchCache, "name")); + callback(_.map($scope.orgsSearchCache, "name")); return; } backendSrv.get('/api/orgs', {query: ''}).then(function(result) { $scope.orgsSearchCache = result; - callback(_.pluck(result, "name")); + callback(_.map(result, "name")); }); }; $scope.addOrgUser = function() { if (!$scope.addOrgForm.$valid) { return; } - var orgInfo = _.findWhere($scope.orgsSearchCache, {name: $scope.newOrg.name}); + var orgInfo = _.find($scope.orgsSearchCache, {name: $scope.newOrg.name}); if (!orgInfo) { return; } $scope.newOrg.loginOrEmail = $scope.user.login; diff --git a/public/app/features/admin/partials/settings.html b/public/app/features/admin/partials/settings.html index 5e070f4d3c0..5371670a9ba 100644 --- a/public/app/features/admin/partials/settings.html +++ b/public/app/features/admin/partials/settings.html @@ -7,7 +7,7 @@
    - These system settings are defined in grafana.ini or grafana.custom.ini (or overriden in ENV variables). + These system settings are defined in grafana.ini or custom.ini (or overriden in ENV variables). To change these you currently need to restart grafana.
    diff --git a/public/app/features/admin/partials/stats.html b/public/app/features/admin/partials/stats.html index 1ad114f50e2..92e32f4f947 100644 --- a/public/app/features/admin/partials/stats.html +++ b/public/app/features/admin/partials/stats.html @@ -22,10 +22,6 @@ Total users {{ctrl.stats.user_count}} - - Total grafana admins - {{ctrl.stats.grafana_admin_count}} - Total organizations {{ctrl.stats.org_count}} @@ -50,6 +46,10 @@ Total starred dashboards {{ctrl.stats.starred_db_count}} + + Total alerts + {{ctrl.stats.alert_count}} + diff --git a/public/app/features/alerting/alert_def.ts b/public/app/features/alerting/alert_def.ts new file mode 100644 index 00000000000..e6bd75379b2 --- /dev/null +++ b/public/app/features/alerting/alert_def.ts @@ -0,0 +1,141 @@ +/// + +import _ from 'lodash'; +import { + QueryPartDef, + QueryPart, +} from 'app/core/components/query_part/query_part'; + +var alertQueryDef = new QueryPartDef({ + type: 'query', + params: [ + {name: "queryRefId", type: 'string', dynamicLookup: true}, + {name: "from", type: "string", options: ['1s', '10s', '1m', '5m', '10m', '15m', '1h', '24h', '48h']}, + {name: "to", type: "string", options: ['now']}, + ], + defaultParams: ['#A', '5m', 'now', 'avg'] +}); + +var conditionTypes = [ + {text: 'Query', value: 'query'}, +]; + +var alertStateSortScore = { + alerting: 1, + no_data: 2, + pending: 3, + ok: 4, + paused: 5, +}; + +var evalFunctions = [ + {text: 'IS ABOVE', value: 'gt'}, + {text: 'IS BELOW', value: 'lt'}, + {text: 'IS OUTSIDE RANGE', value: 'outside_range'}, + {text: 'IS WITHIN RANGE', value: 'within_range'}, + {text: 'HAS NO VALUE' , value: 'no_value'} +]; + +var evalOperators = [ + {text: 'OR', value: 'or'}, + {text: 'AND', value: 'and'}, +]; + +var reducerTypes = [ + {text: 'avg()', value: 'avg'}, + {text: 'min()', value: 'min'}, + {text: 'max()', value: 'max'}, + {text: 'sum()' , value: 'sum'}, + {text: 'count()', value: 'count'}, + {text: 'last()', value: 'last'}, + {text: 'median()', value: 'median'}, +]; + +var noDataModes = [ + {text: 'Alerting', value: 'alerting'}, + {text: 'No Data', value: 'no_data'}, + {text: 'Keep Last State', value: 'keep_state'}, + {text: 'Ok', value: 'ok'}, +]; + +var executionErrorModes = [ + {text: 'Alerting', value: 'alerting'}, + {text: 'Keep Last State', value: 'keep_state'}, +]; + +function createReducerPart(model) { + var def = new QueryPartDef({type: model.type, defaultParams: []}); + return new QueryPart(model, def); +} + +function getStateDisplayModel(state) { + switch (state) { + case 'ok': { + return { + text: 'OK', + iconClass: 'icon-gf icon-gf-online', + stateClass: 'alert-state-ok' + }; + } + case 'alerting': { + return { + text: 'ALERTING', + iconClass: 'icon-gf icon-gf-critical', + stateClass: 'alert-state-critical' + }; + } + case 'no_data': { + return { + text: 'NO DATA', + iconClass: "fa fa-question", + stateClass: 'alert-state-warning' + }; + } + case 'execution_error': { + return { + text: 'EXECUTION ERROR', + iconClass: 'icon-gf icon-gf-critical', + stateClass: 'alert-state-critical' + }; + } + + case 'paused': { + return { + text: 'paused', + iconClass: "fa fa-pause", + stateClass: 'alert-state-paused' + }; + } + case 'pending': { + return { + text: 'PENDING', + iconClass: "fa fa-exclamation", + stateClass: 'alert-state-warning' + }; + } + } +} + +function joinEvalMatches(matches, seperator: string) { + return _.reduce(matches, (res, ev)=> { + if (ev.Metric !== undefined && ev.Value !== undefined) { + res.push(ev.Metric + "=" + ev.Value); + } + + return res; + }, []).join(seperator); +} + +export default { + alertQueryDef: alertQueryDef, + getStateDisplayModel: getStateDisplayModel, + conditionTypes: conditionTypes, + evalFunctions: evalFunctions, + evalOperators: evalOperators, + noDataModes: noDataModes, + executionErrorModes: executionErrorModes, + reducerTypes: reducerTypes, + createReducerPart: createReducerPart, + joinEvalMatches: joinEvalMatches, + alertStateSortScore: alertStateSortScore, +}; diff --git a/public/app/features/alerting/alert_list_ctrl.ts b/public/app/features/alerting/alert_list_ctrl.ts new file mode 100644 index 00000000000..5e3cce35c6e --- /dev/null +++ b/public/app/features/alerting/alert_list_ctrl.ts @@ -0,0 +1,68 @@ +/// + +import angular from 'angular'; +import _ from 'lodash'; +import coreModule from '../../core/core_module'; +import appEvents from '../../core/app_events'; +import moment from 'moment'; +import alertDef from './alert_def'; + +export class AlertListCtrl { + + alerts: any; + stateFilters = [ + {text: 'All', value: null}, + {text: 'OK', value: 'ok'}, + {text: 'Alerting', value: 'alerting'}, + {text: 'No Data', value: 'no_data'}, + ]; + + filters = { + state: 'ALL' + }; + + /** @ngInject */ + constructor(private backendSrv, private $location, private $scope) { + var params = $location.search(); + this.filters.state = params.state || null; + this.loadAlerts(); + } + + filtersChanged() { + this.$location.search(this.filters); + } + + loadAlerts() { + this.backendSrv.get('/api/alerts', this.filters).then(result => { + this.alerts = _.map(result, alert => { + alert.stateModel = alertDef.getStateDisplayModel(alert.state); + alert.newStateDateAgo = moment(alert.newStateDate).fromNow().replace(" ago", ""); + return alert; + }); + }); + } + + pauseAlertRule(alertId: any) { + var alert = _.find(this.alerts, {id: alertId}); + + var payload = { + paused: alert.state !== "paused" + }; + + this.backendSrv.post(`/api/alerts/${alert.id}/pause`, payload).then(result => { + alert.state = result.state; + alert.stateModel = alertDef.getStateDisplayModel(result.state); + }); + } + + openHowTo() { + appEvents.emit('show-modal', { + src: 'public/app/features/alerting/partials/alert_howto.html', + modalClass: 'confirm-modal', + model: {} + }); + } +} + +coreModule.controller('AlertListCtrl', AlertListCtrl); + diff --git a/public/app/features/alerting/alert_model.ts b/public/app/features/alerting/alert_model.ts new file mode 100644 index 00000000000..b7091a3f066 --- /dev/null +++ b/public/app/features/alerting/alert_model.ts @@ -0,0 +1,11 @@ + /// + +import _ from 'lodash'; +import {QueryPart} from 'app/core/components/query_part/query_part'; +import alertDef from './alert_def'; + +export class AlertModel { + constructor() { + } +} + diff --git a/public/app/features/alerting/alert_tab_ctrl.ts b/public/app/features/alerting/alert_tab_ctrl.ts new file mode 100644 index 00000000000..c6683556745 --- /dev/null +++ b/public/app/features/alerting/alert_tab_ctrl.ts @@ -0,0 +1,407 @@ + /// + +import _ from 'lodash'; +import {ThresholdMapper} from './threshold_mapper'; +import {QueryPart} from 'app/core/components/query_part/query_part'; +import alertDef from './alert_def'; +import config from 'app/core/config'; +import moment from 'moment'; +import appEvents from 'app/core/app_events'; + +export class AlertTabCtrl { + panel: any; + panelCtrl: any; + testing: boolean; + testResult: any; + subTabIndex: number; + conditionTypes: any; + alert: any; + conditionModels: any; + evalFunctions: any; + evalOperators: any; + noDataModes: any; + executionErrorModes: any; + addNotificationSegment; + notifications; + alertNotifications; + error: string; + appSubUrl: string; + alertHistory: any; + + /** @ngInject */ + constructor(private $scope, + private $timeout, + private backendSrv, + private dashboardSrv, + private uiSegmentSrv, + private $q, + private datasourceSrv, + private templateSrv) { + this.panelCtrl = $scope.ctrl; + this.panel = this.panelCtrl.panel; + this.$scope.ctrl = this; + this.subTabIndex = 0; + this.evalFunctions = alertDef.evalFunctions; + this.evalOperators = alertDef.evalOperators; + this.conditionTypes = alertDef.conditionTypes; + this.noDataModes = alertDef.noDataModes; + this.executionErrorModes = alertDef.executionErrorModes; + this.appSubUrl = config.appSubUrl; + } + + $onInit() { + this.addNotificationSegment = this.uiSegmentSrv.newPlusButton(); + + // subscribe to graph threshold handle changes + var thresholdChangedEventHandler = this.graphThresholdChanged.bind(this); + this.panelCtrl.events.on('threshold-changed', thresholdChangedEventHandler); + + // set panel alert edit mode + this.$scope.$on("$destroy", () => { + this.panelCtrl.events.off("threshold-changed", thresholdChangedEventHandler); + this.panelCtrl.editingThresholds = false; + this.panelCtrl.render(); + }); + + // build notification model + this.notifications = []; + this.alertNotifications = []; + this.alertHistory = []; + + return this.backendSrv.get('/api/alert-notifications').then(res => { + this.notifications = res; + + this.initModel(); + this.validateModel(); + }); + } + + getAlertHistory() { + this.backendSrv.get(`/api/annotations?dashboardId=${this.panelCtrl.dashboard.id}&panelId=${this.panel.id}&limit=50`).then(res => { + this.alertHistory = _.map(res, ah => { + ah.time = moment(ah.time).format('MMM D, YYYY HH:mm:ss'); + ah.stateModel = alertDef.getStateDisplayModel(ah.newState); + ah.metrics = alertDef.joinEvalMatches(ah.data, ', '); + return ah; + }); + }); + } + + getNotificationIcon(type) { + switch (type) { + case "email": return "fa fa-envelope"; + case "slack": return "fa fa-slack"; + case "victorops": return "fa fa-pagelines"; + case "webhook": return "fa fa-cubes"; + case "pagerduty": return "fa fa-bullhorn"; + case "opsgenie": return "fa fa-bell"; + } + } + + getNotifications() { + return Promise.resolve(this.notifications.map(item => { + return this.uiSegmentSrv.newSegment(item.name); + })); + } + + changeTabIndex(newTabIndex) { + this.subTabIndex = newTabIndex; + + if (this.subTabIndex === 2) { + this.getAlertHistory(); + } + } + + notificationAdded() { + var model = _.find(this.notifications, {name: this.addNotificationSegment.value}); + if (!model) { + return; + } + + this.alertNotifications.push({ + name: model.name, + iconClass: this.getNotificationIcon(model.type), + isDefault: false + }); + this.alert.notifications.push({id: model.id}); + + // reset plus button + this.addNotificationSegment.value = this.uiSegmentSrv.newPlusButton().value; + this.addNotificationSegment.html = this.uiSegmentSrv.newPlusButton().html; + } + + removeNotification(index) { + this.alert.notifications.splice(index, 1); + this.alertNotifications.splice(index, 1); + } + + initModel() { + var alert = this.alert = this.panel.alert; + if (!alert) { + return; + } + + alert.conditions = alert.conditions || []; + if (alert.conditions.length === 0) { + alert.conditions.push(this.buildDefaultCondition()); + } + + alert.noDataState = alert.noDataState || 'no_data'; + alert.executionErrorState = alert.executionErrorState || 'alerting'; + alert.frequency = alert.frequency || '60s'; + alert.handler = alert.handler || 1; + alert.notifications = alert.notifications || []; + + var defaultName = this.panel.title + ' alert'; + alert.name = alert.name || defaultName; + + this.conditionModels = _.reduce(alert.conditions, (memo, value) => { + memo.push(this.buildConditionModel(value)); + return memo; + }, []); + + ThresholdMapper.alertToGraphThresholds(this.panel); + + for (let addedNotification of alert.notifications) { + var model = _.find(this.notifications, {id: addedNotification.id}); + if (model && model.isDefault === false) { + model.iconClass = this.getNotificationIcon(model.type); + this.alertNotifications.push(model); + } + } + + for (let notification of this.notifications) { + if (notification.isDefault) { + notification.iconClass = this.getNotificationIcon(notification.type); + notification.bgColor = "#00678b"; + this.alertNotifications.push(notification); + } + } + + this.panelCtrl.editingThresholds = true; + this.panelCtrl.render(); + } + + graphThresholdChanged(evt) { + for (var condition of this.alert.conditions) { + if (condition.type === 'query') { + condition.evaluator.params[evt.handleIndex] = evt.threshold.value; + this.evaluatorParamsChanged(); + break; + } + } + } + + buildDefaultCondition() { + return { + type: 'query', + query: {params: ['A', '5m', 'now']}, + reducer: {type: 'avg', params: []}, + evaluator: {type: 'gt', params: [null]}, + operator: {type: 'and'}, + }; + } + + validateModel() { + if (!this.alert) { + return; + } + + let firstTarget; + var fixed = false; + let foundTarget = null; + + for (var condition of this.alert.conditions) { + if (condition.type !== 'query') { + continue; + } + + for (var target of this.panel.targets) { + if (!firstTarget) { + firstTarget = target; + } + if (condition.query.params[0] === target.refId) { + foundTarget = target; + break; + } + } + + if (!foundTarget) { + if (firstTarget) { + condition.query.params[0] = firstTarget.refId; + foundTarget = firstTarget; + fixed = true; + } else { + this.error = "Could not find any metric queries"; + } + } + + var datasourceName = foundTarget.datasource || this.panel.datasource; + this.datasourceSrv.get(datasourceName).then(ds => { + if (!ds.meta.alerting) { + this.error = 'The datasource does not support alerting queries'; + } else if (ds.targetContainsTemplate(foundTarget)) { + this.error = 'Template variables are not supported in alert queries'; + } else { + this.error = ''; + } + }); + } + } + + buildConditionModel(source) { + var cm: any = {source: source, type: source.type}; + + cm.queryPart = new QueryPart(source.query, alertDef.alertQueryDef); + cm.reducerPart = alertDef.createReducerPart(source.reducer); + cm.evaluator = source.evaluator; + cm.operator = source.operator; + + return cm; + } + + handleQueryPartEvent(conditionModel, evt) { + switch (evt.name) { + case "action-remove-part": { + break; + } + case "get-part-actions": { + return this.$q.when([]); + } + case "part-param-changed": { + this.validateModel(); + } + case "get-param-options": { + var result = this.panel.targets.map(target => { + return this.uiSegmentSrv.newSegment({ value: target.refId }); + }); + + return this.$q.when(result); + } + } + } + + handleReducerPartEvent(conditionModel, evt) { + switch (evt.name) { + case "action": { + conditionModel.source.reducer.type = evt.action.value; + conditionModel.reducerPart = alertDef.createReducerPart(conditionModel.source.reducer); + break; + } + case "get-part-actions": { + var result = []; + for (var type of alertDef.reducerTypes) { + if (type.value !== conditionModel.source.reducer.type) { + result.push(type); + } + } + return this.$q.when(result); + } + } + } + + addCondition(type) { + var condition = this.buildDefaultCondition(); + // add to persited model + this.alert.conditions.push(condition); + // add to view model + this.conditionModels.push(this.buildConditionModel(condition)); + } + + removeCondition(index) { + this.alert.conditions.splice(index, 1); + this.conditionModels.splice(index, 1); + } + + delete() { + appEvents.emit('confirm-modal', { + title: 'Delete Alert', + text: 'Are you sure you want to delete this alert rule?', + text2: 'You need to save dashboard for the delete to take effect', + icon: 'fa-trash', + yesText: 'Delete', + onConfirm: () => { + delete this.panel.alert; + this.alert = null; + this.panel.thresholds = []; + this.conditionModels = []; + this.panelCtrl.alertState = null; + this.panelCtrl.render(); + } + }); + } + + enable() { + this.panel.alert = {}; + this.initModel(); + } + + evaluatorParamsChanged() { + ThresholdMapper.alertToGraphThresholds(this.panel); + this.panelCtrl.render(); + } + + evaluatorTypeChanged(evaluator) { + // ensure params array is correct length + switch (evaluator.type) { + case "lt": + case "gt": { + evaluator.params = [evaluator.params[0]]; + break; + } + case "within_range": + case "outside_range": { + evaluator.params = [evaluator.params[0], evaluator.params[1]]; + break; + } + case "no_value": { + evaluator.params = []; + } + } + + this.evaluatorParamsChanged(); + } + + clearHistory() { + appEvents.emit('confirm-modal', { + title: 'Delete Alert History', + text: 'Are you sure you want to remove all history & annotations for this alert?', + icon: 'fa-trash', + yesText: 'Yes', + onConfirm: () => { + this.backendSrv.post('/api/annotations/mass-delete', { + dashboardId: this.panelCtrl.dashboard.id, + panelId: this.panel.id, + }).then(res => { + this.alertHistory = []; + this.panelCtrl.refresh(); + }); + } + }); + } + + test() { + this.testing = true; + + var payload = { + dashboard: this.dashboardSrv.getCurrent().getSaveModelClone(), + panelId: this.panelCtrl.panel.id, + }; + + return this.backendSrv.post('/api/alerts/test', payload).then(res => { + this.testResult = res; + this.testing = false; + }); + } +} + +/** @ngInject */ +export function alertTab() { + 'use strict'; + return { + restrict: 'E', + scope: true, + templateUrl: 'public/app/features/alerting/partials/alert_tab.html', + controller: AlertTabCtrl, + }; +} diff --git a/public/app/features/alerting/all.ts b/public/app/features/alerting/all.ts new file mode 100644 index 00000000000..01c93ec3581 --- /dev/null +++ b/public/app/features/alerting/all.ts @@ -0,0 +1,4 @@ +import './alert_list_ctrl'; +import './notifications_list_ctrl'; +import './notification_edit_ctrl'; + diff --git a/public/app/features/alerting/notification_edit_ctrl.ts b/public/app/features/alerting/notification_edit_ctrl.ts new file mode 100644 index 00000000000..ed05264cdb3 --- /dev/null +++ b/public/app/features/alerting/notification_edit_ctrl.ts @@ -0,0 +1,93 @@ +/// + +import angular from 'angular'; +import _ from 'lodash'; +import config from 'app/core/config'; +import {appEvents, coreModule} from 'app/core/core'; + +export class AlertNotificationEditCtrl { + theForm: any; + testSeverity: string = "critical"; + notifiers: any; + notifierTemplateId: string; + + model: any; + defaults: any = { + type: 'email', + settings: { + httpMethod: 'POST', + autoResolve: true, + }, + isDefault: false + }; + + /** @ngInject */ + constructor(private $routeParams, private backendSrv, private $location, private $templateCache) { + this.backendSrv.get(`/api/alert-notifiers`).then(notifiers => { + this.notifiers = notifiers; + + // add option templates + for (let notifier of this.notifiers) { + this.$templateCache.put(this.getNotifierTemplateId(notifier.type), notifier.optionsTemplate); + } + + if (!this.$routeParams.id) { + return this.model; + } + + return this.backendSrv.get(`/api/alert-notifications/${this.$routeParams.id}`).then(result => { + return result; + }); + }).then(model => { + this.model = model; + this.notifierTemplateId = this.getNotifierTemplateId(this.model.type); + }); + } + + save() { + if (!this.theForm.$valid) { + return; + } + + if (this.model.id) { + this.backendSrv.put(`/api/alert-notifications/${this.model.id}`, this.model).then(res => { + this.model = res; + appEvents.emit('alert-success', ['Notification updated', '']); + }); + } else { + this.backendSrv.post(`/api/alert-notifications`, this.model).then(res => { + appEvents.emit('alert-success', ['Notification created', '']); + this.$location.path('alerting/notifications'); + }); + } + } + + getNotifierTemplateId(type) { + return `notifier-options-${type}`; + } + + typeChanged() { + this.model.settings = {}; + this.notifierTemplateId = this.getNotifierTemplateId(this.model.type); + } + + testNotification() { + if (!this.theForm.$valid) { + return; + } + + var payload = { + name: this.model.name, + type: this.model.type, + settings: this.model.settings, + }; + + this.backendSrv.post(`/api/alert-notifications/test`, payload) + .then(res => { + appEvents.emit('alert-succes', ['Test notification sent', '']); + }); + } +} + +coreModule.controller('AlertNotificationEditCtrl', AlertNotificationEditCtrl); + diff --git a/public/app/features/alerting/notifications_list_ctrl.ts b/public/app/features/alerting/notifications_list_ctrl.ts new file mode 100644 index 00000000000..705f3a27c4f --- /dev/null +++ b/public/app/features/alerting/notifications_list_ctrl.ts @@ -0,0 +1,34 @@ +/// + +import angular from 'angular'; +import _ from 'lodash'; +import coreModule from '../../core/core_module'; +import config from 'app/core/config'; + +export class AlertNotificationsListCtrl { + + notifications: any; + + /** @ngInject */ + constructor(private backendSrv, private $scope) { + this.loadNotifications(); + } + + loadNotifications() { + this.backendSrv.get(`/api/alert-notifications`).then(result => { + this.notifications = result; + }); + } + + deleteNotification(id) { + this.backendSrv.delete(`/api/alert-notifications/${id}`).then(() => { + this.notifications = this.notifications.filter(notification => { + return notification.id !== id; + }); + }); + } +} + +coreModule.controller('AlertNotificationsListCtrl', AlertNotificationsListCtrl); + + diff --git a/public/app/features/alerting/partials/alert_howto.html b/public/app/features/alerting/partials/alert_howto.html new file mode 100644 index 00000000000..c62906f69b8 --- /dev/null +++ b/public/app/features/alerting/partials/alert_howto.html @@ -0,0 +1,30 @@ + + diff --git a/public/app/features/alerting/partials/alert_list.html b/public/app/features/alerting/partials/alert_list.html new file mode 100644 index 00000000000..35305b9bf03 --- /dev/null +++ b/public/app/features/alerting/partials/alert_list.html @@ -0,0 +1,69 @@ + + + +
    + + +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    + +
      +
    1. +
      +
      + +
      +
      +
      + +
      + + + {{alert.stateModel.text}} + for {{alert.newStateDateAgo}} +
      +
      + {{alert.executionError}} +
      +
      +
      +
      +
    2. +
    +
    + +
    + diff --git a/public/app/features/alerting/partials/alert_tab.html b/public/app/features/alerting/partials/alert_tab.html new file mode 100644 index 00000000000..8b11ec4ebc1 --- /dev/null +++ b/public/app/features/alerting/partials/alert_tab.html @@ -0,0 +1,179 @@ +
    + + +
    +
    +
    + {{ctrl.error}} +
    + +
    +
    Alert Config
    +
    + Name + + Evaluate every + +
    +
    + +
    +
    Conditions
    +
    +
    + + WHEN +
    +
    + + + OF +
    +
    + + +
    +
    + + + + +
    +
    + +
    +
    + +
    + +
    + +
    + +
    +
    + If no data or all values are null + SET STATE TO +
    + +
    +
    + +
    + If execution error or timeout + SET STATE TO +
    + +
    +
    + +
    + +
    +
    + +
    + Evaluating rule +
    + +
    + +
    +
    + +
    +
    Notifications
    +
    +
    + Send to + +  {{nc.name}}  + + + +
    +
    +
    + Message + +
    +
    + +
    + +
    + State history (last 50 state changes) +
    + +
    +
    + No state changes recorded +
    + +
    +
      +
    1. +
      +
      +
      +
      + + + {{ah.stateModel.text}} + {{ah.metrics}} +
      +
      + {{ah.time}} +
      +
      +
      +
      +
    2. +
    +
    +
    +
    +
    + +
    +
    + +
    +
    diff --git a/public/app/features/alerting/partials/notification_edit.html b/public/app/features/alerting/partials/notification_edit.html new file mode 100644 index 00000000000..dfdfb115f4b --- /dev/null +++ b/public/app/features/alerting/partials/notification_edit.html @@ -0,0 +1,54 @@ + + + + Notification channels + + + +
    + + +
    +
    +
    + Name + +
    +
    + Type +
    + +
    +
    +
    + + +
    +
    + +
    +
    + +
    +
    +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    diff --git a/public/app/features/alerting/partials/notifications_list.html b/public/app/features/alerting/partials/notifications_list.html new file mode 100644 index 00000000000..32ac4a44476 --- /dev/null +++ b/public/app/features/alerting/partials/notifications_list.html @@ -0,0 +1,43 @@ + + + +
    + + + + + + + + + + + + + +
    NameType
    + + {{notification.name}} + + + {{notification.type}} + + + default + + + + edit + + + + +
    + +
    diff --git a/public/app/features/alerting/specs/alert_tab_specs.ts b/public/app/features/alerting/specs/alert_tab_specs.ts new file mode 100644 index 00000000000..3c407297dee --- /dev/null +++ b/public/app/features/alerting/specs/alert_tab_specs.ts @@ -0,0 +1,20 @@ +import {describe, beforeEach, it, sinon, expect, angularMocks} from 'test/lib/common'; + +import {AlertTabCtrl} from '../alert_tab_ctrl'; +import helpers from '../../../../test/specs/helpers'; + +describe('AlertTabCtrl', () => { + var $scope = { + ctrl: {} + }; + + describe('with null parameters', () => { + it('can be created', () => { + var alertTab = new AlertTabCtrl($scope, null, null, null, null, null, null, null); + + expect(alertTab).to.not.be(null); + }); + }); +}); + + diff --git a/public/app/features/alerting/specs/threshold_mapper_specs.ts b/public/app/features/alerting/specs/threshold_mapper_specs.ts new file mode 100644 index 00000000000..1f42fb84840 --- /dev/null +++ b/public/app/features/alerting/specs/threshold_mapper_specs.ts @@ -0,0 +1,78 @@ +import {describe, beforeEach, it, sinon, expect} from 'test/lib/common'; + +import {ThresholdMapper} from '../threshold_mapper'; + +describe('ThresholdMapper', () => { + + describe('with greater than evaluator', () => { + it('can mapp query conditions to thresholds', () => { + var panel: any = { + type: 'graph', + alert: { + conditions: [ + { + type: 'query', + evaluator: { type: 'gt', params: [100], } + } + ] + } + }; + + var updated = ThresholdMapper.alertToGraphThresholds(panel); + expect(updated).to.be(true); + expect(panel.thresholds[0].op).to.be('gt'); + expect(panel.thresholds[0].value).to.be(100); + }); + }); + + describe('with outside range evaluator', () => { + it('can mapp query conditions to thresholds', () => { + var panel: any = { + type: 'graph', + alert: { + conditions: [ + { + type: 'query', + evaluator: { type: 'outside_range', params: [100, 200], } + } + ] + } + }; + + var updated = ThresholdMapper.alertToGraphThresholds(panel); + expect(updated).to.be(true); + expect(panel.thresholds[0].op).to.be('lt'); + expect(panel.thresholds[0].value).to.be(100); + + expect(panel.thresholds[1].op).to.be('gt'); + expect(panel.thresholds[1].value).to.be(200); + }); + }); + + describe('with inside range evaluator', () => { + it('can mapp query conditions to thresholds', () => { + var panel: any = { + type: 'graph', + alert: { + conditions: [ + { + type: 'query', + evaluator: { type: 'within_range', params: [100, 200], } + } + ] + } + }; + + var updated = ThresholdMapper.alertToGraphThresholds(panel); + expect(updated).to.be(true); + expect(panel.thresholds[0].op).to.be('gt'); + expect(panel.thresholds[0].value).to.be(100); + + expect(panel.thresholds[1].op).to.be('lt'); + expect(panel.thresholds[1].value).to.be(200); + }); + }); + +}); + + diff --git a/public/app/features/alerting/threshold_mapper.ts b/public/app/features/alerting/threshold_mapper.ts new file mode 100644 index 00000000000..b14f9a4d933 --- /dev/null +++ b/public/app/features/alerting/threshold_mapper.ts @@ -0,0 +1,72 @@ + +export class ThresholdMapper { + + static alertToGraphThresholds(panel) { + var alert = panel.alert; + + if (panel.type !== 'graph') { + return false; + } + + for (var i = 0; i < panel.alert.conditions.length; i++) { + let condition = panel.alert.conditions[i]; + if (condition.type !== 'query') { + continue; + } + + var evaluator = condition.evaluator; + var thresholds = panel.thresholds = []; + + switch (evaluator.type) { + case "gt": { + let value = evaluator.params[0]; + thresholds.push({value: value, op: 'gt'}); + break; + } + case "lt": { + let value = evaluator.params[0]; + thresholds.push({value: value, op: 'lt'}); + break; + } + case "outside_range": { + let value1 = evaluator.params[0]; + let value2 = evaluator.params[1]; + + if (value1 > value2) { + thresholds.push({value: value1, op: 'gt'}); + thresholds.push({value: value2, op: 'lt'}); + } else { + thresholds.push({value: value1, op: 'lt'}); + thresholds.push({value: value2, op: 'gt'}); + } + + break; + } + case "within_range": { + let value1 = evaluator.params[0]; + let value2 = evaluator.params[1]; + + if (value1 > value2) { + thresholds.push({value: value1, op: 'lt'}); + thresholds.push({value: value2, op: 'gt'}); + } else { + thresholds.push({value: value1, op: 'gt'}); + thresholds.push({value: value2, op: 'lt'}); + } + break; + } + } + break; + } + + for (var t of panel.thresholds) { + t.fill = true; + t.line = true; + t.colorMode = 'critical'; + } + + var updated = true; + return updated; + } + +} diff --git a/public/app/features/all.js b/public/app/features/all.js index c110bcff7cd..cd7adb49de6 100644 --- a/public/app/features/all.js +++ b/public/app/features/all.js @@ -2,13 +2,10 @@ define([ './panellinks/module', './dashlinks/module', './annotations/annotations_srv', - './templating/templateSrv', + './templating/all', './dashboard/all', './playlist/all', './snapshot/all', './panel/all', - './profile/profileCtrl', - './profile/changePasswordCtrl', - './profile/selectOrgCtrl', './styleguide/styleguide', ], function () {}); diff --git a/public/app/features/annotations/annotations_srv.js b/public/app/features/annotations/annotations_srv.js deleted file mode 100644 index b0022135ef5..00000000000 --- a/public/app/features/annotations/annotations_srv.js +++ /dev/null @@ -1,97 +0,0 @@ -define([ - 'angular', - 'lodash', - './editor_ctrl', -], function (angular, _) { - 'use strict'; - - var module = angular.module('grafana.services'); - - module.service('annotationsSrv', function($rootScope, $q, datasourceSrv, alertSrv, timeSrv) { - var promiseCached; - var list = []; - var self = this; - - this.init = function() { - $rootScope.onAppEvent('refresh', this.clearCache, $rootScope); - $rootScope.onAppEvent('dashboard-loaded', this.clearCache, $rootScope); - }; - - this.clearCache = function() { - promiseCached = null; - list = []; - }; - - this.getAnnotations = function(dashboard) { - if (dashboard.annotations.list.length === 0) { - return $q.when(null); - } - - if (promiseCached) { - return promiseCached; - } - - self.dashboard = dashboard; - var annotations = _.where(dashboard.annotations.list, {enable: true}); - - var range = timeSrv.timeRange(); - var rangeRaw = timeSrv.timeRange(false); - - var promises = _.map(annotations, function(annotation) { - if (annotation.snapshotData) { - self.receiveAnnotationResults(annotation.snapshotData); - return; - } - return datasourceSrv.get(annotation.datasource).then(function(datasource) { - var query = {range: range, rangeRaw: rangeRaw, annotation: annotation}; - return datasource.annotationQuery(query) - .then(self.receiveAnnotationResults) - .then(function(results) { - if (dashboard.snapshot) { - annotation.snapshotData = angular.copy(results); - } - }) - .then(null, errorHandler); - }, this); - }); - - promiseCached = $q.all(promises) - .then(function() { - return list; - }); - - return promiseCached; - }; - - this.receiveAnnotationResults = function(results) { - for (var i = 0; i < results.length; i++) { - self.addAnnotation(results[i]); - } - - return results; - }; - - this.addAnnotation = function(options) { - list.push({ - annotation: options.annotation, - min: options.time, - max: options.time, - eventType: options.annotation.name, - title: options.title, - tags: options.tags, - text: options.text, - score: 1 - }); - }; - - function errorHandler(err) { - console.log('Annotation error: ', err); - var message = err.message || "Annotation query failed"; - alertSrv.set('Annotations error', message,'error'); - } - - // Now init - this.init(); - }); - -}); diff --git a/public/app/features/annotations/annotations_srv.ts b/public/app/features/annotations/annotations_srv.ts new file mode 100644 index 00000000000..759e4500c7d --- /dev/null +++ b/public/app/features/annotations/annotations_srv.ts @@ -0,0 +1,141 @@ +/// + +import './editor_ctrl'; + +import angular from 'angular'; +import _ from 'lodash'; +import $ from 'jquery'; +import coreModule from 'app/core/core_module'; + +export class AnnotationsSrv { + globalAnnotationsPromise: any; + alertStatesPromise: any; + + /** @ngInject */ + constructor(private $rootScope, + private $q, + private datasourceSrv, + private backendSrv, + private timeSrv) { + $rootScope.onAppEvent('refresh', this.clearCache.bind(this), $rootScope); + $rootScope.onAppEvent('dashboard-initialized', this.clearCache.bind(this), $rootScope); + } + + clearCache() { + this.globalAnnotationsPromise = null; + this.alertStatesPromise = null; + } + + getAnnotations(options) { + return this.$q.all([ + this.getGlobalAnnotations(options), + this.getPanelAnnotations(options), + this.getAlertStates(options) + ]).then(results => { + + // combine the annotations and flatten results + var annotations = _.flattenDeep([results[0], results[1]]); + + // look for alert state for this panel + var alertState = _.find(results[2], {panelId: options.panel.id}); + + return { + annotations: annotations, + alertState: alertState, + }; + + }).catch(err => { + this.$rootScope.appEvent('alert-error', ['Annotations failed', (err.message || err)]); + }); + } + + getPanelAnnotations(options) { + var panel = options.panel; + var dashboard = options.dashboard; + + if (panel && panel.alert) { + return this.backendSrv.get('/api/annotations', { + from: options.range.from.valueOf(), + to: options.range.to.valueOf(), + limit: 100, + panelId: panel.id, + dashboardId: dashboard.id, + }).then(results => { + return this.translateQueryResult({iconColor: '#AA0000', name: 'panel-alert'}, results); + }); + } + + return this.$q.when([]); + } + + getAlertStates(options) { + if (!options.dashboard.id) { + return this.$q.when([]); + } + + // ignore if no alerts + if (options.panel && !options.panel.alert) { + return this.$q.when([]); + } + + if (options.range.raw.to !== 'now') { + return this.$q.when([]); + } + + if (this.alertStatesPromise) { + return this.alertStatesPromise; + } + + this.alertStatesPromise = this.backendSrv.get('/api/alerts/states-for-dashboard', {dashboardId: options.dashboard.id}); + return this.alertStatesPromise; + } + + getGlobalAnnotations(options) { + var dashboard = options.dashboard; + + if (dashboard.annotations.list.length === 0) { + return this.$q.when([]); + } + + if (this.globalAnnotationsPromise) { + return this.globalAnnotationsPromise; + } + + var annotations = _.filter(dashboard.annotations.list, {enable: true}); + var range = this.timeSrv.timeRange(); + + this.globalAnnotationsPromise = this.$q.all(_.map(annotations, annotation => { + if (annotation.snapshotData) { + return this.translateQueryResult(annotation, annotation.snapshotData); + } + + return this.datasourceSrv.get(annotation.datasource).then(datasource => { + // issue query against data source + return datasource.annotationQuery({range: range, rangeRaw: range.raw, annotation: annotation}); + }) + .then(results => { + // store response in annotation object if this is a snapshot call + if (dashboard.snapshot) { + annotation.snapshotData = angular.copy(results); + } + // translate result + return this.translateQueryResult(annotation, results); + }); + })); + + return this.globalAnnotationsPromise; + } + + translateQueryResult(annotation, results) { + for (var item of results) { + item.source = annotation; + item.min = item.time; + item.max = item.time; + item.scope = 1; + item.eventType = annotation.name; + } + return results; + } +} + +coreModule.service('annotationsSrv', AnnotationsSrv); diff --git a/public/app/features/annotations/editor_ctrl.js b/public/app/features/annotations/editor_ctrl.js deleted file mode 100644 index 8d3887ee757..00000000000 --- a/public/app/features/annotations/editor_ctrl.js +++ /dev/null @@ -1,75 +0,0 @@ -define([ - 'angular', - 'lodash', - 'jquery' -], -function (angular, _, $) { - 'use strict'; - - var module = angular.module('grafana.controllers'); - - module.controller('AnnotationsEditorCtrl', function($scope, datasourceSrv) { - var annotationDefaults = { - name: '', - datasource: null, - iconColor: 'rgba(255, 96, 96, 1)', - enable: true - }; - - $scope.init = function() { - $scope.mode = 'list'; - $scope.datasources = datasourceSrv.getAnnotationSources(); - $scope.annotations = $scope.dashboard.annotations.list; - $scope.reset(); - - $scope.$watch('mode', function(newVal) { - if (newVal === 'new') { $scope.reset(); } - }); - }; - - $scope.datasourceChanged = function() { - return datasourceSrv.get($scope.currentAnnotation.datasource).then(function(ds) { - $scope.currentDatasource = ds; - $scope.currentAnnotation.datasource = ds.name; - }); - }; - - $scope.edit = function(annotation) { - $scope.currentAnnotation = annotation; - $scope.currentIsNew = false; - $scope.datasourceChanged(); - $scope.mode = 'edit'; - - $(".tooltip.in").remove(); - }; - - $scope.reset = function() { - $scope.currentAnnotation = angular.copy(annotationDefaults); - $scope.currentIsNew = true; - $scope.datasourceChanged(); - }; - - $scope.update = function() { - $scope.reset(); - $scope.mode = 'list'; - $scope.broadcastRefresh(); - }; - - $scope.add = function() { - $scope.annotations.push($scope.currentAnnotation); - $scope.reset(); - $scope.mode = 'list'; - $scope.updateSubmenuVisibility(); - $scope.broadcastRefresh(); - }; - - $scope.removeAnnotation = function(annotation) { - var index = _.indexOf($scope.annotations, annotation); - $scope.annotations.splice(index, 1); - $scope.updateSubmenuVisibility(); - $scope.broadcastRefresh(); - }; - - }); - -}); diff --git a/public/app/features/annotations/editor_ctrl.ts b/public/app/features/annotations/editor_ctrl.ts new file mode 100644 index 00000000000..cb76045dbec --- /dev/null +++ b/public/app/features/annotations/editor_ctrl.ts @@ -0,0 +1,82 @@ +/// + +import angular from 'angular'; +import _ from 'lodash'; +import $ from 'jquery'; +import coreModule from 'app/core/core_module'; + +export class AnnotationsEditorCtrl { + mode: any; + datasources: any; + annotations: any; + currentAnnotation: any; + currentDatasource: any; + currentIsNew: any; + + annotationDefaults: any = { + name: '', + datasource: null, + iconColor: 'rgba(255, 96, 96, 1)', + enable: true + }; + + /** @ngInject */ + constructor(private $scope, private datasourceSrv) { + $scope.ctrl = this; + + this.mode = 'list'; + this.datasources = datasourceSrv.getAnnotationSources(); + this.annotations = $scope.dashboard.annotations.list; + this.reset(); + + $scope.$watch('mode', newVal => { + if (newVal === 'new') { + this.reset(); + } + }); + } + + datasourceChanged() { + return this.datasourceSrv.get(this.currentAnnotation.datasource).then(ds => { + this.currentDatasource = ds; + }); + } + + edit(annotation) { + this.currentAnnotation = annotation; + this.currentIsNew = false; + this.datasourceChanged(); + this.mode = 'edit'; + $(".tooltip.in").remove(); + } + + reset() { + this.currentAnnotation = angular.copy(this.annotationDefaults); + this.currentAnnotation.datasource = this.datasources[0].name; + this.currentIsNew = true; + this.datasourceChanged(); + } + + update() { + this.reset(); + this.mode = 'list'; + this.$scope.broadcastRefresh(); + }; + + add() { + this.annotations.push(this.currentAnnotation); + this.reset(); + this.mode = 'list'; + this.$scope.broadcastRefresh(); + this.$scope.dashboard.updateSubmenuVisibility(); + }; + + removeAnnotation(annotation) { + var index = _.indexOf(this.annotations, annotation); + this.annotations.splice(index, 1); + this.$scope.updateSubmenuVisibility(); + this.$scope.broadcastRefresh(); + } +} + +coreModule.controller('AnnotationsEditorCtrl', AnnotationsEditorCtrl); diff --git a/public/app/features/annotations/partials/editor.html b/public/app/features/annotations/partials/editor.html index 702d8921bef..0bfc8bb2028 100644 --- a/public/app/features/annotations/partials/editor.html +++ b/public/app/features/annotations/partials/editor.html @@ -1,4 +1,4 @@ -
    +

    Annotations @@ -6,16 +6,16 @@ @@ -26,27 +26,27 @@

    -
    -
    +
    +
    No annotations defined
    - + - - + + @@ -54,43 +54,43 @@
      {{annotation.name}} - + Edit - +
    -
    + -
    +
    Name - +
    Datasource
    - +
    - +
    - +
    - - + +
    diff --git a/public/app/features/dashboard/ad_hoc_filters.ts b/public/app/features/dashboard/ad_hoc_filters.ts new file mode 100644 index 00000000000..f962f8ca2f4 --- /dev/null +++ b/public/app/features/dashboard/ad_hoc_filters.ts @@ -0,0 +1,171 @@ +/// + +import _ from 'lodash'; +import angular from 'angular'; +import coreModule from 'app/core/core_module'; + +export class AdHocFiltersCtrl { + segments: any; + variable: any; + removeTagFilterSegment: any; + + /** @ngInject */ + constructor(private uiSegmentSrv, private datasourceSrv, private $q, private templateSrv, private $rootScope) { + this.removeTagFilterSegment = uiSegmentSrv.newSegment({fake: true, value: '-- remove filter --'}); + this.buildSegmentModel(); + } + + buildSegmentModel() { + this.segments = []; + + if (this.variable.value && !_.isArray(this.variable.value)) { + } + + for (let tag of this.variable.filters) { + if (this.segments.length > 0) { + this.segments.push(this.uiSegmentSrv.newCondition('AND')); + } + + if (tag.key !== undefined && tag.value !== undefined) { + this.segments.push(this.uiSegmentSrv.newKey(tag.key)); + this.segments.push(this.uiSegmentSrv.newOperator(tag.operator)); + this.segments.push(this.uiSegmentSrv.newKeyValue(tag.value)); + } + } + + this.segments.push(this.uiSegmentSrv.newPlusButton()); + } + + getOptions(segment, index) { + if (segment.type === 'operator') { + return this.$q.when(this.uiSegmentSrv.newOperators(['=', '!=', '<', '>', '=~', '!~'])); + } + + if (segment.type === 'condition') { + return this.$q.when([this.uiSegmentSrv.newSegment('AND')]); + } + + return this.datasourceSrv.get(this.variable.datasource).then(ds => { + var options: any = {}; + var promise = null; + + if (segment.type !== 'value') { + promise = ds.getTagKeys(); + } else { + options.key = this.segments[index-2].value; + promise = ds.getTagValues(options); + } + + return promise.then(results => { + results = _.map(results, segment => { + return this.uiSegmentSrv.newSegment({value: segment.text}); + }); + + // add remove option for keys + if (segment.type === 'key') { + results.splice(0, 0, angular.copy(this.removeTagFilterSegment)); + } + return results; + }); + }); + } + + segmentChanged(segment, index) { + this.segments[index] = segment; + + // handle remove tag condition + if (segment.value === this.removeTagFilterSegment.value) { + this.segments.splice(index, 3); + if (this.segments.length === 0) { + this.segments.push(this.uiSegmentSrv.newPlusButton()); + } else if (this.segments.length > 2) { + this.segments.splice(Math.max(index-1, 0), 1); + if (this.segments[this.segments.length-1].type !== 'plus-button') { + this.segments.push(this.uiSegmentSrv.newPlusButton()); + } + } + } else { + if (segment.type === 'plus-button') { + if (index > 2) { + this.segments.splice(index, 0, this.uiSegmentSrv.newCondition('AND')); + } + this.segments.push(this.uiSegmentSrv.newOperator('=')); + this.segments.push(this.uiSegmentSrv.newFake('select tag value', 'value', 'query-segment-value')); + segment.type = 'key'; + segment.cssClass = 'query-segment-key'; + } + + if ((index+1) === this.segments.length) { + this.segments.push(this.uiSegmentSrv.newPlusButton()); + } + } + + this.updateVariableModel(); + } + + updateVariableModel() { + var filters = []; + var filterIndex = -1; + var operator = ""; + var hasFakes = false; + + this.segments.forEach(segment => { + if (segment.type === 'value' && segment.fake) { + hasFakes = true; + return; + } + + switch (segment.type) { + case 'key': { + filters.push({key: segment.value}); + filterIndex += 1; + break; + } + case 'value': { + filters[filterIndex].value = segment.value; + break; + } + case 'operator': { + filters[filterIndex].operator = segment.value; + break; + } + case 'condition': { + filters[filterIndex].condition = segment.value; + break; + } + } + }); + + if (hasFakes) { + return; + } + + this.variable.setFilters(filters); + this.$rootScope.$emit('template-variable-value-updated'); + this.$rootScope.$broadcast('refresh'); + } +} + +var template = ` +
    +
    + +
    +
    +`; + +export function adHocFiltersComponent() { + return { + restrict: 'E', + template: template, + controller: AdHocFiltersCtrl, + bindToController: true, + controllerAs: 'ctrl', + scope: { + variable: "=" + } + }; +} + +coreModule.directive('adHocFilters', adHocFiltersComponent); diff --git a/public/app/features/dashboard/alerting_srv.ts b/public/app/features/dashboard/alerting_srv.ts new file mode 100644 index 00000000000..0e1c160b726 --- /dev/null +++ b/public/app/features/dashboard/alerting_srv.ts @@ -0,0 +1,22 @@ +/// + +import config from 'app/core/config'; +import angular from 'angular'; +import moment from 'moment'; +import _ from 'lodash'; + +import coreModule from 'app/core/core_module'; + +export class AlertingSrv { + dashboard: any; + alerts: any[]; + + init(dashboard, alerts) { + this.dashboard = dashboard; + this.alerts = alerts || []; + } +} + + +coreModule.service('alertingSrv', AlertingSrv); + diff --git a/public/app/features/dashboard/all.js b/public/app/features/dashboard/all.js index d110019add6..976bff07058 100644 --- a/public/app/features/dashboard/all.js +++ b/public/app/features/dashboard/all.js @@ -1,20 +1,24 @@ define([ - './dashboardCtrl', + './dashboard_ctrl', + './alerting_srv', './dashboardLoaderSrv', './dashnav/dashnav', './submenu/submenu', './saveDashboardAsCtrl', - './rowCtrl', './shareModalCtrl', './shareSnapshotCtrl', - './dashboardSrv', - './keybindings', + './dashboard_srv', './viewStateSrv', './timeSrv', './unsavedChangesSrv', './timepicker/timepicker', './graphiteImportCtrl', - './dynamicDashboardSrv', - './importCtrl', './impression_store', + './upload', + './import/dash_import', + './export/export_modal', + './dash_list_ctrl', + './ad_hoc_filters', + './row/row_ctrl', + './repeat_option/repeat_option', ], function () {}); diff --git a/public/app/features/dashboard/dash_list_ctrl.ts b/public/app/features/dashboard/dash_list_ctrl.ts new file mode 100644 index 00000000000..f08d7507e65 --- /dev/null +++ b/public/app/features/dashboard/dash_list_ctrl.ts @@ -0,0 +1,11 @@ +/// + +import coreModule from 'app/core/core_module'; + +export class DashListCtrl { + /** @ngInject */ + constructor() { + } +} + +coreModule.controller('DashListCtrl', DashListCtrl); diff --git a/public/app/features/dashboard/dashboardCtrl.js b/public/app/features/dashboard/dashboardCtrl.js deleted file mode 100644 index ea0d91019b8..00000000000 --- a/public/app/features/dashboard/dashboardCtrl.js +++ /dev/null @@ -1,143 +0,0 @@ -define([ - 'angular', - 'jquery', - 'app/core/config', - 'moment', -], -function (angular, $, config, moment) { - "use strict"; - - var module = angular.module('grafana.controllers'); - - module.controller('DashboardCtrl', function( - $scope, - $rootScope, - dashboardKeybindings, - timeSrv, - templateValuesSrv, - dynamicDashboardSrv, - dashboardSrv, - unsavedChangesSrv, - dashboardViewStateSrv, - contextSrv, - $timeout) { - - $scope.editor = { index: 0 }; - $scope.panels = config.panels; - - var resizeEventTimeout; - - this.init = function(dashboard) { - $scope.resetRow(); - $scope.registerWindowResizeEvent(); - $scope.onAppEvent('show-json-editor', $scope.showJsonEditor); - $scope.setupDashboard(dashboard); - }; - - $scope.setupDashboard = function(data) { - $rootScope.performance.dashboardLoadStart = new Date().getTime(); - $rootScope.performance.panelsInitialized = 0; - $rootScope.performance.panelsRendered = 0; - - var dashboard = dashboardSrv.create(data.dashboard, data.meta); - dashboardSrv.setCurrent(dashboard); - - // init services - timeSrv.init(dashboard); - - // template values service needs to initialize completely before - // the rest of the dashboard can load - templateValuesSrv.init(dashboard).finally(function() { - dynamicDashboardSrv.init(dashboard); - unsavedChangesSrv.init(dashboard, $scope); - - $scope.dashboard = dashboard; - $scope.dashboardMeta = dashboard.meta; - $scope.dashboardViewState = dashboardViewStateSrv.create($scope); - - dashboardKeybindings.shortcuts($scope); - - $scope.updateSubmenuVisibility(); - $scope.setWindowTitleAndTheme(); - - $scope.appEvent("dashboard-loaded", $scope.dashboard); - }).catch(function(err) { - if (err.data && err.data.message) { err.message = err.data.message; } - $scope.appEvent("alert-error", ['Dashboard init failed', 'Template variables could not be initialized: ' + err.message]); - }); - }; - - $scope.updateSubmenuVisibility = function() { - $scope.submenuEnabled = $scope.dashboard.isSubmenuFeaturesEnabled(); - }; - - $scope.setWindowTitleAndTheme = function() { - window.document.title = config.window_title_prefix + $scope.dashboard.title; - }; - - $scope.broadcastRefresh = function() { - $rootScope.performance.panelsRendered = 0; - $rootScope.$broadcast('refresh'); - }; - - $scope.addRow = function(dash, row) { - dash.rows.push(row); - }; - - $scope.addRowDefault = function() { - $scope.resetRow(); - $scope.row.title = 'New row'; - $scope.addRow($scope.dashboard, $scope.row); - }; - - $scope.resetRow = function() { - $scope.row = { - title: '', - height: '250px', - editable: true, - }; - }; - - $scope.showJsonEditor = function(evt, options) { - var editScope = $rootScope.$new(); - editScope.object = options.object; - editScope.updateHandler = options.updateHandler; - $scope.appEvent('show-dash-editor', { src: 'public/app/partials/edit_json.html', scope: editScope }); - }; - - $scope.onDrop = function(panelId, row, dropTarget) { - var info = $scope.dashboard.getPanelInfoById(panelId); - if (dropTarget) { - var dropInfo = $scope.dashboard.getPanelInfoById(dropTarget.id); - dropInfo.row.panels[dropInfo.index] = info.panel; - info.row.panels[info.index] = dropTarget; - var dragSpan = info.panel.span; - info.panel.span = dropTarget.span; - dropTarget.span = dragSpan; - } - else { - info.row.panels.splice(info.index, 1); - info.panel.span = 12 - $scope.dashboard.rowSpan(row); - row.panels.push(info.panel); - } - - $rootScope.$broadcast('render'); - }; - - $scope.registerWindowResizeEvent = function() { - angular.element(window).bind('resize', function() { - $timeout.cancel(resizeEventTimeout); - resizeEventTimeout = $timeout(function() { $scope.$broadcast('render'); }, 200); - }); - $scope.$on('$destroy', function() { - angular.element(window).unbind('resize'); - }); - }; - - $scope.formatDate = function(date) { - return moment(date).format('MMM Do YYYY, h:mm:ss a'); - }; - - }); - -}); diff --git a/public/app/features/dashboard/dashboardLoaderSrv.js b/public/app/features/dashboard/dashboardLoaderSrv.js index 1af0894b462..c6df45f53b2 100644 --- a/public/app/features/dashboard/dashboardLoaderSrv.js +++ b/public/app/features/dashboard/dashboardLoaderSrv.js @@ -47,6 +47,7 @@ function (angular, moment, _, $, kbn, dateMath, impressionStore) { } promise.then(function(result) { + if (result.meta.dashboardNotFound !== true) { impressionStore.impressions.addDashboardImpression(result.dashboard.id); } diff --git a/public/app/features/dashboard/dashboardSrv.js b/public/app/features/dashboard/dashboardSrv.js deleted file mode 100644 index b3194868d97..00000000000 --- a/public/app/features/dashboard/dashboardSrv.js +++ /dev/null @@ -1,488 +0,0 @@ -define([ - 'angular', - 'jquery', - 'lodash', - 'moment', -], -function (angular, $, _, moment) { - 'use strict'; - - var module = angular.module('grafana.services'); - - module.factory('dashboardSrv', function() { - - function DashboardModel (data, meta) { - if (!data) { - data = {}; - } - - if (!data.id && data.version) { - data.schemaVersion = data.version; - } - - this.id = data.id || null; - this.title = data.title || 'No Title'; - this.originalTitle = this.title; - this.tags = data.tags || []; - this.style = data.style || "dark"; - this.timezone = data.timezone || 'browser'; - this.editable = data.editable !== false; - this.hideControls = data.hideControls || false; - this.sharedCrosshair = data.sharedCrosshair || false; - this.rows = data.rows || []; - this.time = data.time || { from: 'now-6h', to: 'now' }; - this.timepicker = data.timepicker || {}; - this.templating = this._ensureListExist(data.templating); - this.annotations = this._ensureListExist(data.annotations); - this.refresh = data.refresh; - this.snapshot = data.snapshot; - this.schemaVersion = data.schemaVersion || 0; - this.version = data.version || 0; - this.links = data.links || []; - this._updateSchema(data); - this._initMeta(meta); - } - - var p = DashboardModel.prototype; - - p._initMeta = function(meta) { - meta = meta || {}; - - meta.canShare = meta.canShare !== false; - meta.canSave = meta.canSave !== false; - meta.canStar = meta.canStar !== false; - meta.canEdit = meta.canEdit !== false; - - if (!this.editable) { - meta.canEdit = false; - meta.canDelete = false; - meta.canSave = false; - this.hideControls = true; - } - - this.meta = meta; - }; - - // cleans meta data and other non peristent state - p.getSaveModelClone = function() { - var copy = angular.copy(this); - delete copy.meta; - return copy; - }; - - p._ensureListExist = function (data) { - if (!data) { data = {}; } - if (!data.list) { data.list = []; } - return data; - }; - - p.getNextPanelId = function() { - var i, j, row, panel, max = 0; - for (i = 0; i < this.rows.length; i++) { - row = this.rows[i]; - for (j = 0; j < row.panels.length; j++) { - panel = row.panels[j]; - if (panel.id > max) { max = panel.id; } - } - } - return max + 1; - }; - - p.forEachPanel = function(callback) { - var i, j, row; - for (i = 0; i < this.rows.length; i++) { - row = this.rows[i]; - for (j = 0; j < row.panels.length; j++) { - callback(row.panels[j], j, row, i); - } - } - }; - - p.getPanelById = function(id) { - for (var i = 0; i < this.rows.length; i++) { - var row = this.rows[i]; - for (var j = 0; j < row.panels.length; j++) { - var panel = row.panels[j]; - if (panel.id === id) { - return panel; - } - } - } - return null; - }; - - p.rowSpan = function(row) { - return _.reduce(row.panels, function(p,v) { - return p + v.span; - },0); - }; - - p.addPanel = function(panel, row) { - var rowSpan = this.rowSpan(row); - var panelCount = row.panels.length; - var space = (12 - rowSpan) - panel.span; - panel.id = this.getNextPanelId(); - - // try to make room of there is no space left - if (space <= 0) { - if (panelCount === 1) { - row.panels[0].span = 6; - panel.span = 6; - } - else if (panelCount === 2) { - row.panels[0].span = 4; - row.panels[1].span = 4; - panel.span = 4; - } - } - - row.panels.push(panel); - }; - - p.isSubmenuFeaturesEnabled = function() { - var visableTemplates = _.filter(this.templating.list, function(template) { - return template.hideVariable === undefined || template.hideVariable === false; - }); - - return visableTemplates.length > 0 || this.annotations.list.length > 0 || this.links.length > 0; - }; - - p.getPanelInfoById = function(panelId) { - var result = {}; - _.each(this.rows, function(row) { - _.each(row.panels, function(panel, index) { - if (panel.id === panelId) { - result.panel = panel; - result.row = row; - result.index = index; - } - }); - }); - - if (!result.panel) { - return null; - } - - return result; - }; - - p.duplicatePanel = function(panel, row) { - var rowIndex = _.indexOf(this.rows, row); - var newPanel = angular.copy(panel); - newPanel.id = this.getNextPanelId(); - - delete newPanel.repeat; - delete newPanel.repeatIteration; - delete newPanel.repeatPanelId; - delete newPanel.scopedVars; - - var currentRow = this.rows[rowIndex]; - currentRow.panels.push(newPanel); - return newPanel; - }; - - p.formatDate = function(date, format) { - date = moment.isMoment(date) ? date : moment(date); - format = format || 'YYYY-MM-DD HH:mm:ss'; - - return this.timezone === 'browser' ? - moment(date).format(format) : - moment.utc(date).format(format); - }; - - p.getRelativeTime = function(date) { - date = moment.isMoment(date) ? date : moment(date); - - return this.timezone === 'browser' ? - moment(date).fromNow() : - moment.utc(date).fromNow(); - }; - - p.getNextQueryLetter = function(panel) { - var letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; - - return _.find(letters, function(refId) { - return _.every(panel.targets, function(other) { - return other.refId !== refId; - }); - }); - }; - - p._updateSchema = function(old) { - var i, j, k; - var oldVersion = this.schemaVersion; - var panelUpgrades = []; - this.schemaVersion = 12; - - if (oldVersion === this.schemaVersion) { - return; - } - - // version 2 schema changes - if (oldVersion < 2) { - - if (old.services) { - if (old.services.filter) { - this.time = old.services.filter.time; - this.templating.list = old.services.filter.list || []; - } - delete this.services; - } - - panelUpgrades.push(function(panel) { - // rename panel type - if (panel.type === 'graphite') { - panel.type = 'graph'; - } - - if (panel.type !== 'graph') { - return; - } - - if (_.isBoolean(panel.legend)) { panel.legend = { show: panel.legend }; } - - if (panel.grid) { - if (panel.grid.min) { - panel.grid.leftMin = panel.grid.min; - delete panel.grid.min; - } - - if (panel.grid.max) { - panel.grid.leftMax = panel.grid.max; - delete panel.grid.max; - } - } - - if (panel.y_format) { - panel.y_formats[0] = panel.y_format; - delete panel.y_format; - } - - if (panel.y2_format) { - panel.y_formats[1] = panel.y2_format; - delete panel.y2_format; - } - }); - } - - // schema version 3 changes - if (oldVersion < 3) { - // ensure panel ids - var maxId = this.getNextPanelId(); - panelUpgrades.push(function(panel) { - if (!panel.id) { - panel.id = maxId; - maxId += 1; - } - }); - } - - // schema version 4 changes - if (oldVersion < 4) { - // move aliasYAxis changes - panelUpgrades.push(function(panel) { - if (panel.type !== 'graph') { return; } - _.each(panel.aliasYAxis, function(value, key) { - panel.seriesOverrides = [{ alias: key, yaxis: value }]; - }); - delete panel.aliasYAxis; - }); - } - - if (oldVersion < 6) { - // move pulldowns to new schema - var annotations = _.findWhere(old.pulldowns, { type: 'annotations' }); - - if (annotations) { - this.annotations = { - list: annotations.annotations || [], - }; - } - - // update template variables - for (i = 0 ; i < this.templating.list.length; i++) { - var variable = this.templating.list[i]; - if (variable.datasource === void 0) { variable.datasource = null; } - if (variable.type === 'filter') { variable.type = 'query'; } - if (variable.type === void 0) { variable.type = 'query'; } - if (variable.allFormat === void 0) { variable.allFormat = 'glob'; } - } - } - - if (oldVersion < 7) { - if (old.nav && old.nav.length) { - this.timepicker = old.nav[0]; - delete this.nav; - } - - // ensure query refIds - panelUpgrades.push(function(panel) { - _.each(panel.targets, function(target) { - if (!target.refId) { - target.refId = this.getNextQueryLetter(panel); - } - }, this); - }); - } - - if (oldVersion < 8) { - panelUpgrades.push(function(panel) { - _.each(panel.targets, function(target) { - // update old influxdb query schema - if (target.fields && target.tags && target.groupBy) { - if (target.rawQuery) { - delete target.fields; - delete target.fill; - } else { - target.select = _.map(target.fields, function(field) { - var parts = []; - parts.push({type: 'field', params: [field.name]}); - parts.push({type: field.func, params: []}); - if (field.mathExpr) { - parts.push({type: 'math', params: [field.mathExpr]}); - } - if (field.asExpr) { - parts.push({type: 'alias', params: [field.asExpr]}); - } - return parts; - }); - delete target.fields; - _.each(target.groupBy, function(part) { - if (part.type === 'time' && part.interval) { - part.params = [part.interval]; - delete part.interval; - } - if (part.type === 'tag' && part.key) { - part.params = [part.key]; - delete part.key; - } - }); - - if (target.fill) { - target.groupBy.push({type: 'fill', params: [target.fill]}); - delete target.fill; - } - } - } - }); - }); - } - - // schema version 9 changes - if (oldVersion < 9) { - // move aliasYAxis changes - panelUpgrades.push(function(panel) { - if (panel.type !== 'singlestat' && panel.thresholds !== "") { return; } - - if (panel.thresholds) { - var k = panel.thresholds.split(","); - - if (k.length >= 3) { - k.shift(); - panel.thresholds = k.join(","); - } - } - }); - } - - // schema version 10 changes - if (oldVersion < 10) { - // move aliasYAxis changes - panelUpgrades.push(function(panel) { - if (panel.type !== 'table') { return; } - - _.each(panel.styles, function(style) { - if (style.thresholds && style.thresholds.length >= 3) { - var k = style.thresholds; - k.shift(); - style.thresholds = k; - } - }); - }); - } - - if (oldVersion < 12) { - // update template variables - _.each(this.templating.list, function(templateVariable) { - if (templateVariable.refresh) { templateVariable.refresh = 1; } - if (!templateVariable.refresh) { templateVariable.refresh = 0; } - if (templateVariable.hideVariable) { - templateVariable.hide = 2; - } else if (templateVariable.hideLabel) { - templateVariable.hide = 1; - } else { - templateVariable.hide = 0; - } - }); - } - - if (oldVersion < 12) { - // update graph yaxes changes - panelUpgrades.push(function(panel) { - if (panel.type !== 'graph') { return; } - if (!panel.yaxes) { - panel.yaxes = [ - { - show: panel['y-axis'], - min: panel.grid.leftMin, - max: panel.grid.leftMax, - logBase: panel.grid.leftLogBase, - format: panel.y_formats[0], - label: panel.leftYAxisLabel, - }, - { - show: panel['y-axis'], - min: panel.grid.rightMin, - max: panel.grid.rightMax, - logBase: panel.grid.rightLogBase, - format: panel.y_formats[1], - label: panel.rightYAxisLabel, - } - ]; - - panel.xaxis = { - show: panel['x-axis'], - }; - - delete panel.grid.leftMin; - delete panel.grid.leftMax; - delete panel.grid.leftLogBase; - delete panel.grid.rightMin; - delete panel.grid.rightMax; - delete panel.grid.rightLogBase; - delete panel.y_formats; - delete panel.leftYAxisLabel; - delete panel.rightYAxisLabel; - delete panel['y-axis']; - delete panel['x-axis']; - } - }); - } - - if (panelUpgrades.length === 0) { - return; - } - - for (i = 0; i < this.rows.length; i++) { - var row = this.rows[i]; - for (j = 0; j < row.panels.length; j++) { - for (k = 0; k < panelUpgrades.length; k++) { - panelUpgrades[k].call(this, row.panels[j]); - } - } - } - }; - - return { - create: function(dashboard, meta) { - return new DashboardModel(dashboard, meta); - }, - setCurrent: function(dashboard) { - this.currentDashboard = dashboard; - }, - getCurrent: function() { - return this.currentDashboard; - }, - }; - }); -}); diff --git a/public/app/features/dashboard/dashboard_ctrl.ts b/public/app/features/dashboard/dashboard_ctrl.ts new file mode 100644 index 00000000000..c07f84e820c --- /dev/null +++ b/public/app/features/dashboard/dashboard_ctrl.ts @@ -0,0 +1,140 @@ +/// + +import config from 'app/core/config'; +import angular from 'angular'; +import moment from 'moment'; +import _ from 'lodash'; + +import coreModule from 'app/core/core_module'; + +export class DashboardCtrl { + + /** @ngInject */ + constructor( + private $scope, + private $rootScope, + keybindingSrv, + timeSrv, + variableSrv, + alertingSrv, + dashboardSrv, + unsavedChangesSrv, + dynamicDashboardSrv, + dashboardViewStateSrv, + contextSrv, + alertSrv, + $timeout) { + + $scope.editor = { index: 0 }; + + var resizeEventTimeout; + + $scope.setupDashboard = function(data) { + try { + $scope.setupDashboardInternal(data); + } catch (err) { + $scope.onInitFailed(err, 'Dashboard init failed', true); + } + }; + + $scope.setupDashboardInternal = function(data) { + var dashboard = dashboardSrv.create(data.dashboard, data.meta); + dashboardSrv.setCurrent(dashboard); + + // init services + timeSrv.init(dashboard); + alertingSrv.init(dashboard, data.alerts); + + // template values service needs to initialize completely before + // the rest of the dashboard can load + variableSrv.init(dashboard) + // template values failes are non fatal + .catch($scope.onInitFailed.bind(this, 'Templating init failed', false)) + // continue + .finally(function() { + dynamicDashboardSrv.init(dashboard); + dynamicDashboardSrv.process(); + + unsavedChangesSrv.init(dashboard, $scope); + + $scope.dashboard = dashboard; + $scope.dashboardMeta = dashboard.meta; + $scope.dashboardViewState = dashboardViewStateSrv.create($scope); + + keybindingSrv.setupDashboardBindings($scope, dashboard); + + $scope.dashboard.updateSubmenuVisibility(); + $scope.setWindowTitleAndTheme(); + + $scope.appEvent("dashboard-initialized", $scope.dashboard); + }) + .catch($scope.onInitFailed.bind(this, 'Dashboard init failed', true)); + }; + + $scope.onInitFailed = function(msg, fatal, err) { + console.log(msg, err); + + if (err.data && err.data.message) { + err.message = err.data.message; + } else if (!err.message) { + err = {message: err.toString()}; + } + + $scope.appEvent("alert-error", [msg, err.message]); + + // protect against recursive fallbacks + if (fatal && !$scope.loadedFallbackDashboard) { + $scope.loadedFallbackDashboard = true; + $scope.setupDashboard({dashboard: {title: 'Dashboard Init failed'}}); + } + }; + + $scope.templateVariableUpdated = function() { + dynamicDashboardSrv.process(); + }; + + $scope.setWindowTitleAndTheme = function() { + window.document.title = config.window_title_prefix + $scope.dashboard.title; + }; + + $scope.broadcastRefresh = function() { + $rootScope.$broadcast('refresh'); + }; + + $scope.addRowDefault = function() { + $scope.dashboard.addEmptyRow(); + }; + + $scope.showJsonEditor = function(evt, options) { + var editScope = $rootScope.$new(); + editScope.object = options.object; + editScope.updateHandler = options.updateHandler; + $scope.appEvent('show-dash-editor', { src: 'public/app/partials/edit_json.html', scope: editScope }); + }; + + $scope.registerWindowResizeEvent = function() { + angular.element(window).bind('resize', function() { + $timeout.cancel(resizeEventTimeout); + resizeEventTimeout = $timeout(function() { $scope.$broadcast('render'); }, 200); + }); + + $scope.$on('$destroy', function() { + angular.element(window).unbind('resize'); + $scope.dashboard.destroy(); + }); + }; + + $scope.timezoneChanged = function() { + $rootScope.$broadcast("refresh"); + }; + } + + init(dashboard) { + this.$scope.onAppEvent('show-json-editor', this.$scope.showJsonEditor); + this.$scope.onAppEvent('template-variable-value-updated', this.$scope.templateVariableUpdated); + this.$scope.setupDashboard(dashboard); + this.$scope.registerWindowResizeEvent(); + } +} + +coreModule.controller('DashboardCtrl', DashboardCtrl); diff --git a/public/app/features/dashboard/dashboard_srv.ts b/public/app/features/dashboard/dashboard_srv.ts new file mode 100644 index 00000000000..5939ff83a15 --- /dev/null +++ b/public/app/features/dashboard/dashboard_srv.ts @@ -0,0 +1,118 @@ +/// + +import _ from 'lodash'; +import coreModule from 'app/core/core_module'; +import {DashboardModel} from './model'; + +export class DashboardSrv { + dash: any; + + /** @ngInject */ + constructor(private backendSrv, private $rootScope, private $location) { + } + + create(dashboard, meta) { + return new DashboardModel(dashboard, meta); + } + + setCurrent(dashboard) { + this.dash = dashboard; + } + + getCurrent() { + return this.dash; + } + + saveDashboard(options) { + if (!this.dash.meta.canSave && options.makeEditable !== true) { + return Promise.resolve(); + } + + if (this.dash.title === 'New dashboard') { + return this.saveDashboardAs(); + } + + var clone = this.dash.getSaveModelClone(); + + return this.backendSrv.saveDashboard(clone, options).then(data => { + this.dash.version = data.version; + + this.$rootScope.appEvent('dashboard-saved', this.dash); + + var dashboardUrl = '/dashboard/db/' + data.slug; + if (dashboardUrl !== this.$location.path()) { + this.$location.url(dashboardUrl); + } + + this.$rootScope.appEvent('alert-success', ['Dashboard saved', 'Saved as ' + clone.title]); + }).catch(this.handleSaveDashboardError.bind(this)); + } + + handleSaveDashboardError(err) { + if (err.data && err.data.status === "version-mismatch") { + err.isHandled = true; + + this.$rootScope.appEvent('confirm-modal', { + title: 'Conflict', + text: 'Someone else has updated this dashboard.', + text2: 'Would you still like to save this dashboard?', + yesText: "Save & Overwrite", + icon: "fa-warning", + onConfirm: () => { + this.saveDashboard({overwrite: true}); + } + }); + } + + if (err.data && err.data.status === "name-exists") { + err.isHandled = true; + + this.$rootScope.appEvent('confirm-modal', { + title: 'Conflict', + text: 'Dashboard with the same name exists.', + text2: 'Would you still like to save this dashboard?', + yesText: "Save & Overwrite", + icon: "fa-warning", + onConfirm: () => { + this.saveDashboard({overwrite: true}); + } + }); + } + + if (err.data && err.data.status === "plugin-dashboard") { + err.isHandled = true; + + this.$rootScope.appEvent('confirm-modal', { + title: 'Plugin Dashboard', + text: err.data.message, + text2: 'Your changes will be lost when you update the plugin. Use Save As to create custom version.', + yesText: "Overwrite", + icon: "fa-warning", + altActionText: "Save As", + onAltAction: () => { + this.saveDashboardAs(); + }, + onConfirm: () => { + this.saveDashboard({overwrite: true}); + } + }); + } + } + + saveDashboardAs() { + var newScope = this.$rootScope.$new(); + newScope.clone = this.dash.getSaveModelClone(); + newScope.clone.editable = true; + newScope.clone.hideControls = false; + + this.$rootScope.appEvent('show-modal', { + src: 'public/app/features/dashboard/partials/saveDashboardAs.html', + scope: newScope, + modalClass: 'modal--narrow' + }); + } + +} + +coreModule.service('dashboardSrv', DashboardSrv); + diff --git a/public/app/features/dashboard/dashnav/dashnav.html b/public/app/features/dashboard/dashnav/dashnav.html index 19112f77a43..7cb22c756cd 100644 --- a/public/app/features/dashboard/dashnav/dashnav.html +++ b/public/app/features/dashboard/dashnav/dashnav.html @@ -14,6 +14,18 @@ + +
  • - + +
  • +
  • +
  • Settings
  • Annotations
  • Templating
  • -
  • Export
  • -
  • View JSON
  • +
  • View JSON
  • Make Editable
  • Save As...
  • +
  • Delete dashboard
  • - -