-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
Sharing saved-objects in multiple spaces: phase 2 #54837
Comments
Pinging @elastic/kibana-security (Team:Security) |
Something that recently occurred to me is that I've generally presented index-patterns as an example of a saved-object which would be supported starting in Phase 2. index-patterns don't have references to any saved-objects. However, saved-objects do have references to index-patterns. When originally writing #27004, this seemed fine. It required that the migration be written such that when we regenerate the IDs for these index-patterns, the saved-objects which reference the index-patterns are updated. However, given what we've learned in #59598, not all saved-objects are using references correctly right now. |
@elastic/kibana-security @elastic/kibana-platform @kobelb @stacey-gammon @arisonl I've spent some time discussing this feature with Larry, Brandon, and Rudolf, and I worked out some of the details with a POC. I think I'm ready to finalize the requirements and the technical approach so I can build it. All of your input would be appreciated. I didn't think this really necessitated a full blown Architecture Review meeting, but I'd be happy to schedule one if need be (or hop on separate call/s to walk through and discuss the details). @stacey-gammon @arisonl In particular I'm looking for feedback from you on Section 3 Aliases -- NOTE: The original description for Phase 2 included converting Index Patterns into multi-namespace object types. That is currently blocked based on the issues at the top of the description. However, we can still build the entirety of Phase 2 without being blocked. |
When would a plugin prefer to use How do aliases work with the Saved Objects HTTP API? Unless we resolve ID's for all operations I think this will break any existing integrations (where a hardcoded Saved Object ID is being used)? I might not understand the use-cases we have in mind, but my first reaction is that we should not expose aliases to users as a first-class concept. Although a plugin might wish to implement functionality to create "links" that point to other objects I don't think we should bring this concept into the SavedObjectsRepository. It's not a feature a storage/persistence layer should be concerned with, its part of the plugin's domain. This is better modelled in a higher layer like we currently do with URL saved objects. |
Do we intend to add a reference from a saved object to it's alias so that the alias is also exported? |
I had conversations offline with @stacey-gammon and @rudolf. Summary: How users can interact with Aliases: There is not much real benefit to allowing users to create and edit Aliases. Many URLs in Kibana are quite long (Dashboard, Visualization, etc.) because of our current reliance on storing state in the URL. These users are better served by existing short URL functionality. In a nutshell: we shouldn't add functionality "just because we can", because then we're committing to supporting it long term. As such, we'll keep Alias functionality to a minimum. Consensus appears to be that Aliases are a necessary stop-gap in converting existing saved single-namespace objects to multi-namespace types. In a nutshell:
We will limit the total impact of Aliases by:
The Nice to have / to be discussed:
In the spirit of limiting Alias usage/impact: no. |
My two cents from a user perspective, after chatting with @jportner:
|
Since rewriting ID's will break any Saved Object API integrations this will be a breaking change for users. So the plan as outlined in this issue can only be released in 8.x Having an integration fail every time a new Saved Object type gets converted across several minors will be a very painful experience. Users will more likely adopt the breaking change if it means they can use tagging across all their plugins instead of just a handful. Although we can explore resolving ID's in the Saved Objects API, I would motivate that we postpone releasing this until 8.x. This will also allow us to remove "psuedo copy" which will further simplify the user experience and prevent users from getting into sticky situations. |
I agree that having conversions spread out across minors (and potentially causing integrations to fail across minors) is undesirable, and we should avoid it by lumping all conversions together in a single release. We had good intentions when we planned to convert index patterns first, but that's not even possible for the foreseeable future anyway, so we might as well wait IMO. However, "rewriting ID's will break any Saved Object API integrations": I feel like that statement is disingenuous. It might break some existing integrations that depend upon old IDs in non-Default Spaces, but it isn't guaranteed to break any/all integrations. The introduction of Aliases is specifically intended to avoid breaking external integrations which depend upon Kibana app URLs (such as iframed dashboards/visualizations, for example). These saved objects APIs are experimental and we can change them in a potentially-breaking way in a minor release, though we should have very good reason to do so.
If we don't convert existing saved objects during 7.x, we won't be able to obtain accurate telemetry data to determine if people still depend upon "pseudo copy" before 8.0. We have our assumptions that such usage will taper off when all saved objects are shareable, but we aren't sure. There may be other use cases for pseudo copy that we aren't yet considering. |
Agreed. We should rather break these experimental API's than introduce technical debt which we might never be able to remove or otherwise prevent us from delivering value to users. Still, unless we know we can deliver significant value to users in 7.x, which would mean several plugins adopting multiple namespaces this might not be justified.
As I see it, the reason we want to remove "psuedo copy" is because in a multi-namespace world this feature is fundamentally broken. Keeping it will create confusion and difficult to resolve conflicts for users (not to mention the technical complexity it adds to our code base). If we discover workflows that depend on this we should rather find better alternatives. One use case we already know of is import and export and more specifically selective import/export. The problem is that import/export was written for a single namespace world. When you export a multi-namespace object you loose all the namespace data associated with that object. There is no way to restore an object's namespaces to a previous state. Keeping "psuedo copy" will just put a plaster over the fact that our exports are no longer true backups of the data inside Kibana. |
I met with @arisonl @mdefazio @kobelb @bmcconaghy and @legrego today to discuss the UI/UX for Aliases. Here are the salient points and decisions (please keep me honest if I fudged or forgot anything, folks!):
To summarize, here are the only ways that end users will interact with Aliases:
|
@joshdover wondered if we could introduce a This will significantly reduce the impact on users using our HTTP API. This will probably degrade performance but then the solution would be for users to adapt their code and change Overall I feel like this has a low impact on the code base while significantly lowering the impact on users. Could this work or am I missing something critical? |
I solicited feedback internally before finalizing the "Technical details" section and we agreed not to allow resolving on multiple/all SO APIs. That creates a bigger testing burden for a feature that we ultimately don't want to continue supporting forever. Not to mention that consumers need to understand the resolution "outcome" which required that we change the shape of the response. Where the {
"body": [Object]
} the {
"body": {
saved_object: [Object],
outcome: "exactMatch" // or "aliasMatch" or "conflict"
}
} |
@rudolf and @joshdover, I don't think that we should be adding a Our biggest backward compatibility concern is continuing to support the existing URLs. URLs are a stable contract that we're obligated to support because they're GA and not experimental or beta. Users may have created bookmarks to a specific Dashboard, Visualization, etc. or put links in a Markdown visualization to enable intra-app navigation. During minor version updates, we should continue to support URLs regardless of the amount of effort, maintenance burden or technical debt we incur doing so as breaking this contract would have a significant impact on a large number of users. Regenerating IDs, with the current plan, will create a breaking change for consumers of the saved-object APIs, but I think we should treat this differently than URLs. The breaking change that we're planning to implement will only be for programmatic usage of these APIs for saved-objects outside of the default space using a static ID. This breaking change won't affect all usages of the saved-object APIs, only certain usages. We already have far fewer consumers of these APIs in general, which is further reduced by the conditions in which these breaking changes are relevant. Additionally, the saved-object APIs are currently marked as experimental, so while I do think we should be avoiding introducing breaking changes out of consideration for our users, we do have the leeway to do so when necessary. However, it's my understanding that @jportner is planning to implement telemetry to determine the usage of these APIs, and if we find out from this telemetry that we do have a ton of programmatic consumers outside of the default space, we should likely revisit this decision. |
So, following this logic, it is the type owner's responsibility to change all its calls to I may be wrong, but this seems like way more error-prone, and overall 'dangerous' than allowing to do that 'under the hood' for our base SO apis? |
Yes, exactly.
Well:
|
Phase 2 from #27004.
This is currently blocked on #59960 and #63358
Note to self: add UI docs for Spaces (sharing).
1. Overview
The “Sharing saved objects” feature (#27004) changes how saved objects are stored in Elasticsearch. Particularly, objects that exist in different spaces will no longer be able to have the same ID; each object of a given type must have a globally unique ID.
In Phase 2, we will add support for converting existing "single-namespace" saved object types into new "multi-namespace" types. This entails two core pieces of work:
id
,references
), add new object fields (namespaces
,originId
), and create new Alias objects.Note: the
originId
field is used during Copy and Transform operations, but it is not a substitute for Aliases.2. Migrations
2.1. Usage
When registering an existing object type, consumers will need to change the
namespaceType
field and add a newconvertToMultiNamespaceTypeVersion
field. This new field will inform the Kibana platform that objects of this type need to be converted when Kibana is upgraded to the specified version.(Example)
Before
In Kibana 7.10, the "doodad" object is a single-namespace type:
After
In Kibana 8.0 and later, the "doodad" object is a multi-namespace type:
2.2. Technical Details
The
DocumentMigrator
currently applies consumer-defined "migration transforms" to each object with an outdatedmigrationVersion
field at two times: 1. When Kibana is upgraded, and 2. When creating a new object. During upgrade only, we will apply two new types of transforms:"Conversion transforms"
During the upgrade process, for each object that has an outdated
migrationVersion
field, if its type has aconvertToMultiNamespaceTypeVersion
defined, we apply a "conversion transform" to it.The conversion process follows this algorithm:
namespace
field and add the correspondingnamespaces
field.id
field (using uuidv5)originId
field, equivalent to the old ID"Reference transforms"
The
SavedObject
type will be updated to define a newcoreMigrationVersion
field. Whenever an object is created or Kibana is upgraded, this value is set to match the current Kibana version.During the upgrade process, for each object that has an outdated
coreMigrationVersion
field, its references are enumerated, and we apply one or more "reference transforms" to it. These transforms are defined by other object types.The reference transform is only applied to objects that do not exist in the default namespace. It deterministically regenerates the reference ID for the affected types.
Examples
Kibana 8.0 defines three object types:
Scenario 1: "bar" object
Existing object:
Transforms:
conversion-8.0.0-bar
-->reference-8.0.0-foo
-->migration-8.0.0-bar
Output object:
In addition, an Alias is created with ID 'namespace:bar:111', which points to the new object ID.
Scenario 2: "baz" object
Existing object:
Transforms:
migration-7.10.0-baz
-->reference-8.0.0-foo
-->reference-8.0.0-bar
-->migration-8.0.0-baz
Output object:
3. Aliases
3.1. Usage
A new API will be exposed to retrieve objects use aliases. Instead of
SavedObjectsClient.get
, consumers should useSavedObjectsClient.resolve
. For example, if a consumer callsclient.resolve('bar', '111')
, it will attempt to find an object with the ID or a matching alias with that ID.If an object and alias exist for the same namespace+type+id combination, a new "alias conflict" error will occur. That must be resolved by the end user -- either the object must be deleted, or the alias must be disabled/deleted. Some diagrams that describe this scenario are below.
(Diagrams)
Since "alias conflict" errors can occur, at a minimum users need to be able to directly read and delete object aliases. A user interface will also be needed to facilitate this. We can add two pages:
getTitle
andgetInAppUrl
when that object type is registered).3.2. Technical Details
How aliases will be stored
Aliases will be stored as separate saved objects.
(Example)
We also considered storing aliases in an array inside of each existing object, but decided on this approach instead. Benefits of this approach:
get
instead of search)How aliases will be resolved
The action of "resolving" an alias attempts to find the specified object (namespace + type + ID). There are four possible outcomes when resolving an alias:
Aliases will only be resolved by using the new
SavedObjectsClient.resolve
API.We also considered automatically resolving aliases in all SOC APIs, but decided on this approach instead. Benefits of this approach:
How users can interact with aliases
TBDDecision: end users can only read and delete aliases.(Two approaches were considered -- click to expand)
In the first approach, end users can only read and delete aliases.
In the second approach, end users can create, read, update, and delete aliases.
Benefits of each approach are detailed below:
* We can add create/update functionality later without any rework
Regardless of which approach is used, alias authorization would be determined by the user's Kibana privileges the same way that it is handled for other saved objects.
Time permitting: users will also be able to disable aliases. This may come in handy if they're not sure whether the alias is being used or not.
The text was updated successfully, but these errors were encountered: