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

Resource IDs: new Common ID for CompositeResourceID #188

Closed
tombuildsstuff opened this issue Nov 3, 2023 · 1 comment
Closed

Resource IDs: new Common ID for CompositeResourceID #188

tombuildsstuff opened this issue Nov 3, 2023 · 1 comment
Assignees
Labels
enhancement New feature or request new-common-id

Comments

@tombuildsstuff
Copy link
Contributor

tombuildsstuff commented Nov 3, 2023

Composite Resource IDs are two Resource IDs combined together with a pipe character (e.g. {first}|{second}) and are used in the AzureRM Provider primarily for Virtual Resources which map 1:1 - for example the association resources.

Whilst every time we need one of these today we end up reimplementing the same logic, we should be able to use Generics to have a single Composite Resource ID which both implements the ResourceId interface, but also takes two generic arguments for the ResourceId type, for example:

// to ensure this implements `.ID()` and `.String()` so this can be used as a regular Resource ID
var _ resourceids.ResourceID = CompositeResourceID[resourceids.ResourceId, resourceids.ResourceID]{}

type CompositeResourceID[T1 resourceids.ResourceId, T2 resourceids.ResourceID] struct {
  First T1
  Second T2
}

However where this currently falls down is the way that ResourceID Parsing is done, where the resourceids.Parser.Parse method returns a ParseResult, which is a mapping of the Resource ID Segment Name : Values - which must be then assigned to the Fields within each struct, which isn't currently possible without calling the specific Parse functions for T1 and T2 above.

As such, this work is dependent on #190, which adds a new FromParseResult method to the resourceids.ResourceId interface, but once that's available it should be possible to make a generic Parse function similar to below:

func Parse[resourceids.ResourceId, T2 resourceids.ResourceID](input string) (*CompositeResourceID[T1, T2], error) {
  components := strings.Split(input, "|")
  if len(components) != 2 {
    // TODO
  }

  output := CompositeResourceID[T1, T2]{}

  // Parse the first of the two Resource IDs from the components
  firstParser := resourceids.NewParserFromResourceIdType(T1{})
  firstParseResult, err := firstParser.Parse(components[0], false)
  if err != nil {
    // TODO
  }
  first, err := T1{}.FromParseResult(firstParseResult.ParseResult)
  if err != nil {
    // TODO
  }
  output.First = first
  
  // ...
}

Which would mean that the code used in the Provider can be reduced from:

components := strings.Split(d.GetID(), "|")
if len(components) != 2 {
  // TODO
}
first, err := ParseFirstID(components[0])
if err != nil {
  // TODO
}
second, err :=ParseSecondID(components[1])
if err != nil {
  // TODO
}

To the same as used elsewhere in the Provider:

id, err := ParseCompositeResourceID[FirstId, SecondId](d.GetID())
if err != nil {
  // TODO
}
@tombuildsstuff
Copy link
Contributor Author

Closing since this has shipped

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request new-common-id
Projects
None yet
Development

No branches or pull requests

2 participants