Adds Engineer documentation for our recently improved render-template helper, plus some ideas for further work/improvement here should anyone ever want to pick that up.
For our dc, nspace and partition 'bucket' menus, sometimes when selecting one 'bucket' we need to reset a different 'bucket' back to the one that your token has by default (or the default if not). For example when switching to a different partition whilst you are in a non-default namespace of another partition, we need to switch you to the token default namespace of the partition you are switching to.
Various CSS tweaks/HTML cleanup around upstreams (but impacts other 'rows')
- Prefer {{tooltip}} to <Tooltip>
- Removed some now unnecessary spans
- Stop using an empty class="" for styling purposes.
- Renamed any classes used to identify response properties to follow the exact property name but kebab-cased.
- Fixed up the alignment of things in the rows when used with a 'tiny copy button' (see screengrab) which was minus positioning and knocking things out (pending a proper refactor of our copy button CSS which is from the very very start of things)
Fixes an issue where the code editor would not resizing to the full extent of the browser window plus CodeEditor restyling/refactoring
- :label named block
- :tools named block
- :content named block
- code and CSS cleanup
- CodeEditor.mdx
Signed-off-by: Alessandro De Blasis <alex@deblasis.net>
Co-authored-by: John Cowen <johncowen@users.noreply.github.com>
Most HTTP API calls will use the default namespace of the calling token to additionally filter/select the data used for the response if one is not specified by the frontend.
The internal permissions/authorize endpoint does not do this (you can ask for permissions from different namespaces in on request).
Therefore this PR adds the tokens default namespace in the frontend only to our calls to the authorize endpoint. I tried to do it in a place that made it feel like it's getting added in the backend, i.e. in a place which was least likely to ever require changing or thinking about.
Note: We are probably going to change this internal endpoint to also inspect the tokens default namespace on the backend. At which point we can revert this commit/PR.
* Add the same support for the tokens default partition
Temporarily revert to pre-1.10 UI functionality by overwriting frontend
permissions. These are used to hide certain UI elements, but they are
still enforced on the backend.
This temporary measure should be removed again once https://github.com/hashicorp/consul/issues/11098
has been resolved
* ui: Filter global intentions list by namespace and partition
Filters global intention listing by the current partition rather than trying to use a wildcard.
Port of: Ensure we check intention service prefix permissions for per service (#11270)
Previously, when showing some action buttons for 'per service intentions' we used a global 'can I do something with any intention' permission to decide whether to show a certain button or not. If a user has a token that does not have 'global' intention permissions, but does have intention permissions on one or more specific services (for example via service / service_prefix), this meant that we did not show them certain buttons required to create/edit the intentions for this specific service.
This PR adds that extra permissions check so we now check the intentions permissions per service instead of using the 'global' "can I edit intentions" question/request.
**Notes:**
- If a HTML button is `disabled` this means tippy.js doesn't adopt the
popover properly and subsequently hide it from the user, so aswell as
just disabling the button so you can't active the popover, we also don't
even put the popover on the page
- If `ability.item` or `ability.item.Resources` are empty then assume no access
**We don't try to disable service > right hand side intention actions here**
Whether you can create intentions for a service depends on the
_destination_ of the intention you would like to create. For the
topology view going from the LHS to the center, this is straightforwards
as we only need to know the permissions for the central service, as when
you are going from the LHS to the center, the center is the
_destination_.
When going from the center to the RHS the _destination[s]_ are on the
RHS. This means we need to know the permissions for potentially 1000s of
services all in one go in order to know when to show a button or not.
We can't realistically discover the permissions for service > RHS
services as we'd have either make a HTTP request per right hand service,
or potentially make an incredibly large POST request for all the
potentially 1000s of services on the right hand side (more preferable to
1000s of HTTP requests).
Therefore for the moment at least we keep the old functionality (thin client)
for the middle to RHS here. If you do go to click on the button and you
don't have permissions to update the intention you will still not be
able to update it, only you won't know this until you click the button
(at which point you'll get a UI visible 403 error)
Note: We reversed the conditional here between 1.10 and 1.11
So this make 100% sense that the port is different here to 1.11
Previously we had "Open metrics Dashboard" and "Configure metrics
dashboard" in the topology cards and then we had "Open Dashboard" in the
top nav when the dashboard was configured.
Now we use "Open dashboard" and "Configure dashboard".
This change was made for consistency in wording and casing. In addition,
the dashboard could be used for metrics but also other dashboards so
there's no need to scope it only to metrics. Also the config is:
```hcl
ui_config {
dashboard_url_templates
}
```
Which does not mention metrics
* ui: Ensure dc selector correctly shows the currently selected dc
* ui: Restrict access to non-default partitions in non-primaries (#11420)
This PR restricts access via the UI to only the default partition when in a non-primary datacenter i.e. you can only have multiple (non-default) partitions in the primary datacenter.
Attempt to document out what a beginner to the project needs to know here in order to get started quickly
Co-authored-by: Jared Kirschner <85913323+jkirschner-hashicorp@users.noreply.github.com>
This commit tries to make the development experience of working on our OIDC support a little more realistic, essentially by creating our own OIDC provider in our application (only during development builds). You can still provide a real OIDC provider to work with via our dev time environment/cookie variables as before, just now we default to the behaviour in this commit. Overall this makes it much easier to verify our OIDC support in the UI, and also opens up avenues for us to be able to test more scenarios that we couldn't before (for example not only successful logins, but also erroneous, potentially with multiple error reasons).
* Add `is` and `test` helpers in a similar vein to `can`
Adds 2 new helpers in a similar vein to ember-cans can:
- `is` allows you to use vocab/phrases such as (is "something model") which calls isSomething() on the models ability.
- `test` allows you to use vocab/phrases such as (test "is something model") or (test "can something model")which calls isSomething() / canSomething() on the models ability. Mostly using the is helper and the can helper. It's basically the is/can helper combined.
* Adds TextInput component + related modifiers/helpers/machines/services (#11189)
Adds a few new components/modifiers/helpers to aid building forms.
- state-chart helper, used in lieu of a more generic approach for requiring our statecharts.
- A few modifications to our existing disabled modifier.
- A new 'validation' modifier, a super small form validation approach built to make use of state charts (optionally). Eventually we should be able to replace our current validation approach (ember-changeset-validations + extra deps) with this.
- A new TextInput component, which is the first of our new components specifically to make it easy to build forms with validations. This is still a WIP, I left some comments in pointing out where this one would be progressed, but as we don't need the planned functionality yet, I left it where it was. All of this will be fleshed out more at a later date.
Documentation is included for all of ^
* ui: Adds initial CRUD for partitions (#11190)
Adds basic CRUD support for partitions. Engineering-wise probably the biggest takeaway here is that we needed to write very little javascript code to add this entire feature, and the little javascript we did need to write was very straightforwards. Everything is pretty much just HTML. Another note to make is that both ember-changeset and ember-data (model layer things) are now completely abstracted away from the view layer of the application.
New components:
- Consul::Partition::Form
- Consul::Partition::List
- Consul::Partition::Notifications
- Consul::Partition::SearchBar
- Consul::Partition::Selector
See additional documentation here for more details
New Route templates:
- index.hbs partition listing/searching/filtering
- edit.hbs partition editing and creation
Additionally:
There is some additional debug work here for better observability and to prevent any errors regarding our href-to usage when a dc is not available in our documentation site.
Our softDelete functionality has been DRYed out a little to be used across two repos.
isLinkable was removed from our ListCollection component for lists like upstream and service listing, and instead use our new is helper from within the ListCollection, meaning we've added a few more lighterweight templateOnly components.
* ui: Exclude all debug-like files from the build (#11211)
This PR adds **/*-debug.* to our test/prod excluded files (realised I needed to add test-support.js also so added that here as its more or less the same thing). Conditionally juggling ES6 static imports (specifically debug ones) for this was also getting a little hairy, so I moved it all to use the same approach as our conditional routes. All in all it brings the vendor build back down to ~430kb gzipped.
From an engineers perspective, whenever specifying colors from now on we should use the form:
```
color: rgb(var(--tone-red-500));
```
Please note:
- Use rgb. This lets us do this like rgb(var(--tone-red-500) / 10%) so we can use a 10% opacity red-500 if we ever need to whilst still making use of our color tokens.
- Use --tone-colorName-000 (so the prefix tone). Previously we could use a mix of --gray-500: $gray-500 (note the left hand CSS prop and right hand SASS var) for the things we need to theme currently. As we no longer use SASS we can't do --gray-500: --gray-500, so we now do --tone-gray-500: --gray-500.
Just for clarity after that, whenever specifying a color anywhere, use rgb and --tone. There is only one reason where you might not use tone, and that is if you never want a color to be affected by a theme (for example a background shadow probably always should use --black)
There are a 2 or 3 left for the code editor, plus our custom-query values
> In the future, this should all be moved to each individual repository now, which will mean we can finally get rid of this service.
This PR moves reconciliation to 'each individual repository'. I stopped short of getting rid of the service, but its so small now we pretty much don't need it. I'd rather wait until I look at the equivalent DataSink service and see if we can get rid of both equivalent services together (this also currently dependant on work soon to be merged)
Reconciliation of models (basically doing the extra work to clean up the ember-data store and bring our frontend 'truth' into line with the actual backend truth) when blocking/long-polling on different views/filters of data is slightly more complicated due to figuring out what should be cleaned up and what should be left in the store. This is especially apparent for KVs.
I built in a such a way to hopefully make sure it will all make sense for the future. I also checked that this all worked nicely with all our models, even KV which has never supported blocking queries. I left all that work in so that if we want to enable blocking queries/live updates for KV it now just involves deleting a couple of lines of code.
There is a tonne of old stuff that we can clean up here now (our 'fake headers' that we pass around) and I've added that to my list of thing for a 'Big Cleanup PR' that will remove lots of code that we no longer require.
This commit addresses some left over admin partition FIXMEs
1. Adds Partition correctly to Service Instances
2. Converts non-important 'we can do this later' FIXMEs to TODOs
3. Removes some FIXMEs that I've double checked and addressed.
Most of the remaining FIXMEs I'm waiting on responses to questions from
the consul core folks for. I'll address those in a separate PR.
Our DataSource came in very iteratively, when we first started using it we specifically tried not to use it for things that would require portions of the @src="" attribute to be URL encoded (so things like service names couldn't be used, but dc etc would be fine). We then gradually added an easy way to url encode the @src="" attributes with a uri helper and began to use the DataSource component more and more. This meant that some DataSource usage continued to be used without our uri helper.
Recently we hit #10901 which was a direct result of us not encoding @src values/URIs (I didn't realise this was one of the places that required URL encoding) and not going back over things to finish things off once we had implemented our uri helper, resulting in ~half of the codebase using it and ~half of it not.
Now that almost all of the UI uses our DataSource component, this PR makes it even harder to not use the uri helper, by wrapping the string that it requires in a private URI class/object, that is then expected/asserted within the DataSource component/service. This means that as a result of this PR you cannot pass a plain string to the DataSource component without seeing an error in your JS console, which in turn means you have to use the uri helper, and it's very very hard to not URL encode any dynamic/user provided values, which otherwise could lead to bugs/errors similar to the one mentioned above.
The error that you see when you don't use the uri helper is currently a 'soft' dev time only error, but like our other functionality that produces a soft error when you mistakenly pass an undefined value to a uri, at some point soon we will make these hard failing "do not do this" errors.
Both of these 'soft error' DX features have been used this to great effect to implement our Admin Partition feature and these kind of things will minimize the amount of these types of bugs moving forwards in a preventative rather than curative manner. Hopefully these are the some of the kinds of things that get added to our codebase that prevent a multitude of problems and therefore are often never noticed/appreciated.
Additionally here we moved the remaining non-uri using DataSources to use uri (that were now super easy to find), and also fixed up a place where I noticed (due to the soft errors) where we were sometimes passing undefined values to a uri call.
The work here also led me to find another couple of non-important 'bugs' that I've PRed already separately, one of which is yet to be merged (#11105), hence the currently failing tests here. I'll rebase that once that PR is in and the tests here should then pass 🤞
Lastly, I didn't go the whole hog here to make DataSink also be this strict with its uri usage, there is a tiny bit more work on DataSink as a result of recently work, so I may (or may not) make DataSink equally as strict as part of that work in a separate PR.
This PR adds a check to policy, role and namespace list pages to make sure the user has can write those things before offering to create them via a button. (The create page/form would then be a read-only form)
* ui: Don't show the CRD menu for read-only intentions
The UI bug here manifests itself only when a user/token is configured to have read-only access to intentions. Instead of only letting folks click to see a read only page of the intention, we would show an additional message saying that the intention was read-only due to it being 'Managed by [a kubernetes] CRD'. Whilst the intention was still read only, this extra message was still confusing for users.
This PR fixes up the conditional logic and further moves the logic to use ember-can - looking at the history of the files in question, this bug snuck itself in partly due to it being 'permission-y type stuff' previous to using ember-can and when something being editable or not was nothing to do with ACLs. Then we moved to start using ember-can without completely realising what IsEditable previously meant. So overall the code here is a tiny bit clearer/cleaner by adding a proper can view CRD intention instead of overloading the idea of 'editability'.
* ui: Gracefully recover from non-existent DC errors
This PR fixes what happens in the UI if you try to navigate to a non-existing DC.
When we received a 500 error from an API response due to a non-existent DC, previously we would show a 404 error, which is what we were trying to convey. But in the spirit of the UI being a 'thin client', its probably best to just show the 500 error from the API response, which may help folks to debug any issues better.
* Automatically set the CONSUL_DATACENTER_LOCAL env var for testing
* ui: Ignore response from API for KV permissions
Currently there is no way for us to use our HTTP authorization API
endpoint to tell us whether a user has access to any KVs (including the
case where a user may not have access to the root KV store, but do have
access to a sub item)
This is a little weird still as in the above case the user would click
on this link and still get a 403 for the root, and then have to manually
type in the URL for the KV they do have access to.
Despite this we think this change makes sense as at least something about KV is
visible in the main navigation.
Once we have the ability to know if any KVs are accessible, we can add
this guard back in.
We'd initially just removed the logic around the button, but then
noticed there may be further related KV issues due to the nested nature
of KVs so we finally decided on simply ignoring the responses from the
HTTP API, essentially reverting the KV area back to being a thin client.
This means when things are revisited in the backend we can undo this
easily change in one place.
* Move acceptance tests to use ACLs perms instead of KV ones
This PR supersedes #10706 and fixes#10686 whilst making sure that saving intentions continues to work.
The original fix in #10706 ignored the change action configured for the change event on the menus, meaning that the selected source/destination namespace could not be set by the user when editing/creating intentions. This, coupled with the fact that using the later intention exact endpoint for API requests endpoint means that you could not use wildcard namespaces for saving intentions.
All in all this meant that intentions could no longer be saved using the UI (whilst using ENT)
This PR reverts #10706 to fix the intention saving issue, and adds a fix for the original visual issue of nspaces doubling up in the menu once clicked. This meant repeating the existing functionality for nspaces aswell as services. It did seem strange to me that the original issue was only apparent for the nspace menus and not the service menus which should all function exactly the same way.
There is potentially more to come here partly related to what the exact functionality should be, but I'm working with other folks to figure out what the best way forwards is longer term. In the meantime this brings us back to the original functionality with the visual issue fixed.
Squashed commits:
* Revert "ui: Fix dropdown option duplications (#10706)"
This reverts commit eb5512fb74.
* ui: Ensure additional nspaces are added to the unique list of nspaces
* Add some acceptance tests
* Add Partition to all our models
* Add partitions into our serializers/fingerprinting
* Make some amends to a few adapters ready for partitions
* Amend blueprints to avoid linting error
* Update all our repositories to include partitions, also
Remove enabled/disable nspace repo and just use a nspace with
conditionals
* Ensure nspace and parition parameters always return '' no matter what
* Ensure data-sink finds the model properly
This will later be replaced by a @dataSink decorator but we are find
kicking that can down the road a little more
* Add all the new partition data layer
* Add a way to set the title of the page from inside the route
and make it accessibile via a route announcer
* Make the Consul Route the default/basic one
* Tweak nspace and partition abilities not to check the length
* Thread partition through all the components that need it
* Some ACL tweaks
* Move the entire app to use partitions
* Delete all the tests we no longer need
* Update some Unit tests to use partition
* Fix up KV title tests
* Fix up a few more acceptance tests
* Fixup and temporarily ignore some acceptance tests
* Stop using ember-cli-page-objects fillable as it doesn't seem to work
* Fix lint error
* Remove old ACL related test
* Add a tick after filling out forms
* Fix token warning modal
* Found some more places where we need a partition var
* Fixup some more acceptance tests
* Tokens still needs a repo service for CRUD
* Remove acceptance tests we no longer need
* Fixup and "FIXME ignore" a few tests
* Remove an s
* Disable blocking queries for KV to revert to previous release for now
* Fixup adapter tests to follow async/function resolving interface
* Fixup all the serializer integration tests
* Fixup service/repo integration tests
* Fixup deleting acceptance test
* Fixup some ent tests
* Make sure nspaces passes the dc through for when thats important
* ...aaaand acceptance nspaces with the extra dc param
This PR mainly adds partition to our HTTP adapter. Additionally and perhaps most importantly, we've also taken the opportunity to move our 'conditional namespaces' deeper into the app.
The reason for doing this was, we like that namespaces should be thought of as required instead of conditional, 'special' things and would like the same thinking to be applied to partitions.
Now, instead of using code throughout the app throughout the adapters to add/remove namespaces or partitions depending on whether they are enabled or not. As a UI engineer you just pretend that namespaces and partitions are always enabled, and we remove them for you deeper in the app, out of the way of you forgetting to treat these properties as a special case.
Notes:
Added a PartitionAbility while we were there (not used as yet)
Started to remove the CONSTANT variables we had just for property names. I prefer that our adapters are as readable and straightforwards as possible, it just looks like HTTP.
We'll probably remove our formatDatacenter method we use also at some point, it was mainly too make it look the same as our previous formatNspace, but now we don't have that, it instead now looks different!
We enable parsing of partition in the UIs URL, but this is feature flagged so still does nothing just yet.
All of the test changes were related to the fact that we were treating client.url as a function rather than a method, and now that we reference this in client.url (etc) it needs binding to client.
This commit fixes a problem where parent Failovers where not showing (subset children were fine).
Seems to have been introduced with a move/glimmer upgrade here #9154 so I'm adding a 1.9.x backport.
During #9617 we added a list view only for AuthMethods, but not a detail view. We did add the Adapter/Serializer that collected/reshaped data for a detail view.
The test for this serializer was skipped here, but I'm not sure why.
We then added #9845 which began to use this AuthMethod Serializer, but we didn't go back to finish up the skipped test here either.
This PR unskips this test and finishes off the test correctly.
This commit fixes 2 problems with our OIDC flow in the UI, the first is straightforwards, the second is relatively more in depth:
1: A typo (1.10.1 only)
During #10503 we injected our settings service into the our oidc-provider service, there are some comments in the PR as to the whys and wherefores for this change (https://github.com/hashicorp/consul/pull/10503/files#diff-aa2ffda6d0a966ba631c079fa3a5f60a2a1bdc7eed5b3a98ee7b5b682f1cb4c3R28)
Fixing the typo so it was no longer looking for an unknown service (repository/settings > settings)
fixed this.
2: URL encoding (1.9.x, 1.10.x)
TL;DR: /oidc/authorize/provider/with/slashes/code/with/slashes/status/with/slashes should be /oidc/authorize/provider%2Fwith%2Fslashes/code%2Fwith%2Fslashes/status%2Fwith%2Fslashes
When we receive our authorization response back from the OIDC 3rd party, we POST the code and status data from that response back to consul via acallback as part of the OIDC flow. From what I remember back when this feature was originally added, the method is a POST request to avoid folks putting secret-like things into API requests/URLs/query params that are more likely to be visible to the human eye, and POSTing is expected behaviour.
Additionally, in the UI we identify all external resources using unique resource identifiers. Our OIDC flow uses these resources and their identifiers to perform the OIDC flow using a declarative state machine. If any information in these identifiers uses non-URL-safe characters then these characters require URL encoding and we added a helper a while back to specifically help us to do this once we started using this for things that required URL encoding.
The final fix here make sure that we URL encode code and status before using them with one of our unique resource identifiers, just like we do with the majority of other places where we use these identifiers.
Previously when namespaces were enabled, we weren't requesting permission for the actively selected namespace, and instead always checking the permissions for the default namespace.
This commit ensures we request permissions for the actively selected namespace.
This commit adds a bit of string wrangling to avoid the keys in our javascript source file also being transformed. Additionally, whilst looking at this we decided that Maps are a better dictionary than javascript objects, so we moved to use those here also (but this doesn't affect the issue)
Adds 'can access ACLs' which means one of two things
1. When ACLs are disabled I can access the 'please enable ACLs' page
2. When ACLs are enabled, its the same as canRead
When clicking to create a KV within folder name, would would be viewing a form that was a form for creating a KV in the root, which when the user clicked to save, saved the KV in the root.
For the moment at least I've removed the code that strips double slashes, and whilst this isn't ideal, it looks like we've picked up one of those bugs that turns into a 'feature', and completely reworking KV to not rely on the double slashes is not really an option right now.
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.
This commit adds a couple of debug utilities to help us to continue slowly adding i18n support:
- We've added a CONSUL_INTL_DEBUG env/cookie variable to turn off variable interpolation within the t helper so you can see which variables are being interpolated.
- We've added a CONSUL_INTL_LOCALE env/cookie which currently supports two 'pseudo-locales' - la-fk (fake latin) and - (just dashes) either of which will make it easier to see what has not been localized until we can add prettier rules to prevent adding any copy into templates at all. I would guess if we ever translated the app we would use this for looking at things whilst developing also - but as yet I've not adding anything for that here seeing as we don't translate anything.
Both variables are dev-time only and all code for this is removed from the production build.
* ui: Standardize logo naming
According to structure it should always be logo-name not name-logo
* Make sure all our logos use logo-name format
* Upgrade to @hashicorp/structure-icons 1.9.0
* Add `-color` to be consistent with other logos
* Add ms logo back in
* Remove all the old `*-color` icons from before when we got masks
* Add missing files
* Missed glimmer extend name change
* ui: Move all our icons to use CSS custom properties
The good thing about SASS vars is, if you don't use them they get removed from the final build. Whereas with CSS we have no tree-shaking to get rid of unused CSS custom properties. We can mostly work around this and for some things like colors its no big deal if we have some hex-codes in the build that we don't use as hex-codes are relatively small.
We've been slowly but surely moving all of our colors (and other things) to use CSS custom properties instead of SASS vars now that we have them available.
This commit makes use of the 'tree-shaking' abilities of @extend to ensure that we only compile in the icons that we use.
This commit is mostly churn-less as we already use @extend for the majority of our icons, so generally there is zero change here for working on the UI, but I did spot one single place where we were using SASS vars instead of @extend. This now uses the new form (second commit)
Interestingly this reduces our CSS payload by ~2kb to ~53kb (around 25kb of that is these icons)
This commit uses docfy to isolate the individual parts and options and investigates the why you might use certain options and document how you might use certain options.
Originally we used a single %icon-definition CSS component to represent this, but seeing as some of them don't have icons, it didn't seem like the best name. So this PR splits this component into various different ones and then uses the new ones to continue to provide a now deprecated %icon-definition.
The component is currently a CSS only component that assumes a single (or multiple) description lists for its markup component, and provides for multiple different options (including a reversed mode which I'm still not totally sure about, but we don't use this right now anyway).
- %icon-definition
- %horizontal-kv-list
- %csv-list
- %tag-list
- %badge
* 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
* ui: change coloring of secondary navigation elements
* Remove top border, this was probably from older designs/iterations
* ui: Move app-view styles into components also...
1. Remove dead %app-view-content-error
2. Remove TabNav border overwriting
* Bring into line with our 'project standard' class/attributes pattern
* Add docs for AppView
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 conditionals to Lock Session list items
* Add changelog
* Show ID in details if there is a name to go in title
* Add copy-button if ID is in the title
* Update TTL conditional
* Update .changelog/10121.txt
Co-authored-by: John Cowen <johncowen@users.noreply.github.com>
Co-authored-by: John Cowen <johncowen@users.noreply.github.com>
This fixes the spacing bug in nspaces only by only showing Description if the namespace has one, and removing the extra 2 pixel margin of dds for when dts aren't rendered/don't exist.
* ui: Add support for showing partial lists in ListCollection
* Add CSS for partial 'View more' button, and move all CSS to /components
* Enable partial view for intention permissions
* ui: Loader amends/improvements
1. Create a JS compatible template only 'glimmer' component so we can
use it with or without glimmer.
2. Add a set of `rose` colors.
3. Animate the brand loader to keep it centered when the side
navigation appears.
4. Tweak the color of Consul::Loader to use a 'rose' color.
5. Move everything loader related to the `app/components/` folder and
add docs.
* ui: Fix text search for upstream instances
* Clean up predicates for other model types
* Add some docs around DataCollection and searching
* Enable UI Engineering Docs for our preview sites
* Use debug CSS in dev and staging
* Update header logo and inline icon
* Update full logos + layout on loading screen
* Update favicon assets and strategy
- Switches to serve an ico file alongside an SVG file
- Introduces an apple-touch-icon
* Removes unused favicon/meta assets
* Changelog item for ui
* Create component for logo
* Simplify logo component, set brand color
* Fix docs loading state CSS issue
* ui: Add Admin Partition feature flag
This adds a `PartitionEnabled`/`CONSUL_PARTITIONS_ENABLED` feature flag
that can be set during production form the consul binary, or
additionally during development/testing via cookies.
* Add partitions bookmarklet and docs, and all eng docs from main README to the docs instead.
You probably already have the app running once you need these, and it reduces the amount of text/detail in the main README
* Add the env variable section back into the README with actual env vars
* Add inline-code CSS component
* Add %inline-code to all the places where we need it
* Inject selected env variables into the translations file
* Add ingress gateway upstream 'host header' intro text
* Make sure we can use actual correct component casing for titles but still have nice consistent menu item casing in the side nav
We noticed that our mock API would sometimes respond with an empty array
of addresses - which resulted in an empty space in the gateway upstream
listing which looked as though it could be broken.
I checked with backend, and as this will never happen, I made the change
here also so the gateway upstream list is always fully populated with
addresses.
The extra argument meant that the blocking query configuration wasn't
being read properly, and therefore the correct ?index wasn't being sent
with the request.
* Install Duration JS
* Use Duration.js to sortBy reformatted MaxTokenTTL
* Remove @icholy/duration package
* Install parse-duration package
* Use parse-duration in auth-method model
* 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
* Add mock data for NamespaceRules
* Create NamespaceTable component and styling
* Add NamespaceRules route and add to model
* Create Namespace Rules tab and implement with flag to only show in ent
* Add emptystate to namespace rules page
* Rename namespace-rules to be nspace-rules
* Rename NamespaceTable to be NspaceList
* 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 Certificate to be monospaced
* Add empty states for claim and list claim mappings
* Update the styling of empty state actions block
* Update mocked PEM certificate format
* ui: Add all tooltips to the default tabbing order in the page
This amends our tooltip modifier to automatically add a tabindex="0" to
all of our tooltips (if they aren't tabbable already).
This means that all tooltips will automatically be
added to the natural tab order of the page. I'm pretty sure we don't
currently require the ability to disable this automatic functionality
but if we do at some point in the future we can add an option to disable
it, meaning all tooltips will be tabbable by default.
* 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
* Configure ember-auto-import so we can use a stricter CSP
* Create a fake filesystem using JSON to avoid inline scripts in index
We used to have inline scripts in index.html in order to support embers
filepath fingerprinting and our configurable rootURL.
Instead of using inline scripts we use application/json plus a JSON blob
to create a fake filesystem JSON blob/hash/map to hold all of the
rootURL'ed fingerprinted file paths which we can then retrive later in
non-inline scripts.
We move our inlined polyfills script into the init.js external script,
and we move the CodeMirror syntax highlighting configuration inline
script into the main app itself - into the already existing CodeMirror
initializer (this has been moved so we can lookup a service located
document using ember's DI container)
* Set a strict-ish CSP policy during development
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.
This PR removes storybook and adds docfy and uses docfy to render our existing README files.
This now means we can keep adding README documentation without committing any specific format or framework. If we eventually move to storybook then fine, or if we just want to remove docfy for whatever reason then fine - we will still have a full set of README files viewable via GitHub.
* Add Routlet service and Route Component
* Add ember-assign-helper (already an indirect dependency)
* Use EventListeners for is-href instead of observing
* Don't include :active in '-intent' styles
* Remove footer and add the Consul version to the Help menu
* Tweak menu text and button styling
* Tweak some coloring and spacing
* Add slightly larger Consul logo
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.
Here we look for a TESTEM_AUTOLAUNCH environment variable, which can be
set to either Chrome, Firefox or Safari, which will control which
browser to automatically start when running testem tests.
If the variable is set to anything else, then it will not automatically
start a browser in order to run the tests and you will need to visit the
tests manually. e.g.:
TESTEM_AUTOLAUNCH=0 make test-oss-view
Previously we only ever tested in Chrome and therefore there are no
specific settings for Firefox or Safari. If specific settings are
required for these browsers they can be added at a later date.
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
* Use NodeName not Node for cross checking proxies/instances
* Also copy over the meta data to keep the correct cursor/index
* When we sync checks to the ProxyInstance replace rather than accumulate
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.
We've always had this idea of being able to markup up information
semantically without thinking about what it should look like, then
applying our %h* placeholder styles to control what the information
should look like.
Back when we originally made our set of %h* placeholders, we tried to
follow Structure as much as possible, which defined the largest header
(which we thought would have been the h1 style) as a super large 3.5rem.
Therefore we made our set of %h* placeholders the same as Structure
beginning at a huge 3.5 size. We then re-overwrote those sizes only in
Consul specific CSS files thinking that this was due to us existing
before Structure did.
Lately we saw an extra clue in Structure - the extra large 3.5 header was
called 'h0'.
This commit moves all our headers to use a zero based scale, and
additionally uses our 3 digit scale as opposed to 1 digit (h1 vs h100),
similar to our color scales (note we don't use a hypen, which we can
alter later if need be), which means we can insert additional h150 etc
if need be.
Additional we stop styling our headers globally (h1 { @extend %h100; }
). This means there is no reason not to use headers for marking up
content depending on what it is rather than what it should look like,
and as a consequence means we can be more purposeful in ordering h*
tags.
Lastly, we use the new scale over the entire codebase and update a
couple of places where we were using using header tags due to what the
styleing for them looked like rather than what the meaning/order was.
* 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.
This originally comes form the ember-href-to helper and is one of those
errors that when I see it I think ... hmmm
This gives a little bit more of a clue as to what is wrong by logging
the route name you asked for plus the params you passed to it so you:
1. Have more help finding the href-to that is problematic in the
template/component
2. Can see all the parameters you passed (including a potential null
parameter for the thing you are missing)
* 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: Add EmptyState for exposed paths, plus additional details
1. Add the port to the combined address
2. Use the proxy address for the ip address used
* Convert to glimmer component
* Add spaces to ListenerPort and LocalPathPort Tooltips
* 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
* Add service collections to get all ExternalServices
* Add a basic collection helper
* Use the collections to get all ExternalSources
* Remove old Controllers
* 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
* Refactor Stats and Series components
* Refactor metrics error message for ingress-gateway
* Fix upLines icon positioning
* Remove unused variable from being passed down to Stats
* 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.