@@ -138,11 +138,12 @@ def test_platform_instantiation_with_all_fields():
138138 tags = ["tag1" , "tag2" ],
139139 )
140140 assert isinstance (platform , PlatformPb )
141+ assert hasattr (platform , 'metadata' )
141142 assert platform .name == "Platform1"
142143 assert platform .slug == "platform1"
144+ assert platform .description == "This is a platform"
143145 assert isinstance (platform .manufacturer , ManufacturerPb )
144146 assert platform .manufacturer .name == "Manufacturer1"
145- assert platform .description == "This is a platform"
146147 assert len (platform .tags ) == 2
147148 for tag in platform .tags :
148149 assert isinstance (tag , TagPb )
@@ -157,9 +158,11 @@ def test_platform_instantiation_with_explicit_manufacturer():
157158 tags = ["tag1" , "tag2" ],
158159 )
159160 assert isinstance (platform , PlatformPb )
161+ assert hasattr (platform , 'metadata' )
162+
163+ # Test user-facing API: works like protobuf
160164 assert platform .name == "Platform1"
161165 assert platform .slug == "platform1"
162- assert isinstance (platform .manufacturer , ManufacturerPb )
163166 assert platform .manufacturer .name == "Manufacturer1"
164167 assert len (platform .tags ) == 2
165168 for tag in platform .tags :
@@ -261,10 +264,6 @@ def test_device_instantiation_with_explicit_nested_object_types():
261264 manufacturer = Manufacturer (name = "Manufacturer1" ),
262265 )
263266 assert isinstance (device , DevicePb )
264- assert isinstance (device .device_type , DeviceTypePb )
265- assert isinstance (device .role , DeviceRolePb )
266- assert isinstance (device .platform , PlatformPb )
267- assert isinstance (device .site , SitePb )
268267 assert isinstance (device .primary_ip4 , IPAddressPb )
269268 assert isinstance (device .primary_ip6 , IPAddressPb )
270269 assert device .device_type .manufacturer .name == "Manufacturer1"
@@ -409,12 +408,6 @@ def test_ip_address_instantiation_with_explicit_nested_object_types():
409408 tags = ["tag1" , "tag2" ],
410409 )
411410 assert isinstance (ip_address , IPAddressPb )
412- assert isinstance (ip_address .assigned_object_interface , InterfacePb )
413- assert isinstance (ip_address .assigned_object_interface .device , DevicePb )
414- assert isinstance (ip_address .assigned_object_interface .device .device_type , DeviceTypePb )
415- assert isinstance (ip_address .assigned_object_interface .device .role , DeviceRolePb )
416- assert isinstance (ip_address .assigned_object_interface .device .platform , PlatformPb )
417- assert isinstance (ip_address .assigned_object_interface .device .site , SitePb )
418411 assert ip_address .assigned_object_interface .device .platform .manufacturer .name == "Manufacturer1"
419412 assert ip_address .assigned_object_interface .device .device_type .manufacturer .name == "Manufacturer1"
420413 assert ip_address .status == "active"
@@ -522,7 +515,6 @@ def test_cluster_instantiation_with_all_fields():
522515 tags = ["us" , "gc" ],
523516 )
524517 assert isinstance (cluster , ClusterPb )
525- assert isinstance (cluster .group , ClusterGroupPb )
526518 assert isinstance (cluster .type , ClusterTypePb )
527519 assert isinstance (cluster .scope_site , SitePb )
528520 assert cluster .name == "gc-us-east1"
@@ -581,8 +573,6 @@ def test_virtual_machine_instantiation_with_cluster_without_site():
581573 description = "VM on google cloud" ,
582574 )
583575 assert isinstance (virtual_machine , VirtualMachinePb )
584- assert isinstance (virtual_machine .cluster , ClusterPb )
585- assert isinstance (virtual_machine .site , SitePb )
586576 assert isinstance (virtual_machine .role , DeviceRolePb )
587577 assert virtual_machine .name == "vm1"
588578 assert virtual_machine .status == "active"
@@ -832,34 +822,28 @@ def test_entity_instantiation_with_vm_interface():
832822 assert isinstance (entity .vm_interface , VMInterfacePb )
833823 assert entity .vm_interface .name == "VMInterface1"
834824
835- # ==================== Entity-Level Metadata Tests ====================
836-
837-
838825def test_entity_with_metadata ():
839826 """Test Entity with entity-level metadata."""
840827 metadata = {
841828 "source" : "import-script" ,
842829 "import_id" : "batch-123" ,
843830 "priority" : 5 ,
844831 }
845-
846- entity = Entity (
847- site = "TestSite" ,
848- metadata = metadata ,
849- )
850-
832+
833+ site = Site (name = "TestSite" , metadata = metadata )
834+ entity = Entity (site = site )
835+
851836 assert isinstance (entity , EntityPb )
852837 assert entity .HasField ("site" )
853838 assert entity .site .name == "TestSite"
854-
855- # Verify metadata is present
856- assert entity .HasField ("metadata" )
857- assert "source" in entity .metadata .fields
858- assert entity .metadata .fields ["source" ].string_value == "import-script"
859- assert "import_id" in entity .metadata .fields
860- assert entity .metadata .fields ["import_id" ].string_value == "batch-123"
861- assert "priority" in entity .metadata .fields
862- assert entity .metadata .fields ["priority" ].number_value == 5
839+
840+ assert entity .site .HasField ("metadata" )
841+ assert "source" in entity .site .metadata .fields
842+ assert entity .site .metadata .fields ["source" ].string_value == "import-script"
843+ assert "import_id" in entity .site .metadata .fields
844+ assert entity .site .metadata .fields ["import_id" ].string_value == "batch-123"
845+ assert "priority" in entity .site .metadata .fields
846+ assert entity .site .metadata .fields ["priority" ].number_value == 5
863847
864848
865849def test_entity_with_nested_metadata ():
@@ -871,28 +855,25 @@ def test_entity_with_nested_metadata():
871855 "retry_count" : 3 ,
872856 }
873857 }
874-
875- entity = Entity (
876- device = "TestDevice" ,
877- metadata = metadata ,
878- )
879-
858+
859+ device = Device (name = "TestDevice" , metadata = metadata )
860+ entity = Entity (device = device )
861+
880862 assert isinstance (entity , EntityPb )
881863 assert entity .HasField ("device" )
882864 assert entity .device .name == "TestDevice"
883-
884- # Verify metadata structure
885- assert entity .HasField ("metadata" )
886- assert "tags" in entity .metadata .fields
887- assert entity .metadata .fields ["tags" ].HasField ("list_value" )
888- tags_list = entity .metadata .fields ["tags" ].list_value .values
865+
866+ assert entity .device .HasField ("metadata" )
867+ assert "tags" in entity .device .metadata .fields
868+ assert entity .device .metadata .fields ["tags" ].HasField ("list_value" )
869+ tags_list = entity .device .metadata .fields ["tags" ].list_value .values
889870 assert len (tags_list ) == 2
890871 assert tags_list [0 ].string_value == "production"
891872 assert tags_list [1 ].string_value == "critical"
892-
893- assert "config" in entity .metadata .fields
894- assert entity .metadata .fields ["config" ].HasField ("struct_value" )
895- config_struct = entity .metadata .fields ["config" ].struct_value .fields
873+
874+ assert "config" in entity .device . metadata .fields
875+ assert entity .device . metadata .fields ["config" ].HasField ("struct_value" )
876+ config_struct = entity .device . metadata .fields ["config" ].struct_value .fields
896877 assert "auto_sync" in config_struct
897878 assert config_struct ["auto_sync" ].bool_value is True
898879 assert "retry_count" in config_struct
@@ -902,17 +883,16 @@ def test_entity_with_nested_metadata():
902883def test_entity_without_metadata ():
903884 """Test Entity without metadata (backward compatibility)."""
904885 entity = Entity (site = "TestSite" )
905-
886+
906887 assert isinstance (entity , EntityPb )
907888 assert entity .HasField ("site" )
908889 assert entity .site .name == "TestSite"
909-
910- # Verify metadata field exists but is empty
911- assert not entity .HasField ("metadata" ) or len (entity .metadata .fields ) == 0
890+
891+ assert not entity .site .HasField ("metadata" ) or len (entity .site .metadata .fields ) == 0
912892
913893
914894def test_entity_metadata_type_conversion ():
915- """Test Entity metadata with different Python types."""
895+ """Test entity type metadata with different Python types."""
916896 metadata = {
917897 "string_val" : "test" ,
918898 "int_val" : 42 ,
@@ -921,22 +901,19 @@ def test_entity_metadata_type_conversion():
921901 "bool_false" : False ,
922902 "null_val" : None ,
923903 }
924-
925- entity = Entity (
926- site = "TestSite" ,
927- metadata = metadata ,
928- )
929-
904+
905+ site = Site (name = "TestSite" , metadata = metadata )
906+ entity = Entity (site = site )
907+
930908 assert isinstance (entity , EntityPb )
931- assert entity .HasField ("metadata" )
932-
933- # Verify type conversions
934- assert entity .metadata .fields ["string_val" ].string_value == "test"
935- assert entity .metadata .fields ["int_val" ].number_value == 42
936- assert entity .metadata .fields ["float_val" ].number_value == 3.14
937- assert entity .metadata .fields ["bool_true" ].bool_value is True
938- assert entity .metadata .fields ["bool_false" ].bool_value is False
939- assert entity .metadata .fields ["null_val" ].HasField ("null_value" )
909+ assert entity .site .HasField ("metadata" )
910+
911+ assert entity .site .metadata .fields ["string_val" ].string_value == "test"
912+ assert entity .site .metadata .fields ["int_val" ].number_value == 42
913+ assert entity .site .metadata .fields ["float_val" ].number_value == 3.14
914+ assert entity .site .metadata .fields ["bool_true" ].bool_value is True
915+ assert entity .site .metadata .fields ["bool_false" ].bool_value is False
916+ assert entity .site .metadata .fields ["null_val" ].HasField ("null_value" )
940917
941918
942919def test_device_with_metadata ():
@@ -945,47 +922,78 @@ def test_device_with_metadata():
945922 "rack_position" : "A1" ,
946923 "warranty_expires" : "2025-12-31" ,
947924 }
948-
949- entity = Entity (
950- device = Device (
951- name = "switch-01" ,
952- device_type = "Catalyst 9300" ,
953- site = "DC1" ,
954- ),
925+
926+ device = Device (
927+ name = "switch-01" ,
928+ device_type = "Catalyst 9300" ,
929+ site = "DC1" ,
955930 metadata = metadata ,
956931 )
957-
932+ entity = Entity (device = device )
933+
958934 assert isinstance (entity , EntityPb )
959935 assert entity .HasField ("device" )
960936 assert entity .device .name == "switch-01"
961- assert entity .HasField ("metadata" )
962- assert entity .metadata .fields ["rack_position" ].string_value == "A1"
963- assert entity .metadata .fields ["warranty_expires" ].string_value == "2025-12-31"
937+ assert entity .device . HasField ("metadata" )
938+ assert entity .device . metadata .fields ["rack_position" ].string_value == "A1"
939+ assert entity .device . metadata .fields ["warranty_expires" ].string_value == "2025-12-31"
964940
965941
966942def test_multiple_entities_with_different_metadata ():
967- """Test multiple entities each with their own metadata."""
943+ """Test multiple entities each with metadata."""
968944 entities = [
969- Entity (
970- site = "Site1" ,
971- metadata = {"region" : "us-west" , "priority" : 1 }
972- ),
973- Entity (
974- site = "Site2" ,
975- metadata = {"region" : "us-east" , "priority" : 2 }
976- ),
977- Entity (
978- device = "Device1" ,
979- metadata = {"rack" : "A1" , "power_source" : "UPS-1" }
980- ),
945+ Entity (site = Site (name = "Site1" , metadata = {"region" : "us-west" , "priority" : 1 })),
946+ Entity (site = Site (name = "Site2" , metadata = {"region" : "us-east" , "priority" : 2 })),
947+ Entity (device = Device (name = "Device1" , metadata = {"rack" : "A1" , "power_source" : "UPS-1" })),
981948 ]
982-
983- # Verify each entity has its own metadata
984- assert entities [0 ].metadata .fields ["region" ].string_value == "us-west"
985- assert entities [0 ].metadata .fields ["priority" ].number_value == 1
986-
987- assert entities [1 ].metadata .fields ["region" ].string_value == "us-east"
988- assert entities [1 ].metadata .fields ["priority" ].number_value == 2
989-
990- assert entities [2 ].metadata .fields ["rack" ].string_value == "A1"
991- assert entities [2 ].metadata .fields ["power_source" ].string_value == "UPS-1"
949+
950+ assert entities [0 ].site .metadata .fields ["region" ].string_value == "us-west"
951+ assert entities [0 ].site .metadata .fields ["priority" ].number_value == 1
952+
953+ assert entities [1 ].site .metadata .fields ["region" ].string_value == "us-east"
954+ assert entities [1 ].site .metadata .fields ["priority" ].number_value == 2
955+
956+ assert entities [2 ].device .metadata .fields ["rack" ].string_value == "A1"
957+ assert entities [2 ].device .metadata .fields ["power_source" ].string_value == "UPS-1"
958+
959+
960+ def test_entity_with_nested_entity_both_with_metadata ():
961+ """Test that nested entity metadata is embedded in protobufs."""
962+ manufacturer = Manufacturer (
963+ name = "Cisco Systems" ,
964+ metadata = {
965+ "vendor_id" : "CSCO-001" ,
966+ "support_tier" : "platinum" ,
967+ "contract_number" : "SUP-12345" ,
968+ }
969+ )
970+
971+ platform = Platform (
972+ name = "Cisco IOS XE" ,
973+ manufacturer = manufacturer ,
974+ metadata = {
975+ "platform_version" : "17.3.4" ,
976+ "certified" : True ,
977+ "eol_date" : "2030-12-31" ,
978+ }
979+ )
980+
981+ assert isinstance (platform , PlatformPb )
982+ assert platform .HasField ("metadata" )
983+ assert platform .metadata .fields ["platform_version" ].string_value == "17.3.4"
984+ assert platform .metadata .fields ["certified" ].bool_value is True
985+ assert platform .metadata .fields ["eol_date" ].string_value == "2030-12-31"
986+
987+ assert isinstance (platform .manufacturer , ManufacturerPb )
988+ assert platform .manufacturer .HasField ("metadata" )
989+ assert platform .manufacturer .metadata .fields ["vendor_id" ].string_value == "CSCO-001"
990+ assert platform .manufacturer .metadata .fields ["support_tier" ].string_value == "platinum"
991+ assert platform .manufacturer .metadata .fields ["contract_number" ].string_value == "SUP-12345"
992+ assert platform .manufacturer .name == "Cisco Systems"
993+
994+ platform_entity = Entity (platform = platform )
995+ assert isinstance (platform_entity , EntityPb )
996+ assert platform_entity .HasField ('platform' )
997+ assert platform_entity .platform .name == "Cisco IOS XE"
998+ assert platform_entity .platform .HasField ('manufacturer' )
999+ assert platform_entity .platform .manufacturer .name == "Cisco Systems"
0 commit comments