📜 ⬆️ ⬇️

PowerShell, AWS CLI and json

When working with the Amazon cloud, it is often necessary to perform many routine operations through the Web console. But I want to automate them.
AWS CLI, a command line interface, is good for this. Of course, you can write an application on Scala, but in everyday tasks it is better to go without “heavy artillery”.
AWS teams can return data in various formats, including json. You can use bash and jq , but the latter is not in the cygwin repository, and install laziness with your hands. Meanwhile, PowerShell has great json support! True, it turned out that taking advantage of it was not entirely easy.
C:\Users\mpotanin> $instance = aws ec2 describe-instances --instance-ids i-ecf1fe5c C:\Users\...> ConvertFrom-Json $instance ConvertFrom-Json : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'InputObject'.    . At line:1 char:19 + ConvertFrom-Json $instance + ~~~~~~~~~ + CategoryInfo : InvalidArgument: (:) [ConvertFrom-Json], ParameterBindingException + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.ConvertFromJsonCommand 

The fact is that json is issued in the form of several lines, and is treated as an array. You can feed him in PowerShell in different ways:
 $instance | ConvertFrom-Json ConvertFrom-Json ($instance -join "") ConvertFrom-Json "$instance" 

Getting the right information is now not difficult:
 (aws ec2 describe-instances --instance-ids i-ecf1fe5c | ConvertFrom-Json).Reservations[0].Instances[0].PublicIpAddress 

In simple cases, retrieving information can be reassigned to aws:
 aws ec2 describe-instances --instance-ids i-ecf1fe5c --query 'Reservations[0].Instances[0].PublicIpAddress' | ConvertFrom-Json 

or even so
 aws ec2 describe-instances --instance-ids i-ecf1fe5c --query 'Reservations[0].Instances[0].PublicIpAddress' --output=text 

So, watching the strange behavior of the autoscaling group through the console, I can copy the instance name with the mouse and access it via ssh:
 function get-address([String]$instanceId) { aws ec2 describe-instances --instance-ids $instanceId --query 'Reservations[0].Instances[0].PublicIpAddress' | convertfrom-json } ssh -i devkey.pem -l ubuntu (get-address i-ecf1fe5c) 


In more complex cases, you have to write a non-trivial code. For example, the output parameters of the cloud formation stack can be obtained as follows:
 function reduce ($f,$a) { if ($a.Length -eq 1) { $a } else { $p = $a[0] foreach ($x in 1..($a.Length-1)) { $p = $f.Invoke($p,$a[$x])[0] } $p } } function get-json($data) { ConvertFrom-json "$data" } function get-cf-outputs($cfName) { $o = (get-json(aws cloudformation describe-stacks --stack-name $cfName)).Stacks[0].Outputs $r = foreach($i in $o) { @{$i.OutputKey = $i.OutputValue} } reduce {param($a,$i); $a+$i } $r } 

Now I can get the parameters of the database connection with the command
 (get-cf-outputs microservice-rds-dev).DatabaseEndpoint 


Passing json to the aws cli commands also surprises. For example, an attempt to add an entry to the dynamodb table simply fails:
 C:\Users\...> aws dynamodb put-item --table-name tableName --item '{"groupId":{"S":"5"}, "ancestors":{"L":[{"S":"5"},{"S":"0"}]}}' Error parsing parameter '--item': Invalid JSON: Expecting property name enclosed in double quotes: line 1 column 2 (char 1) 

That is, somewhere deep aws, cli interprets this line before passing it to the json library. (If it were bash, I would understand, but why it may be needed in a python program is beyond my comprehension.)
To get around this strange behavior, it is enough to escape special characters:
 function put-item([string]$table, $data) { aws dynamodb put-item --table-name $table --item (convertto-json -Depth 128 $data).Replace('\','\\').Replace('"','\"') } 

In principle, there is also a native AWS client for PowerShell, but it seemed to me more complicated and less documented.

')

Source: https://habr.com/ru/post/273473/


All Articles