vCAC has the a built-in feature to define properties as drop down lists that can display information based on a selection of a different (parent) property (as described in the vCAC 5.2 Operating Guide). This is called a “ValueExpression”. Though this mechanism is a bit buggy and might even raise some security issues it is still quite useful in certain scenarios. However, to define a large list of values to be used as a drop down is quite some work if you create it manually. When reading the properties (for example, the classic: a list of network segments based on a location) you have these values stored digitally somewhere anywhere. So the next step would be to “import” it automatically into vCAC. Luckily vCAC has methods and properties to create “Property Definitions” along with “Property Attributes” via its MgmtContext, and PowerShell has an XMLWriter that lets you create XML on the fly quite easily. So here we go (with a shortened version of Cmdlet):

function ConvertTo-VcacArrayOfProperties {
  [CmdletBinding(
    SupportsShouldProcess=$true,
    ConfirmImpact="Low",
  HelpURI='http://dfch.biz/PS/vCAC/Utilities/ConvertTo-VcacArrayOfProperties/'
    )]
Param(
  [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)]
  $InputObject
  ,
  [Parameter(Mandatory = $false, Position = 1)]
  [Alias('fn')]
  [String] $FilterName = 'FilterName'
  ,
  [Parameter(Mandatory = $false, Position = 2)]
  [Alias('fv')]
  [String] $FilterValue = 'FilterValue'
  ,
  [Parameter(Mandatory = $false, Position = 3)]
  [Alias('val')]
  [String] $Value = 'Value'
  )

BEGIN {
  
  $datBegin = [datetime]::Now;
  [string] $fn = $MyInvocation.MyCommand.Name;
  Log-Debug -fn $fn -msg ("CALL. FilterName: '{0}'. FilterValue: '{1}'. Value: '{2}'" 
    -f $FilterName, $FilterValue, $Value) -fac 1;
  [Boolean] $fReturn = $false;
  # Return values are always and only returned via OutputParameter.
  $OutputParameter = $null;
  
  $IO = New-Object System.IO.StringWriter;
  $XmlWriter = New-Object System.Xml.XmlTextWriter($IO);
  $XmlWriter.WriteStartDocument($true);
  $XmlWriter.WriteStartElement('ArrayOfPropertyValue');
  $XmlWriter.WriteAttributeString("xmlns", "xsi", "http://www.w3.org/2000/xmlns/", 
    "http://www.w3.org/2001/XMLSchema-instance");

} # BEGIN
PROCESS {

try {
  foreach($Object in $InputObject) {
    $ValueFilterName = $Object.($FilterName);
    $ValueFilterValue = $Object.($FilterValue);
    $ValueValue = $Object.($Value);
    
    if($PSCmdlet.ShouldProcess( ("FilterName: '{0}', FilterValue: '{1}'. Value: '{2}'" 
      -f $FilterName, $FilterValue, $Value) )) {
      $XmlWriter.WriteStartElement('PropertyValue');
        if($ValueFilterName) {
          $XmlWriter.WriteElementString('FilterName', $ValueFilterName);
        } else {
          $XmlWriter.WriteElementString('FilterName', $FilterName);
        } # if
        $XmlWriter.WriteElementString('FilterValue', $ValueFilterValue);
        $XmlWriter.WriteElementString('Value', $ValueValue);
      $XmlWriter.WriteEndElement();
    } # if
  } # foreach
} # try
catch {
  # ...
} # catch
finally {
  # Clean up
  # N/A
} # finally

} # PROCESS

END {
  $XmlWriter.WriteEndElement();
  $XmlWriter.WriteEndDocument();
  $XmlWriter.Flush();
  $XmlWriter.Close();
  $fReturn = $true;
  $OutputParameter = $IO.ToString().Replace('encoding="utf-16"', 'encoding="utf-8"');
  $XmlWriter.Dispose();
  $IO.Dispose();
  $datEnd = [datetime]::Now;
  Log-Debug -fn $fn -msg ("RET. fReturn: [{0}]. Execution time: [{1}]ms. Started: [{2}]." 
    -f $fReturn, ($datEnd - $datBegin).TotalMilliseconds, 
    $datBegin.ToString('yyyy-MM-dd HH:mm:ss.fffzzz')) -fac 2;
  return $OutputParameter;
} # END

} # ConvertTo-VcacArrayOfProperties
Export-ModuleMember -Function ConvertTo-VcacArrayOfProperties;

There is one gotcha with the XmlWriter that it only produces “utf-16” tagged encodings. vCAC has a default encoding as “utf-8”. With the ugly “.Replace()” we can take care of that.

So whenever reading an array of hastables/dictionary/Properties or having a RecordSet from a SQL database you just pass it to the Cmdlet and tell it the names of the properties within to build the ValueExpression. The returned output you only have to insert as a PropertyAttribute to a PropertyDefintion that you can then link to a BuildProfile or BluePrint directly.

As a side effect: whenever you have to rebuild your vCAC database or you stage from integration to production you now have a reliable, reproducible way to set up your vCAC environment.

1 Comment »

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.