The default namespace, and the tokens default namespace (or its origin namespace) is slightly more complicated than other things we deal with in the UI, there's plenty of info/docs on this that I've added in this PR.
Previously:
When a namespace was not specified in the URL, we used to default to the default namespace. When you logged in using a token we automatically forward you the namespace URL that your token originates from, so you are then using the namespace for your token by default. You can of course then edit the URL to remove the namespace portion, or perhaps revisit the UI at the root path with you token already set. In these latter cases we would show you information from the default namespace. So if you had no namespace segment/portion in the URL, we would assume default, perform actions against the default namespace and highlight the default namespace in the namespace selector menu. If you wanted to perform actions in your tokens origin namespace you would have to manually select it from the namespace selector menu.
This PR:
Now, when you have no namespace segment/portion in the URL, we use the token's origin namespace instead (and if you don't have a token, we then use the default namespace like it was previously)
Notes/thoughts:
I originally thought we were showing an incorrectly selected namespace in the namespace selector, but it also matched up with what we were doing with the API, so it was in fact correct. The issue was more that we weren't selecting the origin namespace of the token for the user when a namespace segment was omitted from the URL. Seeing as we automatically forward you to the tokens origin namespace when you log in, and we were correctly showing the namespace we were acting on when you had no namespace segment in the URL (in the previous case default), I'm not entirely sure how much of an issue this actually was.
This characteristic of namespace+token+namespace is a little weird and its easy to miss a subtlety or two so I tried to add some documentation in here for future me/someone else (including some in depth code comment around one of the API endpoints where this is very subtle and very hard to miss). I'm not the greatest at words, so would be great to get some edits there if it doesn't seem clear to folks.
The fact that we used to save your previous datacenter and namespace into local storage for reasons also meant the interaction here was slightly more complicated than it needed to be, so whilst we were here we rejigged things slightly to satisfy said reasons still but not use local storage (we try and grab the info from higher up). A lot of the related code here is from before we had our Routlets which I think could probably make all of this a lot less complicated, but I didn't want to do a wholesale replacement in this PR, we can save that for a separate PR on its own at some point.
* Create and use collapsible notices
* Refactor collapsible-notices
* Split up the topology acceptance tests
* Add acceptance tests for tproxy notices
* Add component file
* Adds additional TProxy notices tests
* Adds conditional to only show collapsable if more than 2 notices are present
* Adds changelog
* Refactorting the conditonal for collapsing the notices
* Renaming undefinedIntention to be notDefinedIntention
* Refactor tests
When the Consul serf health check is failing, this means that the health checks registered with the agent may no longer be correct. Therefore we show a notice to the user when we detect that the serf health check is failing both for the health check listing for nodes and for service instances.
There were a few little things we fixed up whilst we were here:
- We use our @replace decorator to replace an empty Type with serf in the model.
- We noticed that ServiceTags can be null, so we replace that with an empty array.
- We added docs for both our Notice component and the Consul::HealthCheck::List component. Notice now defaults to @type=info.
* Add before and after skip links portals
* Move EmptyState and ErrorState to use a @login action/function
* Move page title setting to the Route component
* Add Routes and Outlets everywhere, and use those to access login modal
* Add some aria-labels to the modals
* Docs
* Remove the label/input now we no longer need it, fixup pageobject
* Add basic modal docs
* Switch out old toggle names for ids
* Wrap nspace Route template in a Route component
* type > class
* Create BindingRule adapter and tests
* Create BindingRule serializer and test
* Create BindingRule model and repository
* Add binding-rules mock data
* Create binding-rules router and call endpoint
* Create Binding rules tab
* Create and use BindingView component
* Create empty state for BindingView
* Remove binding rule requestForQueryRecord endpoint and tests
* Update binding rules selector to be monospaced
* Add bind type tooltip
* Create and Tabular-dl styling component
* Update hr tag global styling
* Rename BindingView to BindingList and refactor
* Add translations for bind types tooltip info
* Remove unused endpoint
* Refactor based on review notes
* Pin ember-changeset-validations and its dependencies to 3.9
Future versions produce a 'validator is not a function' error
* yarn upgrade
* Upgrade the majority of user facing deps that don't required add. change
not upgraded here due to more changes required:
- ember-page-title
- ember-href-to
* Upgrade ember-page-title which no longer requires ember-cli-head
* Upgrade some devtools related dependencies
* Upgrade some non ember-core test utils
* Upgrade js-yaml which required safeLoad > load
* Upgrade some compilation utils
* Yarn install from workspace root
* Add Python-2.0 to compliance checker
* Update list items to be linkable to auth-methods show
* Add general, namespace, and binding sub-routes
* Remove namespace and binding tabs to be done separately
* Update auth-method byId endpoint
* Style the show auth-method kubernetes type
* Finish Kubernetes auth-method type styling
* OIDC and JWT auth-method styling
* Create consul-auth-method-view component
* Add navigation test for auth-methods
* Create Certificate component
This PR uses the excellent a11y-dialog to implement our modal functionality across the UI.
This package covers all our a11y needs - overlay click and ESC to close, controlling aria-* attributes, focus trap and restore. It's also very small (1.6kb) and has good DOM and JS APIs and also seems to be widely used and well tested.
There is one downside to using this, and that is:
We made use of a very handy characteristic of the relationship between HTML labels and inputs in order to implement our modals previously. Adding a for="id" attribute to a label meant you can control an <input id="id" /> from anywhere else in the page without having to pass javascript objects around. It's just based on using the same string for the for attribute and the id attribute. This allowed us to easily open our login dialog with CSS from anywhere within the UI without having to manage passing around a javascript object/function/method in order to open the dialog.
We've PRed #9813 which includes an approach which would make passing around JS modal object easier to do. But in the meantime we've added a little 'hack' here using an additional <input /> element and a change listener which allows us to keep this label/input characteristic of our old modals. I'd originally thought this would be a temporary amend in order to wait on #9813 but the more I think about it, the more I think its quite a nice thing to keep - so longer term we may/may not keep this.
We use a `<DataSource @src={{url}} />` component throughout our UI for when we want to load data from within our components. The URL specified as the `@src` is used to map/lookup what is used in to retrieve data, for example we mostly use our repository methods wrapped with our Promise backed `EventSource` implementation, but DataSource URLs can also be mapped to EventTarget backed `EventSource`s and native `EventSource`s or `WebSockets` if we ever need to use those (for example these are options for potential streaming support with the Consul backend).
The URL to function/method mapping previous to this PR used a very naive humongous `switch` statement which was a temporary 'this is fine for the moment' solution, although we'd always wanted to replace with something more manageable.
Here we add `wayfarer` as a dependency - a very small (1kb), very fast, radix trie based router, and use that to perform the URL to function/method mapping.
This essentially turns every `DataSource` into a very small SPA - change its URL and the view of data changes. When the data itself changes, either the yielded view of data changes or the `onchange` event is fired with the changed data, making the externally sourced view of data completely reactive.
```javascript
// use the new decorator a service somewhere to annotate/decorate
// a method with the URL that can be used to access this method
@dataSource('/:ns/:dc/services')
async findAllByDatacenter(params) {
// get the data
}
// can use with JS in a route somewhere
async model() {
return this.data.source(uri => uri`/${nspace}/${dc}/services`)
}
```
```hbs
{{!-- or just straight in a template using the component --}}
<DataSource @src="/default/dc1/services" @onchange="" />
```
This also uses a new `container` Service to automatically execute/import certain services yet not execute them. This new service also provides a lookup that supports both standard ember DI lookup plus Class based lookup or these specific services. Lastly we also provide another debug function called DataSourceRoutes() which can be called from console which gives you a list of URLs and their mappings.
This commit use the internal authorize endpoint along wiht ember-can to further restrict user access to certain UI features and navigational elements depending on the users ACL token
* Add a way to set the local datacenter
* Amend step so we can positively and negatively look for elements
* Add a data-test selector so we can get to the topology series graph
* Add a couple of tests to verify the series graph shows/doesn't show
* Create mock-api endpoints for auth-methods
* Implement auth-method endpoints and model with tests
* Create route and tab for auth-methods
* Create auth-method list and type components with styles
* Add JWT and OIDC svg logos to codebase
* Add brand translations
* Add SearchBar to Auth Methods
* Add acceptance test for Auth Methods UI
* Skip auth method repo test
* Changes from review notes
* Fixup auth-method modela and mock-data
* Update SearhBar with rebased changes
* Add filterBy source and sortBy max token ttl
* Update to SortBy MethodName
* Update UI acceptance tests
* Update mock data DisplayNames
* Skip repo test
* Fix to breaking serializer test
* Implement auth-method endpoints and model with tests
* Add acceptance test for Auth Methods UI
* Update SearhBar with rebased changes
* Add filterBy source and sortBy max token ttl
* Update to SortBy MethodName
* Update UI acceptance tests
* Update mock data DisplayNames
* Fix to breaking serializer test
* Update class for search
* Add auth-methods link to sidebar
* Fixup PR review notes
* Fixup review notes
* Only show OIDC filter with enterprise
* Update conditionals for MaxTokenTTL & TokenLocality
* Refactor
There are many places in the API where we receive a property set to
`null` which can then lead to defensive code deeper in the app in order
to guard for this type of thing when usually we are expecting an array
or for the property to be undefined using omitempty on the backend.
Previously we had two places where we would deal with this in the
serializer using our 'remove-null' util (KV and Intentions).
This new decorator lets you declaritively define this type of data using
a decorator @NullValue([]) (which would replce a null value with [].
@NullValue in turn uses a more generic @replace helper, which we
currently don't need but would let you replace any value with another,
not just a null value.
An additional benefit here is that the guard/replacement is executed
lazily when we get the property instead of serializing all the values
when they come in via the API. On super large datasets, where we only
visualize part of the dataset (say in our scroll panes), this feels like
a good improvement on the previous approach.
* CSS for moving from a horizontal main menu to a side/vertical one
* Add <App /> Component and rearrange <HashcorpConsul /> to use it
1. HashicorpConsul now uses <App />
2. <App /> is now translated and adds 'skip to main content' functionality
3. Adds ember-in-viewport addon in order to visibly hide main navigation
items in order to take them out of focus/tabbing
4. Slight amends to the dom service while I was there
Adds a 'status' for the filtering/searching in the UI, without this its not super clear that you are filtering a recordset due to the menu selections being hidden once closed. You can also use the pills in this status view to delete individual filters.
* Add templating to inject JSON into an application/json script tag
Plus an external script in order to pick it out and inject the values we
need injecting into ember's environment meta tag.
The UI still uses env style naming (CONSUL_*) but we uses the new style
JSON/golang props behind the scenes.
Co-authored-by: Paul Banks <banks@banksco.de>
* ui: Convert Service.GatewayConfig to a model fragment
We added the ember-intl addon, which has its own format-number helper.
We replaced our own similarly named helper with this one, but the
ember-intl one is far stricter and errors if the arguments passed are
undefined. Our previously one would cope with this.
We'd rather continue to use the stricter ember-intl helper, so here we
convert the GatewayConfig property to a model fragment so that we can
give the GatewayConfig.AssociatedServices property a default zero value.
* ui: Keep track of existing intentions and use those to save changes
Previously we risked overwriting existing data in an intention if we
tried to save an intention without having loaded it first, for example
Description and Metadata would have been overwritten.
This change loads in all the intentions for an origin service so we can
pick off the one we need to save and change to ensure that we don't
overwrite any existing data.
* Rename a model attr to not be overwritten by ember-data
* Make sure we can click on the instances
* Make sure we can click back to the preevious page, not root
* Add a forwards/back/forwards navigation test for service instances
* Rename a model attr to not be overwritten by ember-data
Co-authored-by: John Cowen <jcowen@hashicorp.com>
* ui: Remove all vestiges of role=tabpanel
* Switch out tablist role for a label, default to Secondary
* Move healthcheckout-output headers to h2, ideally these would be outside the component
* Add aria-label for empty button
* Fix up non-unique ids in topology component
* Temporarily fixup h2 in KV > LockSession
* Fixup dl with no dt
* h3 > h2
* Fix up page objects that were reliant on ids
This PR adds the ns=* query parameter when namespaces are enabled to keep backwards compatibility with how the UI used to work (Intentions page always lists all intention across all namespace you have access to)
I found a tiny dev bug for printing out the current URL during acceptance testing and fixed that up while I was there.
Nodes themselves are not namespaced, so we'd originally assumed we did not need to pass through the ns query parameter when listing or viewing nodes.
As it turns out the API endpoints we use to list and view nodes (and related things) return things that are namespaced, therefore any API requests for nodes do require a the ns query parameter to be passed through to the request.
This PR adds the necessary ns query param to all things Node, apart from the querying for the leader which only returns node related information.
Additionally here we decided to show 0 Services text in the node listing if there are nodes with no service instances within the namespace you are viewing, as this is clearer than showing nothing at all. We also cleaned up/standardized the text we use to in the empty state for service instances.
Moves search things around to match an interface that can be switched in and out of fuzzy searching using fuse.js. We add both fuzzy searching and regex based searching to the codebase here, but it is not yet compiled in.
* Use DataLoader errors for Service Detail and Service Instance
* uiCfg > config use the repo-like async interface where possible
* Clean up node show
* Make sure you can put `=` in dev cookie values
* Never default to default
* Tweak chain variable
* Remove env service
* Pass chain through to the template for the tempalte to clean it up
* Delete controller tests
* Remove cleanup in Nodes show as this is still being used in another tab
* Use dc.Local
* ui: Install ember-intl
Also:
1. Removes our own format-number in order to use ember-intl's instead
2. Moves format-time to format-short-time so as to not clash with
ember-intls own format-time
In order to test certain setups for our metrics visualizations we need to be able to setup several different `ui_config` settings during development/testing. Generally in the UI, we use the Web Inspector to set various cookie values to configure the UI how we need to see it whilst developing, so this PR:
1. Routes `ui_config` through a dev time only `CONSUL_UI_CONFIG` env variable so we can change it via cookies vars.
2. Adds `CONSUL_METRICS_PROXY_ENABLE`, `CONSUL_METRICS_PROVIDER` and `CONSUL_SERVICE_DASHBOARD_URL` so it's easy to set/unset these only values during development.
3. Adds an acceptance testing step so we can setup `ui_config` to whatever we want during testing.
4. Adds an async 'repository-like' method to the `UiConfig` Service so it feels like a repository - incase we ever need to get this via an HTTP API+blocking query.
5. Vaguely unrelated: we allow cookie values to be set via the location.hash whilst in development only e.g. `/ui/services#CONSUL_METRICS_PROXY_ENABLE=1` so we can link to different setups if we ever need to.
All values added here are empty/falsey by default, so in order to see how it was previously you'll need to set the appropriate cookies values, but you can now also easily preview/test the the metrics viz in different/disabled states (with differing `ui_config`)
* Add `Local` property to Datacenters
* If you have not previous datacenter, redirect the user to the local dc
* Add an `is-local` class to the local datacenter in the DC picker
* ui: Controller dead code removal
This commit removes a little code that became 'dead' as a result of
previous PRs/commits
* Remove a little more from the settings Controller
* Remove CSS related to being able to set the dashboard_url in settings
* Switch upstream-instances to use new style of searchable
* Add search action to DataCollection plus basic README
* Use DataCollection for PowerSelect searching in child-selectors
* Remove old style filterable search for role/policies and instances
* Remove old helpers/components related to search/sort/filter
* Model layer changes to turn Node:ServiceInstances into hasMany
We tried to make something that feels a little like ember-data yet
not leave our approach of re-shaping the JSON directly from the
response.
1. We added transformHasManyResponse for re-shaping JSON for hasMany
relationships. we avoided the normalize word as ember-data serialize
methods usually return something JSON:API shaped and we distinctly don't
want to do that. Transform was the best word we could think of.
2. The integration tests across all of our models here feel very much
like those types of tests that aren't really testing much, or assert
too much to an extent that they get in the way rather than be of any
use. I'd very much like to move a lot of this to unit tests. Currently
most of the fingerprinting functionality is unit tested and these
integration tests were originally to give confidence that IDs and
related properties were being added correctly.
3. We've added a hasMany relationship, but not the corresponding
belongsTo - yet at least. We don't require the belongsTo right now, and
if we do we can add it later.
* Integrate ServiceInstance search bar for Node:ServiceInstances
* Hide Node.Meta when on the Node:ServiceINstance page
We use a little string replace hack here for a human-like label, this is
soon to be replaced with proper i10n replacement
* Always ensure that a Namespace is set, and add comment explaining
* Adds model layer changes around HealthChecks
1. Makes a HealthCheck model fragment and uses it in ServiceInstances and
Nodes
2. Manually adds a relationship between a ServiceInstance and its
potential ServiceInstanceProxy
3. Misc changes related to the above such as an Exposed property on
MeshChecks, MeshChecks itself
* Add a potential temporary endpoint to distinguish ProxyServiceInstance
* Fix up Node search bar class
* Add search/sort/filter logic
* Fixup Service default sort key
* Add Healthcheck search/sort/filtering
* Tweak CSS add a default Type of 'Serf' when type is blank
* Fix up tests and new test support
* Add ability to search on Service/Node name depending on where you are
* Fixup CheckID search predicate
* Use computed for DataCollection to use caching
* Alpha sort the Type menu
* Temporary fix for new non-changing style Ember Proxys
* Only special case EventSource proxies
* ui: ServiceInstance.Name should be the Service.Name, never the ID
The ServiceInstance.ID should try Service.ID and fallback to
Service.Name, not ServiceInstance.Name. ServiceInstance.Name is just an
alias to Service.Name which is always set.
* ui: Ensure search is enabled for child items in the ACLs area
* Refactor comparators to reuse some utility functions
* Add search and sorting to the ACLs child selector
* Add tests for searching within child selectors
* Allow sorting by CreateIndex