itglue / powershellwrapper

This PowerShell module acts as a wrapper for the IT Glue API.
Apache License 2.0
120 stars 51 forks source link

Writing Flexible Assets #143

Open mrobinson-ws opened 2 years ago

mrobinson-ws commented 2 years ago

So, 2 things: 1) I cannot ONLY update 1 item in a flexible asset, it overwrites with only the data I enter 2) I have written out a way to pull the data into my $data variable, and it works for basic flexible-assets. If I add one that has a "contact" entry, it will not send back.


$org = Get-ITGlueOrganizations -filter_name "Contoso Corporation"
$alltypes = Get-ITGlueFlexibleAssetTypes
$selectedtype = $alltypes.data.attributes.name | Sort-Object | Out-GridView -Title "Select the category to search for changes" -OutputMode Single
$type = Get-ITGlueFlexibleAssetTypes -filter_name $selectedtype
$assets = Get-ITGlueFlexibleAssets -filter_flexible_asset_type_id $type.data.id -filter_organization_id $org.data.id
$chosenassets = $assets.data.attributes.name | Sort-Object | Out-GridView -Title "Select $selectedtype items to Edit" -Passthru
foreach($chosenasset in $chosenassets){
    Clear-Variable data -ErrorAction SilentlyContinue
    Clear-Variable asset -ErrorAction SilentlyContinue
    Clear-Variable AssetTraits -ErrorAction SilentlyContinue
    $asset = Get-ITGlueFlexibleAssets -filter_flexible_asset_type_id $type.data.id -filter_organization_id $org.data.id -filter_name $chosenasset
    $data = @{
        type = $asset.data.type
        attributes = @{
            traits = @{

            }
        }
    }

    [array]$AssetTraits = $asset.data.attributes.traits | Get-Member | Where-Object {$_.MemberType -eq "NoteProperty"}
    for ($i = 0; $i -lt $AssetTraits.Count; $i ++)
    {
        if($AssetTraits[$i].Definition -match 'string' -or 'int' -or 'bool'){
            $data.attributes.traits += @{
                "$($AssetTraits[$i].Name)" = $asset.data.attributes.traits."$($AssetTraits[$i].Name)"
            }
        }
        else{
            [array]$NonStringObject = $asset.data.attributes.traits.'$($AssetTraits[$i].Name)'.values | Get-Member | Where-Object {$_.MemberType -eq "NoteProperty"}
            for ($j = 0; $j -lt $NonStringObject.Count; $j ++){
                $data.attributes.traits += @{
                    "$($AssetTraits[$i].Name)" = @{
                        "$($NonStringObject[$j].Name)" = $asset.data.attributes.traits."$($AssetTraits[$i].Name)"."$($NonStringObject[$j].Name)"
                    }
                }
            }
        }
    }

    $changes = $data.attributes.traits | Sort-Object | Out-GridView -Title "Select Items to change on $($asset.data.attributes.name)" -Passthru
    foreach($change in $changes){
        Clear-Variable newvalue -ErrorAction SilentlyContinue
        $newvalue = Read-Host "Enter new value for $($change.name), the current value is $($Change.value)"
        if($newvalue){
            $data.attributes.traits."$($Change.Name)" = $newvalue
            Write-Host "Value has been changed to $($Data.attributes.traits."$($Change.Name)")"
        }
        else
        {
            Write-Host "No changes made"
        }
    }
    Try{
        Set-ITGlueFlexibleAssets -id $asset.data.id -Data $data -ErrorAction Stop
        Write-Host "Updated ITG with changes"
    }
    Catch {
        Write-Host "ITG Update Failed"
    }
}

Basically, it reads everything in to the $data variable, and if it's an object type that Powershell doesn't know, it adds it in. I can compare my "asset" to my "data" and everything is exactly the same in terms of object type, membership, etc. Any insight would be appreciated.

image

image image

Using a Flexible-Asset without the "contact" field, it works without issue: image

ecspresso commented 2 years ago
  1. I cannot ONLY update 1 item in a flexible asset, it overwrites with only the data I enter

This is intended. Not sure if it stated in more the one place but look at Flexible Assets | Update:

Any traits you don't specify will be deleted. Passing a null value will also delete a trait's value.

 

  1. I have written out a way to pull the data into my $data variable, and it works for basic flexible-assets. If I add one that has a "contact" entry, it will not send back.

Wild guess here, I don't work with IT Glue anymore so I cannot test this but do you have a Hashtable or a PSCustomObject when you are updating contacts? That is the only difference I can spot at a glance.

Try replacing the dot annotation for adding new keys to your hashtables with squre brackets.

$data.attributes.traits += @{
    "$($AssetTraits[$i].Name)" = $asset.data.attributes.traits."$($AssetTraits[$i].Name)"
}

becomes

$data["attributes"]["traits"] += @{
    "$($AssetTraits[$i].Name)" = $asset["data"]["attributes"]["traits"]"$($AssetTraits[$i].Name)"
}

Since it works with contacts and not flexible assets, there has to be a difference between the two API calls or there is a bug (very possible given the 500 error code), in which case you will have to talk to the IT Glue support. I suggest looking close at what kind of data you have and that everything looks correct. If it does, contact their support.

mrobinson-ws commented 2 years ago

I was thinking it had to do with that. It ends up creating that "subobject" (for lack of a better term) as a pscustomobject, even in it's own pulled data, but the $data variable has to go back as a full hashtable, so if the brackets do that, that should do it. I'll update after I've had time to test. Thanks!

Edit: I think there was a bit of a misunderstanding. The "contacts" is a subobject inside the flexible-asset, and it does NOT work if it is included. It DOES work without it being included.

So, the bit you square bracketed is the working bit, the chunk underneath (nonstringobjects - badly named, I know) is the bit I will have to test. Thanks again though!

mrobinson-ws commented 2 years ago

Ok, I've updated the relevant block to as shown below:

[array]$AssetTraits = $asset.data.attributes.traits | Get-Member | Where-Object {$_.MemberType -eq "NoteProperty"}
    for ($i = 0; $i -lt $AssetTraits.Count; $i ++)
    {
        if($AssetTraits[$i].Definition -match 'string' -or 'int' -or 'bool'){
            $data.attributes.traits += @{
                "$($AssetTraits[$i].Name)" = $asset.data.attributes.traits."$($AssetTraits[$i].Name)"
            }
        }
        else{
            [array]$NonStringObject = $asset.data.attributes.traits.'$($AssetTraits[$i].Name)'.values | Get-Member | Where-Object {$_.MemberType -eq "NoteProperty"}
            for ($j = 0; $j -lt $NonStringObject.Count; $j ++){
                $data["attributes"]["traits"] += @{
                    "$($AssetTraits[$i].Name)" = @{
                        "$($NonStringObject[$j].Name)" = $asset["data"]["attributes"]["traits"]."$($AssetTraits[$i].Name)"."$($NonStringObject[$j].Name)"
                    }
                }
            }
        }
    }

I am still getting the same error when attempting to update with a contact (which is basically a full sub-object/array inside the original array). Sorry for the delay, haven't had much time to get back on this one.

ecspresso commented 2 years ago

At this point, I would contact the IT Glue support, the problem could very well be at their side. I've had problems before with the API which they helped me solve.