mirror of
				https://git.dn42.dev/dn42/registry.git
				synced 2025-10-31 11:40:40 +08:00 
			
		
		
		
	update rpsl tooling
This commit is contained in:
		
							parent
							
								
									07f2eddcd0
								
							
						
					
					
						commit
						d4966a3b7a
					
				
					 24 changed files with 691 additions and 606 deletions
				
			
		
							
								
								
									
										8
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -2,6 +2,8 @@ _MTN | ||||||
| lib/ | lib/ | ||||||
| whoisd/ | whoisd/ | ||||||
| __pycache__ | __pycache__ | ||||||
| .index | 
 | ||||||
| .links | /data/.rpsl/index | ||||||
| .nettree | /data/.rpsl/links | ||||||
|  | /data/.rpsl/nettree | ||||||
|  | /data/.rpsl/schema | ||||||
							
								
								
									
										13
									
								
								data/.rpsl
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								data/.rpsl
									
										
									
									
									
								
							|  | @ -1,13 +0,0 @@ | ||||||
| namespace:        dn42 |  | ||||||
| schema:           schema |  | ||||||
| owner:            mntner |  | ||||||
| default-owner:    DN42-MNT |  | ||||||
| network-owner:    inet6num inet6num |  | ||||||
| network-owner:    inet6num route |  | ||||||
| network-owner:    inet6num inetnum |  | ||||||
| network-owner:    inetnum  inetnum |  | ||||||
| network-owner:    inetnum  route |  | ||||||
| primary-key:      inetnum  cidr |  | ||||||
| primary-key:      inet6num cidr |  | ||||||
| primary-key:      person   nic-hdl |  | ||||||
| primary-key:      role     nic-hdl |  | ||||||
							
								
								
									
										16
									
								
								data/.rpsl/config
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								data/.rpsl/config
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | ||||||
|  | namespace:          dn42 | ||||||
|  | schema:             schema | ||||||
|  | owners:             mntner | ||||||
|  | default-owner:      DN42-MNT | ||||||
|  | primary-key:        person nic-hdl | ||||||
|  | primary-key:        role nic-hdl | ||||||
|  | primary-key:        inetnum cidr | ||||||
|  | primary-key:        inet6num cidr | ||||||
|  | network-owner:      inet6num inet6num | ||||||
|  | network-owner:      inet6num inetnum | ||||||
|  | network-owner:      inetnum inetnum | ||||||
|  | network-owner:      inetnum route | ||||||
|  | network-owner:      inet6num route6 | ||||||
|  | mnt-by:             DN42-MNT | ||||||
|  | source:             DN42 | ||||||
|  | 
 | ||||||
							
								
								
									
										9
									
								
								data/aut-num/AS134098
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								data/aut-num/AS134098
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | ||||||
|  | aut-num:            AS134098 | ||||||
|  | as-name:            SYLVEON-AS-AP | ||||||
|  | admin-c:            LICSON-NEONETWORK | ||||||
|  | tech-c:             LICSON-NEONETWORK | ||||||
|  | descr:              Licson Internet Service | ||||||
|  | remarks:              Sylveon Network (Hong Kong) Limited. | ||||||
|  | remarks:              This was created to fix missing object from neonetwork. | ||||||
|  | mnt-by:             DN42-MNT | ||||||
|  | source:             DN42 | ||||||
|  | @ -19,7 +19,5 @@ key:                org         optional   single    lookup=dn42.organisation | ||||||
| key:                remarks     optional   multiple | key:                remarks     optional   multiple | ||||||
| key:                source      required   single    lookup=dn42.registry | key:                source      required   single    lookup=dn42.registry | ||||||
| network-owner:      inet6num | network-owner:      inet6num | ||||||
| network-owner:      inetnum |  | ||||||
| network-owner:      route6 |  | ||||||
| mnt-by:             DN42-MNT | mnt-by:             DN42-MNT | ||||||
| source:             DN42 | source:             DN42 | ||||||
|  |  | ||||||
|  | @ -18,7 +18,7 @@ key:                mnt-routes  optional  multiple  lookup=dn42.mntner | ||||||
| key:                org         optional  single    lookup=dn42.organisation | key:                org         optional  single    lookup=dn42.organisation | ||||||
| key:                remarks     optional  multiple | key:                remarks     optional  multiple | ||||||
| key:                source      required  single    lookup=dn42.registry | key:                source      required  single    lookup=dn42.registry | ||||||
|  | network-owner:      inet6num | ||||||
| network-owner:      inetnum | network-owner:      inetnum | ||||||
| network-owner:      route |  | ||||||
| mnt-by:             DN42-MNT | mnt-by:             DN42-MNT | ||||||
| source:             DN42 | source:             DN42 | ||||||
|  |  | ||||||
|  | @ -11,5 +11,6 @@ key:                remarks     optional  multiple | ||||||
| key:                source      required  single    lookup=dn42.registry | key:                source      required  single    lookup=dn42.registry | ||||||
| key:                pingable    optional  multiple | key:                pingable    optional  multiple | ||||||
| key:                max-length  optional  single | key:                max-length  optional  single | ||||||
|  | network-owner:      inetnum | ||||||
| mnt-by:             DN42-MNT | mnt-by:             DN42-MNT | ||||||
| source:             DN42 | source:             DN42 | ||||||
|  |  | ||||||
|  | @ -11,5 +11,6 @@ key:                remarks     optional  multiple | ||||||
| key:                source      required  single    lookup=dn42.registry | key:                source      required  single    lookup=dn42.registry | ||||||
| key:                pingable    optional  multiple | key:                pingable    optional  multiple | ||||||
| key:                max-length  optional  single | key:                max-length  optional  single | ||||||
|  | network-owner:      inet6num | ||||||
| mnt-by:             DN42-MNT | mnt-by:             DN42-MNT | ||||||
| source:             DN42 | source:             DN42 | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ key:                key      required  multiple  > [key-name] | ||||||
| key:                mnt-by   required  multiple    lookup=dn42.mntner > [mntner] | key:                mnt-by   required  multiple    lookup=dn42.mntner > [mntner] | ||||||
| key:                remarks  optional  multiple  > [text]... | key:                remarks  optional  multiple  > [text]... | ||||||
| key:                source   required  single      lookup=dn42.registry | key:                source   required  single      lookup=dn42.registry | ||||||
| key:                network-owner optional multiple > [child-schema] | key:                network-owner optional multiple > [parent-schema] | ||||||
| mnt-by:             DN42-MNT | mnt-by:             DN42-MNT | ||||||
| source:             DN42 | source:             DN42 | ||||||
| remarks:            # option descriptions | remarks:            # option descriptions | ||||||
|  |  | ||||||
|  | @ -1,363 +0,0 @@ | ||||||
| .BEGIN DN42-MNT |  | ||||||
| schema:             AUT-NUM-SCHEMA |  | ||||||
| ref:                dn42.aut-num |  | ||||||
| key:                aut-num    required  single   primary schema |  | ||||||
| key:                as-name    required  single |  | ||||||
| key:                descr      optional  single |  | ||||||
| key:                mnt-by     required  multiple lookup=dn42.mntner |  | ||||||
| key:                member-of  optional  multiple lookup=dn42.as-set,dn42.route-set |  | ||||||
| key:                admin-c    optional  multiple lookup=dn42.person,dn42.role |  | ||||||
| key:                tech-c     optional  multiple lookup=dn42.person,dn42.role |  | ||||||
| key:                org        optional  single   lookup=dn42.organisation |  | ||||||
| key:                import     deprecate multiple |  | ||||||
| key:                export     deprecate multiple |  | ||||||
| key:                default    deprecate multiple |  | ||||||
| key:                mp-peer    deprecate multiple |  | ||||||
| key:                mp-group   deprecate multiple |  | ||||||
| key:                mp-import  optional  multiple |  | ||||||
| key:                mp-export  optional  multiple |  | ||||||
| key:                mp-default optional  multiple |  | ||||||
| key:                geo-loc    optional  multiple > [lat-c] [long-c] [name] |  | ||||||
| key:                remarks    optional  multiple |  | ||||||
| key:                source     required  single    lookup=dn42.registry |  | ||||||
| mnt-by:             DN42-MNT |  | ||||||
| source:             DN42 |  | ||||||
| ... |  | ||||||
| schema:             AS-SET-SCHEMA |  | ||||||
| ref:                dn42.as-set |  | ||||||
| key:                as-set      required  single    primary schema |  | ||||||
| key:                descr       optional  single |  | ||||||
| key:                mnt-by      required  multiple  lookup=dn42.mntner |  | ||||||
| key:                members     optional  multiple  lookup=dn42.aut-num,dn42.as-set |  | ||||||
| key:                mbrs-by-ref optional  multiple  lookup=dn42.mntner |  | ||||||
| key:                admin-c     optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                tech-c      optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                remarks     optional  multiple |  | ||||||
| key:                source      required  single    lookup=dn42.registry |  | ||||||
| mnt-by:             DN42-MNT |  | ||||||
| source:             DN42 |  | ||||||
| ... |  | ||||||
| schema:             ROUTE6-SCHEMA |  | ||||||
| ref:                dn42.route6 |  | ||||||
| key:                route6      required  single    primary schema |  | ||||||
| key:                mnt-by      required  multiple  lookup=dn42.mntner |  | ||||||
| key:                origin      required  multiple  lookup=dn42.aut-num |  | ||||||
| key:                member-of   optional  multiple  lookup=dn42.route-set |  | ||||||
| key:                admin-c     optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                tech-c      optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                descr       optional  multiple |  | ||||||
| key:                remarks     optional  multiple |  | ||||||
| key:                source      required  single    lookup=dn42.registry |  | ||||||
| key:                pingable    optional  multiple |  | ||||||
| key:                max-length  optional  single |  | ||||||
| mnt-by:             DN42-MNT |  | ||||||
| source:             DN42 |  | ||||||
| ... |  | ||||||
| schema:             TINC-KEYSET-SCHEMA |  | ||||||
| ref:                dn42.tinc-keyset |  | ||||||
| key:                tinc-keyset  required  single    primary schema |  | ||||||
| key:                descr        optional  single |  | ||||||
| key:                remarks      optional  multiple |  | ||||||
| key:                member       required  multiple  lookup=dn42.tinc-key |  | ||||||
| key:                admin-c      optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                tech-c       optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                mnt-by       required  multiple  lookup=dn42.mntner |  | ||||||
| key:                source       required  single    lookup=dn42.registry |  | ||||||
| mnt-by:             DN42-MNT |  | ||||||
| source:             DN42 |  | ||||||
| ... |  | ||||||
| schema:             ROLE-SCHEMA |  | ||||||
| ref:                dn42.role |  | ||||||
| key:                role            required   single    schema |  | ||||||
| key:                nic-hdl         required   single    primary |  | ||||||
| key:                mnt-by          required   multiple  lookup=dn42.mntner |  | ||||||
| key:                org             optional   multiple  lookup=dn42.organisation |  | ||||||
| key:                admin-c         optional   multiple  lookup=dn42.person |  | ||||||
| key:                tech-c          optional   multiple  lookup=dn42.person |  | ||||||
| key:                abuse-c         optional   multiple  lookup=dn42.person |  | ||||||
| key:                abuse-mailbox   optional   multiple |  | ||||||
| key:                descr           optional   single |  | ||||||
| key:                remarks         optional   multiple |  | ||||||
| key:                source          required   single    lookup=dn42.registry |  | ||||||
| mnt-by:             DN42-MNT |  | ||||||
| source:             DN42 |  | ||||||
| ... |  | ||||||
| schema:             INET6NUM-SCHEMA |  | ||||||
| ref:                dn42.inet6num |  | ||||||
| key:                inet6num    required   single    schema |  | ||||||
| key:                cidr        required   single    primary |  | ||||||
| key:                netname     required   single |  | ||||||
| key:                nserver     optional   multiple  > [domain-name] |  | ||||||
| key:                country     optional   multiple |  | ||||||
| key:                descr       optional   single |  | ||||||
| key:                status      optional   single    > {ALLOCATED|ASSIGNED} {PI|PA|} |  | ||||||
| key:                policy      optional   single    > {open|closed|ask|reserved} |  | ||||||
| key:                admin-c     optional   multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                tech-c      optional   multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                zone-c      optional   multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                ds-rdata    optional   multiple |  | ||||||
| key:                mnt-by      optional   multiple  lookup=dn42.mntner |  | ||||||
| key:                mnt-lower   optional   multiple  lookup=dn42.mntner |  | ||||||
| key:                mnt-routes  optional   multiple  lookup=dn42.mntner |  | ||||||
| key:                org         optional   single    lookup=dn42.organisation |  | ||||||
| key:                remarks     optional   multiple |  | ||||||
| key:                source      required   single    lookup=dn42.registry |  | ||||||
| network-owner:      inet6num |  | ||||||
| network-owner:      inetnum |  | ||||||
| network-owner:      route6 |  | ||||||
| mnt-by:             DN42-MNT |  | ||||||
| source:             DN42 |  | ||||||
| ... |  | ||||||
| schema:             MNTNER-SCHEMA |  | ||||||
| ref:                dn42.mntner |  | ||||||
| key:                mntner         required  single    primary schema |  | ||||||
| key:                descr          optional  single |  | ||||||
| key:                mnt-by         required  multiple  lookup=dn42.mntner |  | ||||||
| key:                admin-c        optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                tech-c         optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                auth           optional  multiple  > [method] [value]... |  | ||||||
| key:                org            optional  multiple  lookup=dn42.organisation |  | ||||||
| key:                abuse-mailbox  optional  single |  | ||||||
| key:                remarks        optional  multiple |  | ||||||
| key:                source         required  single    lookup=dn42.registry |  | ||||||
| mnt-by:             DN42-MNT |  | ||||||
| source:             DN42 |  | ||||||
| ... |  | ||||||
| schema:             ORGANISATION-SCHEMA |  | ||||||
| ref:                dn42.organisation |  | ||||||
| key:                organisation   required  single    primary schema |  | ||||||
| key:                org-name       required  single |  | ||||||
| key:                descr          optional  single |  | ||||||
| key:                admin-c        optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                tech-c         optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                abuse-c        optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                mnt-by         required  multiple  lookup=dn42.mntner |  | ||||||
| key:                mnt-ref        optional  multiple  lookup=dn42.mntner |  | ||||||
| key:                phone          optional  multiple |  | ||||||
| key:                fax-no         optional  multiple |  | ||||||
| key:                www            optional  multiple |  | ||||||
| key:                abuse-mailbox  optional  multiple |  | ||||||
| key:                e-mail         optional  multiple |  | ||||||
| key:                geoloc         optional  multiple |  | ||||||
| key:                language       optional  multiple |  | ||||||
| key:                remarks        optional  multiple |  | ||||||
| key:                address        optional  multiple |  | ||||||
| key:                source         required  single    lookup=dn42.registry |  | ||||||
| mnt-by:             DN42-MNT |  | ||||||
| source:             DN42 |  | ||||||
| ... |  | ||||||
| schema:             TINC-KEY-SCHEMA |  | ||||||
| ref:                dn42.tinc-key |  | ||||||
| key:                tinc-key      required  single    primary schema |  | ||||||
| key:                tinc-host     required  single |  | ||||||
| key:                tinc-file     required  single |  | ||||||
| key:                descr         optional  single |  | ||||||
| key:                remarks       optional  multiple |  | ||||||
| key:                compression   optional  single |  | ||||||
| key:                subnet        optional  multiple |  | ||||||
| key:                tinc-address  optional  single |  | ||||||
| key:                port          optional  single |  | ||||||
| key:                admin-c       optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                tech-c        optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                mnt-by        required  multiple  lookup=dn42.mntner |  | ||||||
| key:                source        required  single    lookup=dn42.registry |  | ||||||
| mnt-by:             DN42-MNT |  | ||||||
| source:             DN42 |  | ||||||
| ... |  | ||||||
| schema:             AS-BLOCK-SCHEMA |  | ||||||
| ref:                dn42.as-block |  | ||||||
| key:                as-block   required  single    primary schema |  | ||||||
| key:                descr      optional  single |  | ||||||
| key:                policy     required  single    > {open|ask|closed} |  | ||||||
| key:                mnt-by     required  multiple  lookup=dn42.mntner |  | ||||||
| key:                admin-c    optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                tech-c     optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                remarks    optional  multiple |  | ||||||
| key:                source     required  single    lookup=dn42.registry |  | ||||||
| mnt-by:             DN42-MNT |  | ||||||
| source:             DN42 |  | ||||||
| ... |  | ||||||
| schema:             SCHEMA-SCHEMA |  | ||||||
| ref:                dn42.schema |  | ||||||
| key:                schema   required  single    primary schema > [name] |  | ||||||
| key:                ref      required  single    > [schema] |  | ||||||
| key:                key      required  multiple  > [key-name] |  | ||||||
|                     {required|optional|recommend|deprecate} |  | ||||||
|                     {single|multiple} {primary|} {schema|} |  | ||||||
|                     lookup=str '>' [spec]... |  | ||||||
| key:                mnt-by   required  multiple    lookup=dn42.mntner > [mntner] |  | ||||||
| key:                remarks  optional  multiple  > [text]... |  | ||||||
| key:                source   required  single      lookup=dn42.registry |  | ||||||
| key:                network-owner optional multiple > [child-schema] |  | ||||||
| mnt-by:             DN42-MNT |  | ||||||
| source:             DN42 |  | ||||||
| remarks:            # option descriptions |  | ||||||
|                     Attribute names must match /[a-zA-Z]([a-zA-Z0-9_\-]*[a-zA-Z0-9])?/. |  | ||||||
| + |  | ||||||
|                     required |  | ||||||
|                     :    object required to have at least one |  | ||||||
|                     optional |  | ||||||
|                     :    object not required to have at least one |  | ||||||
| + |  | ||||||
|                     single |  | ||||||
|                     :    only one of this type allowed |  | ||||||
|                     multiple |  | ||||||
|                     :    more than one of this type allowed |  | ||||||
| + |  | ||||||
|                     primary |  | ||||||
|                     :    use field as lookup key for lookup |  | ||||||
|                     * only one allowed per schema |  | ||||||
|                     * does not allow newlines |  | ||||||
| + |  | ||||||
|                     schema |  | ||||||
|                     :    use field name as the name of the schema |  | ||||||
|                     * only one allowed per schema |  | ||||||
|                     * does not allow newlines |  | ||||||
| + |  | ||||||
|                     lookup |  | ||||||
|                     :    schema match to use for related record |  | ||||||
| + |  | ||||||
|                     \> option specs |  | ||||||
|                     :    defines the option specifications for the key. |  | ||||||
|                     * must come last in option list |  | ||||||
| + |  | ||||||
|                     [label] string value. A positional string argument required. |  | ||||||
|                     Text inside brackets represent a label for the string and must match the same rules as attribute names. |  | ||||||
|                     If follwed by '...' values are gathered as an array. |  | ||||||
| + |  | ||||||
|                     {enum1|enum2|} enumeration. One option in pipe('|') deliniation is allowed. |  | ||||||
|                     If there is a trailing pipe it means the enum is optional. Enum values must match the same rules as attribute names. |  | ||||||
| + |  | ||||||
|                     'literal' Literal value. literal text value which must not contain any whitespace or single quotes. |  | ||||||
| ... |  | ||||||
| schema:             ROUTE-SET-SCHEMA |  | ||||||
| ref:                dn42.route-set |  | ||||||
| key:                route-set    required  single    primary schema |  | ||||||
| key:                descr        optional  single |  | ||||||
| key:                mnt-by       required  multiple  lookup=dn42.mntner |  | ||||||
| key:                members      deprecate multiple |  | ||||||
| key:                mp-members   optional  multiple |  | ||||||
| key:                mbrs-by-ref  optional  multiple  lookup=dn42.mntner |  | ||||||
| key:                admin-c      optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                tech-c       optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                remarks      optional  multiple |  | ||||||
| key:                source       required  single    lookup=dn42.registry |  | ||||||
| mnt-by:             DN42-MNT |  | ||||||
| source:             DN42 |  | ||||||
| ... |  | ||||||
| schema:             REGISTRY-SCHEMA |  | ||||||
| ref:                dn42.registry |  | ||||||
| key:                registry   required  single    primary schema |  | ||||||
| key:                url        required  multiple |  | ||||||
| key:                descr      optional  multiple |  | ||||||
| key:                mnt-by     required  multiple  lookup=dn42.mntner |  | ||||||
| key:                admin-c    optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                tech-c     optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                source     required  single    lookup=dn42.registry |  | ||||||
| mnt-by:             DN42-MNT |  | ||||||
| source:             DN42 |  | ||||||
| ... |  | ||||||
| schema:             KEY-CERT-SCHEMA |  | ||||||
| ref:                dn42.key-cert |  | ||||||
| key:                key-cert     required  single    primary schema |  | ||||||
| key:                method       required  single    > {PGP|X509|MTN} |  | ||||||
| key:                owner        required  multiple |  | ||||||
| key:                fingerpr     required  single |  | ||||||
| key:                certif       required  multiple |  | ||||||
| key:                org          optional  multiple  lookup=dn42.organisation |  | ||||||
| key:                remarks      optional  multiple |  | ||||||
| key:                admin-c      optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                tech-c       optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                mnt-by       required  multiple  lookup=dn42.mntner |  | ||||||
| key:                source       required  single |  | ||||||
| mnt-by:             DN42-MNT |  | ||||||
| source:             DN42 |  | ||||||
| ... |  | ||||||
| schema:             ROUTE-SCHEMA |  | ||||||
| ref:                dn42.route |  | ||||||
| key:                route       required  single    primary schema |  | ||||||
| key:                mnt-by      required  multiple  lookup=dn42.mntner |  | ||||||
| key:                origin      required  multiple  lookup=dn42.aut-num |  | ||||||
| key:                member-of   optional  multiple  lookup=dn42.route-set |  | ||||||
| key:                admin-c     optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                tech-c      optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                descr       optional  single |  | ||||||
| key:                remarks     optional  multiple |  | ||||||
| key:                source      required  single    lookup=dn42.registry |  | ||||||
| key:                pingable    optional  multiple |  | ||||||
| key:                max-length  optional  single |  | ||||||
| mnt-by:             DN42-MNT |  | ||||||
| source:             DN42 |  | ||||||
| ... |  | ||||||
| schema:             PERSON-SCHEMA |  | ||||||
| ref:                dn42.person |  | ||||||
| key:                person          required   single    schema |  | ||||||
| key:                nic-hdl         required   single    primary |  | ||||||
| key:                mnt-by          required   multiple  lookup=dn42.mntner |  | ||||||
| key:                org             optional   multiple  lookup=dn42.organisation |  | ||||||
| key:                nick            optional   multiple |  | ||||||
| key:                pgp-fingerprint optional   multiple |  | ||||||
| key:                www             optional   multiple |  | ||||||
| key:                e-mail          optional   multiple |  | ||||||
| key:                contact         optional   multiple |  | ||||||
| key:                abuse-mailbox   optional   multiple |  | ||||||
| key:                phone           optional   multiple |  | ||||||
| key:                fax-no          optional   multiple |  | ||||||
| key:                address         optional   multiple |  | ||||||
| key:                remarks         optional   multiple |  | ||||||
| key:                source          required   single    lookup=dn42.registry |  | ||||||
| mnt-by:             DN42-MNT |  | ||||||
| source:             DN42 |  | ||||||
| ... |  | ||||||
| schema:             INETNUM-SCHEMA |  | ||||||
| ref:                dn42.inetnum |  | ||||||
| key:                inetnum     required  single    schema |  | ||||||
| key:                cidr        required  single    primary |  | ||||||
| key:                netname     required  single |  | ||||||
| key:                nserver     optional  multiple  > [domain-name] |  | ||||||
| key:                country     optional  multiple |  | ||||||
| key:                descr       optional  single |  | ||||||
| key:                status      optional  single    > {ALLOCATED|ASSIGNED} {PI|PA|} |  | ||||||
| key:                policy      optional  single    > {open|closed|ask|reserved} |  | ||||||
| key:                admin-c     optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                tech-c      optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                zone-c      optional  multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                ds-rdata    optional  multiple |  | ||||||
| key:                mnt-by      optional  multiple  lookup=dn42.mntner |  | ||||||
| key:                mnt-lower   optional  multiple  lookup=dn42.mntner |  | ||||||
| key:                mnt-routes  optional  multiple  lookup=dn42.mntner |  | ||||||
| key:                org         optional  single    lookup=dn42.organisation |  | ||||||
| key:                remarks     optional  multiple |  | ||||||
| key:                source      required  single    lookup=dn42.registry |  | ||||||
| network-owner:      inetnum |  | ||||||
| network-owner:      route |  | ||||||
| mnt-by:             DN42-MNT |  | ||||||
| source:             DN42 |  | ||||||
| ... |  | ||||||
| schema:             NAMESPACE-SCHEMA |  | ||||||
| ref:                dn42.namespace |  | ||||||
| key:                namespace     required single   primary schema > [name] |  | ||||||
| key:                ns-schema     required single   > [schema] |  | ||||||
| key:                ns-owner      required single   > [schema] |  | ||||||
| key:                default-owner optional single   lookup=dn42.mntner  > [mntner] |  | ||||||
| key:                network-owner optional multiple > [parent-schema] [child-schema] |  | ||||||
| key:                primary-key   optional multiple > [schema] [primary] |  | ||||||
| mnt-by:             DN42-MNT |  | ||||||
| source:             DN42 |  | ||||||
| ... |  | ||||||
| schema:             DNS-SCHEMA |  | ||||||
| ref:                dn42.domain |  | ||||||
| key:                domain     required   single    primary schema |  | ||||||
| key:                nserver    required   multiple  > [domain-name] [ip-addr] |  | ||||||
| key:                descr      optional   single |  | ||||||
| key:                mnt-by     required   multiple  lookup=dn42.mntner |  | ||||||
| key:                admin-c    optional   multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                tech-c     optional   multiple  lookup=dn42.person,dn42.role |  | ||||||
| key:                org        optional   multiple  lookup=dn42.organisation |  | ||||||
| key:                country    optional   single |  | ||||||
| key:                ds-rdata    optional  multiple |  | ||||||
| key:                remarks    optional   multiple |  | ||||||
| key:                source     required   single    lookup=dn42.registry |  | ||||||
| mnt-by:             DN42-MNT |  | ||||||
| source:             DN42 |  | ||||||
| .END |  | ||||||
|  | @ -1,118 +0,0 @@ | ||||||
| #!/usr/bin/env python3 |  | ||||||
| """Builds registry index to be used by scan-index.py""" |  | ||||||
| 
 |  | ||||||
| import os |  | ||||||
| import sys |  | ||||||
| 
 |  | ||||||
| from typing import Dict, Generator, List |  | ||||||
| 
 |  | ||||||
| from dom.filedom import FileDOM, read_file |  | ||||||
| from dom.schema import SchemaDOM |  | ||||||
| from dom.nettree import NetTree, NetRecord |  | ||||||
| from dom.transact import TransactDOM |  | ||||||
| 
 |  | ||||||
| def index_files(path: str) -> Generator[FileDOM, None, None]: |  | ||||||
|     """generate list of dom files""" |  | ||||||
|     for root, _, files in os.walk(path): |  | ||||||
|         if root == path: |  | ||||||
|             continue |  | ||||||
| 
 |  | ||||||
|         for f in files: |  | ||||||
|             if f[0] == ".": |  | ||||||
|                 continue |  | ||||||
| 
 |  | ||||||
|             dom = read_file(os.path.join(root, f)) |  | ||||||
|             yield dom |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def run(path: str = "."): |  | ||||||
|     """run main script""" |  | ||||||
|     if not os.path.isdir(os.path.join(path, "schema")): |  | ||||||
|         print("schema directory not found in path", file=sys.stderr) |  | ||||||
|         sys.exit(1) |  | ||||||
| 
 |  | ||||||
|     idx = index_files(path) |  | ||||||
| 
 |  | ||||||
|     lookup = {}  # type: Dict[str, FileDOM] |  | ||||||
|     schemas = {}  # type: Dict[str, SchemaDOM] |  | ||||||
|     files = [] |  | ||||||
|     nets = []  # type: List[NetRecord] |  | ||||||
| 
 |  | ||||||
|     print(r"Reading Files...", end="\r", flush=True, file=sys.stderr) |  | ||||||
| 
 |  | ||||||
|     for (i, dom) in enumerate(idx): |  | ||||||
|         if not dom.valid: |  | ||||||
|             print("E", end="", flush=True) |  | ||||||
|             continue |  | ||||||
| 
 |  | ||||||
|         key, value = dom.index |  | ||||||
|         lookup[key] = value |  | ||||||
|         files.append(dom) |  | ||||||
| 
 |  | ||||||
|         if dom.schema == "schema": |  | ||||||
|             schema = SchemaDOM() |  | ||||||
|             schema.parse(dom) |  | ||||||
| 
 |  | ||||||
|             schemas[schema.ref] = schema |  | ||||||
| 
 |  | ||||||
|         if dom.schema in ["inetnum", "inet6num"]: |  | ||||||
|             nets.append(NetRecord( |  | ||||||
|                 dom.get("cidr").as_net6, |  | ||||||
|                 dom.mntner, |  | ||||||
|                 dom.get("policy", default="closed"), |  | ||||||
|                 dom.get("status", default="ASSIGNED"), |  | ||||||
|             )) |  | ||||||
| 
 |  | ||||||
|         if i % 120 == 0: |  | ||||||
|             print( |  | ||||||
|                 f"Reading Files: files: {len(files)} schemas: {len(schemas)}", |  | ||||||
|                 end="\r", flush=True, file=sys.stderr) |  | ||||||
| 
 |  | ||||||
|     print( |  | ||||||
|         f"Reading Files: done! files: {len(files)}, schemas: {len(schemas)}", |  | ||||||
|         file=sys.stderr) |  | ||||||
| 
 |  | ||||||
|     print("Writing .index", file=sys.stderr) |  | ||||||
|     print("Writing .links", file=sys.stderr) |  | ||||||
|     with open(".index", 'w') as out: |  | ||||||
|         with open(".links", 'w') as link_out: |  | ||||||
|             for dom in files: |  | ||||||
|                 s = schemas.get(dom.rel) |  | ||||||
|                 if s is None: |  | ||||||
|                     print( |  | ||||||
|                         f"{dom.src} schema not found for {dom.rel}", |  | ||||||
|                         file=sys.stderr) |  | ||||||
| 
 |  | ||||||
|                 print(dom.rel, |  | ||||||
|                       dom.get(s.primary), |  | ||||||
|                       dom.src, |  | ||||||
|                       ",".join(dom.mntner), |  | ||||||
|                       sep="|", |  | ||||||
|                       file=out) |  | ||||||
| 
 |  | ||||||
|                 for (link, refs) in s.links.items(): |  | ||||||
|                     d = dom.get(link) |  | ||||||
|                     refs_join = ','.join(refs) |  | ||||||
|                     if d is not None: |  | ||||||
|                         print( |  | ||||||
|                             f"{dom.rel}|{dom.name}|{link}|{d}|{refs_join}", |  | ||||||
|                             file=link_out) |  | ||||||
| 
 |  | ||||||
|     print("Generate .nettree", file=sys.stderr) |  | ||||||
|     tree = NetTree(nets) |  | ||||||
| 
 |  | ||||||
|     print("Writing .nettree", file=sys.stderr) |  | ||||||
|     tree.write_csv(".nettree") |  | ||||||
| 
 |  | ||||||
|     print("Writing .schema", file=sys.stderr) |  | ||||||
|     s = TransactDOM() |  | ||||||
|     s.mntner = "DN42-MNT" |  | ||||||
|     s.files = schemas.values() |  | ||||||
|     with open(".schema", "w") as out: |  | ||||||
|         print(s, file=out) |  | ||||||
| 
 |  | ||||||
|     print("done.", file=sys.stderr) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| if __name__ == "__main__": |  | ||||||
|     run(sys.argv[1] if len(sys.argv) > 1 else os.getcwd()) |  | ||||||
|  | @ -2,11 +2,14 @@ | ||||||
| 
 | 
 | ||||||
| import re | import re | ||||||
| from dataclasses import dataclass | from dataclasses import dataclass | ||||||
| from typing import Sequence, NamedTuple, List, Dict, Optional, Tuple, Union | from typing import Sequence, NamedTuple, List, \ | ||||||
|  |     Dict, Optional, Tuple, Union, Generator, TypeVar | ||||||
| from ipaddress import ip_network, IPv4Network, IPv6Network | from ipaddress import ip_network, IPv4Network, IPv6Network | ||||||
| 
 | 
 | ||||||
| import log | import log | ||||||
| 
 | 
 | ||||||
|  | F = TypeVar("F", bound="FileDOM") | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| @dataclass(frozen=True) | @dataclass(frozen=True) | ||||||
| class Value: | class Value: | ||||||
|  | @ -210,6 +213,13 @@ class FileDOM: | ||||||
| 
 | 
 | ||||||
|         return self.dom[self.keys[key][index]].value |         return self.dom[self.keys[key][index]].value | ||||||
| 
 | 
 | ||||||
|  |     def get_all(self, key) -> Generator[str, None, None]: | ||||||
|  |         "Get all values for a key" | ||||||
|  |         if key not in self.keys: | ||||||
|  |             return | ||||||
|  |         for i in self.keys[key]: | ||||||
|  |             yield self.dom[i].value | ||||||
|  | 
 | ||||||
|     def put(self, key, value, index=0, append=False): |     def put(self, key, value, index=0, append=False): | ||||||
|         """Put a value""" |         """Put a value""" | ||||||
|         if key not in self.keys: |         if key not in self.keys: | ||||||
|  | @ -225,10 +235,10 @@ class FileDOM: | ||||||
|         if index not in self.keys[key]: |         if index not in self.keys[key]: | ||||||
|             self.keys[key].append(i) |             self.keys[key].append(i) | ||||||
| 
 | 
 | ||||||
|  |     @staticmethod | ||||||
|  |     def from_file(fn: str) -> F: | ||||||
|  |         """Parses FileDOM from file""" | ||||||
|  |         with open(fn, mode='r', encoding='utf-8') as f: | ||||||
|  |             dom = FileDOM(src=fn, text=f.readlines()) | ||||||
| 
 | 
 | ||||||
| def read_file(fn: str) -> FileDOM: |             return dom | ||||||
|     """Parses FileDOM from file""" |  | ||||||
|     with open(fn, mode='r', encoding='utf-8') as f: |  | ||||||
|         dom = FileDOM(src=fn, text=f.readlines()) |  | ||||||
| 
 |  | ||||||
|         return dom |  | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| 
 | 
 | ||||||
| from ipaddress import ip_network, IPv6Network | from ipaddress import ip_network, IPv6Network | ||||||
| from dataclasses import dataclass | from dataclasses import dataclass | ||||||
| from typing import Dict, List, Tuple, Optional | from typing import Dict, List, Tuple, Optional, Generator | ||||||
| 
 | 
 | ||||||
| NET = IPv6Network | NET = IPv6Network | ||||||
| V6_NET = ip_network("::/0") | V6_NET = ip_network("::/0") | ||||||
|  | @ -113,24 +113,25 @@ class NetTree: | ||||||
|     def write_csv(self, fn: str = ".netindex"): |     def write_csv(self, fn: str = ".netindex"): | ||||||
|         "write tree to csv" |         "write tree to csv" | ||||||
|         with open(fn, "w") as f: |         with open(fn, "w") as f: | ||||||
|             f.writelines({line+"\n" for line in self._lines()}) |             f.writelines(self._lines()) | ||||||
| 
 | 
 | ||||||
|     def __str__(self) -> str: |     def __str__(self) -> str: | ||||||
|         return "\n".join(self._lines()) |         return "".join(self._lines()) | ||||||
| 
 | 
 | ||||||
|     def _lines(self) -> List[str]: |     def _lines(self) -> Generator[str, None, None]: | ||||||
|         for v in self.tree.values(): |         for v in sorted( | ||||||
|  |                 sorted(self.tree.values(), key=lambda x: x.index), | ||||||
|  |                 key=lambda x: x.level): | ||||||
|  | 
 | ||||||
|  |             net_addr = v.net.network.network_address.exploded | ||||||
|  |             net_pfx = v.net.network.prefixlen | ||||||
|             yield ( |             yield ( | ||||||
|                 "|".join([str(i) for i in ( |                 "|".join([str(i) for i in ( | ||||||
|                     v.index, |                     f"{v.index:04d}|{v.parent:04d}|{v.level:04d}", | ||||||
|                     v.parent, |                     net_addr, | ||||||
|                     v.level, |                     net_pfx, | ||||||
|                     v.net.network.network_address.exploded, |  | ||||||
|                     v.net.network.prefixlen, |  | ||||||
|                     v.net.object_type, |  | ||||||
|                     v.net.object_name, |  | ||||||
|                     v.net.policy, |                     v.net.policy, | ||||||
|                     v.net.status, |                     v.net.status, | ||||||
|                     ",".join(v.net.mnters), |                     v.net.object_type, | ||||||
|                     )]) |                     v.net.object_name, | ||||||
|             ) |                     )]) + "\n") | ||||||
|  |  | ||||||
							
								
								
									
										119
									
								
								utils/registry/dom/rspl.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								utils/registry/dom/rspl.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,119 @@ | ||||||
|  | "RPSL" | ||||||
|  | 
 | ||||||
|  | import os | ||||||
|  | import os.path | ||||||
|  | from dataclasses import dataclass, field | ||||||
|  | from typing import Dict, List, Set, Tuple, TypeVar | ||||||
|  | 
 | ||||||
|  | from .filedom import FileDOM | ||||||
|  | from .nettree import NetTree | ||||||
|  | from .schema import SchemaDOM | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | C = TypeVar('C', bound='RPSLConfig') | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @dataclass | ||||||
|  | class RPSLConfig: | ||||||
|  |     "RSPLConfig" | ||||||
|  |     namespace: str | ||||||
|  |     root: str | ||||||
|  |     schema: str | ||||||
|  |     owners: str | ||||||
|  |     default_owner: str | ||||||
|  |     source: str | ||||||
|  |     network_owner: Set[Tuple[str, str]] = field(default_factory=set) | ||||||
|  |     primary_key: Set[Tuple[str, str]] = field(default_factory=set) | ||||||
|  | 
 | ||||||
|  |     @property | ||||||
|  |     def network_parents(self) -> Set[str]: | ||||||
|  |         "return network parents" | ||||||
|  |         return set(self.network_owner.values()) | ||||||
|  | 
 | ||||||
|  |     @property | ||||||
|  |     def schema_dir(self) -> str: | ||||||
|  |         "get schema directory" | ||||||
|  |         return os.path.join(self.root, self.schema) | ||||||
|  | 
 | ||||||
|  |     @property | ||||||
|  |     def owner_dir(self) -> str: | ||||||
|  |         "get owner directory" | ||||||
|  |         return os.path.join(self.root, self.owners) | ||||||
|  | 
 | ||||||
|  |     @property | ||||||
|  |     def config_file(self) -> str: | ||||||
|  |         "get config file" | ||||||
|  |         return os.path.join(self.root, ".rpsl/config") | ||||||
|  | 
 | ||||||
|  |     @staticmethod | ||||||
|  |     def default() -> C: | ||||||
|  |         "create default" | ||||||
|  |         root = os.getcwd() | ||||||
|  |         return RPSLConfig("dn42", root, "schema", "mntner", "DN42-MNT", "DN42", | ||||||
|  |                           {}, {}) | ||||||
|  | 
 | ||||||
|  |     @staticmethod | ||||||
|  |     def from_dom(dom: FileDOM) -> C: | ||||||
|  |         "create from dom" | ||||||
|  |         ns = dom.get("namespace", default="dn42").value | ||||||
|  |         schema = dom.get("schema", default="schema").value | ||||||
|  |         owners = dom.get("owners", default="mntner").value | ||||||
|  |         source = dom.get("source", default="DN42").value | ||||||
|  |         default_owner = dom.get("default-owner", default=dom.mntner).value | ||||||
|  | 
 | ||||||
|  |         root = os.path.dirname(dom.src) | ||||||
|  | 
 | ||||||
|  |         network_owner = {}  # type: Dict[str, str] | ||||||
|  |         for (parent, child) in [ | ||||||
|  |                 i.fields for i in dom.get_all("network-owner")]: | ||||||
|  |             network_owner[child] = parent | ||||||
|  | 
 | ||||||
|  |         primary_key = {}  # type: Dict[str, str] | ||||||
|  |         for (parent, child) in [ | ||||||
|  |                 i.fields for i in dom.get_all("primary-key")]: | ||||||
|  |             primary_key[child] = parent | ||||||
|  | 
 | ||||||
|  |         return RPSLConfig(namespace=ns, | ||||||
|  |                           root=root, | ||||||
|  |                           schema=schema, | ||||||
|  |                           owners=owners, | ||||||
|  |                           source=source, | ||||||
|  |                           default_owner=default_owner, | ||||||
|  |                           network_owner=network_owner, | ||||||
|  |                           primary_key=primary_key, | ||||||
|  |                           ) | ||||||
|  | 
 | ||||||
|  |     def __str__(self): | ||||||
|  |         dom = FileDOM(ns=self.namespace) | ||||||
|  |         dom.put("namespace", self.namespace) | ||||||
|  |         dom.put("schema", self.schema) | ||||||
|  |         dom.put("owners", self.owners) | ||||||
|  |         dom.put("default-owner", self.default_owner) | ||||||
|  |         for (k, v) in self.primary_key: | ||||||
|  |             dom.put("primary-key", f"{k} {v}", append=True) | ||||||
|  |         for (k, v) in self.network_owner: | ||||||
|  |             dom.put("network-owner", f"{v} {k}", append=True) | ||||||
|  |         dom.put("mnt-by", self.default_owner) | ||||||
|  |         dom.put("source", self.source) | ||||||
|  | 
 | ||||||
|  |         return dom.__str__() | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | R = TypeVar('R', bound="RPSL") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @dataclass | ||||||
|  | class RSPL: | ||||||
|  |     "RSPL" | ||||||
|  |     config: RPSLConfig | ||||||
|  |     files: List[FileDOM] | ||||||
|  |     nettree: NetTree | ||||||
|  |     schema: Dict[str, SchemaDOM] | ||||||
|  | 
 | ||||||
|  |     @staticmethod | ||||||
|  |     def from_index(path: str) -> R: | ||||||
|  |         "Create RSPL from indexs" | ||||||
|  | 
 | ||||||
|  |     @staticmethod | ||||||
|  |     def from_files(path: str, schema_only: bool = False) -> R: | ||||||
|  |         "Create RSPL from files" | ||||||
|  | @ -2,12 +2,14 @@ | ||||||
| import re | import re | ||||||
| from dataclasses import dataclass, field | from dataclasses import dataclass, field | ||||||
| from enum import Enum, auto | from enum import Enum, auto | ||||||
| from typing import Optional, List, Tuple, Dict, Set | from typing import Optional, List, Tuple, Dict, Set, TypeVar | ||||||
| 
 | 
 | ||||||
| import log | import log | ||||||
| 
 | 
 | ||||||
| from .filedom import FileDOM, Row | from .filedom import FileDOM, Row | ||||||
| 
 | 
 | ||||||
|  | DOM = TypeVar("DOM", bound="FileDOM") | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class Level(Enum): | class Level(Enum): | ||||||
|     """State error level""" |     """State error level""" | ||||||
|  | @ -59,7 +61,7 @@ class State: | ||||||
| class SchemaDOM: | class SchemaDOM: | ||||||
|     """Schema DOM""" |     """Schema DOM""" | ||||||
|     def __init__(self, |     def __init__(self, | ||||||
|                  dom: Optional[FileDOM] = None, |                  dom: FileDOM, | ||||||
|                  src: Optional[str] = None): |                  src: Optional[str] = None): | ||||||
|         self.valid = False |         self.valid = False | ||||||
|         self.name = None |         self.name = None | ||||||
|  | @ -70,10 +72,8 @@ class SchemaDOM: | ||||||
|         self._schema = {}  # type: Dict[str, Set[str]] |         self._schema = {}  # type: Dict[str, Set[str]] | ||||||
|         self._spec = {}  # type: Dict[str, str] |         self._spec = {}  # type: Dict[str, str] | ||||||
|         self._links = {}  # type: Dict[str, List[str]] |         self._links = {}  # type: Dict[str, List[str]] | ||||||
|         self._dom = dom |         self.dom = dom | ||||||
| 
 |         self.parse(dom) | ||||||
|         if dom is not None: |  | ||||||
|             self.parse(dom) |  | ||||||
| 
 | 
 | ||||||
|     @property |     @property | ||||||
|     def links(self) -> Dict[str, List[str]]: |     def links(self) -> Dict[str, List[str]]: | ||||||
|  | @ -230,13 +230,13 @@ class SchemaDOM: | ||||||
|     def __str__(self) -> str: |     def __str__(self) -> str: | ||||||
|         return self._dom.__str__() |         return self._dom.__str__() | ||||||
| 
 | 
 | ||||||
|  |     @staticmethod | ||||||
|  |     def from_file(src: str) -> DOM: | ||||||
|  |         """Parses SchemaDOM from file""" | ||||||
|  |         with open(src, mode='r', encoding='utf-8') as f: | ||||||
|  |             dom = FileDOM(src=src, text=f.readlines()) | ||||||
| 
 | 
 | ||||||
| def read_file(src: str) -> SchemaDOM: |             return SchemaDOM(dom=dom) | ||||||
|     """Parses SchemaDOM from file""" |  | ||||||
|     with open(src, mode='r', encoding='utf-8') as f: |  | ||||||
|         dom = FileDOM(src=src, text=f.readlines()) |  | ||||||
| 
 |  | ||||||
|         return SchemaDOM(dom=dom) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def inetnum_check(state: State, dom: FileDOM) -> State: | def inetnum_check(state: State, dom: FileDOM) -> State: | ||||||
|  |  | ||||||
|  | @ -1,8 +1,11 @@ | ||||||
| "TransactDOM" | "TransactDOM" | ||||||
| 
 | 
 | ||||||
| from typing import Sequence, List, Optional, Tuple | from typing import Sequence, List, Optional, Tuple, TypeVar | ||||||
| 
 | 
 | ||||||
| from .filedom import FileDOM | from .filedom import FileDOM | ||||||
|  | from .schema import SchemaDOM | ||||||
|  | 
 | ||||||
|  | DOM = TypeVar("DOM", bound="TransactDOM") | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class TransactDOM(): | class TransactDOM(): | ||||||
|  | @ -12,6 +15,7 @@ class TransactDOM(): | ||||||
|                  text: Optional[Sequence[str]] = None): |                  text: Optional[Sequence[str]] = None): | ||||||
|         self.valid = False |         self.valid = False | ||||||
|         self.files = []  # type: List[FileDOM] |         self.files = []  # type: List[FileDOM] | ||||||
|  |         self.schemas = [] | ||||||
|         self.delete = []  # type: List[Tuple[str, str]] |         self.delete = []  # type: List[Tuple[str, str]] | ||||||
|         self.mntner = None  # type: Optional[str] |         self.mntner = None  # type: Optional[str] | ||||||
| 
 | 
 | ||||||
|  | @ -42,9 +46,11 @@ class TransactDOM(): | ||||||
|                     dom = FileDOM(text=buffer) |                     dom = FileDOM(text=buffer) | ||||||
|                     buffer = [] |                     buffer = [] | ||||||
|                     if dom.valid: |                     if dom.valid: | ||||||
|                         print(dom.name) |  | ||||||
|                         self.files.append(dom) |                         self.files.append(dom) | ||||||
| 
 | 
 | ||||||
|  |                         if dom.schema == 'schema': | ||||||
|  |                             self.schemas.append(SchemaDOM(dom)) | ||||||
|  | 
 | ||||||
|                 if line.startswith(".DELETE"): |                 if line.startswith(".DELETE"): | ||||||
|                     sp = line.split() |                     sp = line.split() | ||||||
|                     if len(sp) > 2: |                     if len(sp) > 2: | ||||||
|  | @ -60,3 +66,9 @@ class TransactDOM(): | ||||||
|         s += "...\n".join({str(record) for record in self.files}) |         s += "...\n".join({str(record) for record in self.files}) | ||||||
|         s += ".END" |         s += ".END" | ||||||
|         return s |         return s | ||||||
|  | 
 | ||||||
|  |     @staticmethod | ||||||
|  |     def from_file(src: str) -> DOM: | ||||||
|  |         "Read transact from files" | ||||||
|  |         with open(src) as f: | ||||||
|  |             return TransactDOM(f.readlines()) | ||||||
|  |  | ||||||
							
								
								
									
										110
									
								
								utils/registry/main.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								utils/registry/main.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,110 @@ | ||||||
|  | """rpsl a tool for managing RPSL databases | ||||||
|  | ========================================== | ||||||
|  | 
 | ||||||
|  | Usage: rpsl [command] [options] | ||||||
|  |        rpsl help [command] | ||||||
|  | 
 | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | import os | ||||||
|  | import sys | ||||||
|  | from typing import Tuple, List, Optional | ||||||
|  | 
 | ||||||
|  | import importlib | ||||||
|  | import pkgutil | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def remove_prefix(text, prefix): | ||||||
|  |     "remove the prefix" | ||||||
|  |     if text.startswith(prefix): | ||||||
|  |         return text[len(prefix):] | ||||||
|  |     return text | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | discovered_plugins = { | ||||||
|  |     remove_prefix(name, "rpsl_"): importlib.import_module(name) | ||||||
|  |     for finder, name, ispkg | ||||||
|  |     in pkgutil.iter_modules() | ||||||
|  |     if name.startswith("rpsl_") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def do_help(cmd: Optional[str] = None): | ||||||
|  |     "Print Help and exit" | ||||||
|  | 
 | ||||||
|  |     print(__doc__, file=sys.stderr) | ||||||
|  | 
 | ||||||
|  |     if cmd is None: | ||||||
|  |         print("Available commands:", file=sys.stderr) | ||||||
|  |         for pkg in discovered_plugins.keys(): | ||||||
|  |             print(f" - {pkg}", file=sys.stderr) | ||||||
|  |         return 0 | ||||||
|  | 
 | ||||||
|  |     if cmd not in discovered_plugins: | ||||||
|  |         print(f"Command not found: {cmd}", file=sys.stderr) | ||||||
|  |         return 1 | ||||||
|  | 
 | ||||||
|  |     print(discovered_plugins[cmd].__doc__, file=sys.stderr) | ||||||
|  |     return 0 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def find_rpsl(path: str) -> str: | ||||||
|  |     "Find the root directory for RPSL" | ||||||
|  |     path = os.path.abspath(path) | ||||||
|  |     rpsl = os.path.join(path, ".rpsl") | ||||||
|  |     while not os.path.exists(rpsl): | ||||||
|  |         if path == "/": | ||||||
|  |             break | ||||||
|  |         path = os.path.dirname(path) | ||||||
|  |         rpsl = os.path.join(path, ".rpsl") | ||||||
|  | 
 | ||||||
|  |     if not os.path.exists(rpsl): | ||||||
|  |         return None | ||||||
|  | 
 | ||||||
|  |     return path | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def run() -> int: | ||||||
|  |     "run application" | ||||||
|  |     working_dir = os.getcwd() | ||||||
|  |     working_dir = os.environ.get("WORKING_DIR", working_dir) | ||||||
|  |     prog_dir = os.path.dirname(os.path.realpath(__file__)) | ||||||
|  | 
 | ||||||
|  |     cmd, args = shift(shift(sys.argv)[1]) | ||||||
|  | 
 | ||||||
|  |     if cmd is None or cmd == 'help': | ||||||
|  |         cmd, _ = shift(args) | ||||||
|  |         return do_help(cmd) | ||||||
|  | 
 | ||||||
|  |     if cmd not in discovered_plugins: | ||||||
|  |         print(f"Unsupported Command: {cmd}") | ||||||
|  |         return 1 | ||||||
|  | 
 | ||||||
|  |     pkg = discovered_plugins[cmd] | ||||||
|  | 
 | ||||||
|  |     if 'run' not in dir(pkg): | ||||||
|  |         print(f"Command {cmd} is not compatible with rspl.", file=sys.stderr) | ||||||
|  |         return 1 | ||||||
|  | 
 | ||||||
|  |     return pkg.run(args, { | ||||||
|  |         "WORKING_DIR": working_dir, | ||||||
|  |         "BIN_DIR": prog_dir, | ||||||
|  |         "RPSL_DIR": find_rpsl(working_dir), | ||||||
|  |         }) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def shift(args: List[str]) -> Tuple[str, List[str]]: | ||||||
|  |     "shift off first arg + rest" | ||||||
|  |     if len(args) == 0: | ||||||
|  |         return None, [] | ||||||
|  | 
 | ||||||
|  |     if len(args) == 1: | ||||||
|  |         return args[0], [] | ||||||
|  | 
 | ||||||
|  |     return args[0], args[1:] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | if __name__ == '__main__': | ||||||
|  |     code = run() | ||||||
|  |     sys.exit(code) | ||||||
							
								
								
									
										8
									
								
								utils/registry/rpsl
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										8
									
								
								utils/registry/rpsl
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,8 @@ | ||||||
|  | #!/usr/bin/env python3 | ||||||
|  | 
 | ||||||
|  | import sys | ||||||
|  | from main import run | ||||||
|  | 
 | ||||||
|  | if __name__ == '__main__': | ||||||
|  |     code = run() | ||||||
|  |     sys.exit(code) | ||||||
							
								
								
									
										190
									
								
								utils/registry/rpsl_index/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								utils/registry/rpsl_index/__init__.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,190 @@ | ||||||
|  | """RSPL Build Indexes | ||||||
|  | ===================== | ||||||
|  | 
 | ||||||
|  | Usage: rspl index | ||||||
|  | 
 | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | import os | ||||||
|  | import sys | ||||||
|  | 
 | ||||||
|  | from typing import Dict, Generator, List, Set, Tuple | ||||||
|  | 
 | ||||||
|  | from dom.filedom import FileDOM | ||||||
|  | from dom.schema import SchemaDOM | ||||||
|  | from dom.nettree import NetTree, NetRecord | ||||||
|  | from dom.transact import TransactDOM | ||||||
|  | from dom.rspl import RPSLConfig | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def run(args: List[str], env: Dict[str, str]) -> int: | ||||||
|  |     "rspl index" | ||||||
|  | 
 | ||||||
|  |     _ = args | ||||||
|  | 
 | ||||||
|  |     path = env.get("WORKING_DIR") | ||||||
|  | 
 | ||||||
|  |     if not os.path.isdir(os.path.join(path, "schema")): | ||||||
|  |         print("schema directory not found in path", file=sys.stderr) | ||||||
|  |         sys.exit(1) | ||||||
|  | 
 | ||||||
|  |     print(r"Reading Files...", end="\r", flush=True, file=sys.stderr) | ||||||
|  |     idx = index_files(path) | ||||||
|  |     lookup, schemas, files, nets = build_index(idx) | ||||||
|  | 
 | ||||||
|  |     print( | ||||||
|  |         f"Reading Files: done! files: {len(files)}" + | ||||||
|  |         f" schemas: {len(schemas)}" + | ||||||
|  |         f" networks: {len(nets)}", | ||||||
|  |         file=sys.stderr) | ||||||
|  | 
 | ||||||
|  |     print("Writing .rpsl/index", file=sys.stderr) | ||||||
|  |     with open(".rpsl/index", 'w') as out: | ||||||
|  |         print("Writing .rpsl/links", file=sys.stderr) | ||||||
|  |         with open(".rpsl/links", 'w') as link_out: | ||||||
|  |             for dom in files: | ||||||
|  |                 s = schemas.get(dom.rel) | ||||||
|  |                 if s is None: | ||||||
|  |                     print( | ||||||
|  |                         f"{dom.src} schema not found for {dom.rel}", | ||||||
|  |                         file=sys.stderr) | ||||||
|  |                     continue | ||||||
|  | 
 | ||||||
|  |                 primary, mntner = dom.get(s.primary), ",".join(dom.mntner) | ||||||
|  |                 _ = mntner | ||||||
|  |                 src = remove_prefix(dom.src, path+os.sep) | ||||||
|  |                 print(dom.rel, primary, src,  # mntner, | ||||||
|  |                       sep="|", file=out) | ||||||
|  | 
 | ||||||
|  |                 for (link, rel, d) in generate_links(dom, s.links, lookup): | ||||||
|  |                     print(f"{dom.rel}|{dom.name}|{link}|{rel}|{d}", | ||||||
|  |                           file=link_out) | ||||||
|  | 
 | ||||||
|  |     print("Generate .rpsl/nettree", file=sys.stderr) | ||||||
|  |     tree = NetTree(nets) | ||||||
|  | 
 | ||||||
|  |     print("Writing .rpsl/nettree", file=sys.stderr) | ||||||
|  |     tree.write_csv(".rpsl/nettree") | ||||||
|  | 
 | ||||||
|  |     print("Writing .rpsl/schema", file=sys.stderr) | ||||||
|  |     s = TransactDOM() | ||||||
|  |     s.mntner = "DN42-MNT" | ||||||
|  |     s.files = schemas.values() | ||||||
|  |     with open(".rpsl/schema", "w") as out: | ||||||
|  |         print(s, file=out) | ||||||
|  | 
 | ||||||
|  |     print("done.", file=sys.stderr) | ||||||
|  | 
 | ||||||
|  |     return 0 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class NotRPSLPath(Exception): | ||||||
|  |     "error raised if unable to determine RPSL root" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def index_files(path: str) -> Generator[FileDOM, None, None]: | ||||||
|  |     """generate list of dom files""" | ||||||
|  |     path = os.path.abspath(path) | ||||||
|  |     rpsl = os.path.join(path, ".rpsl/config") | ||||||
|  |     while not os.path.exists(rpsl): | ||||||
|  |         if path == "/": | ||||||
|  |             break | ||||||
|  |         path = os.path.dirname(path) | ||||||
|  |         rpsl = os.path.join(path, ".rpsl/config") | ||||||
|  | 
 | ||||||
|  |     if not os.path.exists(rpsl): | ||||||
|  |         raise NotRPSLPath() | ||||||
|  | 
 | ||||||
|  |     yield FileDOM.from_file(rpsl) | ||||||
|  | 
 | ||||||
|  |     for root, _, files in os.walk(path): | ||||||
|  |         if root == path: | ||||||
|  |             continue | ||||||
|  |         if root.endswith(".rpsl"): | ||||||
|  |             continue | ||||||
|  | 
 | ||||||
|  |         for f in files: | ||||||
|  |             dom = FileDOM.from_file(os.path.join(root, f)) | ||||||
|  |             yield dom | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def build_index( | ||||||
|  |         idx: Generator[FileDOM, None, None] | ||||||
|  |     ) -> Tuple[ | ||||||
|  |         Set[Tuple[str, str]], | ||||||
|  |         Dict[str, SchemaDOM], | ||||||
|  |         List[FileDOM], | ||||||
|  |         List[NetRecord]]: | ||||||
|  |     "build index for files" | ||||||
|  |     rspl = RPSLConfig.default() | ||||||
|  |     lookup = set()  # type: Set[Tuple[str, str]] | ||||||
|  |     schemas = {}  # type: Dict[str, SchemaDOM] | ||||||
|  |     files = []  # type: List[FileDOM] | ||||||
|  |     nets = []  # type: List[NetRecord] | ||||||
|  | 
 | ||||||
|  |     print(r"Reading Files...", end="\r", flush=True, file=sys.stderr) | ||||||
|  | 
 | ||||||
|  |     net_types = rspl.network_parents | ||||||
|  | 
 | ||||||
|  |     for (i, dom) in enumerate(idx): | ||||||
|  |         if not dom.valid: | ||||||
|  |             print("E", end="", flush=True) | ||||||
|  |             continue | ||||||
|  | 
 | ||||||
|  |         key, _ = dom.index | ||||||
|  |         lookup.add(key) | ||||||
|  |         files.append(dom) | ||||||
|  | 
 | ||||||
|  |         if dom.schema == "namespace": | ||||||
|  |             rspl = RPSLConfig.from_dom(dom) | ||||||
|  |             net_types = rspl.network_parents | ||||||
|  | 
 | ||||||
|  |         if dom.schema == rspl.schema: | ||||||
|  |             schema = SchemaDOM(dom) | ||||||
|  |             schemas[schema.ref] = schema | ||||||
|  | 
 | ||||||
|  |         if dom.schema in net_types: | ||||||
|  |             nets.append(NetRecord( | ||||||
|  |                 dom.get("cidr").as_net6, | ||||||
|  |                 dom.mntner, | ||||||
|  |                 dom.get("policy", default="closed"), | ||||||
|  |                 dom.get("status", default="ASSIGNED"), | ||||||
|  |             )) | ||||||
|  | 
 | ||||||
|  |         if i % 120 == 0: | ||||||
|  |             print( | ||||||
|  |                 f"Reading Files: files: {len(files)}" + | ||||||
|  |                 f" schemas: {len(schemas)} " + | ||||||
|  |                 f" networks: {len(nets)}", | ||||||
|  |                 end="\r", flush=True, file=sys.stderr) | ||||||
|  | 
 | ||||||
|  |     return (lookup, schemas, files, nets) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def generate_links( | ||||||
|  |         dom: FileDOM, | ||||||
|  |         links: Dict[str, List[str]], | ||||||
|  |         lookup: Set[Tuple[str, str]] | ||||||
|  |         ) -> Generator[Tuple[str, str, str], None, None]: | ||||||
|  |     "print file links out to file" | ||||||
|  |     for (link, refs) in links.items(): | ||||||
|  |         d = dom.get(link) | ||||||
|  |         if d is None: | ||||||
|  |             return | ||||||
|  | 
 | ||||||
|  |         found = False | ||||||
|  |         for ref in refs: | ||||||
|  |             if (ref, d.value) in lookup: | ||||||
|  |                 found = True | ||||||
|  |                 yield (link, ref, d) | ||||||
|  | 
 | ||||||
|  |         if not found: | ||||||
|  |             print(f"{dom.name} missing link {link} {d.value}") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def remove_prefix(text, prefix): | ||||||
|  |     "remove the prefix" | ||||||
|  |     if text.startswith(prefix): | ||||||
|  |         return text[len(prefix):] | ||||||
|  |     return text | ||||||
							
								
								
									
										89
									
								
								utils/registry/rpsl_init/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								utils/registry/rpsl_init/__init__.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,89 @@ | ||||||
|  | """RSPL Initialize data store | ||||||
|  | ============================= | ||||||
|  | 
 | ||||||
|  | Usage: rspl init [options] | ||||||
|  | 
 | ||||||
|  | Options: | ||||||
|  | --namespace=<ns>       Namespace (default: current working dir name) | ||||||
|  | --schema=<schema>      Schema (default: schema) | ||||||
|  | --owners=<mntner>      Owner (default: mntner) | ||||||
|  | --default-owner=<mnt>  Default Owner (default: DN42-MNT) | ||||||
|  | --source=<src>         Source (default: DN42) | ||||||
|  | --force                Force creation of config | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | import sys | ||||||
|  | import os.path | ||||||
|  | import argparse | ||||||
|  | from typing import List, Dict, Generator, Tuple, Set, TypeVar | ||||||
|  | 
 | ||||||
|  | from dom.rspl import RPSLConfig | ||||||
|  | from dom.filedom import FileDOM | ||||||
|  | from dom.schema import SchemaDOM | ||||||
|  | 
 | ||||||
|  | parser = argparse.ArgumentParser() | ||||||
|  | parser.add_argument("--namespace", type=str, default=None) | ||||||
|  | parser.add_argument("--schema", type=str, default="schema") | ||||||
|  | parser.add_argument("--owners", type=str, default="mntner") | ||||||
|  | parser.add_argument("--default-owner", type=str, default="DN42-MNT") | ||||||
|  | parser.add_argument("--source", type=str, default="DN42") | ||||||
|  | parser.add_argument("--force", action='store_true') | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def run(args: List[str], env: Dict[str, str]) -> int: | ||||||
|  |     "rspl init" | ||||||
|  |     opts = parser.parse_args(args) | ||||||
|  |     if opts.namespace is None: | ||||||
|  |         opts.namespace = os.path.basename(env.get("WORKING_DIR")) | ||||||
|  | 
 | ||||||
|  |     rpsl_dir = env.get("RPSL_DIR") | ||||||
|  |     if rpsl_dir is not None and not opts.force: | ||||||
|  |         print(f"RPSL database already initialized! Found in: {rpsl_dir}") | ||||||
|  |         return 1 | ||||||
|  | 
 | ||||||
|  |     rpsl_dir = env.get("WORKING_DIR") | ||||||
|  |     rpsl = RPSLConfig(root=rpsl_dir, | ||||||
|  |                       namespace=opts.namespace, | ||||||
|  |                       schema=opts.schema, | ||||||
|  |                       owners=opts.owners, | ||||||
|  |                       source=opts.source, | ||||||
|  |                       default_owner=opts.default_owner) | ||||||
|  | 
 | ||||||
|  |     if os.path.exists(rpsl.schema_dir): | ||||||
|  |         rpsl.network_owner, rpsl.primary_key = _parse_schema(rpsl.schema_dir) | ||||||
|  | 
 | ||||||
|  |     os.makedirs(os.path.dirname(rpsl.config_file), exist_ok=True) | ||||||
|  |     with open(rpsl.config_file, "w") as f: | ||||||
|  |         print(rpsl, file=f) | ||||||
|  | 
 | ||||||
|  |     print(f"Created: {rpsl.config_file}", file=sys.stderr) | ||||||
|  |     return 0 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def _read_schemas(path: str) -> Generator[SchemaDOM, None, None]: | ||||||
|  |     for root, _, files in os.walk(path): | ||||||
|  |         for f in files: | ||||||
|  |             dom = FileDOM.from_file(os.path.join(root, f)) | ||||||
|  |             schema = SchemaDOM(dom) | ||||||
|  |             yield schema | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Group = TypeVar("Group", set, tuple) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def _parse_schema(path: str) -> Tuple[Group, Group]: | ||||||
|  |     schemas = _read_schemas(path) | ||||||
|  | 
 | ||||||
|  |     network_owner = set()  # type: Set[str, str] | ||||||
|  |     primary_key = set()  # type: Set[str, str] | ||||||
|  | 
 | ||||||
|  |     for s in schemas: | ||||||
|  |         for i in s.dom.get_all("network-owner"): | ||||||
|  |             network_owner.add((s.type, i.value)) | ||||||
|  | 
 | ||||||
|  |         if s.primary != s.type: | ||||||
|  |             primary_key.add((s.type, s.primary)) | ||||||
|  | 
 | ||||||
|  |     print(network_owner) | ||||||
|  |     return network_owner, primary_key | ||||||
							
								
								
									
										67
									
								
								utils/registry/rpsl_scan/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								utils/registry/rpsl_scan/__init__.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,67 @@ | ||||||
|  | """RSPL Scan | ||||||
|  | ============ | ||||||
|  | 
 | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | import os | ||||||
|  | import sys | ||||||
|  | from typing import List, Dict | ||||||
|  | 
 | ||||||
|  | from dom.filedom import FileDOM | ||||||
|  | from dom.schema import SchemaDOM | ||||||
|  | from dom.transact import TransactDOM | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def index_files(path: str): | ||||||
|  |     """generate list of dom files""" | ||||||
|  |     for root, _, files in os.walk(path): | ||||||
|  |         if root == path: | ||||||
|  |             continue | ||||||
|  |         if root.endswith(".rpsl"): | ||||||
|  |             continue | ||||||
|  | 
 | ||||||
|  |         for f in files: | ||||||
|  |             dom = FileDOM.from_file(os.path.join(root, f)) | ||||||
|  |             yield dom | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def run(args: List[str], env: Dict[str, str]) -> int: | ||||||
|  |     """run scan script""" | ||||||
|  | 
 | ||||||
|  |     path = env.get("RPSL_DIR") | ||||||
|  |     if path is None: | ||||||
|  |         print("RPSL index has not been generated.", file=sys.stderr) | ||||||
|  |         return 1 | ||||||
|  | 
 | ||||||
|  |     index_file = os.path.join(path, ".rpsl/index") | ||||||
|  | 
 | ||||||
|  |     lookups = {}  # type: Dict[str, FileDOM] | ||||||
|  |     schemas = {}  # type: Dict[str, SchemaDOM] | ||||||
|  | 
 | ||||||
|  |     with open(index_file) as fd: | ||||||
|  |         print("Reading index... ", end="", file=sys.stderr, flush=True) | ||||||
|  |         for line in fd.readlines(): | ||||||
|  |             sp = line.strip().split(sep="|") | ||||||
|  |             lookups[(sp[0], sp[1])] = (sp[2], "") | ||||||
|  |         print("done.", file=sys.stderr, flush=True) | ||||||
|  | 
 | ||||||
|  |     schema_file = os.path.join(path, ".rpsl/schema") | ||||||
|  |     schema_set = TransactDOM.from_file(schema_file) | ||||||
|  | 
 | ||||||
|  |     for schema in schema_set.schemas: | ||||||
|  |         schemas[schema.ref] = schema | ||||||
|  | 
 | ||||||
|  |     files = index_files(path) | ||||||
|  |     # for dom in files: | ||||||
|  |     #     key, value = dom.index | ||||||
|  |     #     lookups[key] = value | ||||||
|  | 
 | ||||||
|  |     for dom in files: | ||||||
|  |         s = schemas.get(dom.rel) | ||||||
|  |         if s is None: | ||||||
|  |             print(f"{dom.src} schema not found for {dom.rel}") | ||||||
|  | 
 | ||||||
|  |         status = s.check_file(dom, lookups=lookups) | ||||||
|  |         status.print() | ||||||
|  |     print(status) | ||||||
|  |     return 0 if status is True else 1 | ||||||
							
								
								
									
										12
									
								
								utils/registry/rpsl_status/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								utils/registry/rpsl_status/__init__.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | ||||||
|  | """RSPL Status | ||||||
|  | ============== | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | from typing import List, Dict | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def run(args: List[str], env: Dict[str, str]) -> int: | ||||||
|  |     "do run" | ||||||
|  |     print("RUN STATUS", args, env) | ||||||
|  |     return 0 | ||||||
|  | @ -1,64 +0,0 @@ | ||||||
| #!/usr/bin/env python3 |  | ||||||
| """Scans Registry at given path for issues using an pregenerated index""" |  | ||||||
| 
 |  | ||||||
| import os |  | ||||||
| import sys |  | ||||||
| from typing import Dict |  | ||||||
| 
 |  | ||||||
| from dom.filedom import FileDOM, read_file |  | ||||||
| from dom.schema import SchemaDOM |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def index_files(path: str): |  | ||||||
|     """generate list of dom files""" |  | ||||||
|     for root, _, files in os.walk(path): |  | ||||||
|         if root == path: |  | ||||||
|             continue |  | ||||||
| 
 |  | ||||||
|         for f in files: |  | ||||||
|             if f[0] == ".": |  | ||||||
|                 continue |  | ||||||
| 
 |  | ||||||
|             dom = read_file(os.path.join(root, f)) |  | ||||||
|             yield dom |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def run(path: str = ".", index: str = ".index"): |  | ||||||
|     """run main script""" |  | ||||||
| 
 |  | ||||||
|     lookups = {}  # type: Dict[str, FileDOM] |  | ||||||
|     schemas = {}  # type: Dict[str, SchemaDOM] |  | ||||||
| 
 |  | ||||||
|     schema_set = set() |  | ||||||
|     with open(index) as fd: |  | ||||||
|         for line in fd.readlines(): |  | ||||||
|             sp = line.split() |  | ||||||
|             lookups[(sp[0], sp[1])] = (sp[2], sp[3]) |  | ||||||
| 
 |  | ||||||
|             if sp[0] == "dn42.schema": |  | ||||||
|                 schema_set.add(sp[2]) |  | ||||||
| 
 |  | ||||||
|     for s in schema_set: |  | ||||||
|         dom = read_file(s) |  | ||||||
|         schema = SchemaDOM() |  | ||||||
|         schema.parse(dom) |  | ||||||
| 
 |  | ||||||
|         schemas[schema.ref] = schema |  | ||||||
| 
 |  | ||||||
|     files = index_files(path) |  | ||||||
|     for dom in files: |  | ||||||
|         key, value = dom.index |  | ||||||
|         lookups[key] = value |  | ||||||
| 
 |  | ||||||
|     for dom in files: |  | ||||||
|         s = schemas.get(dom.rel) |  | ||||||
|         if s is None: |  | ||||||
|             print(f"{dom.src} schema not found for {dom.rel}") |  | ||||||
| 
 |  | ||||||
|         status = s.check_file(dom, lookups=lookups) |  | ||||||
|         status.print() |  | ||||||
|         print(status) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| if __name__ == "__main__": |  | ||||||
|     run(sys.argv[1] if len(sys.argv) >= 2 else os.getcwd()) |  | ||||||
|  | @ -5,7 +5,7 @@ import os | ||||||
| import sys | import sys | ||||||
| from typing import Dict | from typing import Dict | ||||||
| 
 | 
 | ||||||
| from dom.filedom import FileDOM, read_file | from dom.filedom import FileDOM | ||||||
| from dom.schema import SchemaDOM | from dom.schema import SchemaDOM | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -19,7 +19,7 @@ def index_files(path: str): | ||||||
|             if f[0] == ".": |             if f[0] == ".": | ||||||
|                 continue |                 continue | ||||||
| 
 | 
 | ||||||
|             dom = read_file(os.path.join(root, f)) |             dom = FileDOM.from_file(os.path.join(root, f)) | ||||||
| 
 | 
 | ||||||
|             yield dom |             yield dom | ||||||
| 
 | 
 | ||||||
|  | @ -44,9 +44,7 @@ def run(path: str = "."): | ||||||
|         files.append(dom) |         files.append(dom) | ||||||
| 
 | 
 | ||||||
|         if dom.schema == "schema": |         if dom.schema == "schema": | ||||||
|             schema = SchemaDOM() |             schema = SchemaDOM(dom) | ||||||
|             schema.parse(dom) |  | ||||||
| 
 |  | ||||||
|             schemas[schema.ref] = schema |             schemas[schema.ref] = schema | ||||||
| 
 | 
 | ||||||
|         if i % 120 == 0: |         if i % 120 == 0: | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jonathan Lundy
						Jonathan Lundy