Model Attributes
Overview
For understanding the various attributes that can live on a domain model, let's look again at the example Node
product and the NodeBlock
product block from the example workflow orchestrator:
Node
Product Type
Example: example-orchestrator/products/product_types/node.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
|
NodeBlock
Product Block
Example: example-orchestrator/products/product_blocks/node.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
|
Resource Types
A resource type is simply an attribute on a product block's python class. These are used to store values on a domain model that are mutable and will be changed over the lifecycle of the product. These are type-annotated so that they can be safely serialized and de-serialized from the database and so that pydantic can validate what you store on your domain model. When these attributes are added to a domain model, the appropriate database table must be populated via a migration. This can be handled automatically for you by the migrate-domain-models
command in the WFO CLI. To better understand how this looks from a database standpoint, you can see the database table that needs to be populated here:
orchestrator.db.models.ResourceTypeTable
Bases: orchestrator.db.database.BaseModel
Source code in orchestrator/db/models.py
383 384 385 386 387 388 389 390 391 392 |
|
You can see what a generated migration looks like that includes a new resource-type here by looking at the "resources":
key inside of the Node
product block :
Example: example-orchestrator/migrations/versions/schema/2023-10-27_a84ca2e5e4db_add_node.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
|
Finally, when a domain model is populated, the values that you put onto the subscription are stored in the SubscriptionInstanceValueTable
in the database, as seen here:
orchestrator.db.models.SubscriptionInstanceValueTable
Bases: orchestrator.db.database.BaseModel
Source code in orchestrator/db/models.py
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 |
|
Fixed Inputs
Fixed inputs are an immutable attribute that will not be changed over the lifecycle of the product. These are attributes with a hard-coded value that live on the root of the Product Type class definition. Fixed Inputs only live on Product Types, not Product Blocks. To better understand how this looks from a database standpoint, you can see the database table that needs to be populated here:
orchestrator.db.models.FixedInputTable
Bases: orchestrator.db.database.BaseModel
Source code in orchestrator/db/models.py
269 270 271 272 273 274 275 276 277 278 279 |
|
Using the same example as above, you can see what a generated migration file looks like that includes a new resource-type here by looking at the "fixed_inputs":
key inside of the node Cisco
or node Nokia
product type:
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
|
Note that because the Node_Type
enum has two choices (Cisco
or Nokia
), we generated two different products, one for each choice. Using fixed inputs in this manner allows you to easily create multiple products that share all of the same attributes aside from their fixed input without having to duplicate a bunch of domain model code. Then, when you are writing your workflows, you can handle the difference between these products by being aware of this fixed input.