Merge lp:~noise/tanuki-agent/tutorial-two-point-oh into lp:tanuki-agent
- tutorial-two-point-oh
- Merge into trunk
Proposed by
Bret Barker
Status: | Merged |
---|---|
Approved by: | Bret Barker |
Approved revision: | 166 |
Merged at revision: | 166 |
Proposed branch: | lp:~noise/tanuki-agent/tutorial-two-point-oh |
Merge into: | lp:tanuki-agent |
Diff against target: |
489 lines (+475/-5) 2 files modified
docs/Makefile (+8/-5) docs/tutorial2.md (+467/-0) |
To merge this branch: | bzr merge lp:~noise/tanuki-agent/tutorial-two-point-oh |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Roberto Alsina (community) | Approve | ||
Review via email: mp+278364@code.launchpad.net |
Commit message
First pass of new tutorial for product-based auth, GM testing.
Description of the change
First pass of new tutorial for product-based auth, GM testing. Lots of TODO placeholders waiting until more code lands to use proper API endpoints and payloads.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'docs/Makefile' |
2 | --- docs/Makefile 2015-11-04 15:57:51 +0000 |
3 | +++ docs/Makefile 2015-11-23 20:04:49 +0000 |
4 | @@ -1,5 +1,8 @@ |
5 | -docs: tutorial.md notes.md api-reference.md agent-reference.md |
6 | - ../env/bin/python3 build.py tutorial.md -o tutorial.html |
7 | - ../env/bin/python3 build.py notes.md -o index.html |
8 | - ../env/bin/python3 build.py api-reference.md -o api-reference.html |
9 | - ../env/bin/python3 build.py agent-reference.md -o agent-reference.html |
10 | +%.html: %.md |
11 | + ../env/bin/python build.py -o $@ $< |
12 | + |
13 | +all: $(addsuffix .html, $(basename $(wildcard *.md))) |
14 | + mv notes.html index.html |
15 | + |
16 | +clean: |
17 | + rm -f *.html |
18 | |
19 | === added file 'docs/tutorial2.md' |
20 | --- docs/tutorial2.md 1970-01-01 00:00:00 +0000 |
21 | +++ docs/tutorial2.md 2015-11-23 20:04:49 +0000 |
22 | @@ -0,0 +1,467 @@ |
23 | +Title: Getting Started with Ubuntu Product Integration |
24 | +Version: 20151119 |
25 | + |
26 | +Ubuntu Product Integration is a system for automated integration |
27 | +testing of products built upon Ubuntu Core. Once configured, the system will |
28 | +monitor for updates to components of your product and run automated |
29 | +tests against target devices to determine if those updates are |
30 | +compatible, and allow you to control the flow of those updates to your |
31 | +customers. |
32 | + |
33 | +This tutorial will guide you step-by-step to create a snap for an application, |
34 | +define a product that includes that application, create a laboratory |
35 | +environment where integration tests for that product can run, and set up the |
36 | +system so that it automatically executes tests in that laboratory when new |
37 | +versions of the snap become available. |
38 | + |
39 | +The document is organized as follows: |
40 | + |
41 | +- **[What you will need:](#what-you-will-need)** A description of everything needed to complete the tutorial. |
42 | +- **[Lab setup:](#lab-setup)** Create and configure your own laboratory. |
43 | +- **[Gold Master Candidate Testing:](#gold-master-candidate-testing)** Testing of Product images composed from the stable channel, to support releasing Gold Master Images. |
44 | +- **[Product update testing:](#product-update-testing)** Testing of software updates prior to releasing them to customers. |
45 | +- **[First-boot update testing:](#first-boot-update-testing)** First-boot update scenario tesitng. |
46 | + |
47 | +<div class="panel panel-info"> |
48 | + <div class="panel-heading"> |
49 | + <h3 class="panel-title">Conventions</h3> |
50 | + </div> |
51 | + <div class="panel-body"> |
52 | + From time to time you will need to execute commands in a terminal. This |
53 | + will be indicated using <code>this particular font and background color</code>, |
54 | + normally on a separate line. This font will also be used to specify |
55 | + filenames or any other cases where spelling matters. |
56 | + </div> |
57 | +</div> |
58 | + |
59 | + |
60 | +## What you will need |
61 | + |
62 | +In order to complete this tutorial, you will need the following resources: |
63 | + |
64 | +- A host computer running [Ubuntu 14.04 (64-bit)](http://www.ubuntu.com/download/desktop), with an SD card reader and at least 6 GB free drive space. |
65 | +- A [Raspberry Pi 2 Model B](https://www.raspberrypi.org/products/raspberry-pi-2-model-b/). |
66 | +- A 4GB (minimum) Micro SDHC card. |
67 | +- The host computer and Raspberry Pi connected on the same local ethernet network. |
68 | +- Access to the Internet from the host computer. |
69 | +- An optional serial USB cable, for debugging the RPI boot sequence. |
70 | +- Ubuntu One OAuth credentials. This will be covered below |
71 | + during [Lab setup](#lab-setup). |
72 | + |
73 | +## Lab setup |
74 | + |
75 | +In order to run tests on your product, the system needs a host computer to serve as a |
76 | +bridge between your device and itself. This computer can be as simple as your |
77 | +desktop, or part of a full device laboratory. |
78 | + |
79 | +For the purposes of this tutorial, your desktop computer will serve as the |
80 | +host and you will use a Raspberry Pi as the product device. The host computer |
81 | +will run a small application called the Agent, which will communicate with |
82 | +Canonical's servers and manage integration tests on the Raspberry Pi. |
83 | + |
84 | +### Setting up the host computer |
85 | + |
86 | +On your host computer, first install the latest Snappy tools: |
87 | + |
88 | + sudo add-apt-repository ppa:snappy-dev/tools |
89 | + sudo apt-get update |
90 | + sudo apt-get dist-upgrade |
91 | + sudo apt-get install snappy-tools |
92 | + |
93 | +See [Snappy Getting Started Guide](https://developer.ubuntu.com/en/snappy/start/) for further details. |
94 | + |
95 | +Also install the software dependencies of the Agent: |
96 | + |
97 | + sudo apt-get install python-requests pv |
98 | + |
99 | +Next you will install and configure the Agent. The most recent release of the Agent can always be found at [this location](https://spi.canonical.com/assets/agent.tar.gz). |
100 | + |
101 | +Download and install the Agent from your host computer as follows: |
102 | + |
103 | + wget https://spi.canonical.com/assets/agent.tar.gz |
104 | + tar -zxf agent.tar.gz |
105 | + cd agent-binaries |
106 | + |
107 | +### Configuring the Agent |
108 | + |
109 | +Once the Agent is installed, you will need to create its configuration: |
110 | + |
111 | +TODO: make interactive-login generate default config as well to condense these steps |
112 | + |
113 | + ./agent.py --default-config > config.ini |
114 | + |
115 | +The Agent authenticates using an Ubuntu One account . To use it, first create an |
116 | +[Ubuntu One account](https://login.ubuntu.com), then instruct the Agent to put |
117 | +your credentials in a configuration file: |
118 | + |
119 | + ./agent.py --interactive-login config.ini |
120 | + |
121 | +<div class="panel panel-danger"> |
122 | + <div class="panel-heading"> |
123 | + <h3 class="panel-title">Security warning</h3> |
124 | + </div> |
125 | + <div class="panel-body"> |
126 | + The config file now has data (<code>consumer_secret</code>, |
127 | + <code>token_secret</code>, and <code>token_key</code>) that are equivalent |
128 | + to your password. You are responsible for storing this securely. The device |
129 | + on which the Agent runs should be protected from unauthorized access. |
130 | + </div> |
131 | +</div> |
132 | + |
133 | + |
134 | +Note: It is best practice to create a separate Ubuntu One account to use for your Agents, but we'll keep things simple for the purposes of this tutorial. |
135 | + |
136 | +### Testing Agent Authorization |
137 | + |
138 | +Before we proceed, let's ensure that your Agent is properly configured. |
139 | + |
140 | + ./agent.py --register config.ini |
141 | + |
142 | +You should see a message similiar to the following: |
143 | + |
144 | + [agent-queue] Registered at https://spi.canonical.com/...TODO |
145 | + [] ... available products: [ ] |
146 | + |
147 | +Please double check your credentials and config.ini if you instead see an error similiar to the following: |
148 | + |
149 | + { |
150 | + "id": "unauthorized", |
151 | + "message": "unauthorized" |
152 | + } |
153 | + |
154 | +Once successfully registered, you can do a test run of the Agent: |
155 | + |
156 | + ./agent.py -v --once config.ini |
157 | + |
158 | +If successful, this will produce output similar to the following: |
159 | + |
160 | + [agent-queue] Registered at https://spi.canonical.com/... TODO |
161 | + [agent-queue] No tests at https://spi.canonical.com/... TODO |
162 | + |
163 | + |
164 | +### Agent Provisioning Kit setup |
165 | + |
166 | +When the Agent receives tests from the server, it will try to run the commands to provision, set up, and run the tests. |
167 | + |
168 | +Together these scripts are called a "Provisioning Kit." A sample kit has been provided for this tutorial and as a starting point for your own projects. |
169 | + |
170 | +Edit ```config.ini``` and replace the following three fields: |
171 | + |
172 | + provcommand = PATH_TO_AGENT/rpi2-sample-provkit/provision |
173 | + setupcommand = PATH_TO_AGENT/rpi2-sample-provkit/setup |
174 | + testcommand = PATH_TO_AGENT/rpi2-sample-provkit/runtest |
175 | + |
176 | +<div class="panel panel-warning"> |
177 | + <div class="panel-heading"> |
178 | + <h3 class="panel-title">Path sensitivity</h3> |
179 | + </div> |
180 | + <div class="panel-body"> |
181 | + The paths in <code>config.ini</code> must be absolute. Be sure to replace |
182 | + the correct values. |
183 | + </div> |
184 | +</div> |
185 | + |
186 | + |
187 | +### Raspberry Pi Setup |
188 | + |
189 | +Next, you will do a tgest provisioning to ensure your Raspberry Pi is setup properly. |
190 | + |
191 | +Download an already prepared sample image: |
192 | + |
193 | + wget https://spi.canonical.com/assets/spi-test_pi2.img.xz |
194 | + |
195 | +Verify that the MD5 hash for the downloaded file matches the value shown below: |
196 | + |
197 | + md5sum spi-test_pi2.img.xz |
198 | + be7cf02999e576aa5eb76e7e85713812 spi-test_pi2.img.xz |
199 | + |
200 | +Because remotely flashing the Raspberry Pi is a feature still in active |
201 | +development, you will need to manually flash an SD card with the image. |
202 | + |
203 | +On the host machine, insert your SD card and determine which device it is |
204 | +(using ```df -h``` or other tools), then copy the image to your flash device: |
205 | + |
206 | + xzcat spi-test_pi2.img | pv -s 4g | sudo dd of=/dev/sdX bs=32M |
207 | + sync |
208 | + |
209 | +<div class="panel panel-danger"> |
210 | + <div class="panel-heading"> |
211 | + <h3 class="panel-title">Careful device selection</h3> |
212 | + </div> |
213 | + <div class="panel-body"> |
214 | + Be careful select the correct output device ('of' flag). The dd command |
215 | + will offer no prompt, nor any protection from accidentally selecting your |
216 | + hard drive. |
217 | + </div> |
218 | +</div> |
219 | + |
220 | +This should take less than five minutes on most modern hardware. For additional instructions see [Getting started with a Raspberry Pi 2](https://developer.ubuntu.com/en/snappy/start/raspberry-pi-2/) |
221 | + |
222 | +When the flashing is complete, insert the SD card in your Raspberry Pi 2, power |
223 | +it on, and wait for it to boot. This typically takes less than a minute to |
224 | +complete. |
225 | + |
226 | +You can check whether it's online just by running: |
227 | + |
228 | + ping webdm.local |
229 | + |
230 | +If the device is not accessible, you can troubleshoot by using a serial cable |
231 | +to [obtain a console on the Raspberry Pi](http://elinux.org/RPi_Serial_Connection). |
232 | +Note that the pins are the same for both versions of the Raspberry Pi. |
233 | + |
234 | +Alternatively, it may be that the image is not properly written. If the device |
235 | +fails to boot, put the SD card back in the host machine and write the image a |
236 | +second time. Verify the write was succesful by confirming that the following |
237 | +commands both return the same hash: |
238 | + |
239 | + sudo dd if=/dev/sdX | head -c `stat -c "%s" spi-test_pi2.img` | pv -s `stat -c "%s" spi-test_pi2.img` | sha1sum |
240 | + sha1sum spi-test_pi2.img |
241 | + |
242 | + |
243 | +## Creating a Product |
244 | + |
245 | +Now it is time to create your first product based on Ubuntu Core. |
246 | + |
247 | +A special type of snap called a "Gadget Snap" (sometimes refererred to as an "OEM Snap" in the current docs) is used to define the components of a device image, i.e. the software stack that powers your device. This includes specifying the base Ubuntu OS, the specific kernel to use, pre-installed applications, configuring hardware access, etc. See [Snappy OEM Documentation](https://developer.ubuntu.com/en/snappy/guides/oem/) for more details. |
248 | + |
249 | +Product Integration data is associated to a snap that you own, which may be either an Application or Gadget snap. |
250 | + |
251 | +For the purposes of this tutorial, you will use the reference ```rpi2.canonical``` gadget snap, and define your product based on an Application snap that you will own. For a real product you would create and manage your own Gadget snap as well. |
252 | + |
253 | + |
254 | +### Publishing an Application Snap |
255 | + |
256 | +We will start by having you publish a copy of our test application snap under your own MyApps account. |
257 | + |
258 | +First, download the test snap: |
259 | + wget https://spi.canonical.com/assets/test-snap_1_all.snap |
260 | + |
261 | +Then you need to publish the snap under your MyApps account, as follows: |
262 | + |
263 | +- visit https://myapps.developer.ubuntu.com/dev/click-apps/upload/ |
264 | +- drag and drop or otherwise select the example snap for upload |
265 | +- select "rolling-core" as the release |
266 | +- select "Developer Tools" as the department |
267 | +- select "GNU GPL v3" as the license |
268 | +- select "stable" as the channel |
269 | +- click "Submit to the Ubuntu store" |
270 | + |
271 | +If all went well, you should now see a page for the package, named like "test-snap.<username>". It will also state "Package status is Ready to Publish". |
272 | + |
273 | +Note: when you have a separate Ubuntu One user for your Agents, this is where you would share access to the Product, by sharing this "primary snap" with the Agent user. |
274 | + |
275 | +Note: Currently only private packages can be shared; public package sharing is under development. |
276 | + |
277 | +Now click the "Publish" button on the test-snap.<username> MyApps page. You will then see details showing that sequence 1 is published in all channels. |
278 | + |
279 | +### Defining the Product |
280 | + |
281 | +So far we have published the application snap, and can build an image with it pre-installed on top of the reference Rasberry Pi Gadget snap. Now we want to codify that arrangement by defining a Product in the Ubuntu Product Integration system. |
282 | + |
283 | +For the purposes of Product Integration testing, we are only concerned about the list of snaps that compose the product and some additional metadata decribed here: |
284 | + |
285 | +- ```name```: A short name to identify this Product, does not need to be unique. |
286 | +- ```release```: the Ubuntu Core release this products aims for (currently "15.04-core" or "rolling-core" as known by the Store) |
287 | +- ```base_image_reference```: optional (TODO: we should make it optional as it shouldn't be needed in all-snaps land anymore) |
288 | +- ```snaps```: the list of snap names that that comprise the product |
289 | + |
290 | +TODO: instruct them to export SSO_USERNAME or have the agent login step do it. |
291 | + |
292 | +TODO: sidebar about the api_example script, oauth, etc. |
293 | + |
294 | +In the agent directory on your computer (where you already authenticated during |
295 | +the [Lab setup](#lab-setup) above), issue the following HTTP request using the api_example.py helper script included with the Agent distribution: |
296 | + |
297 | + ./api_example.py -X POST config.ini https://spi.canonical.com/products --data '{ |
298 | + "name": "test-product.$SSO_USERNAME", |
299 | + "primary_snap_name": "test-snap.$SSO_USERNAME", |
300 | + "release": "rolling-core", |
301 | + "snaps": [ |
302 | + "ubuntu-core.canonical", |
303 | + "pi2.canonical", |
304 | + "webdm.canonical", |
305 | + "test-snap.$SSO_USERNAME" |
306 | + ] |
307 | + }' |
308 | + |
309 | +output will contain the ID newly created product definition. You will need to export this as an environment variable for use in later API calls as follows: |
310 | + |
311 | + export PRODUCT_ID=<id from output above> |
312 | + |
313 | +NOTE/TODO: we are not yet in all-snaps land so there is no kernel snap listed here. |
314 | + |
315 | + |
316 | +## Testing |
317 | + |
318 | +### Defining a Test |
319 | + |
320 | +Next you will define your test scenario via a Test Specification, with the following fields: |
321 | + |
322 | +- ```name```: a unique reference to identify tests and their results |
323 | +- ```product_id```: the unique id for the Product to test |
324 | +- ```channels```: a list of channel pairs. 'base' is the target/live channel generally, and 'update' is where the system will look for changes to trigger update test runs (covered in a later chapter). |
325 | +- ```test_payload```: information for the test to be run; in this case we put where the tests can be downloaded, and the command to trigger their execution |
326 | + |
327 | +Execute the following command to create this Test Specification: |
328 | + |
329 | + ./api_example.py -X POST config.ini https://spi.canonical.com/products/$PRODUCT_ID/tests/specs --data '{ |
330 | + "name": "Tutorial Example Test Specification", |
331 | + "product_id": "$PRODUCT_ID", |
332 | + "channels": [ ['base': 'stable', 'update': 'edge'] ], |
333 | + "test_payload": { |
334 | + "tarball_url": "https://spi.canonical.com/assets/test_tarball2.tar.gz", |
335 | + "test_cmd": "./test" |
336 | + } |
337 | + }' |
338 | + |
339 | +At this point the system is configured for your product and tests, and will supervise the Store for new versions of the snaps listed in your Product. |
340 | + |
341 | +TODO: note about not being in all-snaps land yet. |
342 | + |
343 | + |
344 | +### First test run |
345 | + |
346 | +TODO: system should trigger an initial GM test when the TestSpec is created. |
347 | + |
348 | +This test will be what is called a Gold Master Candidate test. It is triggered by a change to any of the component snaps in the monitored base channel defined in the Test Specification (stable in this case). The server will generate a Test Opportunity that instructs the provisioning kit script to compose a new GM candidate image from the Product's snaps, using the current sequences published in the base channel, provision that image, and then run tests against it. Later chapters of the tutorial will discuss additional testing scenarios. |
349 | + |
350 | +When we first defined our Test Specification, the system generated a new Test Opportunity to test the initial Gold Master Candidate image, since that combination of snaps had not yet been tested. |
351 | + |
352 | +Further GM tests will be automatically generated each time a component snap is updated in the base_channel. |
353 | + |
354 | +You can now run the agent to consume and run your first test. Run the following command: |
355 | + |
356 | + ./agent.py -v --once config.ini |
357 | + |
358 | +As remote flashing of the Raspberry Pi is still in active development, the |
359 | +Raspberry Pi will need to be set up manually. After receiving the test to run, |
360 | +the Agent will output instructions explaining how to write the composed image |
361 | +to the device. Please follow those instructions and let the Agent know when |
362 | +you are ready by pressing the Enter key when prompted. |
363 | + |
364 | +After executing the test, the Agent will automatically retrieve the |
365 | +results and send them back to Canonical's servers. You can query these results |
366 | +in the next section, [Checking test progress and results](#checking-test-progress-and-results). |
367 | + |
368 | + |
369 | +### Checking test progress and results |
370 | + |
371 | +At any time, you can check the progress of tests generated in the |
372 | +system: |
373 | + |
374 | +TODO: we need a way to get our test opp id now that we are not manually triggering |
375 | + |
376 | + ./api_example.py config.ini \ |
377 | + https://spi.canonical.com/products/$PRODUCT_ID/tests/events?test_opportunity_id=<test_opportunity_id> |
378 | + |
379 | +This produces a large JSON document containing all the events that relate to this test, for example: |
380 | + |
381 | + {"event_logs": [ |
382 | + { |
383 | + "updated_at": "2015-10-28T18:35:38.197000+00:00", |
384 | + "events": [ |
385 | + { |
386 | + "timestamp": "2015-10-28T18:34:56.614000+00:00", |
387 | + "event_type": "QUEUED_FOR_AGENTS" |
388 | + }, |
389 | + { |
390 | + "platform": "spi-tutorial-raspi2", |
391 | + "timestamp": "2015-10-28T18:34:58.988000+00:00", |
392 | + "agent_group": "default", |
393 | + "agent_id": "special", |
394 | + "event_type": "PICKED_BY_AGENT" |
395 | + }, |
396 | + |
397 | +The ```event_type``` field will describe what happened, there is a timestamp, and extra information related |
398 | +to the event. |
399 | + |
400 | +It will also contain all the information relevant to the test, such as: |
401 | + |
402 | + "queued_at": "2015-10-28T18:34:56.614000+00:00", |
403 | + "test_spec_id": "2991e1d1-ae89-4afe-9801-140207526f21", |
404 | + "spec_name": "Tutorial Example Test Specification", |
405 | + "image_unique_id": "5e6ff512-87b6-427e-917d-615c4d1c0aec", |
406 | + |
407 | +As well as the test itself in the ```test_opportunity``` field. |
408 | + |
409 | +You can also check the results for an specific image (you can get the image |
410 | +id from the response of the query when you told the system above that a |
411 | +new snap revision was available): |
412 | + |
413 | + ./api_example.py config.ini \ |
414 | + https://spi.canonical.com/products/$PRODUCT_ID/tests/events?image_unique_id=<unique_image_id> |
415 | + |
416 | +Or you may directly poll for specific results using filters, as below: |
417 | + |
418 | + ./api_example.py config.ini https://spi.canonical.com/products/$PRODUCT_ID/results... TODO |
419 | + |
420 | +The result query will return a document describing one or more test results. |
421 | +Each will contain, among other things, the pass or failure status of the test |
422 | +run, as well as all related information such as the manifest, test spec, and so |
423 | +on: |
424 | + |
425 | + { |
426 | + "test_results": [ |
427 | + { |
428 | + "created_at": "2015-10-28T18:34:56.614000+00:00", |
429 | + "result_id": "7348dac1-9191-454c-93f0-cedb463aa477", |
430 | + "test_status": "PASSED", |
431 | + "manifest": { |
432 | + ... |
433 | + "test_spec": { |
434 | + "platform": "spi-tutorial-raspi2", |
435 | + "image_name": "tutorial-raspi2-image", |
436 | + "test_payload": { |
437 | + "test_cmd": "./test", |
438 | + "tarball_url": "https://spi.canonical.com/assets/test_tarball.tar.gz" |
439 | + }, |
440 | + "name": "Tutorial Example Test Specification", |
441 | + "id": "2991e1d1-ae89-4afe-9801-140207526f21", |
442 | + "created_at": "2015-10-28T16:42:42.989056", |
443 | + "active": true |
444 | + }, |
445 | + ... |
446 | + |
447 | +### Artifacts and logs |
448 | + |
449 | +Logs containing the output and errors of the provisioning kit's scripts are always stored in ```logs/```. |
450 | +Saving those logs and any artifacts the provisioning kit creates is the responsibility of your test command. |
451 | + |
452 | +The example provisioning kit will create a tarball with the test opportunity, the test result |
453 | +and all the provisioning kit logs, using this code: |
454 | + |
455 | + ARTIFACTS = [ |
456 | + 'spi_test_result.json', |
457 | + 'spi_test_opportunity.json', |
458 | + 'logs/provisioning.log', |
459 | + 'logs/setup.log', |
460 | + 'logs/testing.log' |
461 | + ] |
462 | + |
463 | + [...] |
464 | + |
465 | + artifact_dir = os.getenv('ARTIFACT_DIR', '/tmp') |
466 | + save_cmd = 'tar czvf {} {}'.format( |
467 | + os.path.join(artifact_dir, test_opp['id'] + '.tar.gz'), |
468 | + ' '.join(ARTIFACTS), |
469 | + ) |
470 | + log.info('Saving artifact with %s', save_cmd) |
471 | + subprocess.check_call(save_cmd, shell=True) |
472 | + |
473 | +Here, the tarball is stored in /tmp by default, but you can override it in the ```[environment]``` section of your ```config.ini```: |
474 | + |
475 | + [environment] |
476 | + ARTIFACT_DIR='/home/user/artifacts' |
477 | + |
478 | +#### Generated GM Candidate images |
479 | + |
480 | +The images that are generated by the provisioning kit may be stored for later use. For example if tests pass and you would like to release the image you will want to retrieve the binary from the Agent host. |
481 | + |
482 | +The sample provisioning kit stores the images in a ./images subdirector of the agent installation. You are responsible for handling transport of the images to a storage system of your choice. |
483 | + |
484 | +Note: the sample kit does not remove old images and they can quickly eat a lot of disk space. |
485 | + |
486 | +## Update Testing |
487 | + |
488 | +Future revisions of this document will cover update testing scenarios allowing for verifying updates before new versions are made available to customers |
489 | + |
LGTM. Made a change in my branch to make the agent print the list of accessible packages on registration like this tutorial says.