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
366 367 368 369 370 371 372 373 374 375 |
|
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
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 |
|
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
252 253 254 255 256 257 258 259 260 261 262 |
|
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.