aws / aws-tools-for-powershell

The AWS Tools for PowerShell lets developers and administrators manage their AWS services from the PowerShell scripting environment.
Apache License 2.0
241 stars 79 forks source link

Tag Model not portable between Services #53

Open petervandivier opened 5 years ago

petervandivier commented 5 years ago

Explicit *.Tag types should be portable between services.

Expected Behavior

I would like to be able to re-use an object of type [Amazon.EC2.Model.Tag] when tagging within the ElasticLoadBalancingV2 service.

PS > $tag = [Amazon.EC2.Model.Tag]@{Key='foo';Value='bar'}
PS > New-EC2Tag -ResourceId $vpcId -Tag $tag
PS > Add-ELB2Tag -ResourceArn $arn -Tag $tag

Current Behavior

ELB2 rejects strongly typed EC2 tags and disallows allow explicit casting from [Amazon.EC2.Model.Tag] to [Amazon.ElasticLoadBalancingV2.Model.Tag]

Steps to Reproduce (for bugs)

PS > Add-ELB2Tag -ResourceArn $arn -Tag $tag
Add-ELB2Tag : Cannot bind parameter 'Tag'. Cannot convert the "Amazon.EC2.Model.Tag" value of type "Amazon.EC2.Model.Tag" to type "Amazon.ElasticLoadBalancingV2.Model.Tag".
At line:1 char:36
+ Add-ELB2Tag -ResourceArn $arn -Tag $tag
+                                    ~~~~
+ CategoryInfo          : InvalidArgument: (:) [Add-ELB2Tag], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Amazon.PowerShell.Cmdlets.ELB2.AddELB2TagCmdlet

PS > $tag = [Amazon.ElasticLoadBalancingV2.Model.Tag]$tag
Cannot convert the "Amazon.EC2.Model.Tag" value of type "Amazon.EC2.Model.Tag" to type "Amazon.ElasticLoadBalancingV2.Model.Tag".
At line:1 char:1
+ $tag = [Amazon.ElasticLoadBalancingV2.Model.Tag]$tag
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : ConvertToFinalInvalidCastException

Possible Solution

As a workaround, currently you can strip the typing from the tag and convert it to a generic hash (optionally re-casting to the Tag type of your target service if needed)

PS > $tag = [Amazon.ElasticLoadBalancingV2.Model.Tag]($tag | ConvertTo-Json | ConvertFrom-Json)  
PS > Add-ELB2Tag -ResourceArn $arn -Tag $tag 
PS > (Get-ELB2Tag -ResourceArn $arn).Tags | Where Key -eq $tag.Key

Key Value
--- -----
foo bar

Context

I was extracting tags from a TagSpecification object used for deploying EC2 instances into an ELB2 tag array so that I could have common tags on the load balancer infrastructure as on the EC2 hosts.

As a point of interest, it appears that tag types are silo'd between other services not named here as well.

PS > [Amazon.IdentityManagement.Model.Tag]$tag
Cannot convert the "Amazon.ElasticLoadBalancingV2.Model.Tag" value of type "Amazon.ElasticLoadBalancingV2.Model.Tag" to type "Amazon.IdentityManagement.Model.Tag".
At line:1 char:1
+ [Amazon.IdentityManagement.Model.Tag]$tag
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : ConvertToFinalInvalidCastException

Your Environment

PS > Get-Module AWSPowerShell

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Binary     3.3.563.1  AWSPowerShell                       {Add-AASScalableTarget, Add-ACMCertificateTag, Add-ADSConfigurationItemsToAppli…

PS > $PSVersionTable

Name                           Value
----                           -----
PSVersion                      6.2.3
PSEdition                      Core
GitCommitId                    6.2.3
OS                             Darwin 18.7.0 Darwin Kernel Version 18.7.0: Tue Aug 20 16:57:14 PDT 2019; root:xnu-4903.271.2~2/RELEASE_X8…
Platform                       Unix
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
matteo-prosperi commented 5 years ago

Hello, thank you for providing this feedback I can see how this would improve the user experience.

ghost commented 5 years ago

+1 to treating various services' .Tags attribute as a hash table. It should not be this hard to extract an instance's Name tag: $ThisInstance.tags |?{$_.Key -eq 'Name'} | select -ExpandProperty value ...where I'd much rather: $ThisInstance.tags['Name']

jakauppila commented 4 years ago

The more work I do with the module, the more painful this becomes. I would love if the tags could be treated as a hash table both on responses and as inputs on cmdlets.

jakauppila commented 3 years ago

Just to give another example to demonstrate the pain this causes.

In this example, I query for all secrets that have a system tag of CONTOSO and want to filter the responses with secrets that also have a environment tag of PRODUCTION (this is because Secrets Manager unfortunately cannot initially query on multiple tag key/value pairs).

I must iterate over all secrets, and then iterate over each tag in order to identify the tag in question, retrieve the value, and do the compare:

$assetSecrets = Get-SECSecretList -Filter @(
  @{Key = 'tag-key'; Values = 'system' },
  @{Key = 'tag-value'; Values = 'CONTOSO' }
)

$assetSecrets | Where-Object {($_.Tags | Where-Object($_.Key -eq 'environment') | Select-Object -ExpandProperty 'value') -eq 'PRODUCTION'}

I would rather just specify the following:

$assetSecrets | Where-Object {$_.Tags['environment'] -eq 'PRODUCTION'}
github-actions[bot] commented 2 years ago

We have noticed this issue has not received attention in 1 year. We will close this issue for now. If you think this is in error, please feel free to comment and reopen the issue.

jakauppila commented 2 years ago

This would still be incredibly useful to have

ashishdhingra commented 1 year ago

The model classes in SDK are autogenerated and strongly types objects cannot be used from one model to other. May be Tag class could be inherited from common interface, however, unsure if it is feasible. Needs review with the team.