Skip to content
This repository was archived by the owner on Apr 6, 2026. It is now read-only.
This repository was archived by the owner on Apr 6, 2026. It is now read-only.

Non-deterministic provider output #67

@covracer

Description

@covracer

Thanks for the awesome software! Something I ran into while trying to automate managing user accounts across providers:

test.py:

import json
from terraformpy import Provider, compile
with Provider("github", alias="github"):
    pass
with Provider("aws", alias="aws"):
    pass
print(json.dumps(compile(), sort_keys=True))
$ for i in $(seq 10); do python test.py; done
{"provider": {"aws": {"alias": "aws"}, "github": {"alias": "github"}}}
{"provider": {"aws": {"alias": "aws"}, "github": {"alias": "github"}}}
{"provider": {"github": {"alias": "github"}, "aws": {"alias": "aws"}}}
{"provider": {"aws": {"alias": "aws"}, "github": {"alias": "github"}}}
{"provider": {"aws": {"alias": "aws"}, "github": {"alias": "github"}}}
{"provider": {"github": {"alias": "github"}, "aws": {"alias": "aws"}}}
{"provider": {"github": {"alias": "github"}, "aws": {"alias": "aws"}}}
{"provider": {"github": {"alias": "github"}, "aws": {"alias": "aws"}}}
{"provider": {"github": {"alias": "github"}, "aws": {"alias": "aws"}}}
{"provider": {"github": {"alias": "github"}, "aws": {"alias": "aws"}}}

It seems like this is because of how the comparison dunder methods in terraformpy.objects.DuplicateKey use the hash:

def __eq__(self, other):
return self.__class__ == other.__class__ and self._hash == other._hash
def __lt__(self, other):
if self.__class__ == other.__class__:
return self._hash < other._hash
return super(DuplicateKey, self).__lt__(other)
def __le__(self, other):
if self.__class__ == other.__class__:
return self._hash <= other._hash
return super(DuplicateKey, self).__le__(other)
def __gt__(self, other):
if self.__class__ == other.__class__:
return self._hash > other._hash
return super(DuplicateKey, self).__gt__(other)
def __ge__(self, other):
if self.__class__ == other.__class__:
return self._hash >= other._hash
return super(DuplicateKey, self).__ge__(other)

In the specific case of providers, it crossed my mind that sorting by alias could be appropriate. But maybe DuplicateKey is used in other situations where there isn't a good field to sort on?

In looking into the Terraform/duplicate key JSON side of the issue, I learned that a JSON array of objects is also accepted.

So here's my current workaround (which relies on the Python 3.7+ dictionary insertion order guarantee):

dictionaries = compile()
provider_items = dictionaries["provider"].items()
if len(provider_items) > 1:
    assert sys.version_info >= (3, 7)
    provider_list = [{str(key): value} for key, value in provider_items]
    dictionaries["provider"] = provider_list

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions