forked from mboldt/docs-tiledev
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtile-upgrades.html.md.erb
313 lines (258 loc) · 13.3 KB
/
tile-upgrades.html.md.erb
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
---
title: Tile updates and migrations
owner: Services
---
Learn how to do tile migrations, which refers to changing the name and values of properties
when a customer upgrades tile versions. Tile authors supply a JavaScript file to trigger chaining migrations.
Chaining migrations allows for multiple migrations to run sequentially.
To use JS migrations, ensure that you are using Tanzu Operations Manager v1.7 or later.
In the tile installer <code>.yml</code> file that Tile Generator creates, form properties appear in
two locations:
* <code>form_types</code> section that defines the contents and layout of the configuration
interface.
* <code>property_blueprints</code> section that defines the corresponding text box value types and
constraints.
Changing the value of<code>single_az_only</code> for jobs started by your tile can cause data loss
for upgrades to Tanzu Operations Manager v1.7 versions later than v1.7.20, or v1.8 versions later than v1.8.12.
To avoid this, contact [VMware Support](https://tanzu.vmware.com/support.html).
## <a id='import'></a> Update values or property names using JavaScript
To update a product tile:
1. In a single `.js` file, write JavaScript functions which return a hash of the tile's properties.
1. Name the file in the format `TIMESTAMP_NAME.js`. `TIMESTAMP` must be in the form "YYYYMMDDHHMM" to indicate when the author created the migration. `NAME` is a human-readable name for the migration, for example, `201606150900_example-product.js`.
1. Copy the `TIMESTAMP_NAME.js` file to the `PRODUCT/migrations/v1` directory.
### <a id='js-example'></a> Example javaScript migration file
The following functions display an example migration file:
```
exports.migrate = function(input) {
// Append text to a string
input.properties['.web_server.example_string']['value'] += '!';
// Delete property 'legacy_property' that's removed in new tile version
delete input.properties['.properties.legacy_property'];
// Rename property 'example_port' to 'example_port_renamed',
// retaining the previous value.
input.properties['.properties.example_port_renamed'] =
input.properties['.properties.example_port'];
delete input.properties['.properties.example_port'];
// Append text to a string list
input.properties['.properties.example_string_list']['value'].push(
'new-string-append-by-migration');
return input;
};
```
The properties object passed to your anonymous JavaScript migration functions are composed of
properties at the [job-level](property-template-references.html#job-types) and [product-level](property-template-references.html#property-blueprints). Review the property names in the example metadata file in [Tutorial Tile V3](https://github.com/pivotal-cf-experimental/ops-manager-example/releases/tag/tutorial-v3) for more information about job-level and product-level properties. The tile author must update migrations to match the corresponding product metadata file.
Each property's key in the properties object is the property reference from the metadata file.
Property references use one of the following forms:
* `.properties.{property_name}` for product-level properties
* `.{job_name}.{property_name}` for job-level properties
* `.properties.{property_name}.options.{option_name}` or `.{job_name}.{property_name}.options.{option_name}` for selector option properties
The object accessed through the property reference contains a value key whose structure is
specific to the type of the property.
Objects can be a string, an array, or a hash. Review the following reference for the structure of each
type of property.
## <a id='js-api'></a> JavaScript migrations API
Inside a JavaScript migration function, the system provides the following functions for your code:
```
console.log(string)
Arguments: string
Return value: none
Description: Prints the string to the Rails log
Example:
console.log("Hello World");
```
```
getCurrentProductVersion()
Arguments: none
Return value: string (example: 1.7.1.0)
Description: Returns the version of the product that is installed
Example:
console.log(getCurrentProductVersion());
```
```
generateGuid()
Arguments: none
Return value: string (example: 115f9ced-3167-4c7c-959b-d52c07f32cbf)
Description: Returns a globally unique identifier (GUID) that can be used as the unique identifier for each element of a Collections property. When updating a Collection property blueprint, you as the migration author are responsible for updating the GUID of each new collection element that you create.
Example:
console.log("Here's a GUID: "+generateGuid())
```
This function can be called a maximum of 100 times per `.js` file. If you need more than 100 GUIDs, break your migration into two `.js` files.
```
abortMigration(string)
Arguments: string containing error message
Return value: none (never returns)
Description: Causes the migration to fail immediately. Rolls back all migrations in the current chain, i.e, no changes are be committed.
Example:
if (something > 5) {
abortMigration("Can't upgrade tile when the value of something is more than 5")
}
```
<table border="1" class="table">
<thead>
<tr>
<th><strong>Property Type</strong></th>
<th><strong>Value Structure</strong></th>
<th><strong>Example</strong></th>
</tr>
</thead>
<tr>
<td><code>single-value properties</code></td>
<td>Single value, but type-specific</td>
<td><code>properties['.properties.my-prop'].value = 'my-string'; properties['.properties.other-prop'].value = true</code></td>
</tr>
<tr>
<td><code>dropdown</code></td>
<td>Array of options</td>
<td><code>properties['.properties.my-prop'].value = ['option1', 'option2']</code></td>
</tr>
<tr>
<td><code>rsa_cert_credentials</code></td>
<td>Object</td>
<td><code>properties['.properties.my-prop'].value = {'private_key_pem' => 'a-private-key', 'cert_pem' => 'a-cert-pem'}</code></td>
</tr>
<tr>
<td><code>rsa_pkey_credentials</code></td>
<td>Object</td>
<td><code>properties['.properties.my-prop'].value = {'private_key_pem' => 'a-private-key'}</code></td>
</tr>
<tr>
<td><code>salted_credentials</code></td>
<td>Object</td>
<td><code>properties['.properties.my-prop'].value = {'identity' => 'an-identity', 'salt' => 'mortons', 'password' => 'books'}</code></td>
</tr>
<tr>
<td><code>simple_credentials</code></td>
<td>Object</td>
<td><code>properties['.properties.my-prop'].value = {'identity' => 'an-identity', 'password' => 'secret'}</code></td>
</tr>
<tr>
<td><code>collections</code></td>
<td>Array of objects</td>
<td><code>properties['.properties.my-prop'].value =
[{name: {value: 'foo'}, record_id: {value: 1}},
{name: {value: 'bar'}, record_id: {value: 2}}]</code>
</td>
</tr>
<tr>
<td><code>selectors</code><br><em>Selected value</em></td>
<td>String</td>
<td><code>properties['.properties.my-prop'].value = 'selected option label'</code>
</td>
</tr>
<tr>
<td><code>selectors</code><br><em>{selector option name.property name}</em></td>
<td>Value object specific to property type</td>
<td><code>properties['.properties.selector.option1.prop1'].value = 'foo'
properties['.properties.selector.option1.prop2'].value = 2
properties['.properties.selector.option2.prop3'].value = ['bar', 'baz']
</code>
</td>
</tr>
</table>
Single value properties refer to properties whose type are any of the following:
- `boolean`
- `ca_certificate`
- `domain`
- `dropdown_select`
- `email`
- `http_url`
- `integer`
- `ip_address`
- `ip_ranges`
- `ldap_url`
- `multi_select_options`
- `network_address`
- `network_address_list`
- `port`
- `smtp_authentication`
- `string`
- `string_list`
- `text`
- `uuid`
Refer to the following example properties when you write your own tile migration JS file:
```
{
properties: {
'.properties.example_boolean': { value: false } ,
'.properties.example_ca_certificate': { value: 'simple-typed-value'},
'.properties.example_domain': { value: 'simple-typed-value'} ,
'.properties.example_dropdown_select': { value: 'simple-typed-value'},
'.properties.example_email': { value: 'simple-typed-value'},
'.properties.example_http_url': { value: 'simple-typed-value'},
'.properties.example_integer': { value: 111},
'.properties.example_ip_address': { value: 'simple-typed-value'},
'.properties.example_ip_ranges': { value: 'simple-typed-value'},
'.properties.example_ldap_url': { value: 'simple-typed-value'},
'.properties.example_multi_select_options': { value: ['simple-typed-value']},
'.properties.example_network_address': { value: 'simple-typed-value'},
'.properties.example_network_address_list': { value: 'simple-typed-value'},
'.properties.example_port': { value: 22},
'.properties.example_smtp_authentication': { value: 'simple-typed-value'},
'.properties.example_string': { value: 'simple-typed-value'},
'.properties.example_string_list': { value: 'simple-typed-value'},
'.properties.example_text': { value: 'simple-typed-value'},
'.properties.example_uuid': { value: 'simple-typed-value'},
'.properties.example_rsa_cert_credentials': {
value: {'private_key_pem': 'a-private-key', 'cert_pem':'a-cert-pem'},
},
'.properties.example_rsa_pkey_credentials': {
value: {'private_key_pem':'a-private-key'},
},
'.properties.example_salted_credentials': {
value: {'identity':'an-identity', 'salt':'mortons', 'password':'books'},
},
'.properties.example_simple_credentials': {
value: {'identity':'an-identity', 'password':'secret'},
},
'.properties.example_collection': [
{name: {value: 'foo'}, record_id: {value: 1}},
{name: {value: 'bar'}, record_id: {value: 2}}
],
'.properties.example_selector': {value: 'option1'},
'.properties.selector.option1.prop1': {value: 'foo'},
'.properties.selector.option1.prop2': {value: 2},
'.properties.selector.option2.prop3': {value: 'bar,baz'}
}
}
```
<p class="note">
<span class="note__title">Note</span>
If your product uses Tanzu Operations Manager v1.6 or earlier metadata, you must write a transmogrifier
content migration for customers using your product on v1.6, and a JavaScript migration for those
on Tanzu Operations Manager v1.7 or later. Review the transmogrifier example in
the <a href="https://github.com/pivotal-cf-experimental/ops-manager-example/releases/tag/tutorial-v1">Tile Tutorial V1</a>.
</p>
## <a id='chaining'></a> Examples demonstrating chaining migrations
You can use migration chaining for multiple migrations to run sequentially when an upgrade
is performed that skips an intermediate version. For example, suppose you have three versions of your
product: v1.6.0, v1.7.0, and v1.7.1. The v1.6.0 product contains v1.6 metadata, so it does not contain
any JavaScript migrations.
![Example of a chain migration scenario.](img/chain-migration-scenario.png)
The following upgrade scenarios illustrate chaining migrations in more detail, and
use the example product versions previously described.
### Scenario A: Upgrading from v1.6.0 -> v1.7.0 -> v1.7.1
In this scenario, you start with the v1.6.0 product installed. After you upgrade to Tanzu Operations Manager v1.7 or
later, you decide to upgrade the product to v1.7.0. This causes the `migration 201606010000_a.js` to run.
Several weeks later, you decide to upgrade from v1.7.0 to v1.7.1. Now the `201607010000_b.js`
migration runs. Even though the v1.7.1 product includes both migrations, Tanzu Operations Manager does
not run `201606010000_a.js` again, because it maintains a record of migrations.
![Example chain migration scenario A](img/chain-migration-scenarioA.png)
### Scenario B: Upgrading directly from v1.6.0 -> v1.7.1
In this scenario, you also start with v1.6.0 installed, but you decide to upgrade directly to v1.7.1,
skipping the v1.7.0 version. Both migrations run in lexicographical order.
![Example chain migration scenario A](img/chain-migration-scenarioB.png)
### Scenario C: Installing v1.7.0, Then Upgrading to v1.7.1
In this scenario, you start with nothing installed. You do a clean installation of version v1.7.0 of the product. On installation of v1.7.0,
no migrations run because migrations only run on upgrades. Later, you decide to upgrade to v1.7.1 of
the product. Because v1.7.1 contains both migrations, and because no migrations have run on this system,
only the second migration `201607010000_b.js` runs. The system recorded the fact that v1.7.0
includes `201606010000_a.js`, so that migration does not run.
![Example of a chain migration scenario C.](img/chain-migration-scenarioC.png)
### Scenario D: Installing v1.7.1
In this scenario, you do a clean installation of v1.7.1, with no previous versions of the
product installed. Since migrations are only triggered by upgrade events, no migrations run.
Do not omit a migration from a later version of your tile. This breaks the
"chaining" nature of migrations. Using the previous example, if you release a v1.7.1 tile without
the <code>201606010000_a.js</code> migration, the system can not detect
that <code>201606010000_b.js</code> is the same migration that was present in the clean installation in
Scenario C.