コード例 #1
0
ファイル: test_links.py プロジェクト: tableau/altimeter
 def testToJson(self):
     pred = "test-pred"
     obj = "test-obj"
     link = SimpleLink(pred=pred, obj=obj)
     expected_link_dict = {"pred": pred, "obj": obj}
     link_dict = link.dict()
     self.assertDictEqual(expected_link_dict, link_dict)
コード例 #2
0
ファイル: test_links.py プロジェクト: tableau/altimeter
    def testToJson(self):
        pred = "test-multi-pred"
        obj = LinkCollection(simple_links=(
            SimpleLink(pred="test-simple-pred-1", obj="test-simple-obj-1"),
            SimpleLink(pred="test-simple-pred-1", obj="test-simple-obj-2"),
            SimpleLink(pred="test-simple-pred-2", obj="test-simple-obj-3"),
        ), )
        link = MultiLink(pred=pred, obj=obj)
        link_dict = link.dict(exclude_unset=True)

        expected_link_dict = {
            "pred": "test-multi-pred",
            "obj": {
                "simple_links": (
                    {
                        "pred": "test-simple-pred-1",
                        "obj": "test-simple-obj-1"
                    },
                    {
                        "pred": "test-simple-pred-1",
                        "obj": "test-simple-obj-2"
                    },
                    {
                        "pred": "test-simple-pred-2",
                        "obj": "test-simple-obj-3"
                    },
                ),
            },
        }
        self.assertDictEqual(expected_link_dict, link_dict)
コード例 #3
0
ファイル: test_links.py プロジェクト: tableau/altimeter
 def testToRdf(self):
     pred = "test-multi-pred"
     obj = LinkCollection(simple_links=(
         SimpleLink(pred="test-simple-pred-1", obj="test-simple-obj-1"),
         SimpleLink(pred="test-simple-pred-2", obj="test-simple-obj-2"),
         SimpleLink(pred="test-simple-pred-3", obj="test-simple-obj-3"),
     ), )
     link = MultiLink(pred=pred, obj=obj)
     bnode = BNode()
     graph = Graph()
     namespace = Namespace("test:")
     node_cache = NodeCache()
     link.to_rdf(subj=bnode,
                 namespace=namespace,
                 graph=graph,
                 node_cache=node_cache)
     results = graph.query(
         "select ?p ?o where {?s a <test:test-multi-pred> ; ?p ?o} order by ?p ?o"
     )
     result_tuples = []
     for result in results:
         self.assertEqual(2, len(result))
         result_tuples.append((str(result[0]), str(result[1])))
     expected_result_tuples = [
         ("http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
          "test:test-multi-pred"),
         ("test:test-simple-pred-1", "test-simple-obj-1"),
         ("test:test-simple-pred-2", "test-simple-obj-2"),
         ("test:test-simple-pred-3", "test-simple-obj-3"),
     ]
     self.assertEqual(result_tuples, expected_result_tuples)
    def test_valid_dicts_input_with_alti_key(self):
        input_str = '{"People": [{"Name": "Bob", "Age": 49}, {"Name": "Sue", "Age": 42}]}'
        field = ListField(
            "People", EmbeddedDictField(ScalarField("Name"), ScalarField("Age")), alti_key="person"
        )

        input_data = json.loads(input_str)
        link_collection = field.parse(data=input_data, context={})

        expected_link_collection = LinkCollection(
            multi_links=(
                MultiLink(
                    pred="person",
                    obj=LinkCollection(
                        simple_links=(
                            SimpleLink(pred="name", obj="Bob"),
                            SimpleLink(pred="age", obj=49),
                        ),
                    ),
                ),
                MultiLink(
                    pred="person",
                    obj=LinkCollection(
                        simple_links=(
                            SimpleLink(pred="name", obj="Sue"),
                            SimpleLink(pred="age", obj=42),
                        ),
                    ),
                ),
            ),
        )
        self.assertEqual(link_collection, expected_link_collection)
コード例 #5
0
    def parse(self, data: Dict[str, Any],
              context: Dict[str, Any]) -> LinkCollection:
        """Parse this field and return a LinkCollection

       Args:
           data: dictionary of data to parse
           context: context dict containing data from higher level parsing code.

        Returns:
            LinkCollection
        """
        value = data.get(self.source_key)
        if value is None:
            if self.default_value is not None:
                return LinkCollection(simple_links=[
                    SimpleLink(pred=self.alti_key, obj=self.default_value)
                ], )
            if self.optional:
                return LinkCollection()
            raise ScalarFieldSourceKeyNotFoundException(
                f"Expected key '{self.source_key}' in data, present keys: {', '.join(data.keys())}"
            )
        if isinstance(value, SCALAR_TYPES):
            return LinkCollection(
                simple_links=[SimpleLink(pred=self.alti_key, obj=value)], )
        raise ScalarFieldValueNotAScalarException(
            (f"Expected data for key '{self.source_key}' to be one "
             f"of {SCALAR_TYPES}, is {type(value)}: {value}"))
コード例 #6
0
 def test_graph_content(self):
     expected_resources = (
         Resource(
             resource_id="123",
             type="test:a",
             link_collection=LinkCollection(
                 simple_links=(SimpleLink(pred="has-foo", obj="goo"),),
             ),
         ),
         Resource(resource_id="456", type="test:a", link_collection=LinkCollection(),),
         Resource(
             resource_id="abc",
             type="test:b",
             link_collection=LinkCollection(
                 simple_links=(SimpleLink(pred="has-a", obj="123"),),
             ),
         ),
         Resource(
             resource_id="def",
             type="test:b",
             link_collection=LinkCollection(simple_links=(SimpleLink(pred="name", obj="sue"),),),
         ),
     )
     expected_errors = ["test err 1", "test err 2"]
     self.assertEqual(self.validated_graph_set.resources, expected_resources)
     self.assertEqual(self.validated_graph_set.errors, expected_errors)
コード例 #7
0
 def setUp(self):
     resource_a1 = Resource(
         resource_id="123",
         type="test:a",
         link_collection=LinkCollection(simple_links=[SimpleLink(pred="has-foo", obj="goo")]),
     )
     resource_a2 = Resource(resource_id="456", type="test:a", link_collection=LinkCollection(),)
     resource_b1 = Resource(
         resource_id="abc",
         type="test:b",
         link_collection=LinkCollection(simple_links=[SimpleLink(pred="has-a", obj="123")]),
     )
     resource_b2 = Resource(
         resource_id="def",
         type="test:b",
         link_collection=LinkCollection(simple_links=[SimpleLink(pred="name", obj="sue")]),
     )
     resources = (resource_a1, resource_a2, resource_b1, resource_b2)
     self.validated_graph_set = ValidatedGraphSet(
         name="test-name",
         version="1",
         start_time=1234,
         end_time=4567,
         resources=resources,
         errors=["test err 1", "test err 2"],
     )
コード例 #8
0
 def test_parse(self):
     schema = Schema(ScalarField("Key1"), ScalarField("Key2"))
     data = {"Key1": "Value1", "Key2": "Value2"}
     link_collection = schema.parse(data, {})
     expected_link_collection = LinkCollection(simple_links=(
         SimpleLink(pred="key1", obj="Value1"),
         SimpleLink(pred="key2", obj="Value2"),
     ))
     self.assertEqual(link_collection, expected_link_collection)
コード例 #9
0
ファイル: test_links.py プロジェクト: tableau/altimeter
 def testToLpgLargeInt(self):
     pred = "test-pred"
     obj = 9223372036854775808
     link = SimpleLink(pred=pred, obj=obj)
     expected_link_dict = {"test-pred": "9223372036854775808"}
     parent = {}
     vertices = []
     edges = []
     link.to_lpg(parent, vertices, edges, "")
     self.assertDictEqual(expected_link_dict, parent)
コード例 #10
0
ファイル: test_links.py プロジェクト: tableau/altimeter
 def testToLpgSmallInt(self):
     pred = "test-pred"
     obj = 1
     link = SimpleLink(pred=pred, obj=obj)
     expected_link_dict = {"test-pred": 1}
     parent = {}
     vertices = []
     edges = []
     link.to_lpg(parent, vertices, edges, "")
     self.assertDictEqual(expected_link_dict, parent)
コード例 #11
0
ファイル: test_links.py プロジェクト: tableau/altimeter
 def testToLpgPrefix(self):
     pred = "test-pred"
     obj = "test-obj"
     link = SimpleLink(pred=pred, obj=obj)
     expected_link_dict = {"abctest-pred": "test-obj"}
     parent = {}
     vertices = []
     edges = []
     link.to_lpg(parent, vertices, edges, "abc")
     self.assertDictEqual(expected_link_dict, parent)
コード例 #12
0
    def test_scan(self):
        account_id = "123456789012"
        region_name = "us-east-1"
        session = boto3.Session()
        client = session.client("iam")

        oidc_url = "https://oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E"
        oidc_client_ids = ["sts.amazonaws.com"]
        oidc_thumbprints = ["9999999999999999999999999999999999999999"]

        _ = client.create_open_id_connect_provider(
            Url=oidc_url,
            ClientIDList=oidc_client_ids,
            ThumbprintList=oidc_thumbprints,
        )

        scan_accessor = AWSAccessor(session=session,
                                    account_id=account_id,
                                    region_name=region_name)
        resources = IAMOIDCProviderResourceSpec.scan(
            scan_accessor=scan_accessor)

        expected_resources = [
            Resource(
                resource_id=
                "arn:aws:iam::123456789012:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E",
                type="aws:iam:oidc-provider",
                link_collection=LinkCollection(
                    simple_links=(
                        SimpleLink(
                            pred="url",
                            obj=
                            "oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E",
                        ),
                        SimpleLink(
                            pred="create_date",
                            obj=resources[0].link_collection.simple_links[1].
                            obj,
                        ),
                        SimpleLink(pred="client_id", obj="sts.amazonaws.com"),
                        SimpleLink(
                            pred="thumbprint",
                            obj="9999999999999999999999999999999999999999"),
                    ),
                    multi_links=None,
                    tag_links=None,
                    resource_links=(ResourceLink(
                        pred="account",
                        obj="arn:aws::::account/123456789012"), ),
                    transient_resource_links=None,
                ),
            )
        ]

        self.assertEqual(resources, expected_resources)
 def create_resource(
     cls: Type["UnscannedAccountResourceSpec"], account_id: str, errors: List[str]
 ) -> Resource:
     simple_links: List[SimpleLink] = []
     simple_links.append(SimpleLink(pred="account_id", obj=account_id))
     if errors:
         error = "\n".join(errors)
         simple_links.append(SimpleLink(pred="error", obj=f"{error} - {uuid.uuid4()}"))
     return Resource(
         resource_id=cls.generate_arn(resource_id=account_id),
         type=cls.get_full_type_name(),
         link_collection=LinkCollection(simple_links=simple_links),
     )
    def test_valid_strings_input(self):
        input_str = '{"Animals": ["cow", "pig", "human"]}'
        field = ListField("Animals", EmbeddedScalarField())

        input_data = json.loads(input_str)
        link_collection = field.parse(data=input_data, context={})

        expected_link_collection = LinkCollection(
            simple_links=(
                SimpleLink(pred="animals", obj="cow"),
                SimpleLink(pred="animals", obj="pig"),
                SimpleLink(pred="animals", obj="human"),
            ),
        )
        self.assertEqual(link_collection, expected_link_collection)
    def test_schema_parse(self):
        resource_arn = "arn:aws:iam:us-west-2:111122223333:account-password-policy/default"
        aws_resource_dict = {
            "MinimumPasswordLength": 12,
            "RequireSymbols": True,
            "RequireNumbers": True,
            "RequireUppercaseCharacters": True,
            "RequireLowercaseCharacters": True,
            "AllowUsersToChangePassword": True,
            "ExpirePasswords": True,
            "MaxPasswordAge": 90,
            "PasswordReusePrevention": 5,
            "HardExpiry": True,
        }

        link_collection = IAMAccountPasswordPolicyResourceSpec.schema.parse(
            data=aws_resource_dict,
            context={
                "account_id": "111122223333",
                "region": "us-west-2"
            })
        resource = Resource(
            resource_id=resource_arn,
            type=IAMAccountPasswordPolicyResourceSpec.type_name,
            link_collection=link_collection,
        )

        expected_resource = Resource(
            resource_id=
            "arn:aws:iam:us-west-2:111122223333:account-password-policy/default",
            type="account-password-policy",
            link_collection=LinkCollection(simple_links=(
                SimpleLink(pred="minimum_password_length", obj=12),
                SimpleLink(pred="require_symbols", obj=True),
                SimpleLink(pred="require_numbers", obj=True),
                SimpleLink(pred="require_uppercase_characters", obj=True),
                SimpleLink(pred="require_lowercase_characters", obj=True),
                SimpleLink(pred="allow_users_to_change_password", obj=True),
                SimpleLink(pred="expire_passwords", obj=True),
                SimpleLink(pred="max_password_age", obj=90),
                SimpleLink(pred="password_reuse_prevention", obj=5),
                SimpleLink(pred="hard_expiry", obj=True),
            )),
        )
        self.assertEqual(resource, expected_resource)
コード例 #16
0
ファイル: test_links.py プロジェクト: tableau/altimeter
 def testToRdfSmallInt(self):
     pred = "test-pred"
     obj = 20
     link = SimpleLink(pred=pred, obj=obj)
     bnode = BNode()
     graph = Graph()
     namespace = Namespace("test:")
     node_cache = NodeCache()
     link.to_rdf(subj=bnode,
                 namespace=namespace,
                 graph=graph,
                 node_cache=node_cache)
     results = graph.query("select ?s ?p ?o where {?s ?p ?o}")
     self.assertEqual(1, len(results))
     for result in results:
         _, _, o = result
         self.assertEqual(
             o.datatype, URIRef("http://www.w3.org/2001/XMLSchema#integer"))
    def test_valid_dicts_input(self):
        input_str = (
            '{"Biota": {"People": [{"Name": "Bob", "Age": 49}, {"Name": "Sue", "Age": 42}]}}'
        )
        field = DictField(
            "Biota",
            AnonymousListField(
                "People", EmbeddedDictField(ScalarField("Name"), ScalarField("Age"))
            ),
        )

        input_data = json.loads(input_str)
        link_collection = field.parse(data=input_data, context={})

        expected_link_collection = LinkCollection(
            multi_links=(
                MultiLink(
                    pred="biota",
                    obj=LinkCollection(
                        multi_links=(
                            MultiLink(
                                pred="biota",
                                obj=LinkCollection(
                                    simple_links=(
                                        SimpleLink(pred="name", obj="Bob"),
                                        SimpleLink(pred="age", obj=49),
                                    ),
                                ),
                            ),
                            MultiLink(
                                pred="biota",
                                obj=LinkCollection(
                                    simple_links=(
                                        SimpleLink(pred="name", obj="Sue"),
                                        SimpleLink(pred="age", obj=42),
                                    ),
                                ),
                            ),
                        ),
                    ),
                ),
            )
        )
        self.assertEqual(link_collection, expected_link_collection)
コード例 #18
0
ファイル: test_links.py プロジェクト: tableau/altimeter
 def testToRdf(self):
     pred = "test-pred"
     obj = "test-obj"
     link = SimpleLink(pred=pred, obj=obj)
     bnode = BNode()
     graph = Graph()
     namespace = Namespace("test:")
     node_cache = NodeCache()
     link.to_rdf(subj=bnode,
                 namespace=namespace,
                 graph=graph,
                 node_cache=node_cache)
     results = graph.query("select ?s ?p ?o where {?s ?p ?o}")
     self.assertEqual(1, len(results))
     for result in results:
         s, p, o = result
         self.assertEqual(s, bnode)
         self.assertEqual(str(p), "test:test-pred")
         self.assertEqual(str(o), "test-obj")
コード例 #19
0
    def test_key_absent_with_default(self):
        input_str = "{}"
        field = ScalarField("FieldName", default_value="DefaultValue")

        input_data = json.loads(input_str)
        link_collection = field.parse(data=input_data, context={})

        expected_link_collection = LinkCollection(simple_links=(SimpleLink(
            pred="field_name", obj="DefaultValue"), ), )
        self.assertEqual(link_collection, expected_link_collection)
コード例 #20
0
    def test_key_present_with_optional(self):
        input_str = '{"FieldName": "Value"}'
        field = ScalarField("FieldName", optional=True)

        input_data = json.loads(input_str)
        link_collection = field.parse(data=input_data, context={})

        expected_link_collection = LinkCollection(simple_links=(SimpleLink(
            pred="field_name", obj="Value"), ), )
        self.assertEqual(link_collection, expected_link_collection)
コード例 #21
0
    def test_valid_input_with_alti_key(self):
        input_str = '{"FieldName": "Value"}'
        field = ScalarField("FieldName", alti_key="alti_field_name")

        input_data = json.loads(input_str)
        link_collection = field.parse(data=input_data, context={})

        expected_link_collection = LinkCollection(simple_links=(SimpleLink(
            pred="alti_field_name", obj="Value"), ), )
        self.assertEqual(link_collection, expected_link_collection)
コード例 #22
0
ファイル: test_links.py プロジェクト: tableau/altimeter
    def testToLpg(self):
        pred = "test-multi-pred"
        obj = LinkCollection(simple_links=(
            SimpleLink(pred="test-simple-pred-1", obj="test-simple-obj-1"),
            SimpleLink(pred="test-simple-pred-2", obj="test-simple-obj-2"),
            SimpleLink(pred="test-simple-pred-3", obj="test-simple-obj-3"),
        ), )
        link = MultiLink(pred=pred, obj=obj)

        parent = {"~id": "parent_id"}
        vertices = []
        edges = []
        link.to_lpg(parent, vertices, edges, "")

        expected_vertex = {
            "~label": "test-multi-pred",
            "test-simple-pred-1": "test-simple-obj-1",
            "test-simple-pred-2": "test-simple-obj-2",
            "test-simple-pred-3": "test-simple-obj-3",
        }

        self.assertEqual(len(vertices), 1)
        self.assertIsInstance(vertices[0]["~id"], uuid.UUID)
        vertex_id = vertices[0]["~id"]
        del vertices[0]["~id"]
        self.assertDictEqual(expected_vertex, vertices[0])

        expected_edge = {
            "~label": "test-multi-pred",
            "~from": "parent_id",
            "~to": vertex_id,
        }
        self.assertEqual(len(edges), 1)
        self.assertIsInstance(edges[0]["~id"], uuid.UUID)
        del edges[0]["~id"]
        self.assertDictEqual(expected_edge, edges[0])

        vertices = []
        edges = []
        link.to_lpg(parent, vertices, edges, "test_prefix")
        self.assertEqual(len(edges), 1)
        self.assertEqual("test_prefix", edges[0]["~label"])
    def test_allow_scalar(self):
        input_str = '{"People": "bob"}'
        field = ListField("People", EmbeddedScalarField(), alti_key="person", allow_scalar=True)

        input_data = json.loads(input_str)
        link_collection = field.parse(data=input_data, context={})

        expected_link_collection = LinkCollection(
            simple_links=(SimpleLink(pred="person", obj="bob"),),
        )
        self.assertEqual(link_collection, expected_link_collection)
コード例 #24
0
    def test_valid_input(self):
        input_data = "foo"
        parent_alti_key = "parent_alti_key"
        field = EmbeddedScalarField()

        link_collection = field.parse(
            data=input_data, context={"parent_alti_key": parent_alti_key})

        expected_link_collection = LinkCollection(simple_links=(SimpleLink(
            pred="parent_alti_key", obj="foo"), ), )
        self.assertEqual(link_collection, expected_link_collection)
    def test_valid_strings_input(self):
        input_str = '{"Biota": {"Animals": ["cow", "pig", "human"], "Plants": ["tree", "fern"]}}'
        field = DictField("Biota", AnonymousListField("Animals", EmbeddedScalarField()))

        input_data = json.loads(input_str)
        link_collection = field.parse(data=input_data, context={})

        expected_link_collection = LinkCollection(
            multi_links=(
                MultiLink(
                    pred="biota",
                    obj=LinkCollection(
                        simple_links=(
                            SimpleLink(pred="biota", obj="cow"),
                            SimpleLink(pred="biota", obj="pig"),
                            SimpleLink(pred="biota", obj="human"),
                        )
                    ),
                ),
            )
        )
        self.assertEqual(link_collection, expected_link_collection)
    def test_allow_scalar(self):
        input_str = '{"Biota": {"Plants": "tree"}}'
        field = DictField(
            "Biota", AnonymousListField("Plants", EmbeddedScalarField(), allow_scalar=True)
        )
        input_data = json.loads(input_str)
        link_collection = field.parse(data=input_data, context={})

        expected_link_collection = LinkCollection(
            multi_links=(
                MultiLink(
                    pred="biota",
                    obj=LinkCollection(simple_links=(SimpleLink(pred="biota", obj="tree"),),),
                ),
            )
        )
        self.assertEqual(expected_link_collection, link_collection)
コード例 #27
0
    def test_scan(self):
        account_id = "123456789012"
        region_name = "us-east-1"

        session = boto3.Session()

        ec2_client = session.client("ec2", region_name=region_name)
        list_resp = ec2_client.describe_vpcs()
        present_vpcs = list_resp["Vpcs"]
        self.assertEqual(len(present_vpcs), 1)
        present_vpc_id = present_vpcs[0]["VpcId"]
        present_vpc_arn = f"arn:aws:ec2:us-east-1:123456789012:vpc/{present_vpc_id}"

        create_resp = ec2_client.create_vpc(CidrBlock="10.0.0.0/16")
        created_vpc_id = create_resp["Vpc"]["VpcId"]
        created_vpc_arn = f"arn:aws:ec2:us-east-1:123456789012:vpc/{created_vpc_id}"

        scan_accessor = AWSAccessor(session=session, account_id=account_id, region_name=region_name)
        resources = VPCResourceSpec.scan(scan_accessor=scan_accessor)

        expected_resources = [
            Resource(
                resource_id=present_vpc_arn,
                type="aws:ec2:vpc",
                link_collection=LinkCollection(
                    simple_links=(
                        SimpleLink(pred="is_default", obj=True),
                        SimpleLink(pred="cidr_block", obj="172.31.0.0/16"),
                        SimpleLink(pred="state", obj="available"),
                    ),
                    resource_links=(
                        ResourceLink(pred="account", obj="arn:aws::::account/123456789012"),
                        ResourceLink(pred="region", obj="arn:aws:::123456789012:region/us-east-1"),
                    ),
                ),
            ),
            Resource(
                resource_id=created_vpc_arn,
                type="aws:ec2:vpc",
                link_collection=LinkCollection(
                    simple_links=(
                        SimpleLink(pred="is_default", obj=False),
                        SimpleLink(pred="cidr_block", obj="10.0.0.0/16"),
                        SimpleLink(pred="state", obj="available"),
                    ),
                    resource_links=(
                        ResourceLink(pred="account", obj="arn:aws::::account/123456789012"),
                        ResourceLink(pred="region", obj="arn:aws:::123456789012:region/us-east-1"),
                    ),
                ),
            ),
        ]
        self.assertEqual(resources, expected_resources)
コード例 #28
0
    def parse(self, data: Union[str, bool, int, float],
              context: Dict[str, Any]) -> LinkCollection:
        """Parse this field and return a LinkCollection.

        Args:
            data: scalar value
            context: context dict containing data from higher level parsing code.

        Returns:
            LinkCollection
        """
        parent_alti_key = self.get_parent_alti_key(data, context)
        if isinstance(data, SCALAR_TYPES):
            link = SimpleLink(pred=parent_alti_key, obj=data)
            return LinkCollection(simple_links=[link], )
        raise ScalarFieldValueNotAScalarException(
            (f"Expected data to be one of {SCALAR_TYPES}, is "
             f"{type(data)}: {data}"))
コード例 #29
0
    def test_scan(self):
        account_id = "123456789012"
        region_name = "us-east-1"

        session = boto3.Session()
        scan_accessor = AWSAccessor(session=session,
                                    account_id=account_id,
                                    region_name=region_name)
        resources = AccountResourceSpec.scan(scan_accessor=scan_accessor)

        expected_resources = [
            Resource(
                resource_id="arn:aws::::account/123456789012",
                type="aws:account",
                link_collection=LinkCollection(simple_links=(SimpleLink(
                    pred="account_id", obj="123456789012"), ), ),
            )
        ]

        self.assertEqual(resources, expected_resources)
    def test(self):
        account_id = "012345678901"
        errors = ["foo", "boo"]
        unscanned_account_resource = UnscannedAccountResourceSpec.create_resource(
            account_id=account_id, errors=errors)
        resource = ResourceSpec.merge_resources("foo",
                                                [unscanned_account_resource])

        self.assertEqual(resource.resource_id, "foo")
        self.assertEqual(resource.type, "aws:unscanned-account")
        self.assertEqual(len(resource.link_collection.simple_links), 2)
        self.assertEqual(
            resource.link_collection.simple_links[0],
            SimpleLink(pred="account_id", obj="012345678901"),
        )
        self.assertEqual(resource.link_collection.simple_links[1].pred,
                         "error")
        self.assertTrue(
            resource.link_collection.simple_links[1].obj.startswith(
                "foo\nboo - "))