I’m trying to use an Output value from a previous ...
# general
s
I’m trying to use an Output value from a previous resource creation in a dictionary that I’m passing to a Helm chart. Here was my first attempt:
Copy code
public_ip = PublicIp(
       f'{env}_public_ip',
       name=f'{PREFIX}-{env}-public-ip',
       resource_group_name=aks_stack.get_output('rg_name'),
       allocation_method='Static',
       domain_name_label=f'{PREFIX}-{env}')

   nginx_chart_opts = ChartOpts(f'{env}-nginx-chart-opts')
   nginx_chart_opts.transformations = [lambda config_file: set_metadata_namespace(config_file, env)]
   nginx_chart_opts.repo = 'stable'
   nginx_chart_opts.chart = 'nginx-ingress'
   nginx_chart_opts.namespace = env
   nginx_chart_opts.values = \
   {
       'controller':
       {
           'service':
           {
               'loadBalancerIP': public_ip.ip_address
           },
           'replicaCount': 2
       },
       'rbac':
       {
           'create': True
       }
   }

   # Deploy the nginx ingress controller.
   nginx_ingress = Chart(
       f'{env}-nginx-ingress',
       nginx_chart_opts,
       opts=ResourceOptions(provider=custom_provider, depends_on=[public_ip]))
This produced the following error:
Copy code
error: Program failed with an unhandled exception:
    error: Traceback (most recent call last):
      File "/usr/local/bin/pulumi-language-python-exec", line 85, in <module>
        loop.run_until_complete(coro)
      File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/base_events.py", line 484, in run_until_complete
        return future.result()
      File "/Users/mike/.pyenv/pulumi/lib/python3.6/site-packages/pulumi/runtime/stack.py", line 38, in run_in_stack
        await RPC_MANAGER.unhandled_exeception()
      File "/Users/mike/.pyenv/pulumi/lib/python3.6/site-packages/pulumi/runtime/rpc_manager.py", line 68, in rpc_wrapper
        result = await rpc_function(*args, **kwargs)
      File "/Users/mike/.pyenv/pulumi/lib/python3.6/site-packages/pulumi/runtime/resource.py", line 411, in do_register_resource_outputs
        serialized_props = await rpc.serialize_properties(outputs, {})
      File "/Users/mike/.pyenv/pulumi/lib/python3.6/site-packages/pulumi/runtime/rpc.py", line 57, in serialize_properties
        result = await serialize_property(v, deps, input_transformer)
      File "/Users/mike/.pyenv/pulumi/lib/python3.6/site-packages/pulumi/runtime/rpc.py", line 146, in serialize_property
        value = await serialize_property(value.future(), deps, input_transformer)
      File "/Users/mike/.pyenv/pulumi/lib/python3.6/site-packages/pulumi/runtime/rpc.py", line 135, in serialize_property
        future_return = await asyncio.ensure_future(value)
      File "/Users/mike/.pyenv/pulumi/lib/python3.6/site-packages/pulumi/output.py", line 155, in run
        transformed: Input[U] = func(value)
      File "/Users/mike/.pyenv/pulumi/lib/python3.6/site-packages/pulumi_kubernetes/helm/v2/helm.py", line 312, in _parse_chart
        data = json.dumps(vals).encode('utf-8')
      File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/__init__.py", line 231, in dumps
        return _default_encoder.encode(obj)
      File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 199, in encode
        chunks = self.iterencode(o, _one_shot=True)
      File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 257, in iterencode
        return _iterencode(o, 0)
      File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 180, in default
        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
My next attempt was:
Copy code
public_ip = PublicIp(
        f'{env}_public_ip',
        name=f'{PREFIX}-{env}-public-ip',
        resource_group_name=aks_stack.get_output('rg_name'),
        allocation_method='Static',
        domain_name_label=f'{PREFIX}-{env}')

    nginx_chart_opts = ChartOpts(f'{env}-nginx-chart-opts')
    nginx_chart_opts.transformations = [lambda config_file: set_metadata_namespace(config_file, env)]
    nginx_chart_opts.repo = 'stable'
    nginx_chart_opts.chart = 'nginx-ingress'
    nginx_chart_opts.namespace = env
    nginx_chart_opts.values = \
    {
        'controller':
        {
            'service':
            {
                'loadBalancerIP': 'SET BELOW'
            },
            'replicaCount': 2
        },
        'rbac':
        {
            'create': True
        }
    }

    def set_load_balancer_ip(ip_address):
        nginx_chart_opts.values['controller']['service']['loadBalancerIP'] = ip_address

    public_ip.ip_address.apply(lambda ip_address: set_load_balancer_ip(ip_address))

    # Deploy the nginx ingress controller.
    nginx_ingress = Chart(
        f'{env}-nginx-ingress',
        nginx_chart_opts,
        opts=ResourceOptions(provider=custom_provider, depends_on=[public_ip]))
This does not produce an error, but the chart is deployed before the loadBalancerIP value has been written in set_load_balancer_ip (I’ve confirmed by inspecting the yaml of the deployed chart). Any thoughts on how I can ensure that set_load_balancer_ip is called before the Chart deployment?
g
Hey @stale-autumn-24797, sorry for the confusion. I’m pretty sure you’re running into https://github.com/pulumi/pulumi-kubernetes/issues/677 which I just pushed a fix for.
b
The initial code that you wrote should have worked (and is the preferred way of expressing this) the fact that it didn't is due to this issue: https://github.com/pulumi/pulumi-kubernetes/issues/677 A fix is coming for this soon, but I think in the interm you can call
nginx_chart_opts.values = Output.from_input({ .... })
s
Thanks guys! I’ve grabbed the code from your PR and will try it out locally in the next hour or so.
The fix works great, thanks @gorgeous-egg-16927 and @bitter-oil-46081! What is the expected ETA for the fix to make it into the official release?
@gorgeous-egg-16927, one other bug I wanted to call out in the helm.py file. I believe that LocalChartOpts should inherit from BaseChartOpts instead of object. Without it (though I haven’t tried it yet), construction of LocalChartOpts should throw when it calls super(). Though I need to use LocalChartOpts in the code I am writing now, I believe that I can work around this by creating a local class that I pass into Chart.
g
I’m hoping to cut a release today, but by tomorrow at the latest
I think you’re right on the LocalChartOpts as well. I’ll open an issue to fix
s
Thanks, Levi — looking forward to getting the new release. Thanks for the quick turnaround on all of the bug fixes.
👍 1
@gorgeous-egg-16927, looks like the last fix (LocalChartOpts) didn’t make the release last night. ETA for a release of this? I’m stuck doing manual deployments until this fix is released.
g
Hoping to release another round of fixes later today
Had several python issues that are still in review
s
Awesome, thanks!
g
Looks like I won’t be able to get a release out today, but I’ll try to get it out Monday