When creating new dashboards to set defaults, not all properties of the
dashboard were being copied. This ensures that they are so that zero
values are not used for things like the ID and Name.
Dashboard responses had data races because multiple goroutines were
reading and modifying dashboards before sending them out on the wire.
This patch introduces immutability in the construction of the response,
so that each goroutine is working with its own set of dashboardResponse
structs.
The contract with the frontend states that bounds should come back as an
empty array instead of null when there are no bounds present. We must
explicitly specify []string{} for this to happen.
Certain aspects of the frontend requires the presence of these three
axes, so part of the contract established is that the backend will
always provide them. Since we centralize creation of
dashboardCellResponses, this is where these axes are added to all cell
responses.
Additionally, because there was previously no coverage over the
dashboard cells endpoints, a test has been added to cover the
DashboardCells method of Service.
Due to various limitations with the previous implementation of Bounds as
a [2]int64{}, we've decided to change this to a []string{}. This will
allow clients to store arbitrary data specifying a bound and interpret
it as they wish.
For the forseeable future, we will only be using the "x", "y", and "y2"
axes, even though the underlying serialization can support arbitrary
axes (for the future).
This ensures that only "x", "y", and "y2" axes are present and updates
the Swagger docs to reflect that fact
Cells now have axes which represent their visualization's viewport. This
updates the Swagger documentation to reflect this.
Things to be aware of
=====================
The form of "axes" is that of a map<string,object>, which is represented
in Swagger by an "additionalProperties" key (search for "string to model
mapping" here: https://swagger.io/specification/).
It's useful for operators to classify users into separate groups which
we have termed "organizations". For other OAuth providers, the notion of
an organization typically fell along company lines. For example,
MegaCorp might have a "MegaCorp" GitHub organiztion, and all email
addresses would have the domain "megacorp.com".
Auth0 is slightly different in that MegaCorp would likely run their own
Auth0 provider for their internal services, so "organizations" in Auth0
are no longer synonymous with "large organizations" (or companies).
Instead, Auth0 organizations could be used to restrict access to
Chronograf instances based on team membership within an organization.
To make use of Auth0 organizations, operators should modify users'
app_metadata to include the key "organization". Its value should be the
organization which that user belongs to. This can be done automatically
through arbitrary rules using Auth0 Rules.
Auth0 is an OpenID Connect compliant OAuth2 provider, so we're able to
re-use the generic OAuth2 provider to implement it. The routes required
by Auth0 have been hardcoded for user convenience.
Also, Auth0 requires users to register a subdomain of auth0.com when
signing up. This must be provided to chronograf through the
`--auth0-domain` parameter (or `AUTH0_DOMAIN` ENV). This is **distinct**
from the `PUBLIC_URL`. For example, for a Chronograf hosted at
`http://www.example.com`, and an Auth0 domain of
`http://oceanic-airlines.auth0.com`, a client-id of `notpennysboat` and a
client-secret of `4-8-15-16-23-42`, the command line options would look
like:
```
chronograf \
--auth0-domain=http://oceanic-airlines.auth0.com \
--auth0-client-id=notpennysboat \
--auth0-secret=4-8-15-16-23-24
--public-url=http://www.example.com
-t `uuidgen`
```