backstage / backstage

Backstage is an open framework for building developer portals
https://backstage.io/
Apache License 2.0
26.89k stars 5.58k forks source link

[RFC] Entity Links #3787

Closed andrewthauer closed 3 years ago

andrewthauer commented 3 years ago

Status: Open for comments

This is a formal proposal for a discussion on discord

Need

It is common to have existing external information or references related to entities in the catalog. These could often be represented as hyperlinks to some external reference when no related well known annotation or plugin exists. Some examples of this might be.

Having the ability to attach this information to entities would open the world for providing a common Links card component on each entity page. These links could contain some basic context in order to indicate their semantic purpose (e.g. admin-dashboard, or api-docs, etc.)

image

Proposal

Provide a lightweight and quick way to extend an entity with an optional list of basic links to external information & references. This new field could be support some well-known links, org specific links, or specific entity instance links. The list of links could then be managed by entity owners or possibly automatically appended through catalog processors.

apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: petstore
  links: # optional
    - url: https://admin.petstore.com  # required
      rel: admin-dashboard # optional but recommended to provide semantic meaning
      label: Admin Dashboard # optional and could be inferred by rel if omitted
spec:
  type: website
  ...

It would also be nice to have the ability to associate icons to links. This could be done through the rel attribute or perhaps more appropriately an optional icon field (or both with rel as a fallback if provided). The icon value could be an enum value that maps to a icon library such as iconify.

metadata:
  links:
    - url: https://admin.petstore.com
      label: Admin Dashboard
      icon: dashboard-icon

It might be possible to have a short form string version that might be expanded to it's constituent parts. However escaping might be a concern that makes this less feasible. For example:

metdata:
  links:
    - http://admin.petstore.com # just a url
    - url=http://admin.petstore.com,rel=admin-dashboard # a inline map
    - { url: 'http://admin.petstore.com' } # inline yaml object

Alternatives

Links could probably be modeled as annotations:

metdata:
  annotations:
    # Format: [links.backstage.io/${rel}]: [value]
    links.backstage.io/admin-dashboard: https://admin.petstore.com

However, since annotations are typically single values the ability to provide additional context of a label & icon, etc. could be harder to maintain.

Risks

The concept of links can overlap with the existing entity annotations and possibly tags. They also could be modeled by extended either of these existing concepts. Also the concept of links is quite subjective and could mean anything making it a bit abstract and difficult to define when you would use a link versus an annotation.

Forcing people to use annotations to model a simple external reference could mean they don't attach this useful information as it requires additional setup for a specific case. On the flip side having a quick to use links field could be used as a dumping ground and therefore deter people from modelling proper annotations when appropriate. However, these potential points of confusion can be reduced through guidance and documentation.

freben commented 3 years ago

Great summary!

As we said in the chat, I think the url + rel form that you mentioned above is a good balance between easy enough to type and still extensible.

andrewthauer commented 3 years ago

@freben - I'd be happy to take this one on. Assuming there are no high level objections to the idea. Any details can be ironed out as part of a PR.

freben commented 3 years ago

@Rugvip @benjdlambert Opinions? Is the concept of links wise enough, and is the concept scoped correctly? I want them to primarily be informational and drive a links collection in the frontend. My main worry is whether there's an unclear overlap with annotations, or if this for some reason isn't the right place for the data or the right time to introduce it.

But I like the idea, and think it is no more odd than for example tags. This is all becoming a case of extending the metadata model with various "fits" or container types into which users can fit their various concerns.

Fox32 commented 3 years ago

I wonder if it's a good idea to allow "any" icon. That would cause a lot of icons to be included and tree shaking not to work. I think it would be better if the backstage instance (configurable) provides a list of support relations and sets the icon there. That would also make the annotation alternative easier to implement. Sure that would limit how free teams can choose their relations.

Beside that, I would love to see this feature!

freben commented 3 years ago

I'm a bit wary of icons too. Same with labels probably. People will want their own symbology and i18n or whatnot and I agree that it's probably something that, in practice, needs to be stitched up in the app using some facility for that.

Edit: well ok labels - if one looks at the label as a fallback / informative label, it's fine and can be extended with i18n later.

andrewthauer commented 3 years ago

I've viewed both label and icon as optional. For icons I figured it would be up to the app integrator to both define the mappings and setup the frontend to do so. There could be a separate plugin or utility API to help with this. I think labels should be less controversial. Some URLs could be very long and or non descriptive, so I see them being needed in many cases.

Both label and icon which could use an enumeration or semantic key which would allow for each org to customize if needed. This would be a frontend concern which is probably most appropriate for any corresponding widget API.

freben commented 3 years ago

Aha, so icon in the form of enum-to-be-mapped rather than actual identifier into an icon lib. Sounds good.

andrewthauer commented 3 years ago

Although, I suppose rel could likely accomplish this for any standardized links. Anything custom per entity might require at minimum a label in some cases.

GoWind commented 3 years ago

My feedback on this links:

I feel that there is a lot of overlap with annotations to justify this. While a link is more clear as to that this is a link (URL mostly), this can still be managed by an annotation.

If a complex type is needed to be stored as a value of for an annotation it can be serialized into a string during storage and de-serialized later (in fact, i believe this approach is already used by some plugins).

The biggest advantage of Links seem to be that it can provide a rel that can be used to fetch the right icon to display on the frontend. My argument is that the name of the annotation provides the exact same functionality (backstage.io/managed-by-location?, as an example).

As to a reference to an icon, I believe that this a leaky abstraction of how the frontend should display a value, seeping into the backend and thus the data model. Assuming rel to be the type of an icon, there 2 assumptions that I consider might be quite flimsy. a. That the enum of all modelable ref's might be very large (and doesn't make sense to enumerate)

b. All frontend's use the same library (iconify for example) as the icons. While The service catalog working along with the backstage frontend is the standard mode of deployment, I would generally not make assumptions about what exact icon is used by the frontend, to seep into the backend (and thus rel doesn't make sense). It is possible that a user might use a different icon library where the names are completely different, or might have to continue using existing icons that might not have a iconify equivalent. In such cases the ref becomes meaningless.

I hope my argument is coherent and understandable.

freben commented 3 years ago

Hey, thanks for pitching in!

I feel that there is a lot of overlap with annotations to justify this. While a link is more clear as to that this is a link (URL mostly), this can still be managed by an annotation.

Yes, there is a potential overlap as mentioned above. However, the way we tend to think about the purpose of annotations is possibly not well aligned with these links. I think the discussions in this issue (especially the linked comment) may be informative. We should make a separate docs page with these considerations clearly outlined.

Annotations risk becoming a "catch-all" for all kinds of info, and I think we should use them judiciously. We could have encoded labels, some parts of spec, even description, as annotations if we had felt compelled to, but it would probably have been unwise.

It's still not 100% clear cut though, and we are very open to listening to these perspectives.

If a complex type is needed to be stored as a value of for an annotation it can be serialized into a string during storage and de-serialized later (in fact, i believe this approach is already used by some plugins).

Sure, but we really REALLY want to avoid encoding things like this, because humans are writing these files :) Hand-encoding data, and getting it right, is a burden placed on every person in the org that wants to make use of Backstage.

We've talked about relaxing the core schema to let annotations contain any JSON data, not just strings. But no decisions yet.

The biggest advantage of Links seem to be that it can provide a rel that can be used to fetch the right icon to display on the frontend. My argument is that the name of the annotation provides the exact same functionality (backstage.io/managed-by-location?, as an example).

Absolutely. Assuming we'll be happy with rel+url (which is a decent assumption) for this, encoding them as annotations is not a problem as such.

But is the shape of annotations a good fit, or the purpose of annotations?

As to a reference to an icon, I believe that this a leaky abstraction of how the frontend should display a value, seeping into the backend and thus the data model. Assuming rel to be the type of an icon, there 2 assumptions that I consider might be quite flimsy.

Right - but the assumption is that the icon string would be a small set of semantic enum values, along the lines of "docs" and "source" or so, nothing tied into visual representation. Sure the rel could be mapped directly as well, but the same icon would likely be used for several rels (e.g. perhaps the docs icon for both runbook and system diagrams and end user docs etc).

One may say, that the main benefit of the rel+icon split could be that the mapping in the app is potentially smaller to set up for the person installing Backstage. I don't think the set of possible rels will be so large that it's a significant factor though.

GoWind commented 3 years ago

Thanks, read through the issue. I think some of my comments about links are still valid

Annotations risk becoming a "catch-all" for all kinds of info, and I think we should use them judiciously. We could have encoded labels, some parts of spec, even description, as annotations if we had felt compelled to, but it would probably have been unwise.

This is in some ways, unavoidable. Abstractions such as Entity, Component etc do not fit universally and some amount of hacks in implementation is to be expected, especially when migrating existing systems to Backstage. Users will try to use some "catch-all" mechanism to shoehorn existing information. With annotations there will be only one possible mechanism of adding extraneous information , whereas if we were to add links, there are possibly 2 ways of now adding extra information.

Sure, but we really REALLY want to avoid encoding things like this, because humans are writing these files :) Hand-encoding data, and getting it right, is a burden placed on every person in the org that wants to make use of Backstage.

I think it might be also be a hybrid model , wherein some sections/entities might end up being hand-written and others auto-generated. For example, A scaffolder plugin might auto generate a lot of fields for the user when the Entity is being created, so that the YAML description doesn't have to be filled in by hand (or a processor might convert existing models -> Entity definitions).

But most importantly, I want to look at the real purpose driving behind links - What are we trying to link to ?

  1. If they are backstage entities - they can be already linked via relations.
  2. External components (dashboard, monitoring, metrics, etc) - This seems like the use case.

Addressing 2:

We will endup showing icons that link to external components, on say, the Catalog Component. To me, as it stands, it looks like the ONLY location where links could be potentially used is in the Catalog UI, to show a list of links to some external components.

In such a case, why not have these links encoded as annotations ? Curently, the Catalog UI uses an annotation to show a link to the Source code and to Tech Docs on the overview page. We also use an annotation to enable an Icon to the CI/CD Tab. We can thus allow plugins to show other visual information using the same mechanism.

In the future, the same annotations can be re-used by other plugins as well. For example, instead of linking to an external metrics dashboard, if the same were to be implemented as a frontend plugin within Backstage, the annotation can be used directly by the Dashboard plugin to provide a dashboard for the Entity in the same SPA.

I don't see non-standardized annotations as an issue. The nice thing about annotations are that they are arbitrary and opt-in (that is feature / plugin X is not activated unless annotation A exists). Plugins can simply ignore the annotations that they do not care about.

You can have an arbitrary number of links to external entities, but I doubt that most PMs, Designers, front-end devs would want to show all of them in an uncontrolled fashion. Most likely there will be certain UI components rendered based on a certain rel or a label. If that is the case, then annotations are just as suitable, and as per @Rugvip 's comments the intended usecase for annotations.

freben commented 3 years ago

The links are in my mind primarily scoped to human, informative (not normative), display. To me, their current intended model is so weak, that they could almost be intentionally left inside description or as part of the README.md of components if we made it possible to ingest and display that. I expect the main consumer of this information is a person that wants to know more about a component that is foreign to them, or for the owners of a component to have a convenient hotlink to monitoring interfaces etc.

It could be a case of an org telling their teams that "Hey please put a runbook link in all of your components, it helps our OPS team to find it more easily".

Note that the links is data that is meant to be written and then read verbatim, just like for example description. Relations are output-only data that could be generated from any other type of input. The links data is super simple and scope-limited when compared to any relation-generating field.

A monitoring related annotation could for example hold some app ID string only. This is great for plugins and other consumers to be able to shape requests to other systems, or form an auto generated entity tab with some helpful default graphs based on requests to your TSDB, etc etc. A link however, could point to your exact main grafana dashboard that you hand crafted and use on your on-the-wall-in-your-team-area monitoring screen.

I don't see non-standardized annotations as an issue. The nice thing about annotations are that they are arbitrary and opt-in (that is feature / plugin X is not activated unless annotation A exists). Plugins can simply ignore the annotations that they do not care about.

This is quite right.

GoWind commented 3 years ago

The links are in my mind primarily scoped to human, informative (not normative), display. To me, their current intended model is so weak, that they could almost be intentionally left inside description or as part of the README.md of components if we made it possible to ingest and display that. I expect the main consumer of this information is a person that wants to know more about a component that is foreign to them, or for the owners of a component to have a convenient hotlink to monitoring interfaces etc.

It could be a case of an org telling their teams that "Hey please put a runbook link in all of your components, it helps our OPS team to find it more easily".

This sums up my feelings as well. I do not think that they are strong enough yet to warrant being added to the core model of entities.

How much interest is in the rest of the community for a feature such as this ? If there isn't much, then perhaps this can be avoided for now ? Or , as an alternate maybe links can be added to the model and documented as an experimental entry in the alpha versions and based on usage, feedback modified or removed later ? As owners you will have to make a decision on this :)

andrewthauer commented 3 years ago

Some good points here for sure.

One strong reason for proposing some sort of links structure is to enable entities to become the central knowledge base for all related things to that entity. A backstage instance will likely gain higher adoption if it can centralize as much information as possible in a single place. There are many things that could be related to an entity / component that are external to backstage and have a low ROI on integrating them into backstage proper. This is where links come into play. They provide a simple way to extend the entity with useful information about the entity and therefore making backstage more useful.

Icons & custom labels are not a necessity, but they do provide a strong UX addition imo. Icons provide a meaningful visual landmark that is easy to parse visually. I think a strict combination of just a rel key & url could be used to model external links and potentially support icons and custom text. The rel key in this case would need to be semantic and meaningful by itself. If this is the case it could be modeled through annotations or a new metadata.links field. However the annotations option would be less extensible and require encoding JSON, etc. which would not be human friendly for maintaining.

As for custom icons, the team maintaining an orgs backstage instance, could setup and provide the appropriate mapping for icons & text. I can see this being necessary from a UX perspective. Take for instance a link to an operational dashboard. The rel might be apm-dashboard, which might be more meaningful to end users to show a grafana icon in some cases or datadog in others. Also, the terminology for apm-dashboard might be different. Now that I think of this a little more, I'm not sure this use case is specific to this RFC. There will be many links used throughout backstage and within various plugins. Having the ability to customize icons and text for more general concepts will pose a similar concern around consistency and customization and tailoring for a specific org. Perhaps this warrants an additional RFC around a potential core API that plugins use which can allow each backstage instance to customize terms, icons, etc.?

A completely different approach to links, could be to create a new entity type and then use an entity relationship to map the entity to the links provider entity. This approach could potentially be a way to extend the entity with arbitrary metadata (not just for links). However, this high level idea feels a little wonky, but I thought I'd just toss it into the discussion.

GoWind commented 3 years ago

A completely different approach to links, could be to create a new entity type and then use an entity relationship to map the entity to the links provider entity. This approach could potentially be a way to extend the entity with arbitrary metadata (not just for links). However, this high level idea feels a little wonky, but I thought I'd just toss it into the discussion.

IMHO, this would simply be replicating the relationship in a new High level entity that duplications the relations field. I think having one place to model relationships would be preferable.

There will be many links used throughout backstage and within various plugins. Having the ability to customize icons and text for more general concepts will pose a similar concern around consistency and customization and tailoring for a specific org. Perhaps this warrants an additional RFC around a potential core API that plugins use which can allow each backstage instance to customize terms, icons, etc.?

I am not a frontend dev, but I assume that to display a certain icon for a link, Backstage UI devs would be writing specific components for a url + rel combo, or a generalinzed Link component that knows exactly which img / svg to fetch based on the rel ? If that is the case, then I do not see a lot of value around standardized icons and terms as there will be PMs and designers doing the very same (feel free to counter this in case I missed something ).

andrewthauer commented 3 years ago

IMHO, this would simply be replicating the relationship in a new High level entity that duplications the relations field. I think having one place to model relationships would be preferable.

Agreed. I only brought this up for completeness in exploring options.

I am not a frontend dev, but I assume that to display a certain icon for a link, Backstage UI devs would be writing specific components for a url + rel combo, or a generalinzed Link component that knows exactly which img / svg to fetch based on the rel ? If that is the case, then I do not see a lot of value around standardized icons and terms as there will be PMs and designers doing the very same (feel free to counter this in case I missed something ).

I think my point may have been unclear here. I was implying the opposite of standardizing icons and text, but making it possible to customize them per backstage instance. This is somewhat related to #3560, but in this case would apply to various labels and icons used throughout the app & plugins. To your point, doing so would require the team maintaining the backstage instance to use some sort of API that allows customization or text and icons throughout the app. In the case of an EntityLink component it might be providing a provider interface that maps rel to a react icon component. Then of course there would be a a fallback (perhaps a material-ui globe icon). The same pattern could be applied to text labels as well. There are of course other ways to accomplish this. I see this as a possible related extension of this RFC.

How much interest is in the rest of the community for a feature such as this ? If there isn't much, then perhaps this can be avoided for now ? Or , as an alternate maybe links can be added to the model and documented as an experimental entry in the alpha versions and based on usage, feedback modified or removed later ? As owners you will have to make a decision on this :)

It seems the concern here is not around the conceptual idea itself, but more about how they are modeled in to the catalog. I'm open to modeling links as annotations using the links.backstage.io/[rel]: [url] pattern if we feel this is more appropriate. The caveat is that the rel key will be the only semantic identifier since annotation values in their current form do not handle complex structures in a human friendly way.

Having links for our company is essential to helping backstage become more widely adopted and useful. We need a quick way to associate custom links to entities without the ceremony of adding a full fledged backstage integration. We can definitely do this as a custom extension of the entity model, but would prefer to have community accepted solution to this.

Rugvip commented 3 years ago

Throwing in that I'd vote for going with, and adding support for, some version of

metadata:
  annotations:
    backstage.io/links:
      - url: ...
        title: ...
        rel: ...
      - url: ...
        title: ...

I do think having a simple way to add a couple of links is important, it's very widely used in the internal version

andrewthauer commented 3 years ago

@Rugvip - So you are suggesting that annotations be extended to support native objects rather then just JSON encoded strings?

I think this could be useful for other means as well. There is already a case that we ended up encoding a JSON string value for a custom annotation. However, the annotation in that case is populated via a catalog processor so its never manually edited.

I think it would be nice to have a short form string version where only rel + URL is provided though. This is one nice thing about the rep being embedded into the key. However there could also be a short form version with a separator to accomplish a similar result.

Would that also mean that certain annotation keys could have their own schemas and validated as such?

Rugvip commented 3 years ago

@andrewthauer yep, had a couple of cases where it would be useful to allow any JSON value as annotation value. Wanna do that change along with removing any way to query annotations by value from the catalog :>

String format would be fine too, but modelling it as multiple annotations is still gonna get pretty meh. You'll have to both figure out enumeration, which is prolly easy enough, but also ordering. Someone that is adding the links will usually want to have the order intact, which JSON processing may or may not do ^_>

freben commented 3 years ago

Still not sure what "makes" this an annotation. That's a pretty special concept. What makes it not go directly in metadata, and how is it different from e.g. description and tags? Does it match your list of criteria for what goes where?

andrewthauer commented 3 years ago

Still not sure what "makes" this an annotation. That's a pretty special concept. What makes it not go directly in metadata, and how is it different from e.g. description and tags? Does it match your list of criteria for what goes where?

I'll rule out 2 of these based on the following:

Annotations, as described in the backstage docs seem to fit the closest of the these. The fact they are non identifying and can be references to external systems seems to match the majority of use cases for links.

I can't see a super strong reason for having them as their own top level metadata vs annotations. Especially if annotations are to be extended to support JSON values. Having them as annotations seems to be the more natural fit that doesn't require introducing something completely new.

freben commented 3 years ago

Oh yeah I didn't mean to use tags or description to model links; I meant that to me, links feel like the exact same class of information as those.

The root of the metadata blob is open for extension and I expect people to throw in more metadata-like things there for their own purposes. But labels and annotations are very specific fields with specific purposes, limitations and semantics. So to me the annotations don't feel like a place to just throw things into or a catch-all; they feel lite something to only pick consciously for a certain subset of things.

That's what led me to wonder what makes links special.

freben commented 3 years ago

Essentially,

A well defined application ID/slug that's used to enable plugins/features in the frontend, and which is used to form queries into third party systems -- sounds like an excellent candidate for an annotation, or actually even a label since you may want to query on a bag of entities related to an application

A random bag of links to various stuff, only used in an informative sense for people to click on -- definitely not annotation like

In my mind :)

andrewthauer commented 3 years ago

The thinking that these are not slugs or identifiers which sets them apart from annotations resonates with me. Therefore, to avoid confusion with typical annotations then perhaps modeling them as a new optional metadata field makes most sense. Especially if metadata is mean to be open for extension. We could simply start out with:

metadata:
  name: foobar
  links: # optional
    - rel: admin-dashboard
      url: https://admin.example.org
    - rel: confluence # maybe rel should also be optional?
      url: https://confluence.example.org/foobar

Maybe the term relatedLinks (or something else) instead of just links might be more meaningful as well?

metadata:
  name: foobar
  relatedLinks:
    - rel: admin-dashboard
      url: https://admin.example.org

Are there any major downsides to adding this as an optional field to metadata besides potentially the risk of people misusing the fields for things that should be more appropriately annotations? I think there will always be potentially the confusion with annotations, but the rationale of them not being slugs or identifiers is a strong case of distinction.

Another thing to note, is that adding a link wouldn't preclude the fact of also adding a related annotation. The difference being the related annotation would be used to drive UI functionality versus a link is just a link. For example, I don't see there being an issue if there is a link to the GitHub project and also a github.com/project-slug annotation that drives the GH actions UI. The difference being there should be no expectation that adding it as a link will do anything more then provide a hyperlink in the UI.

andrewthauer commented 3 years ago

Any additional feedback on this? Based on the last couple of comments, there could be a clear distinction of what a link is and why it may not make sense to model as an annotation. cc @freben, @Rugvip, @GoWind?

freben commented 3 years ago

Not from me. My mind is pretty set on metadata.links.[].{rel,url} at this point :) I'd vote to go ahead and implement, and then extend in the future if we find that we want to decide icons and labels and stuff.

freben commented 3 years ago

By the way, to be clear, @andrewthauer are you looking to do the actual work to add this?

freben commented 3 years ago

Or shall we make a help-wanted issue with the details

Rugvip commented 3 years ago

@andrewthauer Feeling pretty strongly that we should have some proper real-world use-cases to that uses rel if we want to add it. If we want to use it so select where the links go, then let's have some idea of how. If we want to use it for icons we should get that system in place first imo, an app-wide catalog of icons tied to identifiers that people can use, probably accompanied by an icon-browser-plugin for users to use to discover icons.

Even at that point there should be some got reasons to use rel instead of icon, which was also mentioned in the original proposal. We shouldn't forget that these links are gonna be typed out and read by humans and all kinda of disciplines and tech savviness, leaning on established web terminology might make sense for us, but perhaps not for a data scientist.

I actually think the original proposal looks good:

metadata:
  name: petstore
  links: # optional
    - url: https://admin.petstore.com  # required
      rel: admin-dashboard # optional but recommended to provide semantic meaning
      label: Admin Dashboard # optional and could be inferred by rel if omitted

Just that we should drop the rel for now until there's some clear usage. Then I'd open up for a quick debate whether we should go with something else than label as it has potential to be confused with a less human readable concept, kinda like tags. Calling it e.g. title would make it clear that it is for display only, assuming that is what we want.

When it comes to short form it's possible that we could allow just the URL by itself, but tbh we'd only be saving a couple of url:'s. Internally we have a '[Admin Dashboard](https://admin.petstore.com)' form, let's not do that. I think the object form is short enough tbh, typically you wouldn't want too many links anyway as it just clutters the page.

Regarding metadata vs annotation, I'm still sticking to my opinion that we should only be consuming annotations and other labelled data buckets in plugins, to allow for long-term evolution. The links can go in metadata.links, but we'd move them to an annotation in the standard entity processor. Not something that should be blocking this issue though, so happy with just putting and consuming them from metadata for now.

andrewthauer commented 3 years ago

By the way, to be clear, @andrewthauer are you looking to do the actual work to add this?

@freben - Yes, I was thinking of tackling this. Would probably be split into at least 2 or 3 PR's starting with extending the entity model and then providing a component that can be used as a widget in the entity overview page.

Feeling pretty strongly that we should have some proper real-world use-cases to that uses rel if we want to add it. If we want to use it so select where the links go, then let's have some idea of how. If we want to use it for icons we should get that system in place first imo, an app-wide catalog of icons tied to identifiers that people can use, probably accompanied by an icon-browser-plugin for users to use to discover icons.

@Rugvip - I'm viewing rel as more of a slug or type. They would be used to semantically identify what the link represents (e.g. admin-dashboard, logs, storybook, etc.). It would be optional and used similarly to how component.spec.type is meant to tailored to an org. The most concrete use case of consuming this would be to define a icon mapping resolver in which the team maintaining backstage could provide a registry that maps this rel identifier to an icon of their choice which in turn is used by an EntityLinks component. If none is provided it fallback to something generic link a globe icon. Roughly speaking it might boil down to something like:

{links.map(link => {
  const { title, icon, url } = linkRegistry.resolve(link);
  return (<EntityLink text={title} href={url} icon={icon} />);
}}

To your point, maybe rel and label are not the most intuitive names. Perhaps title and type might be more clear?

metadata:
  name: petstore
  links: # optional
    - url: https://admin.petstore.com  # required
      type: admin-dashboard # optional
      title: Admin Dashboard # optional

We could leave out rel/type for now, but I actually feel like it might be more useful and succinct then title. If the org chooses to support a set of well known rel/types then it's easier to maintain consistency and provide context for what the link represents.

Regarding metadata vs annotation, I'm still sticking to my opinion that we should only be consuming annotations and other labelled data buckets in plugins, to allow for long-term evolution. The links can go in metadata.links, but we'd move them to an annotation in the standard entity processor. Not something that should be blocking this issue though, so happy with just putting and consuming them from metadata for now.

Agreed. Metadata links should not be used to drive anything in plugins. We can provide a builtin component to display them as a card widget, but beyond that they should not be used for anything but purely informational purposes. It might be common to start out with a simple link and then upgrade it to an annotation that provides more rich functionality via plugins, etc.

freben commented 3 years ago

After talking a bit yesterday I also was swayed in favour of actually having a title in there after all. My initial idea of rel being able to express essentially both title and icon won't work out in practice; it'll just dilute the rel/type into needing a ton of different possible values.

If we leave the title optional too, I'm not sure how we would draw the actual link in the frontend :)

andrewthauer commented 3 years ago

My thinking was title would resolve using link.title | customTitle(link) | link.url. So the fallback would be the URL if it's optional. I see no problems supporting title as per the original proposal but don't see a strong need to make it required (although it would be recommended to have it). That said, I can go either way.

Are we suggesting supporting title along with rel/type or just URL & title?

freben commented 3 years ago

required url, optional type, optional title sounds good to me - @Rugvip?

Rugvip commented 3 years ago

@andrewthauer @freben yeah was also thing just show the URL itself if the title isn't set.

Regarding type I again think it should be driven be a clear and conrete need. If it's only for icons I think an icon field would be better, but if it's also for deciding how and where to display the link then we should have some ideas for how that would actually be reflected in the UI.

andrewthauer commented 3 years ago

Perhaps icon might be more appropriate since it really is the main use case. I never had the intention for these links to be filtered or selectively used as a subset based on the type. One could still resolve the title based on the icon key if desired, but this would potentially be a misuse of icon. So ...

metadata:
  name: petstore
  links: # optional
    - url: https://admin.petstore.com  # required
      title: Admin Dashboard # optional
      icon: dashboard # optional

Are we ok having the icon value as a key like string? The intention being any components displaying links would have the option of using this icon key to map to an appropriate react icon. This approach would provide the most flexibility but would put more work on the maintainers of backstage. Although, I suspect it could be extended to make this easier and more automatic.

Rugvip commented 3 years ago

@andrewthauer Yep! As long as we also include at least a rudimentary icon system in the initial PR, perhaps with just a couple of hardcoded icons, but with some clear IDs of how to expand and making them configurable.

Vity01 commented 7 months ago

@Rugvip 2 years later, any chance for an extended icon system? why it's not possible to load any MUI icon by name?

freben commented 7 months ago

We've talked recently (after #17474) about how it might make sense to introduce something like an iconsApi or similar. Nothing promised or designed yet, though. Loading MUI icons by name could be one of those implementations, but I'm not sure how that would work in practice. Drawback of that is that now you forcibly package the entire huge MUI icons library in your bundle, no matter how few of them are used in practice. Maybe some allowlist or so then? I don't know.