https://pulumi.com logo
Docs
Join the conversationJoin Slack
Channels
announcements
automation-api
aws
azure
blog-posts
built-with-pulumi
cloudengineering
cloudengineering-support
content-share
contribex
contribute
docs
dotnet
finops
general
getting-started
gitlab
golang
google-cloud
hackathon-03-19-2020
hacktoberfest
install
java
jobs
kubernetes
learn-pulumi-events
linen
localstack
multi-language-hackathon
office-hours
oracle-cloud-infrastructure
plugin-framework
pulumi-cdk
pulumi-crosscode
pulumi-deployments
pulumi-kubernetes-operator
pulumi-service
pulumiverse
python
registry
status
testingtesting123
testingtesting321
typescript
welcome
workshops
yaml
Powered by Linen
python
  • f

    fierce-market-67222

    04/08/2021, 12:23 PM
    and yes i have the rights good configured…
  • b

    broad-church-78931

    04/08/2021, 12:57 PM
    Does anyone know if there are some good ways to abstract Pulumi code with Python? Some samples on the internet?
    r
    • 2
    • 6
  • f

    fast-magician-55948

    04/08/2021, 3:01 PM
    I haven't touched pulumi for a while - coming back to it today, ran into
    Diagnostics:
    pulumi:pulumi:Stack (clearbooks-dev):
    Traceback (most recent call last):
    File "C:\ProgramData\chocolatey\lib\pulumi\tools\Pulumi\bin\pulumi-language-python-exec", line 14, in <module>
    import pulumi
    ModuleNotFoundError: No module named 'pulumi'
    It looks like the Pulumi SDK has not been installed. Have you run pip install?
    If you are running in a virtualenv, you must run pip install -r requirements.txt from inside the virtualenv.
    error: an unhandled error occurred: Program exited with non-zero exit code: 1
  • f

    fast-magician-55948

    04/08/2021, 3:01 PM
    I have installed pulumi
  • f

    fast-magician-55948

    04/08/2021, 3:01 PM
    I've rerun pip install
    b
    • 2
    • 7
  • m

    mysterious-oyster-86659

    04/12/2021, 5:02 PM
    Hi Everyone😃 Our stack is currently written with TypeScript (TS) and have implemented Airflow in AWS. Now, we need to dynamically reference TS resources in Python and have no idea how to do that in manageable way (without just hard-coding them). Is there a way to do this? Note that this is also posted in #typescript channel too.
    b
    r
    w
    • 4
    • 4
  • e

    enough-leather-70274

    04/13/2021, 3:18 AM
    Sorry folks, I'm feeling a bit stupid right now... I'm trying to log out the string value of a stack reference from one stack in another.
    b
    • 2
    • 4
  • f

    few-pillow-1133

    04/14/2021, 12:56 PM
    Hey Guys, Dependency seems to be failing for me when creating data factory in azure
    raise Exception(
        Exception: 'depends_on' was passed a value that was not a Resource.
        error: an unhandled error occurred: Program exited with non-zero exit code: 1
    • 1
    • 1
  • b

    boundless-angle-56560

    04/14/2021, 1:23 PM
    Hi Everyone, I am scratching my head over one thing. I am implementing my own dynamic provider and this provider accepts a file as an input parameter. I want this provider to update itself if the file's content changes. Shall I use pulumi.FileAsset for that? I mean, shall my resource accept FileAsset as an input paramater? If so, I am not sure how to work with the FileAsset in my dynamic provider impementation as it seems that the object doesn't expose anything (like for example getting the contents of the file).
    b
    • 2
    • 3
  • f

    few-pillow-1133

    04/14/2021, 6:23 PM
    Any idea how to use azure native to create azure data factory with encryption enabled, as well as user manged identity
    adf_uai = azure_native.managedidentity.UserAssignedIdentity(
            adf_config['encryption']['user_assigned_identity']['name'],
            resource_name_=adf_config['encryption']['user_assigned_identity']['name'],
            location=config_data['location'],
            resource_group_name=config_mmazzargxx['name'],
            tags=adf_config['tags']
        )
    
    data_factory = azure_native.datafactory.Factory(
        adf_config['factory']['name'],
        factory_name=adf_config['factory']['name'],
        encryption=azure_native.datafactory.EncryptionConfigurationArgs(
            key_name=adf_k.name,
            key_version=pulumi.Output.all(adf_k.key_uri_with_version) \
                .apply(lambda args: urlparse(args[0]).path.rpartition('/')[2]),
            vault_base_url=pulumi.Output.all(adf_k.key_uri_with_version).apply(lambda args: f'{urlparse(args[0]).scheme}://{urlparse(args[0]).netloc}'),
            identity=azure_native.datafactory.CMKIdentityDefinitionArgs(
                user_assigned_identity=adf_uai.id
            )
        ),
        public_network_access=adf_config['networking']['public_network_access'],
        global_parameters=adf_config['factory']['global_parameters'],
        identity=azure_native.datafactory.FactoryIdentityArgs(
            type=adf_config['encryption']['user_assigned_identity']['type'],
            user_assigned_identities={
                adf_config['encryption']['user_assigned_identity']['name']: adf_uai.id
            }
        ),
        ....
    )
    Getting below error....the issue is how do one apply output of keyvault as well as using assigned identity
    error: autorest/azure: Service returned an error. Status=400 Code="LinkedInvalidPropertyId" Message="Property id 'mmazzadwsnduai-dls' at path '' is invalid. Expect fully qualified resource Id that start with '/subscriptions/{subscriptionId}' or '/providers/{resourceProviderNamespace}/'."
    w
    • 2
    • 6
  • h

    handsome-state-59775

    04/15/2021, 5:32 AM
    pulumi up (v2.25.0) creates a venv with python 3.7 even though pulumi-python has moved up to 3.9.x any insights?
    ✅ 1
    r
    • 2
    • 4
  • h

    handsome-state-59775

    04/19/2021, 12:56 PM
    any plans for bringing https://github.com/pulumi/pulumi-query-kubernetes to python?
    r
    • 2
    • 1
  • i

    important-zebra-56988

    04/19/2021, 6:32 PM
    hi everyone 🙂 Somewhat new to the Pulumi ecosystem but trying my best to read through what’s available. Curious if any of you may have an idea on an issue I’m seeing with deploying a Stateful set. I took a working vanilla Kubernetes Statefulset yaml and piped it through
    kube2pulumi
    , and have it set up in my project - but I can’t seem to figure out how to get this ConfigMap to mount as a volume to my containers.
    spec.volumes
    "volumes": 
                        [{
                            "name": "prometheus-config-volume",
                            "config_map": {
                                "default_mode": 420,
                                "name": "prometheus-config",
                            },
                        }]
                },
    yields a:
    for key, value in attr.items():
        TypeError: 'NoneType' object is not callable
        error: an unhandled error occurred: Program exited with non-zero exit code: 1
    however - if I comment out the
    config_map
    nested in that object, I can see that it at least rendered a
    volumes
    attribute for the PodTemplateSpec
    + volumes         : [
                      +     [0]: {
                              + name: "prometheus-config-volume"
                            }
                        ]
                    }
  • w

    worried-queen-62794

    04/21/2021, 2:34 AM
    Hi. I have a strange problem where I am running refresh and it is failing with:
    pulumi-python:dynamic:Resource (GeneratedTemporaryPlatformSSHKey):
        error: Preview failed: Exception calling application: No module named 'ssh'
    The strange thing about this is that I had already deleted this resource and module but its still in my state. There is no where in my code that is still referring to the ssh module so where is Pulumi getting this from?
    r
    • 2
    • 2
  • e

    enough-leather-70274

    04/21/2021, 3:33 AM
    Hi folks - where can I find the python reference docs for the automation library?
    r
    • 2
    • 22
  • e

    enough-leather-70274

    04/21/2021, 3:51 AM
    Another question - with the new changes for v3.0.0, what new dependencies does pulumi bring in?
    r
    s
    • 3
    • 15
  • e

    enough-garden-22763

    04/21/2021, 9:58 PM
    Hello 👋 I’m wondering if people are using
    mypy
    or any other static checkers with Pulumi, and how’s the experience been?
    e
    h
    • 3
    • 21
  • w

    worried-queen-62794

    04/22/2021, 1:57 AM
    This no longer seems to work in v3:
    class NetworkLoadBalancer(aws.lb.LoadBalancer):
        network_interface: Output[aws.ec2.AwaitableGetNetworkInterfaceResult]
    
        # TODO: Network ACL.
        def __init__(self, name: str, public_subnet_id: Input[str], opts: ResourceOptions = None):
            super(NetworkLoadBalancer, self).__init__(
                name,
                opts=opts,
                internal=False,
                load_balancer_type='network',
                subnets=[public_subnet_id]
            )
    
            self.network_interface = self.id.apply(lambda id: get_elb_network_interface(id, opts))
    
            self.record_alias = aws.route53.RecordAliasArgs(
                evaluate_target_health=False,
                name=self.dns_name,
                zone_id=self.zone_id
            )
    I get:
    error: aws:route53/record:Record resource 'PlatformBackendAlias' has a problem: Missing required argument: The argument "alias.0.name" is required, but no definition was found.. Examine values at 'Record.Aliases'.
    Same problem with
    zone_id
    . Any idea what is going on?
    f
    m
    • 3
    • 2
  • w

    worried-queen-62794

    04/22/2021, 1:58 AM
    If I
    apply
    those outputs with a
    print
    statement then it never gets called.
  • n

    nutritious-shampoo-16116

    04/22/2021, 9:08 AM
    I tried to bump the library to 3.0 but I am getting weird errors in tests
    def ReadResource(self, request):
            # Ensure we have an event loop on this thread because it's needed when deserializing resource references.
            _ensure_event_loop()
        
            state = rpc.deserialize_properties(request.properties)
            print("REQUEST:", request)
            resource_args = MockResourceArgs(typ=request.type,
                                             name=request.name,
                                             inputs=state,
                                             provider=request.provider,
                                             resource_id=request.id,
    >                                        custom=request.custom or False)
    E       AttributeError: custom
    
    ../../../.local/share/virtualenvs/cyclope-mw2Vtk-i/lib/python3.9/site-packages/pulumi/runtime/mocks.py:174: AttributeError
    ========================================================================================================== short test summary info ===========================================================================================================
    FAILED tests/helpers/test_autoscaling_group.py::test_setup_autoscaling_group - AttributeError: custom
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    =============================================================================================== 1 failed, 71 deselected, 57 warnings in 6.11s ================================================================================================
    Task exception was never retrieved
    future: <Task finished name='Task-23' coro=<StackReference.__is_secret_name() done, defined at /home/matt/.local/share/virtualenvs/cyclope-mw2Vtk-i/lib/python3.9/site-packages/pulumi/stack_reference.py:99> exception=AttributeError('custom')>
    anybody knows why this
    custom
    attribute is missing?
    r
    g
    • 3
    • 2
  • n

    nutritious-shampoo-16116

    04/22/2021, 10:28 AM
    seems to be related to StackReference mocking, did anything change in 3.0 for that?
    b
    • 2
    • 2
  • n

    nutritious-shampoo-16116

    04/22/2021, 10:37 AM
    yup, I am not able anymore to mock any StackReference
  • f

    future-hydrogen-91224

    04/25/2021, 5:41 PM
    Running on Ubuntu 21.04 Python version 3.9.4 pip 21.0.1 from /usr/local/lib/python3.9/dist-packages/pip (python 3.9)
    b
    • 2
    • 3
  • b

    billowy-army-68599

    04/25/2021, 6:04 PM
    @future-hydrogen-91224 please thread these long messages, it makes the channel unreadable
    f
    • 2
    • 3
  • b

    billowy-army-68599

    04/25/2021, 6:07 PM
    it looks to me that these warnings and errors are related to your python configuration, rather than Pulumi
    f
    s
    a
    • 4
    • 26
  • f

    few-pillow-1133

    04/25/2021, 11:06 PM
    structured config error Given
    config:
      aws:profile: mra_nonprod
      rds:data:
        username: test
        password:
          secure: AAABAL8fPsdZipEyyFiU/rw8a1bkvv1oL/KAhTBNGtGKL7TL
      rds:data2:
        instance:
          password:
            secure: AAABADa3wuZn+sjN4DHRso/Ap07nSI1w1c7TY5nK6U90CYxk
      rds:mykey:
        some:
          secretkey:
            secure: AAABAK5wKE2QbOnIBj4zQShhwNko7LA0xwwlNXrI+BViL0wx9ekM9FDHOLM=
      rds:password:
        secure: AAABAL8fPsdZipEyyFiU/rw8a1bkvv1oL/KAhTBNGtGKL7TL
      rds:work:
        check: false
    Config access seems not to be able to see most data
    print (pulumi.Config('aws').get('profile')) # None
    print (pulumi.Config('rds').get_object('data2')) # None
    print (pulumi.Config('rds').get_object('mykey')) # None
    print (pulumi.Config('rds').get_object('data')) # print config data correctly
    print (pulumi.Config('rds').get_secret_object('mykey.some.secretkey')) # None
    print (pulumi.Config('rds').get_secret_object('password')) # None
    print (pulumi.Config('rds').get_secret_object('data2.instance.password')) # None
    a
    • 2
    • 2
  • c

    clever-lawyer-94920

    04/26/2021, 9:15 AM
    Hi, I have created an EKS cluster and added a nodegroup to it. When I tried to delete the nodegroup, it failed saying there is a dependent security group. But when I tried to delete it using pulumi the cluster itself had to be deleted and created anew. Is there a work around where I don't need to remove the cluster in order to remove a nodegroup?
    b
    • 2
    • 2
  • p

    proud-art-41399

    04/27/2021, 6:53 AM
    Hi, can I somewhere find Python version requirements for the Pulumi provider Python SDK? I've just upgraded the pulumi-aws-tags package to Pulumi v3 (and Pulumi AWS v4) but the tests fail for Python 3.6 with:
    args = (), kwargs = {}
    
        def wrapper(*args, **kwargs):
            from .. import Output  # pylint: disable=import-outside-toplevel
    >       _sync_await(run_pulumi_func(lambda: _sync_await(Output.from_input(fn(*args, **kwargs)).future())))
    
    /opt/hostedtoolcache/Python/3.6.13/x64/lib/python3.6/site-packages/pulumi/runtime/mocks.py:37: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    ...shortened...
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    arg = ~T, tvars = (~T, ~T), args = [<class 'str'>]
    
        def _replace_arg(arg, tvars, args):
            """An internal helper function: replace arg if it is a type variable
            found in tvars with corresponding substitution from args or
            with corresponding substitution sub-tree if arg is a generic type.
            """
        
            if tvars is None:
                tvars = []
            if hasattr(arg, '_subs_tree') and isinstance(arg, (GenericMeta, _TypingBase)):
                return arg._subs_tree(tvars, args)
            if isinstance(arg, TypeVar):
                for i, tvar in enumerate(tvars):
                    if arg == tvar:
    >                   return args[i]
    E                   IndexError: list index out of range
    
    /opt/hostedtoolcache/Python/3.6.13/x64/lib/python3.6/typing.py:566: IndexError
    r
    • 2
    • 3
  • f

    few-pillow-1133

    04/27/2021, 12:13 PM
    What's the best way to use secret that will work for both normal pulumi up as well as unit test?
    rds_inst = aws.rds.Instance(
            rds_config['name'],
            .....
            password=rds_config['password']
        )
    rds_config['password'] is a secret Above fails during unit test with below, since the secret is normally within secure field
    AssertionError: Unexpected type. Expected 'dict' got '<class 'str'>'
  • f

    few-pillow-1133

    04/27/2021, 10:24 PM
    Deploy pipeline sudden failure We noticed one of our pipeline for azure started to fail recently without making modification to the pipeline
    File ".../appservices/venv/lib/python3.6/site-packages/pulumi/output.py", line 91, in is_value_known
            return await is_known and not contains_unknowns(await future)
          File "/usr/lib/python3.6/asyncio/tasks.py", line 250, in _wakeup
            future.result()
          File "/usr/lib/python3.6/asyncio/tasks.py", line 182, in _step
            result = coro.throw(exc)
          File ".../appservices/venv/lib/python3.6/site-packages/pulumi/output.py", line 91, in is_value_known
            return await is_known and not contains_unknowns(await future)
          File "/usr/lib/python3.6/asyncio/tasks.py", line 250, in _wakeup
            future.result()
          File "/usr/lib/python3.6/asyncio/tasks.py", line 182, in _step
            result = coro.throw(exc)
          File ".../appservices/venv/lib/python3.6/site-packages/pulumi/output.py", line 91, in is_value_known
            return await is_known and not contains_unknowns(await future)
          File "/usr/lib/python3.6/asyncio/tasks.py", line 250, in _wakeup
            future.result()
          File "/usr/lib/python3.6/asyncio/tasks.py", line 182, in _step
            result = coro.throw(exc)
          File ".../appservices/venv/lib/python3.6/site-packages/pulumi/output.py", line 91, in is_value_known
            return await is_known and not contains_unknowns(await future)
          File "/usr/lib/python3.6/asyncio/tasks.py", line 250, in _wakeup
            future.result()
          File "/usr/lib/python3.6/asyncio/tasks.py", line 180, in _step
            result = coro.send(None)
          File ".../appservices/venv/lib/python3.6/site-packages/pulumi/runtime/resource.py", line 438, in do_register
            resolver = await prepare_resource(res, ty, custom, remote, props, opts, typ)
          File ".../appservices/venv/lib/python3.6/site-packages/pulumi/runtime/resource.py", line 100, in prepare_resource
            serialized_props = await rpc.serialize_properties(props, property_dependencies_resources, translate, typ)
          File ".../appservices/venv/lib/python3.6/site-packages/pulumi/runtime/rpc.py", line 112, in serialize_properties
            types = _types.input_type_types(typ)
          File ".../appservices/venv/lib/python3.6/site-packages/pulumi/_types.py", line 461, in input_type_types
            return _types_from_py_properties(input_type_cls)
          File ".../appservices/venv/lib/python3.6/site-packages/pulumi/_types.py", line 714, in _types_from_py_properties
            cls_hints = get_type_hints(prop.fget, globalns=globalns, localns=localns)
          File "/usr/lib/python3.6/typing.py", line 1543, in get_type_hints
            value = _eval_type(value, globalns, localns)
          File "/usr/lib/python3.6/typing.py", line 350, in _eval_type
            return t._eval_type(globalns, localns)
          File "/usr/lib/python3.6/typing.py", line 767, in _eval_type
            return self.__class__(ev_args, ev_origin, _root=True)
          File "/usr/lib/python3.6/typing.py", line 752, in __new__
            subs_tree = self._subs_tree()
          File "/usr/lib/python3.6/typing.py", line 808, in _subs_tree
            tree_args = _subs_tree(self, tvars, args)
          File "/usr/lib/python3.6/typing.py", line 608, in _subs_tree
            new_tree_args.append(_replace_arg(arg, ocls.__parameters__, tree_args))
          File "/usr/lib/python3.6/typing.py", line 562, in _replace_arg
            return arg._subs_tree(tvars, args)
          File "/usr/lib/python3.6/typing.py", line 1086, in _subs_tree
            tree_args = _subs_tree(self, tvars, args)
          File "/usr/lib/python3.6/typing.py", line 603, in _subs_tree
            tree_args.append(_replace_arg(arg, tvars, args))
          File "/usr/lib/python3.6/typing.py", line 566, in _replace_arg
            return args[i]
        IndexError: list index out of range
        error: an unhandled error occurred: Program exited with non-zero exit code: 1
    b
    r
    p
    • 4
    • 4
Powered by Linen
Title
f

few-pillow-1133

04/27/2021, 10:24 PM
Deploy pipeline sudden failure We noticed one of our pipeline for azure started to fail recently without making modification to the pipeline
File ".../appservices/venv/lib/python3.6/site-packages/pulumi/output.py", line 91, in is_value_known
        return await is_known and not contains_unknowns(await future)
      File "/usr/lib/python3.6/asyncio/tasks.py", line 250, in _wakeup
        future.result()
      File "/usr/lib/python3.6/asyncio/tasks.py", line 182, in _step
        result = coro.throw(exc)
      File ".../appservices/venv/lib/python3.6/site-packages/pulumi/output.py", line 91, in is_value_known
        return await is_known and not contains_unknowns(await future)
      File "/usr/lib/python3.6/asyncio/tasks.py", line 250, in _wakeup
        future.result()
      File "/usr/lib/python3.6/asyncio/tasks.py", line 182, in _step
        result = coro.throw(exc)
      File ".../appservices/venv/lib/python3.6/site-packages/pulumi/output.py", line 91, in is_value_known
        return await is_known and not contains_unknowns(await future)
      File "/usr/lib/python3.6/asyncio/tasks.py", line 250, in _wakeup
        future.result()
      File "/usr/lib/python3.6/asyncio/tasks.py", line 182, in _step
        result = coro.throw(exc)
      File ".../appservices/venv/lib/python3.6/site-packages/pulumi/output.py", line 91, in is_value_known
        return await is_known and not contains_unknowns(await future)
      File "/usr/lib/python3.6/asyncio/tasks.py", line 250, in _wakeup
        future.result()
      File "/usr/lib/python3.6/asyncio/tasks.py", line 180, in _step
        result = coro.send(None)
      File ".../appservices/venv/lib/python3.6/site-packages/pulumi/runtime/resource.py", line 438, in do_register
        resolver = await prepare_resource(res, ty, custom, remote, props, opts, typ)
      File ".../appservices/venv/lib/python3.6/site-packages/pulumi/runtime/resource.py", line 100, in prepare_resource
        serialized_props = await rpc.serialize_properties(props, property_dependencies_resources, translate, typ)
      File ".../appservices/venv/lib/python3.6/site-packages/pulumi/runtime/rpc.py", line 112, in serialize_properties
        types = _types.input_type_types(typ)
      File ".../appservices/venv/lib/python3.6/site-packages/pulumi/_types.py", line 461, in input_type_types
        return _types_from_py_properties(input_type_cls)
      File ".../appservices/venv/lib/python3.6/site-packages/pulumi/_types.py", line 714, in _types_from_py_properties
        cls_hints = get_type_hints(prop.fget, globalns=globalns, localns=localns)
      File "/usr/lib/python3.6/typing.py", line 1543, in get_type_hints
        value = _eval_type(value, globalns, localns)
      File "/usr/lib/python3.6/typing.py", line 350, in _eval_type
        return t._eval_type(globalns, localns)
      File "/usr/lib/python3.6/typing.py", line 767, in _eval_type
        return self.__class__(ev_args, ev_origin, _root=True)
      File "/usr/lib/python3.6/typing.py", line 752, in __new__
        subs_tree = self._subs_tree()
      File "/usr/lib/python3.6/typing.py", line 808, in _subs_tree
        tree_args = _subs_tree(self, tvars, args)
      File "/usr/lib/python3.6/typing.py", line 608, in _subs_tree
        new_tree_args.append(_replace_arg(arg, ocls.__parameters__, tree_args))
      File "/usr/lib/python3.6/typing.py", line 562, in _replace_arg
        return arg._subs_tree(tvars, args)
      File "/usr/lib/python3.6/typing.py", line 1086, in _subs_tree
        tree_args = _subs_tree(self, tvars, args)
      File "/usr/lib/python3.6/typing.py", line 603, in _subs_tree
        tree_args.append(_replace_arg(arg, tvars, args))
      File "/usr/lib/python3.6/typing.py", line 566, in _replace_arg
        return args[i]
    IndexError: list index out of range
    error: an unhandled error occurred: Program exited with non-zero exit code: 1
b

billowy-army-68599

04/27/2021, 10:29 PM
@red-match-15116 another python3.6 regression?
👀 1
r

red-match-15116

04/28/2021, 12:25 AM
Yeah it looks the same as https://github.com/pulumi/pulumi/issues/6886
p

proud-art-41399

04/28/2021, 5:43 AM
Yup, seems to be the same issue as I observed.
r

red-match-15116

04/28/2021, 2:59 PM
We’re working on a fix!
👍 1
View count: 1