https://pulumi.com logo
#python
Title
# python
c

colossal-room-15708

04/14/2020, 5:33 AM
Struggling with Outputs again, I think...
Copy code
compute.Extension("{0}install".format(server),
        virtual_machine_id=vm.id,
        publisher="Microsoft.Compute",
        type="CustomScriptExtension",
        type_handler_version="1.9",
        auto_upgrade_minor_version=True,
        settings= json.dumps({'commandToExecute': command_to_execute, 'fileUris': [args.bootstrap_file_name]}),
        protected_settings=json.dumps({'storageAccountName': args.bootstrap_storage_account_name, 'storageAccountKey': args.bootstrap_storage_access_key})
      )
I'm receiving
Copy code
File "/usr/lib/python3.7/json/encoder.py", line 179, in default
        raise TypeError(f'Object of type {o.__class__.__name__} '
    TypeError: Object of type Output is not JSON serializable
    error: an unhandled error occurred: Program exited with non-zero exit code: 1
I am passing the args in to this component like this:
Copy code
combined_output = Output.all(install_scripts_storage_account.name, install_scripts_storage_account.primary_access_key, install_scripts_storage_blob.url)
bootstrap_storage_account_name = combined_output.apply(lambda lst: lst[0])
bootstrap_storage_access_key = combined_output.apply(lambda lst: lst[1])
bootstrap_file_name = combined_output.apply(lambda lst: lst[2])
Does
json.dumps()
not work in this context? If I pass the actual values in, hard code the actual strings, then it works.
f

faint-table-42725

04/14/2020, 4:13 PM
It won’t work like that because
bootstrap_storage_account_name
is also an
Output
You will want to invert where the
json.dumps
happens:
Copy code
protected_settings=combined_output.apply(lambda lst: json.dumps({'storageAccountName': lst[0], 'storageAccountKey': lst[1]}))
c

colossal-room-15708

04/15/2020, 12:56 AM
how do I pass
combined_output
to a component?
f

faint-table-42725

04/15/2020, 1:30 AM
You had
combined_output = Output.all(install_scripts_storage_account.name, install_scripts_storage_account.primary_access_key, install_scripts_storage_blob.url)
earlier
And that should work just fine
c

colossal-room-15708

04/15/2020, 4:18 AM
yeah, but that's in my
___main___.py
, the
protected_settings
is in a different file, a component, so I have to pass the
combined_output
to the component
f

faint-table-42725

04/15/2020, 5:08 AM
Ah, I didn’t realize that. You can pass it any way you’d normally pass state between files in Python. For example, if the other file defines functions, one of which creates that component, and your
__main__.py
calls that function, you can pass it as an arg when calling that function.
c

colossal-room-15708

04/15/2020, 6:29 AM
interestingly, that's what I have done in my snippet above, just wasn't clear about the fact that the
compute.extensions
is part of the component and the
combined_output
is in the main. That's what threw the error I mentioned.
f

faint-table-42725

04/15/2020, 6:38 AM
Gotcha. Were you able to get this working by having the
json.dumps
within the lambda?
c

colossal-room-15708

04/15/2020, 7:04 AM
I just tried this: `___main___.py`:
Copy code
storage_information = [
  install_scripts_storage_account.name,
  install_scripts_storage_account.primary_access_key,
  install_scripts_storage_blob.url
]
vms = Compute("vms",
  ComputeArgs(
    resource_group_name=resource_group.name,
    vnet=network.vnet,
    public_subnet_id=network.public_subnet_id,
    storage_info=storage_information
  )
)
`component.py`:
Copy code
class ComputeArgs:
  def __init__(
    self,
    resource_group_name: str,
    vnet: network.VirtualNetwork,
    public_subnet_id: str,
    storage_info: list
  ):
    self.resource_group_name = resource_group_name
    self.vnet = vnet
    self.public_subnet_id = public_subnet_id
    self.storage_info = storage_info

compute.Extension("{0}install".format(server),
        name="{0}install".format(server),
        virtual_machine_id=vm.id,
        publisher="Microsoft.Compute",
        type="CustomScriptExtension",
        type_handler_version="1.9",
        auto_upgrade_minor_version=True,
        settings=args.storage_info.apply(lambda lst: json.dumps({'commandToExecute': command_to_execute, 'fileUris': [args.bootstrap_file_name]})),
        protected_settings=args.storage_info.apply(lambda lst: json.dumps({'storageAccountName': lst[0], 'storageAccountKey': lst[1]}))
      )
This doesn't work, saying that
list
doesn't have an
apply
method. I believe I need to do the
apply
in the
main
, which I have tried, but that never worked.
I think I got it working now.
main
Copy code
install_extension_settings = combined_output.apply(lambda lst: json.dumps({'commandToExecute': command_to_execute, 'fileUris': [lst[2]]}))
install_extension_protected_settings = combined_output.apply(lambda lst: json.dumps({'storageAccountName': lst[0], 'storageAccountKey': lst[1]}))
Passing that over to the component. Would've liked to do this inside the component though. Seems like Outputs don't like to do that though.