Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic uiActions & license support #68507

Merged
merged 22 commits into from
Jun 26, 2020
Merged

Conversation

Dosant
Copy link
Contributor

@Dosant Dosant commented Jun 8, 2020

Summary

Needed for #55324

This pr adds convenient license support to dynamic uiActions in x-pack.
Works for actions created with action factories & drilldowns.

All is needed from consumer is to specify optional

minimalLicense?: LicenseType; on ActionFactoryDefinition or DrilldownDefinition

Implements this nice state for action_wizard and drilldows list ⬇️

  1. In case there is an available action factory, but not sufficient license, we still show that action factory, but in disabled state. On hover there is a tooltip. Also a link to subscriptions page in the header (like in alerting)
    Screenshot 2020-06-11 at 13 48 04

  2. In case when there is existing Drilldowns with higher license, then current license, we show this warning in a drilldown list:

Screenshot 2020-06-11 at 13 47 14

To try

yarn start --run-examples. Example url drilldown is available from gold license.

Checklist

Delete any items that are not applicable to this PR.

For maintainers

@@ -39,6 +39,8 @@ export class DashboardToUrlDrilldown implements Drilldown<Config, ActionContext>

public readonly order = 8;

readonly minimalLicense = 'gold'; // example of minimal license support
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only thing required for consumer 🙌

@Dosant Dosant added Feature:UIActions UI actions. These are client side only, not related to the server side actions.. release_note:skip Skip the PR/issue when compiling release notes v7.9.0 v8.0.0 Team:AppArch labels Jun 9, 2020
@Dosant Dosant marked this pull request as ready for review June 9, 2020 08:38
@Dosant Dosant requested review from a team as code owners June 9, 2020 08:38
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-app-arch (Team:AppArch)

@Dosant Dosant requested review from stacey-gammon and streamich June 9, 2020 08:39
@Dosant Dosant mentioned this pull request Jun 9, 2020
Copy link
Contributor

@pgayvallet pgayvallet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM for licensing plugin change once the createStartMock return type is fixed.

x-pack/plugins/licensing/public/mocks.ts Outdated Show resolved Hide resolved
@mdefazio
Copy link
Contributor

We have previously avoided the lock to signify options behind a license. We should however still keep the tooltip (I don't think we need the title 'License' though). In alerting, there is a link to the right of the 'Actions' header that goes to the Licensing page on Elastic.co

image

As for the management screen, let's bring the disabled indicator closer to the title (and show the message Insufficient license level in a tooltip).

image

@Dosant Dosant requested a review from ppisljar June 10, 2020 14:53
@botelastic botelastic bot added the Feature:Drilldowns Embeddable panel Drilldowns label Jun 11, 2020
@mdefazio
Copy link
Contributor

This looks good! Only tiny nit is to increase the spacing between the name and error icon (Try $euiSizeM)

@Dosant
Copy link
Contributor Author

Dosant commented Jun 15, 2020

@elasticmachine merge upstream

@streamich
Copy link
Contributor

streamich commented Jun 16, 2020

I'm thinking maybe we should simplify and instead of creating a way of "enhancing" ActionInternal leave it internal as-is, but allow users to "hook" into specific functionality of actions. Something like this:

image

And ui_actions_enhanced would use it as follows:

plugins.uiActions.registerActionHook({
  isCompatible: (action) => isCompatibleLicense(action),
});

I think it should simplify the architecture and then we don't need to export internal ActionInternal class. Do you see problems with this approach?

Copy link
Contributor

@streamich streamich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chatted with @Dosant, he said he could explore the "hook" approach if @ppisljar, @stacey-gammon you are OK with it.

Idea being that in the "hook" approach we get:

  1. Less and simpler code.
  2. Actions are still registered as before when they are registered, instead definitions being registered and actions created in start life-cycle.
  3. We don't inroduce setup and start life-cycles into, UiActionsService. As before, UiActionsService does not need to know about those life-cycles, actions are simply registered whenever they are registered.
  4. We don't need to export ActionInternal class from ui_actions.

It could looks something like this:

interface ActionDefinition {
  // Add extra information to action definition from X-Pack
  enhancements: unknown;
}

// Register action "hooks" in X-Pack.
plugins.ui_actions.registerActionHook({
  isCompatible: (action, context) => isLicenseValid(action.enhancements),
});

@Dosant Dosant force-pushed the dev/uiactions-license branch from fb0842b to fa41858 Compare June 17, 2020 15:33
…-license

# Conflicts:
#	x-pack/plugins/ui_actions_enhanced/public/plugin.ts
Copy link
Member

@ppisljar ppisljar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code LGTM

@Dosant
Copy link
Contributor Author

Dosant commented Jun 25, 2020

@elasticmachine merge upstream

Copy link
Contributor

@stacey-gammon stacey-gammon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the perspective of a consumer of the ui_actions services, it's not clear to me how to use this functionality, and I think I can easily get into trouble with it.

I first tried to do something like:

    deps.uiActions.registerActionHook({
      onIsCompatible: (action: Action) => {
        return action.isCompatible({}) && ...? // 
      },
    });

Can't do that because onIsCompatible is sync, while isCompatible is async. Even if it was async, and I did the above, I'd hit a circular loop. It'd also pass the typescript check, but because of contra-variance, it'd throw a runtime exception on actions that require more than an empty object to be passed in as context.

Maybe I'm forgetting some context, but is there a reason we can't just do something like this, and rely on our current public APIs to support this:

const createHelloWorldAction = (getStartServices: () => Promise<licensing>) => {
  return createAction({
    type: ACTION_HELLO_WORLD,
    isCompatible: () => return (await getStartServices()).licensing.license$.getValue().hasAtLeast('gold');
    getDisplayName: () => 'Hello World!',
    execute: async () => {},
});

const helloWorldAction = createHelloWorldAction(async () => ({
   licensing: (await core.getStartServices())[0].licensing,
}));

uiActions.registerAction(helloWorldAction);

It's less refactored, but also introduces no extra public APIs.

* @param action
* @param context
*/
onIsCompatible?: (action: Action, context: unknown) => boolean;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is context needed? I don't see it used and since it's unknown, probably not that helpful anyway.

Should it return Promise<boolean> to match isCompatible fns?

@stacey-gammon
Copy link
Contributor

stacey-gammon commented Jun 25, 2020

Also... don't let me block this PR, especially since I'm going on vacation for a couple weeks. I just wanted to bring up some thoughts about maybe simplifying/minimizing public APIs. Also just trying to focus on our public APIs from a public consumer standpoint.

We often add public APIs for very specific use cases, and try to make them general/flexible enough for future use cases, but don't spend enough time thinking about examples/tests for the general cases. What would an example plugin look like to showcase how another plugin can use enhancements and action hooks?

Are we introducing overly flexible APIs that will cause us issues later on the line and maintenance headaches?

Do we want to support giving the ability for one plugin to turn off another plugins actions?

Do we have an answer for how to avoid clashes if multiple plugins add custom state/functionality onto the enhancements object?

If there is an easier way to solve this, without introducing new APIs, might be worth considering, to the support of our dev principles:

Just some thoughts, but ultimately, I leave it to the team to make the final decision!

@Dosant
Copy link
Contributor Author

Dosant commented Jun 26, 2020

@stacey-gammon, thanks for this review! I made a step back and reverted all changes to static uiActions level. I agree that we don't have right now a use case for that functionality.

I left only minimalLicense change on actionFactory and drilldown level.


Initially I was inspired looking at this #63170, What I did in this pr wasn't solving that particular issue, but I thought of similar use cases, where new static action registered in x-pack could benefit of simple minimalRequiredLicense option. And I agree it is not needed now for URL drilldown.


@streamich, @ppisljar, Since Stacey enjoying vacation now, could you please re-review this simpler version? 🙏

@Dosant Dosant changed the title uiActionsEnhanced & license support Dynamic uiActions & license support Jun 26, 2020
Copy link
Contributor

@streamich streamich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@stacey-gammon stacey-gammon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So much simpler, really like the changes. 🎉

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

Build metrics

✅ unchanged

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@Dosant Dosant merged commit 3ac5bc5 into elastic:master Jun 26, 2020
Dosant added a commit to Dosant/kibana that referenced this pull request Jun 26, 2020
This pr adds convenient license support to dynamic uiActions in x-pack.
Works for actions created with action factories & drilldowns.

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
Dosant added a commit that referenced this pull request Jun 27, 2020
This pr adds convenient license support to dynamic uiActions in x-pack.
Works for actions created with action factories & drilldowns.

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
gmmorris added a commit to gmmorris/kibana that referenced this pull request Jun 29, 2020
* master: (59 commits)
  [Lens] Fix broken test (elastic#70117)
  [SIEM] Import timeline fix (elastic#65448)
  [SECURITY SOLUTION][INGEST] UX update for ingest manager edit/create datasource for endpoint (elastic#70079)
  [Telemetry] Collector Schema (elastic#64942)
  [Endpoint] Add Endpoint empty states for onboarding (elastic#69626)
  Hide unused resolver buttons (elastic#70112)
  [Security] `Investigate in Resolver` Timeline Integration (elastic#70111)
  [Discover] Improve styling of graphs in sidebar (elastic#69440)
  [Metrics UI] Fix EuiTheme type issue (elastic#69735)
  skip failing suite (elastic#70104) (elastic#70103)
  [ENDPOINT] Hide the Timeline Flyout while on the Management Pages (elastic#69998)
  [SIEM][CASE] Persist callout when dismissed (elastic#68372)
  [SIEM][Exceptions] - Cleaned up and updated exception list item comment structure (elastic#69532)
  [Maps] remove indexing state from redux (elastic#69765)
  Add API integration test for deleting data streams. (elastic#70020)
  renames SIEM to Security Solution (elastic#70070)
  Adding saved_objects_page in OSS (elastic#69900)
  [Lens] Use accordion menus in field list for available and empty fields (elastic#68871)
  Dynamic uiActions & license support (elastic#68507)
  [SIEM] Update readme for timeline apis (elastic#67038)
  ...
gmmorris added a commit to gmmorris/kibana that referenced this pull request Jun 29, 2020
…bana into alerting/consumer-based-rbac

* 'alerting/consumer-based-rbac' of github.com:gmmorris/kibana: (25 commits)
  [Lens] Fix broken test (elastic#70117)
  [SIEM] Import timeline fix (elastic#65448)
  [SECURITY SOLUTION][INGEST] UX update for ingest manager edit/create datasource for endpoint (elastic#70079)
  [Telemetry] Collector Schema (elastic#64942)
  [Endpoint] Add Endpoint empty states for onboarding (elastic#69626)
  Hide unused resolver buttons (elastic#70112)
  [Security] `Investigate in Resolver` Timeline Integration (elastic#70111)
  [Discover] Improve styling of graphs in sidebar (elastic#69440)
  [Metrics UI] Fix EuiTheme type issue (elastic#69735)
  skip failing suite (elastic#70104) (elastic#70103)
  [ENDPOINT] Hide the Timeline Flyout while on the Management Pages (elastic#69998)
  [SIEM][CASE] Persist callout when dismissed (elastic#68372)
  [SIEM][Exceptions] - Cleaned up and updated exception list item comment structure (elastic#69532)
  [Maps] remove indexing state from redux (elastic#69765)
  Add API integration test for deleting data streams. (elastic#70020)
  renames SIEM to Security Solution (elastic#70070)
  Adding saved_objects_page in OSS (elastic#69900)
  [Lens] Use accordion menus in field list for available and empty fields (elastic#68871)
  Dynamic uiActions & license support (elastic#68507)
  [SIEM] Update readme for timeline apis (elastic#67038)
  ...
@streamich streamich mentioned this pull request Jul 16, 2020
26 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:Drilldowns Embeddable panel Drilldowns Feature:UIActions UI actions. These are client side only, not related to the server side actions.. release_note:skip Skip the PR/issue when compiling release notes v7.9.0 v8.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants