├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── api ├── examples │ ├── certification-minimal │ │ └── qwiklabs.yaml │ ├── classroom-template-minimal │ │ ├── qwiklabs.yaml │ │ └── resources │ │ │ └── choosing_compute_en.pdf │ ├── course-minimal │ │ ├── gcp-intro-course-badge.png │ │ ├── gcp-intro-course-image.png │ │ └── qwiklabs.yaml │ ├── course-robust │ │ ├── gcp-intro-course-badge.png │ │ ├── gcp-intro-course-image.png │ │ ├── qwiklabs.yaml │ │ └── resources │ │ │ ├── storage_options_en.pdf │ │ │ └── storage_options_es.pdf │ ├── course-survey-robust │ │ └── qwiklabs.yaml │ ├── exam-minimal │ │ └── qwiklabs.yaml │ ├── exam-robust │ │ └── qwiklabs.yaml │ ├── game-template-minimal │ │ ├── game-badge.png │ │ ├── game-image.png │ │ ├── qwiklabs.yaml │ │ └── resources │ │ │ ├── choosing_compute_en.pdf │ │ │ ├── choosing_compute_es.pdf │ │ │ └── choosing_compute_ja.pdf │ ├── lab-minimal │ │ ├── instructions │ │ │ └── en.html │ │ └── qwiklabs.yaml │ ├── lab-robust │ │ ├── instructions │ │ │ ├── en.html │ │ │ └── es.html │ │ ├── lab.template │ │ ├── qwiklabs.yaml │ │ ├── resources │ │ │ ├── sample-en.pdf │ │ │ └── sample-es.pdf │ │ ├── startup_script │ │ │ └── qwiklabs.jinja │ │ └── student_policy.json │ ├── lab-v1-gsuite │ │ ├── instruction.html │ │ └── qwiklabs.yaml │ ├── lab-v1-minimal │ │ ├── instruction.html │ │ └── qwiklabs.yaml │ ├── lab-v1-robust │ │ ├── assessment.yaml │ │ ├── dm.zip │ │ ├── instructions │ │ │ ├── en.html │ │ │ └── es.html │ │ ├── qwiklabs.yaml │ │ └── resources │ │ │ ├── sample-en.pdf │ │ │ └── sample-es.pdf │ ├── learning-path-minimal │ │ ├── gcp-intro-path-badge.png │ │ ├── qwiklabs.yaml │ │ └── resources │ │ │ └── choosing_compute_en.pdf │ ├── peer-assignment-minimal │ │ ├── instructions │ │ │ └── en.html │ │ └── qwiklabs.yaml │ ├── peer-assignment-robust │ │ ├── instructions │ │ │ ├── en.html │ │ │ ├── es.html │ │ │ └── img │ │ │ │ └── example.png │ │ └── qwiklabs.yaml │ ├── quiz-minimal │ │ └── qwiklabs.yaml │ ├── quiz-robust │ │ └── qwiklabs.yaml │ └── quiz-sections │ │ └── qwiklabs.yaml ├── lab-bundle-spec-v1.md └── lab-bundle-spec.md ├── classroom-template-bundle-spec.md ├── course-template-bundle-spec.md ├── exam-bundle-spec.md ├── examples ├── course-templates-robust │ ├── qwiklabs.es.yaml │ └── qwiklabs.yaml ├── lab-robust │ └── v2 │ │ ├── assessments │ │ └── step_one_check.rb │ │ ├── cleanup │ │ ├── qwiklabs.jinja │ │ └── vm-type.jinja │ │ ├── iam_policy.json │ │ ├── instructions │ │ ├── en.html │ │ └── es.html │ │ ├── lab.template │ │ ├── qwiklabs.es.yaml │ │ ├── qwiklabs.yaml │ │ ├── resources │ │ ├── sample-en.pdf │ │ └── sample-es.pdf │ │ └── startup │ │ ├── qwiklabs.jinja │ │ └── vm-type.jinja └── peer-assignment-robust │ ├── instructions │ ├── en.html │ ├── es.html │ └── img │ │ └── example.png │ ├── qwiklabs.es.yaml │ └── qwiklabs.yaml ├── game-template-bundle-spec.md ├── github-lab-bundle-spec.md ├── html ├── html-spec.md └── images │ ├── ql-code-01.png │ ├── ql-code-02.png │ ├── ql-code-block-01.png │ ├── ql-code-block-02.png │ ├── ql-code-block-03.png │ ├── ql-variable-01.png │ ├── ql-variable-02.png │ └── ql-variable-03.png ├── lab_control_panel.png ├── learning-path-bundle-spec.md ├── peer-assignment-bundle-spec.md ├── preassessment-bundle-spec.md ├── quiz-bundle-spec.md └── resource-spec.md /.gitignore: -------------------------------------------------------------------------------- 1 | _site/ 2 | .sass-cache/ 3 | .jekyll-metadata 4 | .*-credentials 5 | .idea 6 | *.iml 7 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution; 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | 25 | ## Community Guidelines 26 | 27 | This project follows 28 | [Google's Open Source Community Guidelines](https://opensource.google.com/conduct/). 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Qwiklabs Content Bundle Specs 2 | 3 | This repo houses specs for Qwiklabs content bundles. Each supported bundle type 4 | has a set of examples and a type-specific bundle specification. 5 | 6 | ## Notable Files and Folders 7 | 8 | * `/examples/`: A list of example bundles (of any type) 9 | * `/api/`: Files that define the api version of the bundles 10 | * `github-lab-bundle-spec.md`: A formal-ish specification for `Lab` bundles 11 | * `course-template-bundle-spec.md`: A formal-ish specification for 12 | `CourseTemplate` bundles 13 | * `html-spec.md`: A document outlining what constitutes valid HTML in a 14 | content bundle (e.g. what is required, what is forbidden, etc.) 15 | 16 | ## Introduction 17 | 18 | A Qwiklabs Bundle, or QLB, is a zip file that contains exactly one directory. 19 | Inside of that directory is a `qwiklabs.yaml` file which defines a learning 20 | entity in Qwiklabs. All other files in the bundle should also be inside of the 21 | single parent directory. This specification focuses specifically on the Lab 22 | entity. 23 | 24 | The QLB format aims to: 25 | 26 | 1. Make it easy to author developer learning materials in your native tools. 27 | 28 | 2. Provide a simple format into which existing content can be 29 | **programmatically** transformed, making it convenient to migrate existing 30 | learning materials from diverse sources into Qwiklabs modules. 31 | 32 | > **Note**: The Lab bundle specification is designed for long term support (even 33 | > as the spec evolves) and machine-to-machine communication. As such, this spec 34 | > errs on the side of being overly verbose and comprehensive, which can make it 35 | > more cumbersome to author directly in this format. 36 | > 37 | > A Lab bundle should be the **output** of the authoring process, and not 38 | > necessarily written directly by authors. Qwiklabs will create authoring tools 39 | > that make the authoring experience easier, including a GDoc conversion tool 40 | > and a Git repo management service, all of which will produce lab bundles as 41 | > their end product. Users are also encouraged to build their own authoring 42 | > tools that target this spec. 43 | 44 | ## Design Goals 45 | 46 | ### Localization is a first class concern 47 | 48 | We understand that not all instructional content is localized... but it should 49 | be! Furthermore, localization requires a lot of work, so we want to make it as 50 | easy as possible to add localized content to a lab bundle. 51 | 52 | Therefore, QLB will prioritize explicit and clear localization semantics at the 53 | risk of being overly verbose for authors who only work with one locale. 54 | 55 | For instance, `locales` is a required field for external resources. If you only 56 | have one locale you still need to specify it: 57 | 58 | ```yaml 59 | - type: link 60 | ref_id: my-repo 61 | uri: 62 | locales: 63 | en: https://github.com/CloudVLab/qwiklabs-lab-bundle-spec/tree/v1-prerelease 64 | title: 65 | locales: 66 | en: Self-referential Github Repo 67 | ``` 68 | 69 | ### Prefer explicit configuration over implicit convention 70 | 71 | The only requirement we put on your bundle's file structure is the 72 | `qwiklabs.yaml` MUST be in the root folder of the bundle. You can arrange your 73 | other files in whatever folder structure you choose. 74 | 75 | The lab definition in `qwiklabs.yaml` explicitly references files when 76 | specifying instructions, resources, etc. This makes static validation of your 77 | package easier and ensure that files you intended to be there aren't missing. 78 | 79 | ### Schema versions 80 | 81 | The v1 spec will evolve in an additive manner. The spec is designed to easily 82 | accommodate new feature variants. In particular, content authors should expect: 83 | 84 | - new external resource types (e.g. GitHub repos, YouTube videos, etc.), 85 | - new environment resource types (e.g. GSuite domain, iPython notebook, etc.), 86 | and 87 | - additional supported HTML components for instructions (e.g. inline quiz 88 | elements, embedded videos, etc.). 89 | 90 | #### Breaking Changes 91 | 92 | If a breaking change can not be avoided, a new schema version will be issued 93 | (i.e. v1 -> v2). 94 | 95 | Older schema versions will be supported for a "reasonable" deprecation periods. 96 | 97 | The Qwiklabs team will *try* to create migration tools that make schema updates 98 | a mostly automated process. 99 | -------------------------------------------------------------------------------- /api/examples/certification-minimal/qwiklabs.yaml: -------------------------------------------------------------------------------- 1 | entity_type: Certification 2 | schema_version: 1 3 | 4 | default_locale: en 5 | 6 | title: 7 | locales: 8 | en: Basic Certification 9 | 10 | description: 11 | locales: 12 | en: An English description of a basic certification. 13 | 14 | audience: 15 | locales: 16 | en: The intended audience of a basic certification. 17 | 18 | prerequisites: 19 | locales: 20 | en: Prerequisites for a basic certification. 21 | 22 | credits: 80 23 | 24 | steps: 25 | - type: course_template 26 | id: alexandria/course-template-1@1.0 27 | - type: course_template 28 | id: alexandria/course-template-1 29 | - type: course_template 30 | id: alexandria/course-template-2@1.0 31 | - type: exam 32 | id: alexandria/exam-1 33 | gated: true 34 | - type: course_template 35 | id: alexandria/course-template-3@1.0 36 | - type: exam 37 | id: alexandria/exam-2@1.0 38 | proctor: qwiklabs-live-plus 39 | gated: true 40 | -------------------------------------------------------------------------------- /api/examples/classroom-template-minimal/qwiklabs.yaml: -------------------------------------------------------------------------------- 1 | schema_version: 1 2 | entity_type: ClassroomTemplate 3 | 4 | id: my-library/basic-classroom-template 5 | default_locale: en 6 | version: 7 | locales: 8 | en: ver 2.0 9 | 10 | title: 11 | locales: 12 | en: Good Classroom 13 | 14 | description: 15 | locales: 16 | en: My classroom template description 17 | 18 | modules: 19 | - id: my-module 20 | steps: 21 | - id: my-first-step 22 | activity_options: 23 | - type: lab 24 | id: my-library/a-lab 25 | - id: my-second-step 26 | activity_options: 27 | - type: lab 28 | id: my-other-library/another-lab 29 | -------------------------------------------------------------------------------- /api/examples/classroom-template-minimal/resources/choosing_compute_en.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/api/examples/classroom-template-minimal/resources/choosing_compute_en.pdf -------------------------------------------------------------------------------- /api/examples/course-minimal/gcp-intro-course-badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/api/examples/course-minimal/gcp-intro-course-badge.png -------------------------------------------------------------------------------- /api/examples/course-minimal/gcp-intro-course-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/api/examples/course-minimal/gcp-intro-course-image.png -------------------------------------------------------------------------------- /api/examples/course-minimal/qwiklabs.yaml: -------------------------------------------------------------------------------- 1 | entity_type: CourseTemplate 2 | schema_version: 1 3 | 4 | # CourseTemplate Attributes 5 | default_locale: en 6 | 7 | title: 8 | locales: 9 | en: GCP Intro Course 10 | 11 | description: 12 | locales: 13 | en: Get a taste of what GCP has to offer. 14 | 15 | version: 16 | locales: 17 | en: "2" 18 | es: "1" 19 | 20 | objectives: 21 | locales: 22 | en: | 23 |

This course will teach people

24 | 28 | 29 | audience: 30 | locales: 31 | en: | 32 |

This course is intended for people who

33 | 34 | 35 | prerequisites: 36 | locales: 37 | en:

A basic understanding of serverless architecture is recommended but not required.

38 | 39 | tags: [sample, life-changing, gcp] 40 | product_tags: ['bigquery'] 41 | role_tags: ['database admin'] 42 | domain_tags: ['infrastructure', 'data'] 43 | level: 1 44 | image: gcp-intro-course-image.png 45 | badge: gcp-intro-course-badge.png 46 | 47 | estimated_duration_minutes: 60 48 | 49 | course_surveys: 50 | - survey-f59d1335-ul5lc0 51 | 52 | modules: 53 | - id: module-1 54 | title: 55 | locales: 56 | en: Module 1 57 | es: Módulo 1 58 | steps: 59 | - id: intro-to-gcp 60 | activity_options: 61 | - type: lab 62 | id: intro-to-gcp 63 | - id: intro-to-bigquery 64 | activity_options: 65 | - type: lab 66 | id: intro-to-bigquery 67 | - id: gcp-quiz 68 | activity_options: 69 | - type: quiz 70 | id: gcp-quiz 71 | -------------------------------------------------------------------------------- /api/examples/course-robust/gcp-intro-course-badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/api/examples/course-robust/gcp-intro-course-badge.png -------------------------------------------------------------------------------- /api/examples/course-robust/gcp-intro-course-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/api/examples/course-robust/gcp-intro-course-image.png -------------------------------------------------------------------------------- /api/examples/course-robust/qwiklabs.yaml: -------------------------------------------------------------------------------- 1 | entity_type: CourseTemplate 2 | schema_version: 1 3 | 4 | # CourseTemplate Attributes 5 | default_locale: en 6 | 7 | title: 8 | locales: 9 | en: GCP Intro Course 10 | es: Curso de introducción a GCP 11 | 12 | description: 13 | locales: 14 | en: Get a taste of what GCP has to offer. 15 | es: Prueba lo que GCP tiene para ofrecer. 16 | 17 | version: 18 | locales: 19 | en: v2.3 20 | es: v1 final 21 | 22 | auto_upgrade_to_latest_version: false 23 | 24 | objectives: 25 | locales: 26 | en: | 27 |

This course will teach people

28 | 32 | es: | 33 |

Este curso enseñará a las personas

34 | 38 | 39 | audience: 40 | locales: 41 | en: | 42 |

This course is intended for people who

43 | 44 | es: | 45 |

Este curso está destinado a personas que

46 | 47 | 48 | prerequisites: 49 | locales: 50 | en:

A basic understanding of serverless architecture is recommended but not required.

51 | es:

Se recomienda una comprensión básica de la arquitectura sin servidor, pero no es obligatorio.

52 | 53 | tags: [sample, life-changing, gcp] 54 | product_tags: ['app engine', 'kubernetes engine', 'cloud functions', 'cloud datastore', 'cloud sql', 'spanner', 'bigquery'] 55 | role_tags: ['cloud architect', 'developers backend', 'developers frontend', 'database admin'] 56 | domain_tags: ['infrastructure', 'application development', 'data'] 57 | level: 3 58 | image: gcp-intro-course-image.png 59 | badge: gcp-intro-course-badge.png 60 | 61 | estimated_duration_minutes: 60 62 | 63 | instructor_resources: 64 | - id: how-to-teach 65 | title: 66 | locales: 67 | en: How to teach 68 | es: Como enseñar 69 | uri: 70 | locales: 71 | en: https://www.wikihow.com/Teach 72 | es: https://www.wikihow.es/enseñar 73 | - id: how-to-teach-well 74 | title: 75 | locales: 76 | en: How to teach well 77 | es: Como enseñar bien 78 | uri: 79 | locales: 80 | en: https://www.wikihow.com/TeachingWell 81 | es: https://www.wikihow.com/TeachingWell 82 | 83 | resources: 84 | - type: video 85 | id: intro-video 86 | title: 87 | locales: 88 | en: Welcome to GCP! 89 | es: ¡Bienvenido a GCP! 90 | video_id: 91 | locales: 92 | en: oHg5SJYRHA0 93 | es: 7jjoyy7_RCk 94 | video_provider: YouTube 95 | description: 96 | locales: 97 | en: Overview of Google Cloud Platform 98 | es: Descripción general de Google Cloud Platform 99 | duration: 360 100 | - type: video 101 | id: outro-video 102 | title: 103 | locales: 104 | en: Wasn't that fun?! 105 | es: Eso fue divertido, ¿verdad? 106 | video_id: 107 | locales: 108 | en: oHg5SJYRHA0 109 | es: 7jjoyy7_RCk 110 | video_provider: YouTube 111 | duration: 100 112 | - type: link 113 | id: choosing-compute 114 | title: 115 | locales: 116 | en: Choosing a Compute Option 117 | es: Elegir una opción de cómputo 118 | uri: 119 | locales: 120 | en: https://cloud.google.com/docs/choosing-a-compute-option 121 | es: https://cloud.google.com/docs/choosing-a-compute-option 122 | - type: file 123 | id: storage-options 124 | title: 125 | locales: 126 | en: Storage Options 127 | es: Opciones de Almacenamiento 128 | uri: 129 | locales: 130 | en: resources/storage_options_en.pdf 131 | es: resources/storage_options_es.pdf 132 | 133 | course_surveys: 134 | - survey-f59d1335-ul5lc0 135 | - survey-ul5lc0 136 | - survey-f59d1335 137 | 138 | modules: 139 | - id: intro-module 140 | title: 141 | locales: 142 | en: Introduction 143 | es: Introducción 144 | description: 145 | locales: 146 | en: Some introductory material 147 | es: Algo de material introductorio 148 | learning_objectives: 149 | locales: 150 | en: 151 | - Objective for intro module 152 | es: 153 | - Objetivo para el módulo de introducción 154 | steps: 155 | - id: intro-video 156 | activity_options: 157 | - type: resource 158 | id: intro-video 159 | prompt: 160 | locales: 161 | en: If you've never used GCP, we recommend this overview video. 162 | es: Si nunca ha usado GCP, le recomendamos este video general. 163 | optional: true 164 | 165 | - id: intro-lab 166 | activity_options: 167 | - type: lab 168 | id: intro-to-gcp 169 | 170 | - id: learn-compute 171 | title: 172 | locales: 173 | en: Learn about compute 174 | es: Aprender acerca de la computadora 175 | learning_objectives: 176 | locales: 177 | en: 178 | - Objective for learn module 179 | es: 180 | - Objetivo para el módulo de aprendizaje 181 | steps: 182 | - id: choose-compute 183 | activity_options: 184 | - type: resource 185 | id: choosing-compute 186 | 187 | - id: learn-compute 188 | activity_options: 189 | - type: lab 190 | id: intro-to-appengine-python 191 | - type: lab 192 | id: intro-to-kubernetes-engine 193 | - type: lab 194 | id: intro-to-cloud-functions 195 | prompt: 196 | locales: 197 | en: Learn more about one of these common compute resources. 198 | es: Obtenga más información sobre uno de estos recursos informáticos comunes. 199 | - id: learn-storage 200 | title: 201 | locales: 202 | en: Learn about storage 203 | es: Aprende sobre almacenamiento 204 | learning_objectives: 205 | locales: 206 | en: 207 | - Objective for learn storage 208 | es: 209 | - Objetivo para el almacenamiento de información 210 | steps: 211 | - id: storage-options 212 | activity_options: 213 | - type: resource 214 | id: storage-options 215 | 216 | - id: learn-storage 217 | activity_options: 218 | - type: lab 219 | id: intro-to-datastore 220 | - type: lab 221 | id: intro-to-cloudsql 222 | - type: lab 223 | id: intro-to-spanner 224 | prompt: 225 | locales: 226 | en: Learn more about one of these common database technologies. 227 | es: Obtenga más información sobre una de estas tecnologías de base de datos comunes. 228 | 229 | - id: intro-to-bigquery 230 | activity_options: 231 | - type: lab 232 | id: intro-to-bigquery 233 | 234 | - id: bigquery-quiz 235 | activity_options: 236 | - type: quiz 237 | id: bigquery-quiz 238 | category: graded 239 | version: '1.0' 240 | 241 | - id: peer-assignment 242 | activity_options: 243 | - type: peer_assignment 244 | id: peer-assignment 245 | 246 | - id: outro-module 247 | title: 248 | locales: 249 | en: Finish up 250 | es: Termina 251 | learning_objectives: 252 | locales: 253 | en: 254 | - Objective for outro module 255 | es: 256 | - Objetivo para módulo outro 257 | steps: 258 | - id: advanced-gcp-task 259 | activity_options: 260 | - type: lab 261 | id: advanced-gcp-task 262 | optional: true 263 | prompt: 264 | locales: 265 | en: If you want to try your hand at this advanced task, go for it! 266 | es: Si quieres probar suerte en esta tarea avanzada, ¡hazlo! 267 | 268 | - id: outro-video 269 | activity_options: 270 | - type: resource 271 | id: outro-video 272 | 273 | retake_policies: 274 | - id: practice-quiz-policy 275 | activity_type: 'Quiz' 276 | activity_category: 'practice' 277 | retake_limit: 3 278 | retake_window: 1 279 | - id: graded-quiz-policy 280 | activity_type: 'Quiz' 281 | activity_category: 'graded' 282 | retake_cooldown: 283 | - 1 284 | retake_limit: 3 285 | retake_window: 1 286 | - id: default-lab-policy 287 | activity_type: 'Lab' 288 | retake_cooldown: 289 | - 1 290 | - 2 291 | - 5 292 | -------------------------------------------------------------------------------- /api/examples/course-robust/resources/storage_options_en.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/api/examples/course-robust/resources/storage_options_en.pdf -------------------------------------------------------------------------------- /api/examples/course-robust/resources/storage_options_es.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/api/examples/course-robust/resources/storage_options_es.pdf -------------------------------------------------------------------------------- /api/examples/exam-minimal/qwiklabs.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | entity_type: Exam 3 | schema_version: 1 4 | default_locale: en 5 | title: 6 | locales: 7 | en: Sample Exam Questions 8 | passing_percentage: 100 9 | duration: 120 10 | randomize_items: true 11 | randomize_options: true 12 | randomize_prompts: true 13 | retake_cooldown: 14 | - 0 15 | forms: 16 | - name: Form A 17 | id: form-a 18 | sections: 19 | - name: Science 20 | id: form-a-sec-0 21 | items: 22 | - type: multiple-choice 23 | id: form-a-sec-0-item-0 24 | code: 1.1.1(a).SCI 25 | seed: false 26 | stem: 27 | locales: 28 | en: >- 29 | Who won the Nobel Prize for discovering the cause of the photoelectric effect? 30 | options: 31 | - id: form-a-sec-0-item-0-option-0 32 | title: 33 | locales: 34 | en: Albert Einstein 35 | is_answer: true 36 | - id: form-a-sec-0-item-0-option-1 37 | title: 38 | locales: 39 | en: Francis Crick 40 | is_answer: false 41 | - id: form-a-sec-0-item-0-option-2 42 | title: 43 | locales: 44 | en: Rosalind Franklin 45 | is_answer: false 46 | - id: form-a-sec-0-item-0-option-3 47 | title: 48 | locales: 49 | en: Max Planck 50 | is_answer: false 51 | 52 | - type: multiple-select 53 | id: form-a-sec-0-item-1 54 | code: 1.2.1(a).SCI 55 | seed: false 56 | stem: 57 | locales: 58 | en: >- 59 | Which of the following are scientific elements on the Periodic Table of Elements? 60 | options: 61 | - id: form-a-sec-0-item-1-option-0 62 | title: 63 | locales: 64 | en: Fibrium 65 | is_answer: false 66 | - id: form-a-sec-0-item-1-option-1 67 | title: 68 | locales: 69 | en: Manganese 70 | is_answer: true 71 | - id: form-a-sec-0-item-1-option-2 72 | title: 73 | locales: 74 | en: Plutonium 75 | is_answer: true 76 | - id: form-a-sec-0-item-1-option-3 77 | title: 78 | locales: 79 | en: Hydrogen 80 | is_answer: true 81 | 82 | - name: Geography 83 | id: form-a-sec-1 84 | items: 85 | - type: multiple-choice 86 | id: form-a-sec-0-item-2 87 | code: 1.3.1(a).GEO 88 | seed: true 89 | stem: 90 | locales: 91 | en: >- 92 | Where is Acadia National Park? 93 | options: 94 | - id: form-a-sec-1-item-2-option-0 95 | title: 96 | locales: 97 | en: Montana 98 | is_answer: false 99 | - id: form-a-sec-1-item-2-option-1 100 | title: 101 | locales: 102 | en: Massachusetts 103 | is_answer: false 104 | - id: form-a-sec-1-item-2-option-2 105 | title: 106 | locales: 107 | en: Maine 108 | is_answer: true 109 | - id: form-a-sec-1-item-2-option-3 110 | title: 111 | locales: 112 | en: Minnesota 113 | is_answer: false 114 | 115 | - type: match 116 | id: form-a-sec-1-item-3 117 | code: 1.4.1(a).GEO 118 | seed: false 119 | lead_in: 120 | locales: 121 | en: >- 122 | Match the following cities to their states. 123 | stems: 124 | - id: form-a-sec-1-item-3-prompt-0 125 | title: 126 | locales: 127 | en: San Francisco 128 | answer: form-a-sec-1-item-3-option-0 129 | - id: form-a-sec-1-item-3-prompt-1 130 | title: 131 | locales: 132 | en: Nashville 133 | answer: form-a-sec-1-item-3-option-1 134 | - id: form-a-sec-1-item-3-prompt-2 135 | title: 136 | locales: 137 | en: Salt Lake City 138 | answer: form-a-sec-1-item-3-option-2 139 | options: 140 | - id: form-a-sec-1-item-3-option-0 141 | title: 142 | locales: 143 | en: California 144 | - id: form-a-sec-1-item-3-option-1 145 | title: 146 | locales: 147 | en: Tennessee 148 | - id: form-a-sec-1-item-3-option-2 149 | title: 150 | locales: 151 | en: Utah 152 | 153 | # Second form 154 | - name: Form B 155 | id: form-b 156 | sections: 157 | - name: Science 158 | id: form-b-sec-0 159 | items: 160 | - type: multiple-choice 161 | id: form-b-sec-0-item-0 162 | code: 1.1.1(b).SCI 163 | seed: false 164 | stem: 165 | locales: 166 | en: >- 167 | Who won the Nobel Prize for discovering the cause of the photoelectric effect? 168 | options: 169 | - id: form-b-sec-0-item-0-option-0 170 | title: 171 | locales: 172 | en: Albert Einstein 173 | is_answer: true 174 | - id: form-b-sec-0-item-0-option-1 175 | title: 176 | locales: 177 | en: Francis Crick 178 | is_answer: false 179 | - id: form-b-sec-0-item-0-option-2 180 | title: 181 | locales: 182 | en: Rosalind Franklin 183 | is_answer: false 184 | - id: form-b-sec-0-item-0-option-3 185 | title: 186 | locales: 187 | en: Max Planck 188 | is_answer: false 189 | 190 | - type: multiple-select 191 | id: form-b-sec-0-item-1 192 | code: 1.2.1(b).SCI 193 | seed: false 194 | stem: 195 | locales: 196 | en: >- 197 | Which of the following are scientific elements on the Periodic Table of Elements? 198 | options: 199 | - id: form-b-sec-0-item-1-option-0 200 | title: 201 | locales: 202 | en: Uranium 203 | is_answer: true 204 | - id: form-b-sec-0-item-1-option-1 205 | title: 206 | locales: 207 | en: Manganese 208 | is_answer: true 209 | - id: form-b-sec-0-item-1-option-2 210 | title: 211 | locales: 212 | en: Brillium 213 | is_answer: false 214 | - id: form-b-sec-0-item-1-option-3 215 | title: 216 | locales: 217 | en: Hydrogen 218 | is_answer: true 219 | 220 | - name: Geography 221 | id: form-b-sec-1 222 | items: 223 | - type: multiple-choice 224 | id: form-b-sec-1-item-2 225 | code: 1.3.1(b).GEO 226 | seed: true 227 | stem: 228 | locales: 229 | en: >- 230 | Where is Glacier National Park? 231 | options: 232 | - id: form-b-sec-1-item-2-option-0 233 | title: 234 | locales: 235 | en: Montana 236 | is_answer: true 237 | - id: form-b-sec-1-item-2-option-1 238 | title: 239 | locales: 240 | en: Massachusetts 241 | is_answer: false 242 | - id: form-b-sec-1-item-2-option-2 243 | title: 244 | locales: 245 | en: Maine 246 | is_answer: false 247 | - id: form-b-sec-1-item-2-option-3 248 | title: 249 | locales: 250 | en: Minnesota 251 | is_answer: false 252 | 253 | - type: match 254 | id: form-b-sec-0-item-3 255 | code: 1.4.1(b).GEO 256 | seed: false 257 | lead_in: 258 | locales: 259 | en: >- 260 | Match the following cities to their states. 261 | stems: 262 | - id: form-b-sec-1-item-3-prompt-0 263 | title: 264 | locales: 265 | en: San Diego 266 | answer: form-b-sec-1-item-3-option-0 267 | - id: form-b-sec-1-item-3-prompt-1 268 | title: 269 | locales: 270 | en: Poughkeepsie 271 | answer: form-b-sec-1-item-3-option-1 272 | - id: form-b-sec-1-item-3-prompt-2 273 | title: 274 | locales: 275 | en: Seattle 276 | answer: form-b-sec-1-item-3-option-2 277 | options: 278 | - id: form-b-sec-1-item-3-option-0 279 | title: 280 | locales: 281 | en: California 282 | - id: form-b-sec-1-item-3-option-1 283 | title: 284 | locales: 285 | en: New York 286 | - id: form-b-sec-1-item-3-option-2 287 | title: 288 | locales: 289 | en: Washington 290 | -------------------------------------------------------------------------------- /api/examples/exam-robust/qwiklabs.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | entity_type: Exam 3 | schema_version: 1 4 | default_locale: en 5 | title: 6 | locales: 7 | en: Sample Exam Questions 8 | introduction: 9 | locales: 10 | en: Please schedule your sample exam 11 | passing_percentage: 100 12 | duration: 120 13 | randomize_items: true 14 | randomize_options: true 15 | randomize_prompts: true 16 | show_score: true 17 | retake_cooldown: 18 | - 0 19 | forms: 20 | - name: Form A 21 | id: form-a 22 | sections: 23 | - name: Science 24 | id: form-a-sec-0 25 | items: 26 | - type: multiple-choice 27 | id: form-a-sec-0-item-0 28 | code: 1.1.1(a).SCI 29 | seed: false 30 | stem: 31 | locales: 32 | en: >- 33 | Who won the Nobel Prize for discovering the cause of the photoelectric effect? 34 | options: 35 | - id: form-a-sec-0-item-0-option-0 36 | title: 37 | locales: 38 | en: Albert Einstein 39 | is_answer: true 40 | - id: form-a-sec-0-item-0-option-1 41 | title: 42 | locales: 43 | en: Francis Crick 44 | is_answer: false 45 | - id: form-a-sec-0-item-0-option-2 46 | title: 47 | locales: 48 | en: Rosalind Franklin 49 | is_answer: false 50 | - id: form-a-sec-0-item-0-option-3 51 | title: 52 | locales: 53 | en: Max Planck 54 | is_answer: false 55 | 56 | - type: multiple-select 57 | id: form-a-sec-0-item-1 58 | code: 1.2.1(a).SCI 59 | seed: false 60 | stem: 61 | locales: 62 | en: >- 63 | Which of the following are scientific elements on the Periodic Table of Elements? 64 | options: 65 | - id: form-a-sec-0-item-1-option-0 66 | title: 67 | locales: 68 | en: Fibrium 69 | is_answer: false 70 | - id: form-a-sec-0-item-1-option-1 71 | title: 72 | locales: 73 | en: Manganese 74 | is_answer: true 75 | - id: form-a-sec-0-item-1-option-2 76 | title: 77 | locales: 78 | en: Plutonium 79 | is_answer: true 80 | - id: form-a-sec-0-item-1-option-3 81 | title: 82 | locales: 83 | en: Hydrogen 84 | is_answer: true 85 | 86 | - name: Geography 87 | id: form-a-sec-1 88 | items: 89 | - type: multiple-choice 90 | id: form-a-sec-0-item-2 91 | code: 1.3.1(a).GEO 92 | seed: true 93 | stem: 94 | locales: 95 | en: >- 96 | Where is Acadia National Park? 97 | options: 98 | - id: form-a-sec-1-item-2-option-0 99 | title: 100 | locales: 101 | en: Montana 102 | is_answer: false 103 | - id: form-a-sec-1-item-2-option-1 104 | title: 105 | locales: 106 | en: Massachusetts 107 | is_answer: false 108 | - id: form-a-sec-1-item-2-option-2 109 | title: 110 | locales: 111 | en: Maine 112 | is_answer: true 113 | - id: form-a-sec-1-item-2-option-3 114 | title: 115 | locales: 116 | en: Minnesota 117 | is_answer: false 118 | 119 | - type: match 120 | id: form-a-sec-1-item-3 121 | code: 1.4.1(a).GEO 122 | seed: false 123 | lead_in: 124 | locales: 125 | en: >- 126 | Match the following cities to their states. 127 | stems: 128 | - id: form-a-sec-1-item-3-prompt-0 129 | title: 130 | locales: 131 | en: San Francisco 132 | answer: form-a-sec-1-item-3-option-0 133 | - id: form-a-sec-1-item-3-prompt-1 134 | title: 135 | locales: 136 | en: Nashville 137 | answer: form-a-sec-1-item-3-option-1 138 | - id: form-a-sec-1-item-3-prompt-2 139 | title: 140 | locales: 141 | en: Salt Lake City 142 | answer: form-a-sec-1-item-3-option-2 143 | options: 144 | - id: form-a-sec-1-item-3-option-0 145 | title: 146 | locales: 147 | en: California 148 | - id: form-a-sec-1-item-3-option-1 149 | title: 150 | locales: 151 | en: Tennessee 152 | - id: form-a-sec-1-item-3-option-2 153 | title: 154 | locales: 155 | en: Utah 156 | 157 | # Second form 158 | - name: Form B 159 | id: form-b 160 | sections: 161 | - name: Science 162 | id: form-b-sec-0 163 | items: 164 | - type: multiple-choice 165 | id: form-b-sec-0-item-0 166 | code: 1.1.1(b).SCI 167 | seed: false 168 | stem: 169 | locales: 170 | en: >- 171 | Who won the Nobel Prize for discovering the cause of the photoelectric effect? 172 | options: 173 | - id: form-b-sec-0-item-0-option-0 174 | title: 175 | locales: 176 | en: Albert Einstein 177 | is_answer: true 178 | - id: form-b-sec-0-item-0-option-1 179 | title: 180 | locales: 181 | en: Francis Crick 182 | is_answer: false 183 | - id: form-b-sec-0-item-0-option-2 184 | title: 185 | locales: 186 | en: Rosalind Franklin 187 | is_answer: false 188 | - id: form-b-sec-0-item-0-option-3 189 | title: 190 | locales: 191 | en: Max Planck 192 | is_answer: false 193 | 194 | - type: multiple-select 195 | id: form-b-sec-0-item-1 196 | code: 1.2.1(b).SCI 197 | seed: false 198 | stem: 199 | locales: 200 | en: >- 201 | Which of the following are scientific elements on the Periodic Table of Elements? 202 | options: 203 | - id: form-b-sec-0-item-1-option-0 204 | title: 205 | locales: 206 | en: Uranium 207 | is_answer: true 208 | - id: form-b-sec-0-item-1-option-1 209 | title: 210 | locales: 211 | en: Manganese 212 | is_answer: true 213 | - id: form-b-sec-0-item-1-option-2 214 | title: 215 | locales: 216 | en: Brillium 217 | is_answer: false 218 | - id: form-b-sec-0-item-1-option-3 219 | title: 220 | locales: 221 | en: Hydrogen 222 | is_answer: true 223 | 224 | - name: Geography 225 | id: form-b-sec-1 226 | items: 227 | - type: multiple-choice 228 | id: form-b-sec-1-item-2 229 | code: 1.3.1(b).GEO 230 | seed: true 231 | stem: 232 | locales: 233 | en: >- 234 | Where is Glacier National Park? 235 | options: 236 | - id: form-b-sec-1-item-2-option-0 237 | title: 238 | locales: 239 | en: Montana 240 | is_answer: true 241 | - id: form-b-sec-1-item-2-option-1 242 | title: 243 | locales: 244 | en: Massachusetts 245 | is_answer: false 246 | - id: form-b-sec-1-item-2-option-2 247 | title: 248 | locales: 249 | en: Maine 250 | is_answer: false 251 | - id: form-b-sec-1-item-2-option-3 252 | title: 253 | locales: 254 | en: Minnesota 255 | is_answer: false 256 | 257 | - type: match 258 | id: form-b-sec-0-item-3 259 | code: 1.4.1(b).GEO 260 | seed: false 261 | lead_in: 262 | locales: 263 | en: >- 264 | Match the following cities to their states. 265 | stems: 266 | - id: form-b-sec-1-item-3-prompt-0 267 | title: 268 | locales: 269 | en: San Diego 270 | answer: form-b-sec-1-item-3-option-0 271 | - id: form-b-sec-1-item-3-prompt-1 272 | title: 273 | locales: 274 | en: Poughkeepsie 275 | answer: form-b-sec-1-item-3-option-1 276 | - id: form-b-sec-1-item-3-prompt-2 277 | title: 278 | locales: 279 | en: Seattle 280 | answer: form-b-sec-1-item-3-option-2 281 | options: 282 | - id: form-b-sec-1-item-3-option-0 283 | title: 284 | locales: 285 | en: California 286 | - id: form-b-sec-1-item-3-option-1 287 | title: 288 | locales: 289 | en: New York 290 | - id: form-b-sec-1-item-3-option-2 291 | title: 292 | locales: 293 | en: Washington 294 | -------------------------------------------------------------------------------- /api/examples/game-template-minimal/game-badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/api/examples/game-template-minimal/game-badge.png -------------------------------------------------------------------------------- /api/examples/game-template-minimal/game-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/api/examples/game-template-minimal/game-image.png -------------------------------------------------------------------------------- /api/examples/game-template-minimal/qwiklabs.yaml: -------------------------------------------------------------------------------- 1 | schema_version: 1 2 | entity_type: GameTemplate 3 | 4 | id: my-library/basic-game-template 5 | default_locale: en 6 | 7 | title: 8 | locales: 9 | en: Fun Game 10 | 11 | resources: 12 | - type: video 13 | id: a-resource 14 | title: 15 | locales: 16 | en: Welcome to GCP! 17 | es: ¡Bienvenido a GCP! 18 | video_provider: YouTube 19 | video_id: 20 | locales: 21 | en: oHg5SJYRHA0 22 | es: 7jjoyy7_RCk 23 | duration: 360 24 | 25 | modules: 26 | - id: my-module 27 | title: 28 | locales: 29 | en: My Module 30 | es: Mi módulo 31 | steps: 32 | - id: my-first-step 33 | activity_options: 34 | - type: lab 35 | id: my-library/a-lab 36 | - type: lab 37 | id: my-other-library/another-lab 38 | - id: my-second-step 39 | activity_options: 40 | - type: quiz 41 | id: my-library/a-quiz 42 | - id: my-other-module 43 | title: 44 | locales: 45 | en: My Other Module 46 | es: Mi otro módulo 47 | steps: 48 | - id: my-other-step 49 | activity_options: 50 | - type: resource 51 | id: a-resource 52 | -------------------------------------------------------------------------------- /api/examples/game-template-minimal/resources/choosing_compute_en.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/api/examples/game-template-minimal/resources/choosing_compute_en.pdf -------------------------------------------------------------------------------- /api/examples/game-template-minimal/resources/choosing_compute_es.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/api/examples/game-template-minimal/resources/choosing_compute_es.pdf -------------------------------------------------------------------------------- /api/examples/game-template-minimal/resources/choosing_compute_ja.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/api/examples/game-template-minimal/resources/choosing_compute_ja.pdf -------------------------------------------------------------------------------- /api/examples/lab-minimal/instructions/en.html: -------------------------------------------------------------------------------- 1 |

Robust Lab Example

2 | 3 |

Step 1: Take lab

4 |

We’ve given you a GCP resource. Go ahead and play around with it.

5 | 6 |

Step 2: …

7 |

8 |

9 | 10 |

Step 3: Profit

11 |

Huzzah! You’re ready to take on the world!

12 | -------------------------------------------------------------------------------- /api/examples/lab-minimal/qwiklabs.yaml: -------------------------------------------------------------------------------- 1 | entity_type: Lab 2 | schema_version: 2 3 | 4 | default_locale: en 5 | 6 | title: 7 | locales: 8 | en: Minimal Lab V2 Example 9 | 10 | description: 11 | locales: 12 | en: Just the basics, nothing more. 13 | 14 | duration: 20 15 | level: introductory 16 | 17 | instruction: 18 | type: html 19 | uri: 20 | locales: 21 | en: "./instructions/en.html" 22 | 23 | environment: 24 | resources: 25 | - type: gcp_project 26 | id: my_primary_project 27 | variant: gcpfree 28 | - type: gcp_user 29 | id: user_0 30 | permissions: 31 | - project: project_0 32 | roles: 33 | - roles/editor 34 | - roles/appengine.appAdmin 35 | - roles/bigquery.admin 36 | - roles/bigquery.user 37 | -------------------------------------------------------------------------------- /api/examples/lab-robust/instructions/en.html: -------------------------------------------------------------------------------- 1 |

Robust Lab Example

2 | 3 |

Step 1: Take lab

4 |

We’ve given you a GCP resource. Go ahead and play around with it.

5 | 6 |

Step 2: …

7 |

8 |

9 | 10 |

Step 3: Profit

11 |

Huzzah! You’re ready to take on the world!

12 | -------------------------------------------------------------------------------- /api/examples/lab-robust/instructions/es.html: -------------------------------------------------------------------------------- 1 |

Ejemplo de Robust Lab

2 |

Paso 1: tomar laboratorio

3 |

Le hemos proporcionado un recurso GCP. Adelante y juega con eso.

4 |

Paso 2: …

5 |

6 |

Paso 3: Ganancia

7 |

¡Huzzah! ¡Estás listo para enfrentarte al mundo!

8 | -------------------------------------------------------------------------------- /api/examples/lab-robust/lab.template: -------------------------------------------------------------------------------- 1 | Outputs: 2 | InstanceId: 3 | Value: i-0ac32d6485a60f132 -------------------------------------------------------------------------------- /api/examples/lab-robust/qwiklabs.yaml: -------------------------------------------------------------------------------- 1 | entity_type: Lab 2 | schema_version: 2 3 | 4 | default_locale: en 5 | 6 | title: 7 | locales: 8 | en: Robust Lab Example 9 | es: Ejemplo de Robust Lab 10 | 11 | description: 12 | locales: 13 | en: Seriously the best lab you've ever taken. Bar none. 14 | es: En serio, el mejor lab que has tomado. Sin excepción. 15 | 16 | duration: 60 17 | max_duration: 90 18 | level: introductory 19 | tags: 20 | - sample 21 | - life-changing 22 | - gcp 23 | product_tags: ['app engine', 'kubernetes engine', 'cloud functions'] 24 | role_tags: ['cloud architect', 'developers backend', 'developers frontend'] 25 | domain_tags: 26 | - infrastructure 27 | - application development 28 | - data 29 | 30 | instruction: 31 | type: html 32 | uri: 33 | locales: 34 | en: "./instructions/en.html" 35 | es: "./instructions/es.html" 36 | 37 | resources: 38 | - type: file 39 | title: 40 | locales: 41 | en: Sample PDF 42 | es: Ejemplo de PDF 43 | description: 44 | locales: 45 | en: This PDF contains all of the code samples for the lab. 46 | es: Este PDF contiene todos los ejemplos de código para el laboratorio. 47 | uri: 48 | locales: 49 | en: "./resources/sample-en.pdf" 50 | es: "./resources/sample-es.pdf" 51 | - type: video 52 | id: intro-video 53 | title: 54 | locales: 55 | en: Welcome to GCP! 56 | es: ¡Bienvenido a GCP! 57 | uri: 58 | locales: 59 | en: https://youtube.com/oHg5SJYRHA0 60 | es: https://youtube.com/7jjoyy7_RCk 61 | description: 62 | locales: 63 | en: Overview of Google Cloud Platform 64 | es: Descripción general de Google Cloud Platform 65 | 66 | environment: 67 | resources: 68 | - type: gcp_project 69 | id: my_primary_project 70 | variant: gcpfree 71 | allowed_locations: 72 | - us-east1 73 | - us-central1-a 74 | startup_script: 75 | type: deployment_manager 76 | path: startup_script 77 | custom_properties: 78 | - key: userNameWindows 79 | value: student 80 | - key: Project ID 81 | reference: my_primary_project.project_id 82 | - key: Default Zone 83 | reference: my_primary_project.default_zone 84 | - key: Default Region 85 | reference: my_primary_project.default_region 86 | - key: username 87 | reference: gcp_user.username 88 | - key: userName 89 | reference: gcp_user.local_username 90 | - key: password 91 | reference: gcp_user.password 92 | - key: AWS Account Number 93 | reference: the_account.account_number 94 | parent: my_primary_folder 95 | - type: gcp_project 96 | id: my_secondary_project 97 | variant: gcp_low_extra 98 | startup_script: 99 | type: qwiklabs 100 | path: startup_script 101 | custom_properties: 102 | - key: userNameWindows 103 | value: student 104 | cleanup_script: 105 | type: qwiklabs 106 | path: cleanup_script 107 | - type: gcp_project 108 | id: my_tertiary_project 109 | variant: gcpd 110 | allowed_locations: 111 | - - us-west1 112 | - us-east1 113 | - us-central1 114 | - SAME_AS_FIRST 115 | - SAME_AS_FIRST 116 | allowed_locations_constraint: DIFFERENT_REGIONS 117 | - type: gcp_user 118 | id: user_0 119 | permissions: 120 | - project: project_0 121 | roles: 122 | - roles/editor 123 | - roles/appengine.appAdmin 124 | - roles/bigquery.admin 125 | - roles/bigquery.user 126 | - folder: my_primary_folder 127 | roles: 128 | - roles/compute.xpnAdmin 129 | - type: gsuite_domain 130 | id: primary_domain 131 | - type: cloud_terminal 132 | id: shell 133 | permissions: 134 | - project: my_primary_project 135 | roles: 136 | - roles/editor 137 | - type: linux_terminal 138 | id: no-script-linux 139 | variant: it_cert_extra 140 | - type: linux_terminal 141 | id: script-linux 142 | startup_script: 143 | path: startup.sh 144 | - type: windows_vm 145 | id: no-script-windows 146 | variant: it_cert 147 | - type: windows_vm 148 | id: script-windows 149 | startup_script: 150 | path: startup.bat 151 | - type: aws_account 152 | id: the_account 153 | variant: aws_vpc 154 | allowed_locations: 155 | - us-east-1 156 | - us-central-1 157 | startup_script: 158 | type: cloud_formation 159 | path: lab.template 160 | custom_properties: 161 | - key: userNameWindows 162 | value: student 163 | - key: Project ID 164 | reference: my_primary_project.project_id 165 | - key: GCP Username 166 | reference: gcp_user.username 167 | - key: GCP password 168 | reference: gcp_user.password 169 | - key: AWS Account Number 170 | reference: the_account.account_number 171 | - key: AWS SSH private key 172 | reference: the_account.ssh_key 173 | user_policy: student_policy.json 174 | account_restrictions: 175 | allow_dedicated_instances: false 176 | allow_spot_instances: false 177 | allow_subnet_deletion: false 178 | allowed_rds_instances: ['db.t2.micro'] 179 | - type: google_workspace_domain 180 | id: my_domain 181 | - type: looker_instance 182 | id: looker 183 | permissions: 184 | - project: my_primary_project 185 | roles: 186 | - roles/editor 187 | startup_script: 188 | path: startup.sh 189 | - type: ide 190 | id: ide 191 | startup_script: 192 | path: startup.sh 193 | student_files: 194 | - path: student_files/main.py 195 | - type: azure_resource_group 196 | id: rg_1 197 | variant: default 198 | startup_script: 199 | type: qwiklabs 200 | path: startup_script 201 | custom_properties: 202 | - key: key 203 | value: student 204 | - type: azure_user 205 | id: a_user_1 206 | variant: default 207 | permissions: 208 | - resource_group: rg_1 209 | roles: 210 | - reader 211 | - type: azure_user 212 | id: a_user_2 213 | - type: gcp_folder 214 | id: my_primary_folder 215 | 216 | student_visible_outputs: 217 | - label: 218 | locales: 219 | en: "Open Azure Console" 220 | es: "Abrir La Consola Azure" 221 | reference: rg_1.console_url 222 | - label: 223 | locales: 224 | en: "Azure Resource Group" 225 | reference: rg_1.resource_group_name 226 | - label: 227 | locales: 228 | en: "Azure Username" 229 | es: "Nombre de usuario Azure" 230 | reference: a_user_1.username 231 | - label: 232 | locales: 233 | en: "Azure Password" 234 | reference: a_user_1.password 235 | - label: 236 | locales: 237 | en: "Resource Group Location" 238 | reference: rg_1.startup_script.location 239 | - label: 240 | locales: 241 | en: "Open GCP Console" 242 | es: "Abrir La Consola GCP" 243 | reference: my_primary_project.console_url 244 | - label: 245 | locales: 246 | en: "GCP Project" 247 | es: "Proyecto GCP" 248 | reference: my_primary_project.project_id 249 | - label: 250 | locales: 251 | en: "GCP Project Default Zone 1" 252 | reference: my_tertiary_project.default_zone_1 253 | - label: 254 | locales: 255 | en: "GCP Project Default Zone 2" 256 | reference: my_tertiary_project.default_zone_2 257 | - label: 258 | locales: 259 | en: "GCP Project Default Zone 3" 260 | reference: my_tertiary_project.default_zone_3 261 | - label: 262 | locales: 263 | en: "GCP Folder Name" 264 | es: "Nombre de carpeta de GCP" 265 | reference: my_primary_folder.folder_name 266 | - label: 267 | locales: 268 | en: "GCP Folder Display Name" 269 | es: "Nombre para mostrar de la carpeta GCP" 270 | reference: my_primary_folder.display_name 271 | - label: 272 | locales: 273 | en: "Username" 274 | es: "Nombre de usuario" 275 | reference: user_0.username 276 | - label: 277 | locales: 278 | en: "SSH Key" 279 | es: "Clave SSH" 280 | reference: user_0.ssh_key 281 | - label: 282 | locales: 283 | en: "RDP Session" 284 | reference: script-windows.student_url 285 | - label: 286 | locales: 287 | en: "Public IP" 288 | reference: script-linux.external_ip 289 | - label: 290 | locales: 291 | en: "InstanceDns" 292 | reference: my_primary_project.startup_script.InstanceDns 293 | - label: 294 | locales: 295 | en: "InstanceId" 296 | reference: the_account.startup_script.InstanceId 297 | - label: 298 | locales: 299 | en: "Open AWS Console" 300 | es: "Abrir La Consola AWS" 301 | reference: the_account.console_url 302 | - label: 303 | locales: 304 | en: "AWS Access Key ID" 305 | reference: the_account.access_key_id 306 | - label: 307 | locales: 308 | en: "AWS Secret Access Key" 309 | reference: the_account.secret_access_key 310 | - label: 311 | locales: 312 | en: "Workspace Console" 313 | reference: my_domain.console_url 314 | - label: 315 | locales: 316 | en: "Workspace Admin User" 317 | reference: my_domain.admin_username 318 | - label: 319 | locales: 320 | en: "Workspace Admin Password" 321 | reference: my_domain.admin_password 322 | - label: 323 | locales: 324 | en: "Open Looker" 325 | reference: looker_instance.student_url 326 | - label: 327 | locales: 328 | en: "Looker Developer Username" 329 | reference: looker_instance.developer_username 330 | - label: 331 | locales: 332 | en: "Looker Developer Password" 333 | reference: looker_instance.developer_password 334 | 335 | assessment: 336 | passing_percentage: 75 337 | steps: 338 | - title: 339 | locales: 340 | en: Create a Cloud Storage bucket 341 | es: Crear un depósito de almacenamiento en la nube 342 | maximum_score: 5 343 | student_messages: 344 | success: 345 | locales: 346 | en: 347 | Great job! You created the bucket! 348 | es: 349 | ¡Gran trabajo! ¡Creaste el cubo! 350 | bucket_missing: 351 | locales: 352 | en: 353 | Oops! No bucket found. 354 | es: 355 | ¡Uy! No se ha encontrado el cubo. 356 | bucket_misconfigured: 357 | locales: 358 | en: 359 | Hmm. The bucket is there, but it is misconfigured. 360 | es: 361 | Hmm. El cubo está allí, pero está mal configurado. 362 | services: 363 | - my_primary_project.StorageV1 364 | code: |- 365 | def check(handles: handles, resources: resources, maximum_score: maximum_score) 366 | storage_handle = handles['my_primary_project.StorageV1'] 367 | 368 | # Check for bucket 369 | found_bucket = ... 370 | unless found_bucket 371 | return { score: 0, student_message: 'bucket_missing' } 372 | end 373 | 374 | # Check bucket configuration 375 | bucket_configured_correctly = ... 376 | unless bucket_configured_correctly 377 | return { score: 2, student_message: 'bucket_misconfigured' } 378 | end 379 | 380 | { score: maximum_score, student_message: 'success' } 381 | end 382 | -------------------------------------------------------------------------------- /api/examples/lab-robust/resources/sample-en.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/api/examples/lab-robust/resources/sample-en.pdf -------------------------------------------------------------------------------- /api/examples/lab-robust/resources/sample-es.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/api/examples/lab-robust/resources/sample-es.pdf -------------------------------------------------------------------------------- /api/examples/lab-robust/startup_script/qwiklabs.jinja: -------------------------------------------------------------------------------- 1 | outputs: 2 | - name: InstanceDns 3 | value: 35.238.252.133 4 | -------------------------------------------------------------------------------- /api/examples/lab-robust/student_policy.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /api/examples/lab-v1-gsuite/instruction.html: -------------------------------------------------------------------------------- 1 |

Minimal GSuite Lab Example

2 | 3 |

Step 1: Take lab

4 | 5 |

We’ve given admin credentials for a GSuite domain. Go ahead and play around with it.

6 | 7 |

Step 2: …

8 | 9 |

10 | 11 |

Step 3: Profit

12 | 13 |

Huzzah! You’re ready to take on the world!

14 | -------------------------------------------------------------------------------- /api/examples/lab-v1-gsuite/qwiklabs.yaml: -------------------------------------------------------------------------------- 1 | entity_type: Lab 2 | schema_version: 1 3 | 4 | default_locale: en 5 | 6 | title: 7 | locales: 8 | en: Minimalist Gsuite Domain Example 9 | 10 | description: 11 | locales: 12 | en: Just the basics, nothing more. 13 | 14 | duration: 20 15 | level: introductory 16 | 17 | instruction: 18 | type: html 19 | locales: 20 | en: 'instruction.html' 21 | 22 | environment_resources: 23 | - type: gsuite_domain 24 | -------------------------------------------------------------------------------- /api/examples/lab-v1-minimal/instruction.html: -------------------------------------------------------------------------------- 1 |

Minimal Lab Example

2 | 3 |

Step 1: Take lab

4 | 5 |

We’ve given you a GCP resource. Go ahead and play around with it.

6 | 7 |

Step 2: …

8 | 9 |

10 | 11 |

Step 3: Profit

12 | 13 |

Huzzah! You’re ready to take on the world!

14 | -------------------------------------------------------------------------------- /api/examples/lab-v1-minimal/qwiklabs.yaml: -------------------------------------------------------------------------------- 1 | entity_type: Lab 2 | schema_version: 1 3 | 4 | default_locale: en 5 | 6 | title: 7 | locales: 8 | en: Minialist Lab Example 9 | 10 | description: 11 | locales: 12 | en: Just the basics, nothing more. 13 | 14 | duration: 20 15 | level: introductory 16 | 17 | instruction: 18 | type: html 19 | locales: 20 | en: './instruction.html' 21 | 22 | environment_resources: 23 | - type: gcp_project_and_user 24 | -------------------------------------------------------------------------------- /api/examples/lab-v1-robust/assessment.yaml: -------------------------------------------------------------------------------- 1 | # This file is _not_ standardized at all. It is currently just an export of 2 | # activity tracking from the Qwiklabs interface and is subject to change. 3 | # Consider it an early alpha version of the file. 4 | --- 5 | name: 'BigQuery: Qwik Start - Web User Interface' 6 | description: "This lab has following steps:\r\n\r\n1. Create a dataset\r\n2. Load 7 | the data into a new table" 8 | pass_percent: 75 9 | notify: false 10 | score_completion_only: false 11 | steps: 12 | - title: Create a new dataset 13 | points: 5 14 | max: 30 15 | interval: 30 16 | multi_region: false 17 | api: GCP 18 | services: 19 | - BigqueryV2 20 | method_name: steponecheck 21 | code: | 22 | def steponecheck(handles, points) 23 | bq = handles[:BigqueryV2] 24 | ret_hash = {done: false, score: 0} 25 | datasets = bq.list_datasets&.datasets || [] 26 | if datasets.count > 0 27 | ret_hash[:score] += 2 28 | datasets.each do |dataset| 29 | if dataset.dataset_reference.dataset_id == 'babynames' 30 | ret_hash[:score] += 3 31 | end 32 | end 33 | end 34 | if ret_hash[:score] == points 35 | ret_hash = { :done => true, :score => points } 36 | end 37 | ret_hash 38 | end 39 | - title: Upload the table 40 | points: 5 41 | max: 30 42 | interval: 30 43 | multi_region: false 44 | api: GCP 45 | services: 46 | - BigqueryV2 47 | method_name: steptwocheck 48 | code: | 49 | def steptwocheck(handles, points) 50 | bq = handles[:BigqueryV2] 51 | ret_hash = {done: false, score: 0} 52 | datasets = bq.list_datasets&.datasets || [] 53 | if datasets.count > 0 54 | datasets.each do |dataset| 55 | if dataset.dataset_reference.dataset_id == 'babynames' 56 | tables = bq.list_tables('babynames')&.tables || [] 57 | if tables.count > 0 58 | ret_hash[:score] += 2 59 | tables.each do |table| 60 | if table.table_reference.table_id == 'names_2014' 61 | ret_hash[:score] += 3 62 | end 63 | end 64 | end 65 | end 66 | end 67 | end 68 | if ret_hash[:score] == points 69 | ret_hash = { :done => true, :score => points } 70 | end 71 | ret_hash 72 | end 73 | -------------------------------------------------------------------------------- /api/examples/lab-v1-robust/dm.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/api/examples/lab-v1-robust/dm.zip -------------------------------------------------------------------------------- /api/examples/lab-v1-robust/instructions/en.html: -------------------------------------------------------------------------------- 1 |

Robust Lab Example

2 | 3 |

Step 1: Take lab

4 |

We’ve given you a GCP resource. Go ahead and play around with it.

5 | 6 |

Step 2: …

7 |

8 |

9 | 10 |

Step 3: Profit

11 |

Huzzah! You’re ready to take on the world!

12 | -------------------------------------------------------------------------------- /api/examples/lab-v1-robust/instructions/es.html: -------------------------------------------------------------------------------- 1 |

Ejemplo de Robust Lab

2 |

Paso 1: tomar laboratorio

3 |

Le hemos proporcionado un recurso GCP. Adelante y juega con eso.

4 |

Paso 2: …

5 |

6 |

Paso 3: Ganancia

7 |

¡Huzzah! ¡Estás listo para enfrentarte al mundo!

8 | -------------------------------------------------------------------------------- /api/examples/lab-v1-robust/qwiklabs.yaml: -------------------------------------------------------------------------------- 1 | entity_type: Lab 2 | schema_version: 1 3 | 4 | default_locale: en 5 | 6 | title: 7 | locales: 8 | en: Robust Lab Example 9 | es: Ejemplo de Robust Lab 10 | 11 | description: 12 | locales: 13 | en: Seriously the best lab you've ever taken. Bar none. 14 | es: En serio, el mejor lab que has tomado. Sin excepción. 15 | 16 | credits: 5 17 | duration: 60 18 | level: introductory 19 | tags: 20 | - sample 21 | - life-changing 22 | - gcp 23 | product_tags: ['app engine', 'kubernetes engine', 'cloud functions'] 24 | role_tags: ['cloud architect', 'developers backend', 'developers frontend'] 25 | domain_tags: 26 | - infrastructure 27 | - application development 28 | - data 29 | 30 | instruction: 31 | type: markdown 32 | locales: 33 | en: "./instructions/en.md" 34 | es: "./instructions/es.md" 35 | 36 | resources: 37 | - type: file 38 | title: 39 | locales: 40 | en: Sample PDF 41 | es: Ejemplo de PDF 42 | description: 43 | locales: 44 | en: This PDF contains all of the code samples for the lab. 45 | es: Este PDF contiene todos los ejemplos de código para el laboratorio. 46 | uri: 47 | locales: 48 | en: "./resources/sample-en.pdf" 49 | es: "./resources/sample-es.pdf" 50 | - type: video 51 | id: intro-video 52 | title: 53 | locales: 54 | en: Welcome to GCP! 55 | es: ¡Bienvenido a GCP! 56 | uri: 57 | locales: 58 | en: https://youtube.com/oHg5SJYRHA0 59 | es: https://youtube.com/7jjoyy7_RCk 60 | description: 61 | locales: 62 | en: Overview of Google Cloud Platform 63 | es: Descripción general de Google Cloud Platform 64 | 65 | environment_resources: 66 | - type: gcp_project 67 | id: my_primary_project 68 | fleet: gcpfree 69 | dm_script: dm.zip 70 | - type: gcp_user 71 | id: user_0 72 | permissions: 73 | - project: project_0 74 | roles: 75 | - roles/editor 76 | - roles/appengine.appAdmin 77 | - roles/bigquery.admin 78 | - roles/bigquery.user 79 | - type: gcp_user 80 | id: gcp-only-user 81 | variant: gcp_only 82 | - type: gcp_user 83 | id: default-user 84 | variant: default 85 | 86 | assessment: 87 | name: 'BigQuery: Qwik Start - Web User Interface' 88 | description: "This lab has following steps:\r\n\r\n1. Create a dataset\r\n2. Load 89 | the data into a new table" 90 | pass_percent: 75 91 | notify: false 92 | score_completion_only: false 93 | steps: 94 | - title: Create a new dataset 95 | points: 5 96 | max: 30 97 | interval: 30 98 | multi_region: false 99 | api: GCP 100 | services: 101 | - BigqueryV2 102 | method_name: steponecheck 103 | code: | 104 | def steponecheck(handles, points) 105 | bq = handles[:BigqueryV2] 106 | ret_hash = {done: false, score: 0} 107 | datasets = bq.list_datasets&.datasets || [] 108 | if datasets.count > 0 109 | ret_hash[:score] += 2 110 | datasets.each do |dataset| 111 | if dataset.dataset_reference.dataset_id == 'babynames' 112 | ret_hash[:score] += 3 113 | end 114 | end 115 | end 116 | if ret_hash[:score] == points 117 | ret_hash = { :done => true, :score => points } 118 | end 119 | ret_hash 120 | end 121 | - title: Upload the table 122 | points: 5 123 | max: 30 124 | interval: 30 125 | multi_region: false 126 | api: GCP 127 | services: 128 | - BigqueryV2 129 | method_name: steptwocheck 130 | code: | 131 | def steptwocheck(handles, points) 132 | bq = handles[:BigqueryV2] 133 | ret_hash = {done: false, score: 0} 134 | datasets = bq.list_datasets&.datasets || [] 135 | if datasets.count > 0 136 | datasets.each do |dataset| 137 | if dataset.dataset_reference.dataset_id == 'babynames' 138 | tables = bq.list_tables('babynames')&.tables || [] 139 | if tables.count > 0 140 | ret_hash[:score] += 2 141 | tables.each do |table| 142 | if table.table_reference.table_id == 'names_2014' 143 | ret_hash[:score] += 3 144 | end 145 | end 146 | end 147 | end 148 | end 149 | end 150 | if ret_hash[:score] == points 151 | ret_hash = { :done => true, :score => points } 152 | end 153 | ret_hash 154 | end 155 | -------------------------------------------------------------------------------- /api/examples/lab-v1-robust/resources/sample-en.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/api/examples/lab-v1-robust/resources/sample-en.pdf -------------------------------------------------------------------------------- /api/examples/lab-v1-robust/resources/sample-es.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/api/examples/lab-v1-robust/resources/sample-es.pdf -------------------------------------------------------------------------------- /api/examples/learning-path-minimal/gcp-intro-path-badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/api/examples/learning-path-minimal/gcp-intro-path-badge.png -------------------------------------------------------------------------------- /api/examples/learning-path-minimal/qwiklabs.yaml: -------------------------------------------------------------------------------- 1 | schema_version: 1 2 | entity_type: LearningPath 3 | 4 | id: my-library/basic-learning-path 5 | default_locale: en 6 | 7 | title: 8 | locales: 9 | en: Good Path 10 | 11 | description: 12 | locales: 13 | en: My learning path description 14 | 15 | modules: 16 | - id: my-module 17 | title: 18 | locales: 19 | en: My Module 20 | es: Mi módulo 21 | steps: 22 | - id: my-first-step 23 | activity_options: 24 | - type: lab 25 | id: my-library/a-lab 26 | - type: lab 27 | id: my-other-library/another-lab 28 | - id: my-second-step 29 | activity_options: 30 | - type: quiz 31 | id: my-library/a-quiz 32 | -------------------------------------------------------------------------------- /api/examples/learning-path-minimal/resources/choosing_compute_en.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/api/examples/learning-path-minimal/resources/choosing_compute_en.pdf -------------------------------------------------------------------------------- /api/examples/peer-assignment-minimal/instructions/en.html: -------------------------------------------------------------------------------- 1 |

Minimal Peer Assignment Example

2 | 3 |

Step 1: Access the template

4 |

Use this template for your storyboard.

5 | 6 |

Step 2: Build a big picture storyboard

7 |

8 |

9 | 10 |

Step 3: Build a close-up storyboard

11 |

Huzzah! You’re ready to take on the world!

12 | -------------------------------------------------------------------------------- /api/examples/peer-assignment-minimal/qwiklabs.yaml: -------------------------------------------------------------------------------- 1 | entity_type: PeerAssignment 2 | schema_version: 1 3 | 4 | default_locale: en 5 | 6 | title: 7 | locales: 8 | en: Minimal Peer Assignment Example 9 | 10 | review_criteria: 11 | locales: 12 | en: Just the basics, nothing more. 13 | 14 | duration: 120 15 | 16 | instruction: 17 | type: html 18 | uri: 19 | locales: 20 | en: "./instructions/en.html" 21 | 22 | prompts: 23 | - id: prompt-1 24 | stem: 25 | locales: 26 | en: Upload a big picture storyboard. 27 | response_types: 28 | - file_upload 29 | rubric_items: 30 | - type: multiple-choice 31 | id: prompt-1-rubric-1 32 | stem: 33 | locales: 34 | en: The template is filled out. 35 | options: 36 | - id: prompt-1-rubric-1-option-1 37 | title: 38 | locales: 39 | en: 0 parts of the template are filled out. 40 | points: 0 41 | - id: prompt-1-rubric-1-option-2 42 | title: 43 | locales: 44 | en: Some parts of the template are filled out. 45 | points: 1 46 | - id: prompt-1-rubric-1-option-3 47 | title: 48 | locales: 49 | en: All parts of the template are filled out. 50 | points: 2 51 | - type: true-false 52 | id: prompt-1-rubric-2 53 | stem: 54 | locales: 55 | en: The big picture storyboard is clearly focused on a user. 56 | true_points: 1 57 | false_points: 0 58 | -------------------------------------------------------------------------------- /api/examples/peer-assignment-robust/instructions/en.html: -------------------------------------------------------------------------------- 1 |

Robust Peer Assignment Example

2 | 3 |

Step 1: Access the template

4 |

Use this template for your storyboard.

5 | 6 |

Step 2: Build a big picture storyboard

7 |

8 |

9 | 10 |

Step 3: Build a close-up storyboard

11 |

Huzzah! You’re ready to take on the world!

12 | 13 | Example Image 14 | 15 | Template Link 16 | -------------------------------------------------------------------------------- /api/examples/peer-assignment-robust/instructions/es.html: -------------------------------------------------------------------------------- 1 |

Ejemplo de Robust Peer Assignment

2 | 3 |

Paso 1: Accede a la plantilla

4 |

Utilice esta plantilla para su guión gráfico .

5 | 6 |

Step 2: Cree un guión gráfico de imagen grande

7 |

8 |

9 | 10 |

Step 3: Cree un guión gráfico de primer plano

11 |

¡Huzzah! ¡Estás listo para enfrentarte al mundo!

-------------------------------------------------------------------------------- /api/examples/peer-assignment-robust/instructions/img/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/api/examples/peer-assignment-robust/instructions/img/example.png -------------------------------------------------------------------------------- /api/examples/peer-assignment-robust/qwiklabs.yaml: -------------------------------------------------------------------------------- 1 | entity_type: PeerAssignment 2 | schema_version: 1 3 | 4 | default_locale: en 5 | 6 | title: 7 | locales: 8 | en: Robust Peer Assignment Example 9 | es: Ejemplo de Robust Peer Assignment 10 | 11 | review_criteria: 12 | locales: 13 | en: Just the basics, nothing more. 14 | es: Solo lo básico, nada más. 15 | 16 | duration: 120 17 | 18 | instruction: 19 | type: html 20 | uri: 21 | locales: 22 | en: "./instructions/en.html" 23 | es: "./instructions/es.html" 24 | 25 | objectives: 26 | locales: 27 | en: Learn how to do a peer assignment. 28 | es: Aprende a hacer una tarea entre compañeros. 29 | 30 | passing_score: 5 31 | 32 | prompts: 33 | - id: prompt-1 34 | stem: 35 | locales: 36 | en: Upload a big picture storyboard. 37 | es: Cargue el guión gráfico general. 38 | response_types: 39 | - file_upload 40 | - url 41 | rubric_items: 42 | - type: multiple-choice 43 | id: prompt-1-rubric-1 44 | stem: 45 | locales: 46 | en: The template is filled out. 47 | es: La plantilla está llena. 48 | options: 49 | - id: prompt-1-rubric-1-option-1 50 | title: 51 | locales: 52 | en: 0 parts of the template are filled out. 53 | es: Se completan 0 partes de la plantilla. 54 | points: 0 55 | - id: prompt-1-rubric-1-option-2 56 | title: 57 | locales: 58 | en: Some parts of the template are filled out. 59 | es: Algunas partes de la plantilla están llenas. 60 | points: 1 61 | - id: prompt-1-rubric-1-option-3 62 | title: 63 | locales: 64 | en: All parts of the template are filled out. 65 | es: Todas las partes de la plantilla están llenas. 66 | points: 2 67 | - type: true-false 68 | id: prompt-1-rubric-2 69 | stem: 70 | locales: 71 | en: The big picture storyboard is clearly focused on a user. 72 | es: El guión gráfico general está claramente centrado en un usuario. 73 | true_points: 1 74 | false_points: 0 75 | - id: prompt-2 76 | stem: 77 | locales: 78 | en: Upload a close-up storyboard. 79 | es: Cargue un guión gráfico de primer plano. 80 | response_types: 81 | - file_upload 82 | - url 83 | rubric_items: 84 | - type: multiple-choice 85 | id: prompt-2-rubric-1 86 | stem: 87 | locales: 88 | en: The template is filled out. 89 | es: La plantilla está llena. 90 | options: 91 | - id: prompt-2-rubric-1-option-1 92 | title: 93 | locales: 94 | en: 0 parts of the template are filled out. 95 | es: La plantilla está llena. 96 | points: 0 97 | - id: prompt-2-rubric-1-option-2 98 | title: 99 | locales: 100 | en: Some parts of the template are filled out. 101 | es: Algunas partes de la plantilla están llenas. 102 | points: 1 103 | - id: prompt-2-rubric-1-option-3 104 | title: 105 | locales: 106 | en: All parts of the template are filled out. 107 | es: Todas las partes de la plantilla están llenas. 108 | points: 2 109 | - type: true-false 110 | id: prompt-2-rubric-2 111 | stem: 112 | locales: 113 | en: The close-up storyboard is clearly focused on a user. 114 | es: El guión gráfico de primer plano está claramente centrado en un usuario. 115 | true_points: 1 116 | false_points: 0 117 | - type: reflective-text 118 | id: prompt-2-rubric-3 119 | stem: 120 | locales: 121 | en: Provide feedback on the close-up storyboard. 122 | es: Proporcione comentarios sobre el guión gráfico de primer plano. 123 | 124 | exemplars: 125 | - id: examplar-1 126 | prompt_responses: 127 | - id: prompt-response-1 128 | prompt_id: prompt-1 129 | response_type: url 130 | response_content: 131 | locales: 132 | en: http://www.google.com 133 | es: http://www.google.com 134 | 135 | - id: prompt-response-2 136 | prompt_id: prompt-2 137 | response_type: rich_text 138 | response_content: 139 | locales: 140 | en: This is my rich text answer 141 | es: This is my rich text answer in Spanish 142 | -------------------------------------------------------------------------------- /api/examples/quiz-minimal/qwiklabs.yaml: -------------------------------------------------------------------------------- 1 | entity_type: Quiz 2 | schema_version: 1 3 | 4 | title: 5 | locales: 6 | en: What is democracy? 7 | 8 | passing_percentage: 100 9 | default_locale: en 10 | 11 | items: 12 | - type: true-false 13 | id: item-1 14 | stem: 15 | locales: 16 | en: Direct democracy is a form of government where a single leader has ultimate ruling authority. 17 | answer: false 18 | true_rationale: 19 | locales: 20 | en: Sorry! A single leader having ultimate authority describes an autocracy. 21 | false_rationale: 22 | locales: 23 | en: Right! That form of government would be closer to an autocracy, not democracy. 24 | -------------------------------------------------------------------------------- /api/examples/quiz-robust/qwiklabs.yaml: -------------------------------------------------------------------------------- 1 | entity_type: Quiz 2 | schema_version: 1 3 | 4 | title: 5 | locales: 6 | en: Nobel Prizewinners 7 | 8 | passing_percentage: 67 9 | default_locale: en 10 | 11 | items: 12 | - type: multiple-choice 13 | id: item-1 14 | stem: 15 | locales: 16 | en: Who won the Nobel Prize for discovering the cause of the photoelectric effect? 17 | fr: Qui a remporté le prix Nobel pour avoir découvert la cause de l'effet photoélectrique? 18 | options: 19 | - title: 20 | locales: 21 | en: Albert Einstein 22 | fr: Albert Einstein 23 | id: item-1-option-1 24 | is_answer: true 25 | rationale: 26 | locales: 27 | en: Correct! Albert Einstein won the Nobel Prize in 1922 for work that forms the foundation for how modern solar panels work. 28 | fr: Correct! Albert Einstein a reçu le prix Nobel en 1922 pour des travaux qui constituent le fondement du fonctionnement des panneaux solaires modernes. 29 | - title: 30 | locales: 31 | en: Francis Crick 32 | fr: Francis Crick 33 | id: item-1-option-2 34 | is_answer: false 35 | rationale: 36 | locales: 37 | en: While Crick did win a Nobel Prize, it was for his discovery of DNA along with James Watson. 38 | fr: Bien que Crick ait remporté un prix Nobel, c'était pour sa découverte de l'ADN avec James Watson. 39 | - title: 40 | locales: 41 | en: Rosalind Franklin 42 | fr: Rosalind Franklin 43 | id: item-1-option-3 44 | is_answer: false 45 | rationale: 46 | locales: 47 | en: Sorry! While her work was instrumental in discovering DNA, Rosalind Franklin never won a Nobel Prize. 48 | fr: Désolé! Alors que son travail a joué un rôle déterminant dans la découverte de l'ADN, Rosalind Franklin n'a jamais remporté de prix Nobel. 49 | - title: 50 | locales: 51 | en: Max Planck 52 | fr: Max Planck 53 | id: item-1-option-4 54 | is_answer: false 55 | rationale: 56 | locales: 57 | en: Max Planck won the Nobel Price in Physics in 1918 for his work on quantum theory, and while his work was used in the discovery of the photoelectric effect, he actually rejected the initial theory. 58 | fr: Max Planck a remporté le prix Nobel de physique en 1918 pour ses travaux sur la théorie quantique. Bien que ses travaux aient servi à la découverte de l'effet photoélectrique, il a en réalité rejeté la théorie initiale. 59 | - type: multiple-select 60 | id: item-2 61 | stem: 62 | locales: 63 | en: Which of the following is a state in the United States? 64 | fr: Lequel des États suivants est un État aux États-Unis? 65 | options: 66 | - title: 67 | locales: 68 | en: Massachusetts 69 | fr: Massachusetts 70 | id: item-2-option-1 71 | is_answer: true 72 | rationale: 73 | locales: 74 | en: Yep! Massachusetts is located in the Northeast. 75 | fr: Oui! Le Massachusetts est situé dans le nord-est. 76 | - title: 77 | locales: 78 | en: Manitoba 79 | fr: Manitoba 80 | id: item-2-option-2 81 | is_answer: false 82 | rationale: 83 | locales: 84 | en: Sorry! Manitoba is a Canadian province, though it does share a border with the Midwest United States. 85 | fr: Désolé! Le Manitoba est une province canadienne, même s'il partage une frontière avec le Midwest américain. 86 | - title: 87 | locales: 88 | en: Oregon 89 | fr: l'Oregon 90 | id: item-2-option-3 91 | is_answer: true 92 | rationale: 93 | locales: 94 | en: Yep! Oregon is a state in the Pacific Northwest. 95 | fr: Oui! L'Oregon est un état du nord-ouest du Pacifique. 96 | - title: 97 | locales: 98 | en: Washington, D.C. 99 | fr: Washington, D.C. 100 | id: item-2-option-4 101 | is_answer: false 102 | rationale: 103 | locales: 104 | en: Washington, D.C. is specifically mentioned in the U.S. Constitution as as a district administered by the federal government for the purpose of being the Seat of the Government of the United States. It lacks several of the rights states have, such as full representation in Congress. 105 | fr: Washington, DC, est expressément mentionné dans la Constitution américaine comme un district administré par le gouvernement fédéral dans le but d’être le siège du gouvernement des États-Unis. Il manque plusieurs des droits des États, tels que la pleine représentation au Congrès. 106 | - type: true-false 107 | id: item-3 108 | stem: 109 | locales: 110 | en: Direct democracy is a form of government where a single leader has ultimate ruling authority. 111 | fr: La démocratie directe est une forme de gouvernement où un seul chef a l'autorité suprême. 112 | answer: false 113 | true_rationale: 114 | locales: 115 | en: Sorry! A single leader having ultimate authority describes an autocracy. 116 | fr: Désolé! Un seul chef ayant l'autorité ultime décrit une autocratie. 117 | false_rationale: 118 | locales: 119 | en: Right! That form of government would be closer to an autocracy, not democracy. 120 | fr: C'est ça! Cette forme de gouvernement serait plus proche d'une autocratie, pas d'une démocratie. 121 | - type: match 122 | id: item-4 123 | lead_in: 124 | locales: 125 | en: Match the following cities to their states. 126 | fr: Faites correspondre les villes suivantes à leurs États. 127 | stems: 128 | - title: 129 | locales: 130 | en: San Francisco 131 | fr: San Francisco 132 | answer: item-4-option-0 133 | - title: 134 | locales: 135 | en: Nashville 136 | fr: Nashville 137 | answer: item-4-option-1 138 | options: 139 | - id: item-4-option-0 140 | title: 141 | locales: 142 | en: Tennessee 143 | fr: Tennessee 144 | - id: item-4-option-1 145 | title: 146 | locales: 147 | en: California 148 | fr: Californie 149 | -------------------------------------------------------------------------------- /api/examples/quiz-sections/qwiklabs.yaml: -------------------------------------------------------------------------------- 1 | entity_type: Quiz 2 | schema_version: 1 3 | 4 | title: 5 | locales: 6 | en: Nobel Prizewinners 7 | 8 | passing_percentage: 67 9 | default_locale: en 10 | 11 | sections: 12 | - id: section-1 13 | name: Section 1 14 | item_count: 2 15 | items: 16 | - type: multiple-choice 17 | id: item-1 18 | stem: 19 | locales: 20 | en: Who won the Nobel Prize for discovering the cause of the photoelectric effect? 21 | fr: Qui a remporté le prix Nobel pour avoir découvert la cause de l'effet photoélectrique? 22 | options: 23 | - title: 24 | locales: 25 | en: Albert Einstein 26 | fr: Albert Einstein 27 | id: item-1-option-1 28 | is_answer: true 29 | rationale: 30 | locales: 31 | en: Correct! Albert Einstein won the Nobel Prize in 1922 for work that forms the foundation for how modern solar panels work. 32 | fr: Correct! Albert Einstein a reçu le prix Nobel en 1922 pour des travaux qui constituent le fondement du fonctionnement des panneaux solaires modernes. 33 | - title: 34 | locales: 35 | en: Francis Crick 36 | fr: Francis Crick 37 | id: item-1-option-2 38 | is_answer: false 39 | rationale: 40 | locales: 41 | en: While Crick did win a Nobel Prize, it was for his discovery of DNA along with James Watson. 42 | fr: Bien que Crick ait remporté un prix Nobel, c'était pour sa découverte de l'ADN avec James Watson. 43 | - title: 44 | locales: 45 | en: Rosalind Franklin 46 | fr: Rosalind Franklin 47 | id: item-1-option-3 48 | is_answer: false 49 | rationale: 50 | locales: 51 | en: Sorry! While her work was instrumental in discovering DNA, Rosalind Franklin never won a Nobel Prize. 52 | fr: Désolé! Alors que son travail a joué un rôle déterminant dans la découverte de l'ADN, Rosalind Franklin n'a jamais remporté de prix Nobel. 53 | - title: 54 | locales: 55 | en: Max Planck 56 | fr: Max Planck 57 | id: item-1-option-4 58 | is_answer: false 59 | rationale: 60 | locales: 61 | en: Max Planck won the Nobel Price in Physics in 1918 for his work on quantum theory, and while his work was used in the discovery of the photoelectric effect, he actually rejected the initial theory. 62 | fr: Max Planck a remporté le prix Nobel de physique en 1918 pour ses travaux sur la théorie quantique. Bien que ses travaux aient servi à la découverte de l'effet photoélectrique, il a en réalité rejeté la théorie initiale. 63 | - title: 64 | locales: 65 | en: All of the above 66 | fr: Tout ce qui précède 67 | id: item-1-option-5 68 | is_answer: false 69 | rationale: 70 | locales: 71 | en: Some of the answers are incorrect. Try again! 72 | fr: Certaines des réponses sont incorrectes. Réessayer! 73 | fixedPlace: true 74 | - type: multiple-select 75 | id: item-2 76 | stem: 77 | locales: 78 | en: Which of the following is a state in the United States? 79 | fr: Lequel des États suivants est un État aux États-Unis? 80 | options: 81 | - title: 82 | locales: 83 | en: Massachusetts 84 | fr: Massachusetts 85 | id: item-2-option-1 86 | is_answer: true 87 | rationale: 88 | locales: 89 | en: Yep! Massachusetts is located in the Northeast. 90 | fr: Oui! Le Massachusetts est situé dans le nord-est. 91 | - title: 92 | locales: 93 | en: Manitoba 94 | fr: Manitoba 95 | id: item-2-option-2 96 | is_answer: false 97 | rationale: 98 | locales: 99 | en: Sorry! Manitoba is a Canadian province, though it does share a border with the Midwest United States. 100 | fr: Désolé! Le Manitoba est une province canadienne, même s'il partage une frontière avec le Midwest américain. 101 | - title: 102 | locales: 103 | en: Oregon 104 | fr: l'Oregon 105 | id: item-2-option-3 106 | is_answer: true 107 | rationale: 108 | locales: 109 | en: Yep! Oregon is a state in the Pacific Northwest. 110 | fr: Oui! L'Oregon est un état du nord-ouest du Pacifique. 111 | - title: 112 | locales: 113 | en: Washington, D.C. 114 | fr: Washington, D.C. 115 | id: item-2-option-4 116 | is_answer: false 117 | rationale: 118 | locales: 119 | en: Washington, D.C. is specifically mentioned in the U.S. Constitution as as a district administered by the federal government for the purpose of being the Seat of the Government of the United States. It lacks several of the rights states have, such as full representation in Congress. 120 | fr: Washington, DC, est expressément mentionné dans la Constitution américaine comme un district administré par le gouvernement fédéral dans le but d’être le siège du gouvernement des États-Unis. Il manque plusieurs des droits des États, tels que la pleine représentation au Congrès. 121 | - type: true-false 122 | id: item-3 123 | stem: 124 | locales: 125 | en: Direct democracy is a form of government where a single leader has ultimate ruling authority. 126 | fr: La démocratie directe est une forme de gouvernement où un seul chef a l'autorité suprême. 127 | answer: false 128 | true_rationale: 129 | locales: 130 | en: Sorry! A single leader having ultimate authority describes an autocracy. 131 | fr: Désolé! Un seul chef ayant l'autorité ultime décrit une autocratie. 132 | false_rationale: 133 | locales: 134 | en: Right! That form of government would be closer to an autocracy, not democracy. 135 | fr: C'est ça! Cette forme de gouvernement serait plus proche d'une autocratie, pas d'une démocratie. 136 | - type: match 137 | id: item-4 138 | lead_in: 139 | locales: 140 | en: Match the following cities to their states. 141 | fr: Faites correspondre les villes suivantes à leurs États. 142 | stems: 143 | - title: 144 | locales: 145 | en: San Francisco 146 | fr: San Francisco 147 | answer: item-4-option-0 148 | - title: 149 | locales: 150 | en: Nashville 151 | fr: Nashville 152 | answer: item-4-option-1 153 | options: 154 | - id: item-4-option-0 155 | title: 156 | locales: 157 | en: Tennessee 158 | fr: Tennessee 159 | - id: item-4-option-1 160 | title: 161 | locales: 162 | en: California 163 | fr: Californie 164 | -------------------------------------------------------------------------------- /api/lab-bundle-spec-v1.md: -------------------------------------------------------------------------------- 1 | # Qwiklabs Lab Bundle Specification 2 | 3 | > **Version 1** 4 | > 5 | > This is a DRAFT document. We welcome feedback as this format evolves. 6 | 7 | Previously (in b6086b8f824aa398c1f4413b92351a4956e744cd), the robust example had 8 | some cool ideas for how deployment manager and activity tracking should look in 9 | the future. None of it is implemented yet but the ideas may be useful in the 10 | future. 11 | 12 | ## `qwiklabs.yaml` Structure 13 | 14 | Here's a sample `qwiklabs.yaml` file, with all nested details removed to make it 15 | easier to see the general file structure. 16 | 17 | ```yaml 18 | entity_type: Lab 19 | schema_version: 1 20 | default_locale: en 21 | 22 | title: 23 | locales: 24 | en: Best Lab Ever 25 | 26 | description: 27 | locales: 28 | en: No, seriously. It's the best lab ever. You're going to love it! 29 | 30 | duration: 60 31 | level: intro 32 | tags: [sample, life-changing, gcp] 33 | legacy_display_options: [ 34 | hide_connection_fleetconsole, 35 | show_connection_ssh, 36 | show_connection_vnc, 37 | show_connection_rdp, 38 | show_connection_custom, 39 | show_connection_access_key_id, 40 | allow_immediate_entry 41 | ] 42 | 43 | ... 44 | 45 | 46 | # The primary instruction content for this lab 47 | instruction: ... 48 | 49 | # Other resources the learner may access while taking this lab 50 | resources: ... 51 | 52 | # Lab resources that are provisioned by Qwiklabs 53 | # e.g. cloud account, databases, etc. 54 | environment_resources: ... 55 | 56 | # Checkpoint evaluation and quiz data 57 | assessment: ... 58 | ``` 59 | 60 | Two properties are critical for specifying your lab bundle: 61 | 62 | - `entity_type` 63 | 64 | This should be set to `Lab` for lab bundles. For other entity types such as 65 | `CourseTemplate` or `Quiz` please see their own bundle spec. 66 | 67 | - `schema_version` 68 | 69 | This notes which version of this spec the bundle is using. Currently, the 70 | only valid value is `1` but this will change as new features get added. 71 | 72 | ### Default Locale 73 | 74 | The lab bundle MUST specify a `default_locale`. It corresponds to the locale 75 | that the lab is originally authored in. Authoring tools can use this as a hint 76 | to notify localizers when content in the default locale is updated. Also, it 77 | provides a hint to the learner interface about which locale to display if an 78 | instruction/resource is not localized for the learner's current locale. 79 | 80 | ### Lab attributes 81 | 82 | attribute | required | type | notes 83 | ---------------------- | -------- | ----------- | ----------------------------------------- 84 | title | ✓ | locale dictionary | 85 | description | ✓ | locale dictionary | 86 | duration | ✓ | integer | Amount of time it should take an average learner to complete the lab (in minutes) 87 | max_duration | | integer | Maximum amount of time learner will be given to complete the lab (in minutes) 88 | credits | | integer | 89 | level | | string | 90 | logo | | file path | 91 | tags | | array | 92 | legacy_display_options | | array | Elements to hide/show in ql-lab-control-panel widget 93 | copyright | | string/enum | v2 feature after more research? 94 | 95 | ### Instructions 96 | 97 | attribute | required | type | notes 98 | --------- | -------- | ---------- | ----------------------------------------- 99 | type | ✓ | enum | [See list of valid types below] 100 | locales | ✓ | dictionary | Keys are locale codes, the values are paths to files in the bundle. 101 | 102 | ```yaml 103 | instruction: 104 | type: html 105 | locales: 106 | en: instructions/en.html 107 | es: instructions/es.html 108 | ``` 109 | 110 | #### Valid instruction types 111 | 112 | * `html` 113 | * `pdf` 114 | 115 | HTML is the preferred format for stored instructions. PDFs will be displayed 116 | embedded in the learner interface, but will lack any navigation or interactive 117 | functionality. 118 | 119 | ##### Qwiklabs supported HTML 120 | 121 | There are benefits to formatting lab instructions as HTML. 122 | 123 | * Instruction styling will be updated automatically as the Qwiklabs interface 124 | evolves. 125 | * Qwiklabs will help users navigate within your instruction document with a 126 | table of contents or direct links. It will also remember the learner's 127 | location in the document if they leave the page. 128 | * Authors can specify interactive elements that will be displayed inline with 129 | your instructions in the learner's interface (quizzes, checkpoints, etc). 130 | 131 | However, we will not accept arbitrary HTML. Your input will be heavily scrubbed. 132 | 133 | * Only a standard subset of HTML elements will be supported (`

`, `

`, 134 | ``, etc). All other tags will be stripped out of displayed content. 135 | * All styling will be removed. 136 | * All scripting will be removed. 137 | 138 | See the Instruction part of the [HTML spec](../html/html-spec.md) for details. 139 | 140 | ### Resources 141 | 142 | Resources are additional materials that learners may refer to while taking this 143 | lab. 144 | 145 | See [Resource Spec](../resource-spec.md) for details. 146 | 147 | ### Environment Resources 148 | 149 | The sandbox learning environment is a key feature of Qwiklabs. As the author of 150 | a lab, you need to tell us which cloud accounts to provision for a learner, and 151 | what resources we should create in that account before handing it over to the 152 | learner. 153 | 154 | The properties of each environment resource will depend on their type, i.e. AWS 155 | Accounts and GSuite Users require different configuration data. However, there 156 | are two properties that all resources have regardless of type: 157 | 158 | attribute | required | type | notes 159 | --------- | -------- | ------ | ----------------------------------------- 160 | type | ✓ | enum | [See list of valid types] 161 | id | | string | Identifier that can be used throughout project bundle 162 | 163 | ```yaml 164 | environment_resources: 165 | - type: gcp_project 166 | id: my_primary_project 167 | dm_template: 168 | script: deployment_manager 169 | - type: gcp_user 170 | id: primary_user 171 | permissions: 172 | - project: my_primary_project 173 | roles: 174 | - roles/editor 175 | - roles/bigquery.admin 176 | - type: gcp_user 177 | id: secondary_user 178 | ``` 179 | 180 | #### Valid types 181 | 182 | ##### GCP Project (gcp_project) 183 | 184 | attribute | required | type | notes 185 | ----------------------------- | -------- | ------- | -------------------------------------- 186 | dm_template.script | | path | Relative path to a Deployment Manager directory tree. 187 | dm_template.custom_properties | | array | Array of key/value pairs. 188 | fleet | | enum* | Specify a Qwiklabs fleet to pull the project from. 189 | 190 | ```yaml 191 | - type: gcp_project 192 | id: secondary_project 193 | fleet: gcpfree 194 | dm_template: 195 | script: deployment_manager 196 | custom_properties: 197 | - key: userNameWindows 198 | value: student 199 | ``` 200 | 201 | > **NOTE:** Not all GCP fleet names are supported. 202 | > 203 | > The existing concept of Qwiklabs' Fleets does not have a single analog in 204 | > content bundles. Notice that some fleet types map to resource types (e.g. 205 | > `gsuite_multi_tenant` fleet is now the `gsuite-domain` resource type). However 206 | > other fleets are "variants" of the same resource type (e.g. "free", "ASL", and 207 | > "standard" GCP projects). Therefore, not all fleet names that an experienced 208 | > Qwiklabs author may be familiar with, are allowed in the `fleet` field. 209 | > 210 | > Presently, authors are allowed to specify one of the following fleet types for 211 | > a gcp_project: 212 | > 213 | > * gcpd \[default\] 214 | > * gcpfree 215 | > * gcpasl 216 | > 217 | > Future versions of the Content Bundle spec may use different terminology for 218 | > resource_type variations to avoid conflation. 219 | 220 | ##### GCP User (gcp_user) 221 | 222 | attribute | required | type | notes 223 | ----------- | -------- | ---------- | ---------------------------------------- 224 | permissions | | array | Array of project/roles(array) pairs 225 | 226 | ```yaml 227 | - type: gcp_user 228 | id: primary_user 229 | permissions: 230 | - project: my_primary_project 231 | roles: 232 | - roles/editor 233 | - roles/bigquery.admin 234 | ``` 235 | 236 | ##### GSuite Domain (gsuite_domain) 237 | 238 | attribute | required | type | notes 239 | ----------- | -------- | ---------- | ---------------------------------------- 240 | No additional attributes 241 | 242 | ```yaml 243 | - type: gsuite_domain 244 | id: primary_domain 245 | ``` 246 | 247 | ##### Future Resource Types 248 | 249 | - AWS Account (aws-account) 250 | - iPython Notebook (ipython-notebook) 251 | 252 | > **NOTE:** A draft of the `aws-account` resource type was previously specified 253 | > in this document. See [previous version](https://github.com/CloudVLab/qwiklabs-content-bundle-spec/blob/93896ced4ae5b543132d7a10d838ac17bd5ae3e1/lab-bundle-spec.md) for details. 254 | 255 | ### Activity Tracking (Alpha) 256 | 257 | Activity tracking is a feature for evaluating a students performance in a lab by running a script at "checkpoints". These scripts can call APIs relevant to any environment resource to query their current state. For example, the script may inspect and validate the configuration of GCE instances running in `my-project`, to ensure the user is following the instructions properly. 258 | 259 | Lab bundles will provisionally support the JSON representation of Activity Tracking currently used in the Qwiklabs web interface. The JSON definition should be stored in file separately from (and referenced directly in) `qwiklabs.yaml`. 260 | 261 | ```yaml 262 | entity_type: Lab 263 | 264 | ... 265 | 266 | activity_tracking: ./assessment/activity_tracking.json 267 | ``` 268 | 269 | > **Note:** Support for this format should be considered deprecated. 270 | > 271 | > Further work will be done to define a new DSL for expressing Activity Tracking logic. Exploratory sketches of this DSL can be found in the `./examples` directory of this repository. 272 | -------------------------------------------------------------------------------- /classroom-template-bundle-spec.md: -------------------------------------------------------------------------------- 1 | # Qwiklabs ClassroomTemplate Bundle Specification 2 | 3 | **Version 1** 4 | 5 | > **Note: For Interim Use Only** 6 | > 7 | > This specification is for existing Qwiklabs platform users that are currently 8 | > using the `ClassroomTemplate` model. It should be used to help transition from 9 | > `ClassroomTemplates` to [`CourseTemplates`](./course-template-bundle-spec.md). 10 | > If you are not currently using `ClassroomTemplates`, please use 11 | > `CourseTemplates` instead. 12 | 13 | ## `qwiklabs.yaml` Structure 14 | 15 | Here's a sample `qwiklabs.yaml` file with all nested details removed to make it 16 | easier to see the general file structure. 17 | 18 | ```yaml 19 | entity_type: ClassroomTemplate 20 | schema_version: 1 21 | 22 | # ClassroomTemplate Attributes 23 | default_locale: en 24 | 25 | # Versions should be considered decorators, and are not used as a source of truth for revision history. 26 | version: 27 | locales: 28 | en: ver. 2 29 | 30 | # one of ["Self-paced", "Bootcamp/Workshop", "Instructor-led"] 31 | classroom_type: Instructor-led 32 | 33 | course_code: T-AHYXXX-I 34 | 35 | title: 36 | locales: 37 | en: Architecting with Google Cloud Platform. 38 | 39 | description: 40 | locales: 41 | en: Learn GCP basics in a classroom setting. 42 | 43 | objectives: 44 | locales: 45 | en: | 46 |

This course will teach people

47 |
    48 |
  • What GCP is
  • 49 |
  • How to use some of its core components
  • 50 |
51 | 52 | audience: 53 | locales: 54 | en: | 55 |

This course is intended for people who

56 |
  • Are new to GCP
57 | 58 | prerequisites: 59 | locales: 60 | en:

A basic understanding of serverless architecture is recommended but not required.

61 | 62 | # Outline is a JSON formatted string 63 | outline: 64 | locales: 65 | en: > 66 | {\"subhead\":\"The course includes presentations and hands-on labs.\",\"modules\":[{\"name\":\"Module 1: Anthos Overview\",\"items\":[\"Describe challenges of hybrid cloud\",\"Discuss modern solutions\",\"Describe the Anthos Technology Stack\"]}]} 67 | 68 | external_content_url: 69 | locales: 70 | en: "https://www.coursera.org/specializations/architecting-hybrid-cloud-infrastructure-anthos" 71 | 72 | tags: [sample, life-changing, gcp] 73 | product_tags: ['compute engine', 'cloud storage'] 74 | role_tags: ['cloud architect', 'developers backend'] 75 | domain_tags: ['infrastructure'] 76 | level: 1 77 | 78 | course_surveys: 79 | - my-library/new-cloud-training-survey-fayoci 80 | 81 | # Estimated time to take the course, in days 82 | estimated_duration_days: 1 83 | 84 | # Estimated time to take the course, in minutes 85 | estimated_duration: 60 86 | 87 | # Allow lab order to be changed by the trainer 88 | lock_activity_position: false 89 | 90 | # Trainers must stay within the limits 91 | max_hot_labs: 30 92 | 93 | # Enable DRM on instructions if supported 94 | enable_drm: false 95 | 96 | # Check classroom for fraud 97 | resource_limit_check: false 98 | 99 | # Classroom can be scheduled 100 | published: true 101 | 102 | # Instructions that will be surfaced to students 103 | student_resources: ... 104 | 105 | # Instructions that will not be surfaced to students, but may be referenced by an instructor 106 | instructor_resources: ... 107 | 108 | # The important part of a ClassroomTemplate which lists all of the labs 109 | modules: ... 110 | 111 | ``` 112 | 113 | Note that all of the main chunks of localized content (title, description, 114 | objectives, audience, prerequisites, etc.) are HTML content that may be 115 | displayed in various contexts. All of these chunks will be sanitized according 116 | to the restricted set in the [HTML spec](./html/html-spec.md). 117 | 118 | ### Attribute specification 119 | 120 | The full specification is as follows: 121 | 122 | attribute | required | type | notes 123 | ----------------------- | -------- | ---------- | ----- 124 | entity_type | ✓ | string | Must be `ClassroomTemplate` 125 | schema_version | ✓ | integer | 126 | default_locale | ✓ | enum | Must be a valid locale code 127 | version | | dictionary | Version string used as content decorator from default locale 128 | classroom_type | | enum | One of ["Self-paced", "Bootcamp/Workshop", "Instructor-led"] 129 | course_code | | string | Id for Course, e.g. T_AHYXXX-I, usually determined by Training Ops. Not the same as the Git "slug" 130 | title | ✓ | dictionary | A locale dictionary of titles 131 | description | ✓ | dictionary | A locale dictionary of descriptions 132 | objectives | | dictionary | A locale dictionary of objectives 133 | audience | | dictionary | A locale dictionary of audiences 134 | prerequisites | | dictionary | A locale dictionary of prerequisites 135 | outline | | dictionary | A locale dictionary of outline elements usually formatted as a JSON string 136 | external_content_url | | dictionary | A locale dictionary of URL's to Coursera (or other) external content 137 | tags | | array | Array of strings to be used as hints in searching, etc. 138 | product_tags | | array | Array of strings from the "Products" column in [this sheet](https://docs.google.com/spreadsheets/d/1hUUch85HBRsRJsgRo9VCg0Pn7ZXi21sl6JU7VOr9LP8) 139 | role_tags | | array | Array of strings from the "Roles" column in [this sheet](https://docs.google.com/spreadsheets/d/1hUUch85HBRsRJsgRo9VCg0Pn7ZXi21sl6JU7VOr9LP8) 140 | domain_tags | | array | Array of strings from the "Domain" column in [this sheet](https://docs.google.com/spreadsheets/d/1hUUch85HBRsRJsgRo9VCg0Pn7ZXi21sl6JU7VOr9LP8) 141 | level | | integer | Integer between 1 and 4, with 1 being the easiest 142 | course_surveys | | array | Array of course survey 'library/slugs' 143 | estimated_duration_days | | integer | Estimated time to take the course, in days 144 | estimated_duration | | integer | Estimated time to take the course, in minutes 145 | lock_activity_position | | boolean | Allow lab order to be changed by the trainer 146 | max_hot_labs | | integer | Maximum number of hot labs for this course. 147 | enable_drm | | boolean | Enable DRM on instructions if supported 148 | resource_limit_check | | boolean | Check classroom for fraud 149 | published | | boolean | Classroom can be scheduled 150 | student_resources | | array | Student-specific instructions. See the [Resource Spec](./resource-spec.md) for full specification. 151 | instructor_resources | | array | Instructor-specific instructions. See the [Resource Spec](./resource-spec.md) for full specification. 152 | modules | | array | See below 153 | 154 | ### Modules 155 | 156 | A `ClassroomTemplate` presents labs to the learner in a specific order. To keep 157 | some compatibility with other "bundle entities" we will use a simple collection 158 | of steps, each with one lab activity. 159 | 160 | attribute | required | type | notes 161 | --------- | -------- | ------ | ----------------------------------- 162 | id | ✓ | string | A unique identifier for this module 163 | steps | | array | See below 164 | 165 | ### Steps 166 | 167 | For a ClassroomTemplate, a step consists of one activity option. The valid 168 | activity type is: 169 | 170 | * `lab` 171 | 172 | Where `lab` references content defined elsewhere in the library. 173 | 174 | The overall format should look like: 175 | 176 | ```yaml 177 | steps: 178 | - id: intro-lab 179 | activity_options: 180 | - type: lab 181 | id: intro-to-gcp 182 | 183 | - id: learn-compute 184 | activity_options: 185 | - type: lab 186 | id: intro-to-appengine-python 187 | ``` 188 | 189 | The order in which steps are listed defines the order they will be displayed. 190 | -------------------------------------------------------------------------------- /course-template-bundle-spec.md: -------------------------------------------------------------------------------- 1 | # Qwiklabs CourseTemplate Bundle Specification 2 | 3 | **Version 1** 4 | 5 | > This is a DRAFT document. We welcome feedback as this format evolves. 6 | 7 | ## `qwiklabs.yaml` Structure 8 | 9 | Here's a sample `qwiklabs.yaml` file with all nested details removed to make it 10 | easier to see the general file structure. 11 | 12 | ```yaml 13 | entity_type: CourseTemplate 14 | schema_version: 1 15 | 16 | # CourseTemplate Attributes 17 | default_locale: en 18 | 19 | title: 20 | locales: 21 | en: GCP Intro Course 22 | 23 | description: 24 | locales: 25 | en: Get a taste of what GCP has to offer. 26 | 27 | # Versions should be considered decorators, and are not used as a source of truth for revision history. 28 | version: 29 | locales: 30 | en: 2 31 | es: 1 32 | 33 | auto_upgrade_to_latest_version: false 34 | 35 | objectives: 36 | locales: 37 | en: | 38 |

This course will teach people

39 |
    40 |
  • What GCP is
  • 41 |
  • How to use some of its core components
  • 42 |
43 | 44 | audience: 45 | locales: 46 | en: | 47 |

This course is intended for people who

48 |
  • Are new to GCP
49 | 50 | prerequisites: 51 | locales: 52 | en:

A basic understanding of serverless architecture is recommended but not required.

53 | 54 | course_surveys: 55 | - my-library/new-cloud-training-survey-fayoci 56 | 57 | # Resources that will not be surfaced to students, but may be referenced by an instructor 58 | instructor_resources: 59 | - title: 60 | locales: 61 | en: How to teach 62 | es: Como enseñar 63 | uri: 64 | locales: 65 | en: https://www.wikihow.com/Teach 66 | es: https://www.wikihow.es/enseñar 67 | 68 | skill_ids: [550e8400-e29b-41d4-a716-446655440000, 4ed161b5-0d3c-4f06-8381-5f14678e13da] 69 | tags: [sample, life-changing, gcp] 70 | product_tags: ['compute engine', 'cloud storage'] 71 | role_tags: ['cloud architect', 'developers backend'] 72 | domain_tags: ['infrastructure'] 73 | level: 1 74 | image: gcp-intro-course-image.png 75 | badge: gcp-intro-course-badge.png 76 | 77 | # Estimated time to take the course, in minutes 78 | # This value will be calculated automatically if it is not provided by the author 79 | estimated_duration_minutes: 0 80 | 81 | # Pseudo-deprecated legacy field that we would like to remove 82 | max_hot_labs: 30 83 | 84 | # Resources that may be referenced below in steps 85 | resources: ... 86 | 87 | # The important part of a CourseTemplate which lists all of the activities 88 | modules: 89 | - title: 90 | locales: 91 | en: What GCP is? 92 | es: ¿Qué es GCP? 93 | 94 | description: 95 | locales: 96 | en: Explains what is GCP 97 | es: Explica qué es GCP 98 | 99 | learning_objectives: 100 | locales: 101 | en: 102 | - Learn what is GCP 103 | - Identify what GCP offers 104 | es: 105 | - Más información sobre GCP 106 | - Identifica lo que ofrece GCP 107 | 108 | steps: 109 | ... 110 | 111 | ``` 112 | 113 | Note that all of the main chunks of localized content (title, description, 114 | objectives, audience, and prerequisites) are HTML content that may be displayed 115 | in various contexts. All of these chunks will be sanitized according to the 116 | restricted set in the [HTML spec](./html/html-spec.md). 117 | 118 | ### Attribute specification 119 | 120 | The full specification is as follows: 121 | 122 | attribute | required | type | notes 123 | ---------------------------------- | -------- | ---------- | ----- 124 | entity_type | ✓ | string | Must be `CourseTemplate` 125 | schema_version | ✓ | integer | 126 | default_locale | ✓ | enum | Must be a valid locale code 127 | title | ✓ | dictionary | A locale dictionary of titles 128 | description | ✓ | dictionary | A locale dictionary of descriptions 129 | version | | dictionary | A locale dictionary of version strings. These version strings should be considered decorators, and are not used as a source of truth for revision history. 130 | auto_upgrade_to_latest_version | | boolean | `true` if course enrollees should automatically be upgraded to the latest course version. Otherwise, they'll be asked if they want to upgrade when a new version is available. 131 | objectives | | dictionary | A locale dictionary of objectives 132 | audience | | dictionary | A locale dictionary of audiences 133 | prerequisites | | dictionary | A locale dictionary of prerequisites 134 | skill_ids | | array | Array of strings representing the skill ids of skills associated with a course built in Creator Suite. This field should be omitted if the course was not built in Creator Suite. 135 | tags | | array | Array of strings to be used as hints in searching, etc 136 | product_tags | | array | Array of strings from the "Products" column in [this sheet](https://docs.google.com/spreadsheets/d/1hUUch85HBRsRJsgRo9VCg0Pn7ZXi21sl6JU7VOr9LP8) 137 | role_tags | | array | Array of strings from the "Roles" column in [this sheet](https://docs.google.com/spreadsheets/d/1hUUch85HBRsRJsgRo9VCg0Pn7ZXi21sl6JU7VOr9LP8) 138 | domain_tags | | array | Array of strings from the "Domain" column in [this sheet](https://docs.google.com/spreadsheets/d/1hUUch85HBRsRJsgRo9VCg0Pn7ZXi21sl6JU7VOr9LP8) 139 | level | | integer | Integer between 1 and 4, with 1 being the easiest 140 | image | | string | Link to an image file to be used as the image for the course 141 | badge | | string | Link to an image file to be used as the badge for the course, at least 640px x 640px. 142 | estimated_duration_minutes | | integer | Estimated time to take the course, in minutes. This value will be calculated automatically if it is not provided by the author. 143 | max_hot_labs | | integer | Maximum number of hot labs for this course. Pseudo-deprecated legacy field that we would like to remove. 144 | course_surveys | | array | Array of course survey 'library/slug' 145 | instructor_resources | | array | Instructor-specific resources. Array of dictionaries with keys `title` and `uri` and values locale dictionaries. 146 | resources | | array | See [below](#resources) 147 | modules | ✓ | array | See [below](#modules) 148 | retake_policies | | array | See [below](#retake-policies) 149 | 150 | ### Modules 151 | 152 | The meat of a `CourseTemplate` is an ordered list of modules, each of which is a 153 | collection of steps, defining what a learner needs to do to complete the course. 154 | A module has a `title`, `description`, `learning_objectives`, and array of 155 | `steps`. The full specification is as follows: 156 | 157 | attribute | required | type | notes 158 | ------------------ | -------- | ---------- | ----------------------------------- 159 | id | ✓ | string | A unique identifier for this module 160 | title | ✓ | dictionary | A locale dictionary of titles 161 | description | | dictionary | A locale dictionary of descriptions 162 | steps | ✓ | array | See below 163 | learning_objectives| | dictionary | A locale dictionary of array of learning objectives 164 | ### Resources 165 | 166 | While heavyweight activities like labs and quizzes must be defined elsewhere in 167 | the library, we allow simpler resources to be specified directly in 168 | `qwiklabs.yaml`. They can then be referenced in the `steps` just like labs and 169 | quizzes. 170 | 171 | For details on how to specify resources, see the 172 | [Resource Spec](./resource-spec.md). 173 | 174 | ### Steps 175 | 176 | A step consists of a set of one or more activity options, along with some 177 | metadata. Valid activity types are: 178 | 179 | * `lab` 180 | * `challenge_lab` 181 | * `quiz` 182 | * `peer_assignment` 183 | * `resource` 184 | 185 | `lab`, `challenge_lab`, `quiz` and `peer_assignment` will reference content 186 | defined elsewhere in the library, and `resource` will reference content defined 187 | elsewhere in the same `qwiklabs.yaml` file. 188 | 189 | The overall format should look like: 190 | 191 | ```yaml 192 | steps: 193 | - id: overview-video 194 | activity_options: 195 | - type: resource 196 | id: intro-video 197 | prompt: 198 | locales: 199 | en: If you've never used GCP, we recommend this overview video. 200 | optional: true 201 | 202 | - id: intro-lab 203 | activity_options: 204 | - type: lab 205 | id: intro-to-gcp 206 | 207 | - id: choosing-compute 208 | activity_options: 209 | - type: resource 210 | id: choosing-compute 211 | 212 | - id: learn-compute 213 | activity_options: 214 | - type: lab 215 | id: intro-to-appengine-python 216 | - type: lab 217 | id: intro-to-kubernetes-engine 218 | - type: lab 219 | id: intro-to-cloud-functions 220 | prompt: 221 | locales: 222 | en: Learn more about one of these common compute resources. 223 | 224 | - id: compute-quiz 225 | activity_options: 226 | - type: quiz 227 | category: graded 228 | id: compute-quiz 229 | version: '1.0' 230 | 231 | - id: peer-assignment 232 | activity_options: 233 | - type: peer_assignment 234 | id: peer-assignment 235 | 236 | - id: challenge-lab 237 | activity_options: 238 | - type: challenge_lab 239 | id: challenge-lab 240 | ``` 241 | 242 | The order in which steps are listed defines the order they will be displayed. 243 | When a step has multiple options, the learner will be expected to do exactly one 244 | of the activities. 245 | 246 | The full specification for a step is as follows: 247 | 248 | attribute | required | type | notes 249 | ---------------- | -------- | ---------- | ----- 250 | id | ✓ | string | A unique identifier for this step 251 | activity_options | ✓ | array | `activity_options` is an array of dictionaries with the format: 252 | -- type | ✓ | enum | One of `lab`, `challenge_lab`, `quiz`, `resource`, `peer_assignment` 253 | -- category | | string | A subordinate descriptor for an activity of the above `type` used in the context of retakes to indicate the applicable retake policy. 254 | -- id | ✓ | string | Reference to the unique identifier for the activity - `library/slug`. 255 | -- version | | string | Reference to the semantic version of the activity to which the course step should be frozen. 256 | prompt | | dictionary | Key is `locales` and each locale is a dictionary mapping locale codes to a prompt describing the step 257 | optional | | boolean | `true` if the step is *not* required for completion 258 | 259 | ### Retake Policies 260 | 261 | A retake policy defines any required cooldown periods, retake limits, and retake 262 | windows applicable to a given `CourseTemplate` activity. 263 | 264 | The overall format should look like: 265 | 266 | ```yaml 267 | retake_policies: 268 | - id: default-lab-policy 269 | activity_type: Lab 270 | retake_cooldown: 271 | - 1 272 | - 2 273 | - 5 274 | 275 | - id: practice-quiz-policy 276 | activity_type: Quiz 277 | activity_category: practice 278 | retake_limit: 3 279 | retake_window: 1 280 | 281 | - id: graded-quiz-policy 282 | activity_type: Quiz 283 | activity_category: graded 284 | retake_cooldown: 285 | - 1 286 | retake_limit: 3 287 | retake_window: 1 288 | ``` 289 | 290 | attribute | required | type | notes 291 | ----------------- | -------- | ------- | ----- 292 | activity_type | ✓ | enum | The type of retakeable activity to which this retake policy applies; one of `Lab` or `Quiz` 293 | activity_category | | string | Distinguishes a subset of a given type of retakeable activity to which this retake policy applies (e.g. `graded` for quiz); category must match one of the categories given on a retakeable activity 294 | retake_cooldown | | array | An array of `n` integers (greater than or equal to 0) specifying the required cooldown periods (in days) between consequent retakes; the last integer will be the cooldown period for all retakes after the `nth`; For example, a retake_cooldown of `[1, 2, 5]` would require a student to wait 1 day before their 1st retake, 2 days between their 1st and 2nd retakes, and 3 days between their 2nd and 3rd retakes, 3rd and 4th retakes, and so on. If a student has waited for the appropriate coooldown period, they will only be allowed to retake the activity given they have not exceeded any retake limit. 295 | retake_limit | | integer | The total number of attempts (greater than 0) allowed for the given type and subtype of retakeable activity; required if `retake_window` below is specified. For example, a retake_limit of `3` would indicate a student will *not* be allowed to retake the activity after a total of 3 attempts. If a student is within the retake_limit, they will only be allowed to retake the activity given they have waited for the appropriate cooldown period. 296 | retake_window | | integer | An integer (greater than 0) specifying the period (in days) for which the `retake_limit` above applies. For example, a retake_limit of `3` paired with a retake_window of `1` would indicate a student can retake the activity as long as no more than 3 attempts are made within a 1 day period. 297 | -------------------------------------------------------------------------------- /exam-bundle-spec.md: -------------------------------------------------------------------------------- 1 | # Qwiklabs Exam Bundle Specification 2 | 3 | **Version 1** 4 | 5 | > This is a DRAFT document. We welcome feedback as this format evolves. 6 | 7 | ## `qwiklabs.yaml` Structure 8 | 9 | Here's a sample `qwiklabs.yaml` file with all nested details removed to make it 10 | easier to see the general file structure. 11 | 12 | ```yaml 13 | entity_type: Exam 14 | schema_version: 1 15 | 16 | passing_percentage: 67 17 | default_locale: en 18 | duration: 120 19 | randomize_items: true 20 | randomize_options: true 21 | randomize_prompts: true 22 | retake_cooldown: 23 | - 1 24 | - 7 25 | 26 | title: 27 | locales: 28 | en: My Excellent Exam 29 | 30 | forms: ... 31 | ``` 32 | 33 | Note that all of the localized content (stem, option titles, etc) are HTML 34 | content that may be displayed in various contexts. All of these chunks will be 35 | sanitized according to the restricted set in the 36 | [HTML spec](./html/html-spec.md). 37 | 38 | ### Exam attributes 39 | 40 | attribute | required | type | notes 41 | ------------------ | -------- | ---------- | ----- 42 | default_locale | ✓ | string | Corresponds to the locale that the exam is authored in. Authoring tools can use this as a hint to notify localizers when content in the default locale is updated. Also, it provides a hint to the learner interface about which locale to display if an instruction/resource is not localized for the learner's current locale. 43 | schema_version | ✓ | integer | Which version of the exam bundle schema you are using 44 | title | | dictionary | A locale dictionary of the exam title, such as "My Excellent Exam" 45 | introduction | | dictionary | A locale dictionary of the exam introduction to show before a student starts the exam. May include a description, any terms and conditions, instructions, etc. 46 | passing_percentage | ✓ | integer | The threshold grade that a student needs to achieve in order to count as "passing" the exam. 47 | duration | ✓ | integer | The maximum time a student is allotted for the exam, in minutes. 48 | randomize_items | ✓ | boolean | Whether `items` in `forms` should be presented in a random order; `true` by default 49 | randomize_options | ✓ | boolean | Whether `options` in `items` should be presented in a random order; `true` by default 50 | randomize_prompts | ✓ | boolean | Whether `prompts` in `match items` should be presented in a random order; `true` by default 51 | show_score | | boolean | Whether to show student areas for study if failed exam; `false` by default 52 | retake_cooldown | ✓ | array | An array of `n` number of days specifying the cooldown period between retakes; the last number will be the cooldown period for all retakes after the `nth` 53 | forms | ✓ | array | An array of `forms` (see below for details) 54 | 55 | ### Forms 56 | 57 | Forms are versions of an exam. An exam may have multiple forms (i.e. A and B), 58 | where A and B will have a different collection of items. One student taking an 59 | exam may get form A, and another form B, but both students are considered to be 60 | taking "equivalent" exams. 61 | 62 | ```yaml 63 | id: form-0 64 | name: FormA 65 | sections: ... 66 | ``` 67 | 68 | attribute | required | type | notes 69 | --------- | -------- | ------ | ----- 70 | id | ✓ | string | A unique identifier for this form, to be consistent across revisions 71 | name | ✓ | string | A name for this form 72 | sections | ✓ | array | An ordered array of `sections` (see below for details) in this form 73 | 74 | ### Sections 75 | 76 | Sections are groupings of related exam items. 77 | 78 | ```yaml 79 | name: Networking 80 | items: ... 81 | ``` 82 | 83 | attribute | required | type | notes 84 | --------- | -------- | ------ | ----- 85 | name | ✓ | string | A name for this section 86 | items | ✓ | array | An ordered array of `items` (see below for details) in this section 87 | 88 | ### Items 89 | 90 | Items are polymorphic - i.e. there are several different _item types_ that are 91 | defined slightly differently. `items` is an array of dictionaries with 92 | appropriate attributes for the given `type`. The allowed values for `type` are: 93 | 94 | * `multiple-choice` 95 | * `multiple-select` 96 | * `match` 97 | 98 | #### multiple-choice Items 99 | 100 | An exam item that has multiple options and one answer. One option is the 101 | _answer_, and the rest are _distractors_. There must be exactly one answer. 102 | 103 | attribute | required | type | notes 104 | --------- | -------- | ---------- | ----- 105 | id | ✓ | string | A unique identifier for this item 106 | type | ✓ | string | The item type, which is always `multiple-choice` 107 | stem | ✓ | dictionary | A locale dictionary of the text that asks the question, such as "Which of the following is a color?" 108 | options | ✓ | array | An array of `options` (see below for details); order does not matter 109 | seed | ✓ | boolean | `true` if this item is not to be graded; `false` by default 110 | code | | string | A unique identifier for this item generated by and for the item author 111 | 112 | #### multiple-select Items 113 | 114 | An exam item that has multiple options, any number of which are answers. Correct 115 | options are _answers_, and incorrect options are _distractors_. 116 | 117 | attribute | required | type | notes 118 | --------- | -------- | ---------- | ----- 119 | id | ✓ | string | A unique identifier for this item 120 | type | ✓ | string | The item type, which is always `multiple-select` 121 | stem | ✓ | dictionary | A locale dictionary for the text that asks the question, such as "Which of the following is a color?" 122 | options | ✓ | array | An array of `options` (see below for details); order does not matter 123 | seed | ✓ | boolean | `true` if this item is not to be graded; `false` by default 124 | code | | string | A unique identifier for this item generated by and for the item author 125 | 126 | #### match Items 127 | 128 | An exam item that has multiple stems with a "lead in" prompt. The correct option 129 | for each matching stem is directly specified as the answer. A match item will be 130 | scored based on correctly matching all the stems. 131 | 132 | attribute | required | type | notes 133 | --------- | -------- | ---------- | ----- 134 | id | ✓ | string | A unique identifier for this item 135 | type | ✓ | string | The item type, which is always `match` 136 | lead_in | ✓ | dictionary | A locale dictionary of text that provides a lead-in, such as "Can You Match the Capital City to the Correct US State?" 137 | stems | ✓ | array | An array of `matching stems` (see below for details); order does not matter 138 | options | ✓ | array | An array of `options` (see below for details); order does not matter 139 | seed | ✓ | boolean | `true` if this item is not to be graded; `false` by default 140 | code | | string | A unique identifier for this item generated by and for the item author 141 | 142 | #### matching Stems 143 | 144 | Match items need an additional stems array which contains the question(s) for 145 | which the user must provide the matching answer. 146 | 147 | attribute | required | type | notes 148 | --------- | -------- | ---------- | ----- 149 | id | ✓ | string | A unique ID for this match Stem 150 | title | ✓ | dictionary | A locale dictionary for the content of this stem, such as "Springfield" 151 | answer | ✓ | string | ID for option that is the answer for this stem 152 | 153 | ### Option 154 | 155 | `multiple-choice` and `multiple-select`, and `match` items all have an `options` 156 | array which contains all of the answer(s) and distractors that the user may 157 | choose from. Options are defined for both item types below: 158 | 159 | attribute | required | type | notes 160 | --------- | -------- | ---------- | ----- 161 | id | ✓ | string | A unique ID for this Option 162 | title | ✓ | dictionary | A locale dictionary for the content of this option, such as "Blue" 163 | is_answer | ✓ | boolean | `true` if this option is an answer, and `false` if it is a distractor (not used for `match` type) 164 | -------------------------------------------------------------------------------- /examples/course-templates-robust/qwiklabs.es.yaml: -------------------------------------------------------------------------------- 1 | # qwiklabs.es.yaml for Spanish localization 2 | # There is no need to copy everything over from qwiklabs.yaml. 3 | # Only locale specific attributes need to go in here. 4 | 5 | title: Curso de introducción a GCP 6 | 7 | description: Prueba lo que GCP tiene para ofrecer. 8 | 9 | version: v1 final 10 | 11 | objectives: | 12 |

Este curso enseñará a las personas

13 |
    14 |
  • Qué es GCP
  • 15 |
  • Cómo usar algunos de sus componentes principales
  • 16 |
17 | 18 | audience: | 19 |

Este curso está destinado a personas que

20 |
  • Son nuevas en GCP
21 | 22 | prerequisites:

Se recomienda una comprensión básica de la arquitectura sin servidor, pero no es obligatorio.

23 | 24 | instructor_resources: 25 | - id: how-to-teach 26 | title: Como enseñar 27 | uri: https://www.wikihow.es/enseñar 28 | 29 | - id: how-to-teach-well 30 | title: Como enseñar bien 31 | uri: https://www.wikihow.com/TeachingWell 32 | 33 | resources: 34 | - type: video 35 | id: intro-video 36 | title: ¡Bienvenido a GCP! 37 | video_id: 7jjoyy7_RCk 38 | description: Descripción general de Google Cloud Platform 39 | - type: video 40 | id: outro-video 41 | title: Eso fue divertido, ¿verdad? 42 | video_id: 7jjoyy7_RCk 43 | - type: link 44 | id: choosing-compute 45 | title: Elegir una opción de cómputo 46 | uri: https://cloud.google.com/docs/choosing-a-compute-option 47 | - type: file 48 | id: storage-options 49 | title: Opciones de Almacenamiento 50 | uri: resources/storage_options_es.pdf 51 | 52 | modules: 53 | - id: intro-module 54 | title: Introducción 55 | description: Algo de material introductorio 56 | learning_objectives: 57 | - Objetivo para el módulo de introducción 58 | steps: 59 | - id: intro-video 60 | prompt: Si nunca ha usado GCP, le recomendamos este video general. 61 | 62 | - id: learn-compute 63 | title: Aprender acerca de la computadora 64 | learning_objectives: 65 | - Objetivo para el módulo de aprendizaje 66 | steps: 67 | - id: learn-compute 68 | prompt: Obtenga más información sobre uno de estos recursos informáticos comunes. 69 | - id: learn-storage 70 | title: Aprende sobre almacenamiento 71 | learning_objectives: 72 | - Objetivo para el almacenamiento de información 73 | steps: 74 | - id: learn-storage 75 | prompt: Obtenga más información sobre una de estas tecnologías de base de datos comunes. 76 | 77 | - id: outro-module 78 | title: Termina 79 | learning_objectives: 80 | - Objetivo para módulo outro 81 | steps: 82 | - id: advanced-gcp-task 83 | prompt: Si quieres probar suerte en esta tarea avanzada, ¡hazlo! 84 | -------------------------------------------------------------------------------- /examples/course-templates-robust/qwiklabs.yaml: -------------------------------------------------------------------------------- 1 | entity_type: CourseTemplate 2 | schema_version: 1 3 | 4 | # CourseTemplate Attributes 5 | default_locale: en 6 | 7 | title: GCP Intro Course 8 | 9 | description: Get a taste of what GCP has to offer. 10 | 11 | version: v2.3 12 | 13 | auto_upgrade_to_latest_version: true 14 | 15 | objectives: | 16 |

This course will teach people

17 |
    18 |
  • What GCP is
  • 19 |
  • How to use some of its core components
  • 20 |
21 | 22 | audience: | 23 |

This course is intended for people who

24 |
  • Are new to GCP
25 | 26 | prerequisites:

A basic understanding of serverless architecture is recommended but not required.

27 | 28 | tags: [sample, life-changing, gcp] 29 | product_tags: ['app engine', 'kubernetes engine', 'cloud functions', 'cloud datastore', 'cloud sql', 'spanner', 'bigquery'] 30 | role_tags: ['cloud architect', 'developers backend', 'developers frontend', 'database admin'] 31 | domain_tags: ['infrastructure', 'application development', 'data'] 32 | level: 3 33 | image: gcp-intro-course-image.png 34 | badge: gcp-intro-course-badge.png 35 | 36 | estimated_duration_minutes: 60 37 | 38 | instructor_resources: 39 | - id: how-to-teach 40 | title: How to teach 41 | uri: https://www.wikihow.com/Teach 42 | 43 | - id: how-to-teach-well 44 | title: How to teach well 45 | uri: https://www.wikihow.com/TeachingWell 46 | 47 | resources: 48 | - type: video 49 | id: intro-video 50 | title: Welcome to GCP! 51 | video_id: oHg5SJYRHA0 52 | video_provider: YouTube 53 | description: Overview of Google Cloud Platform 54 | duration: 360 55 | - type: video 56 | id: outro-video 57 | title: Wasn't that fun?! 58 | video_id: oHg5SJYRHA0 59 | video_provider: YouTube 60 | duration: 100 61 | - type: link 62 | id: choosing-compute 63 | title: Choosing a Compute Option 64 | uri: https://cloud.google.com/docs/choosing-a-compute-option 65 | - type: file 66 | id: storage-options 67 | title: Storage Options 68 | uri: resources/storage_options_en.pdf 69 | - type: html_bundle 70 | id: google-threat-intelligence 71 | title: Google Threat Intelligence 72 | uri: https://storage.googleapis.com/cloud-training/cls-html5-courses/C-GTI-I/index.html 73 | 74 | course_surveys: 75 | - survey-f59d1335-ul5lc0 76 | - survey-ul5lc0 77 | - survey-f59d1335 78 | 79 | modules: 80 | - id: intro-module 81 | title: Introduction 82 | description: Some introductory material 83 | learning_objectives: 84 | - Objective for intro module 85 | steps: 86 | - id: intro-video 87 | activity_options: 88 | - type: resource 89 | id: intro-video 90 | prompt: If you've never used GCP, we recommend this overview video. 91 | optional: true 92 | 93 | - id: intro-lab 94 | activity_options: 95 | - type: lab 96 | id: intro-to-gcp 97 | 98 | - id: learn-compute 99 | title: Learn about compute 100 | learning_objectives: 101 | - Objective for learn module 102 | steps: 103 | - id: choose-compute 104 | activity_options: 105 | - type: resource 106 | id: choosing-compute 107 | 108 | - id: learn-compute 109 | activity_options: 110 | - type: lab 111 | id: intro-to-appengine-python 112 | - type: lab 113 | id: intro-to-kubernetes-engine 114 | - type: lab 115 | id: intro-to-cloud-functions 116 | prompt: Learn more about one of these common compute resources. 117 | - id: learn-storage 118 | title: Learn about storage 119 | learning_objectives: 120 | - Objective for learn module 121 | steps: 122 | - id: storage-options 123 | activity_options: 124 | - type: resource 125 | id: storage-options 126 | 127 | - id: google-threat-intelligence 128 | activity_options: 129 | - type: resource 130 | id: google-threat-intelligence 131 | 132 | - id: learn-storage 133 | activity_options: 134 | - type: lab 135 | id: intro-to-datastore 136 | - type: lab 137 | id: intro-to-cloudsql 138 | - type: lab 139 | id: intro-to-spanner 140 | prompt: Learn more about one of these common database technologies. 141 | 142 | - id: intro-to-bigquery 143 | activity_options: 144 | - type: lab 145 | id: intro-to-bigquery 146 | 147 | - id: bigquery-quiz 148 | activity_options: 149 | - type: quiz 150 | id: bigquery-quiz 151 | category: graded 152 | version: '1.0' 153 | 154 | - id: peer-assignment 155 | activity_options: 156 | - type: peer_assignment 157 | id: peer-assignment 158 | 159 | - id: outro-module 160 | title: Finish up 161 | learning_objectives: 162 | - Objective for outro module 163 | steps: 164 | - id: advanced-gcp-task 165 | activity_options: 166 | - type: lab 167 | id: advanced-gcp-task 168 | optional: true 169 | prompt: If you want to try your hand at this advanced task, go for it! 170 | 171 | - id: outro-video 172 | activity_options: 173 | - type: resource 174 | id: outro-video 175 | 176 | retake_policies: 177 | - id: practice-quiz-policy 178 | activity_type: 'Quiz' 179 | activity_category: 'practice' 180 | retake_limit: 3 181 | retake_window: 1 182 | - id: graded-quiz-policy 183 | activity_type: 'Quiz' 184 | activity_category: 'graded' 185 | retake_cooldown: 186 | - 1 187 | retake_limit: 3 188 | retake_window: 1 189 | - id: default-lab-policy 190 | activity_type: 'Lab' 191 | retake_cooldown: 192 | - 1 193 | - 2 194 | - 5 195 | -------------------------------------------------------------------------------- /examples/lab-robust/v2/assessments/step_one_check.rb: -------------------------------------------------------------------------------- 1 | def step_one_check(handles:, maximum_score:, resources:) 2 | storage_handle = handles['primary_project.StorageV1'] 3 | raise 'Invalid handle' if storage_handle.nil? 4 | # Check for bucket, stubbed for testing 5 | found_bucket = true 6 | unless found_bucket 7 | return { score: 0, message: 'bucket is missing' ,student_message: 'bucket_missing' } 8 | end 9 | # Check bucket configuration, stubbed for testing 10 | bucket_configured_correctly = true 11 | unless bucket_configured_correctly 12 | return { score: 2, message: 'bucket is misconfigured', student_message: 'bucket_misconfigured' } 13 | end 14 | { score: max_score, message: 'step completed', student_message: 'success' } 15 | end 16 | -------------------------------------------------------------------------------- /examples/lab-robust/v2/cleanup/qwiklabs.jinja: -------------------------------------------------------------------------------- 1 | resources: 2 | - name: good-vm 3 | type: vm-type.jinja 4 | properties: 5 | zone: {{ properties["zone"] }} 6 | -------------------------------------------------------------------------------- /examples/lab-robust/v2/cleanup/vm-type.jinja: -------------------------------------------------------------------------------- 1 | resources: 2 | - name: name-of-instance 3 | type: compute.v1.instance 4 | properties: 5 | zone: us-central1-c 6 | machineType: https://www.googleapis.com/compute/v1/projects/{{ env["project"] }}/zones/{{ properties["zone"] }}/machineTypes/n1-standard-1 7 | disks: 8 | - deviceName: boot 9 | type: PERSISTENT 10 | boot: true 11 | autoDelete: true 12 | initializeParams: 13 | sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/family/debian-9 14 | networkInterfaces: 15 | - network: https://www.googleapis.com/compute/v1/projects/{{ env["project"] }}/global/networks/default 16 | accessConfigs: 17 | - name: External NAT 18 | type: ONE_TO_ONE_NAT 19 | -------------------------------------------------------------------------------- /examples/lab-robust/v2/iam_policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Action": [ 6 | "iam:List*", 7 | "iam:Get*", 8 | "CloudFormation:*", 9 | "ec2:Get*", 10 | "ec2:List*", 11 | "ec2:Describe*" 12 | ], 13 | "Sid": "Stmt1505156866464", 14 | "Resource": "*", 15 | "Effect": "Allow" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /examples/lab-robust/v2/instructions/en.html: -------------------------------------------------------------------------------- 1 |

Robust Lab Example

2 | 3 |

Step 1: Take lab

4 |

We’ve given you a GCP resource. Go ahead and play around with it.

5 | 6 |

Step 2: …

7 |

8 |

9 | 10 |

Step 3: Profit

11 |

Huzzah! You’re ready to take on the world!

12 | -------------------------------------------------------------------------------- /examples/lab-robust/v2/instructions/es.html: -------------------------------------------------------------------------------- 1 |

Ejemplo de Robust Lab

2 |

Paso 1: tomar laboratorio

3 |

Le hemos proporcionado un recurso GCP. Adelante y juega con eso.

4 |

Paso 2: …

5 |

6 |

Paso 3: Ganancia

7 |

¡Huzzah! ¡Estás listo para enfrentarte al mundo!

8 | -------------------------------------------------------------------------------- /examples/lab-robust/v2/lab.template: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Description: 'AWS Test Bundle' 3 | Outputs: 4 | InstanceId: 5 | Value: !Ref 'Ec2Server' 6 | Parameters: 7 | KeyName: 8 | Description: Name of an existing EC2 KeyPair 9 | Type: String 10 | Bucket: 11 | Default: aws-training 12 | Description: Bucket for staged assets. 13 | Type: String 14 | Prefix: 15 | Default: spl66-intro-iam/ 16 | Description: Prefix for staged assets. 17 | Type: String 18 | PublicSubnet1Param: 19 | Description: Public Subnet 1 20 | Type: String 21 | Default: 10.1.11.0/24 22 | AllowedValues: 23 | - 10.1.11.0/24 24 | VPCCIDR: 25 | Description: CIDR Block for VPC 26 | Type: String 27 | Default: 10.1.0.0/16 28 | AllowedValues: 29 | - 10.1.0.0/16 30 | InstanceType: 31 | Default: t2.micro 32 | Description: EC2 instance type, e.g. m1.small, m1.large, etc. 33 | Type: String 34 | AmazonLinuxAMIID: 35 | Type: AWS::SSM::Parameter::Value 36 | Default: /aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-gp2 37 | 38 | Resources: 39 | VPC: 40 | Type: AWS::EC2::VPC 41 | Properties: 42 | CidrBlock: !Ref 'VPCCIDR' 43 | EnableDnsSupport: 'true' 44 | EnableDnsHostnames: 'true' 45 | Tags: 46 | - Key: Name 47 | Value: Lab VPC 48 | InternetGateway: 49 | Type: AWS::EC2::InternetGateway 50 | DependsOn: VPC 51 | AttachGateway: 52 | Type: AWS::EC2::VPCGatewayAttachment 53 | DependsOn: 54 | - VPC 55 | - InternetGateway 56 | Properties: 57 | VpcId: !Ref 'VPC' 58 | InternetGatewayId: !Ref 'InternetGateway' 59 | PublicSubnet1: 60 | Type: AWS::EC2::Subnet 61 | DependsOn: AttachGateway 62 | Properties: 63 | VpcId: !Ref 'VPC' 64 | MapPublicIpOnLaunch: 'true' 65 | CidrBlock: !Ref 'PublicSubnet1Param' 66 | AvailabilityZone: !Select 67 | - '0' 68 | - !GetAZs '' 69 | Tags: 70 | - Key: Name 71 | Value: Public Subnet 1 72 | PublicRouteTable: 73 | Type: AWS::EC2::RouteTable 74 | DependsOn: 75 | - VPC 76 | - AttachGateway 77 | Properties: 78 | VpcId: !Ref 'VPC' 79 | Tags: 80 | - Key: Name 81 | Value: Public 82 | PublicRoute: 83 | Type: AWS::EC2::Route 84 | DependsOn: 85 | - PublicRouteTable 86 | - AttachGateway 87 | Properties: 88 | RouteTableId: !Ref 'PublicRouteTable' 89 | DestinationCidrBlock: '0.0.0.0/0' 90 | GatewayId: !Ref 'InternetGateway' 91 | PublicSubnet1RouteTableAssociation: 92 | Type: AWS::EC2::SubnetRouteTableAssociation 93 | DependsOn: 94 | - PublicRouteTable 95 | - PublicSubnet1 96 | - AttachGateway 97 | Properties: 98 | SubnetId: !Ref 'PublicSubnet1' 99 | RouteTableId: !Ref 'PublicRouteTable' 100 | Ec2Server: 101 | Type: AWS::EC2::Instance 102 | Properties: 103 | ImageId: !Ref AmazonLinuxAMIID 104 | InstanceType: !Ref 'InstanceType' 105 | SecurityGroupIds: 106 | - !Ref 'Ec2SecurityGroup' 107 | SubnetId: !Ref 'PublicSubnet1' 108 | Ec2SecurityGroup: 109 | Type: AWS::EC2::SecurityGroup 110 | Properties: 111 | GroupDescription: VPC Security Group 112 | VpcId: !Ref 'VPC' 113 | SecurityGroupIngress: 114 | - CidrIp: '0.0.0.0/0' 115 | FromPort: '22' 116 | IpProtocol: tcp 117 | ToPort: '22' 118 | S3Bucket: 119 | Type: AWS::S3::Bucket 120 | user1: 121 | Type: AWS::IAM::User 122 | Properties: 123 | Path: /spl66/ 124 | UserName: user-1 125 | LoginProfile: 126 | Password: lab-password 127 | user2: 128 | Type: AWS::IAM::User 129 | Properties: 130 | Path: /spl66/ 131 | UserName: user-2 132 | LoginProfile: 133 | Password: lab-password 134 | user3: 135 | Type: AWS::IAM::User 136 | Properties: 137 | Path: /spl66/ 138 | UserName: user-3 139 | LoginProfile: 140 | Password: lab-password 141 | S3support: 142 | Type: AWS::IAM::Group 143 | Properties: 144 | Path: /spl66/ 145 | GroupName: S3-Support 146 | ManagedPolicyArns: 147 | - arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess 148 | EC2admin: 149 | Type: AWS::IAM::Group 150 | Properties: 151 | Path: /spl66/ 152 | GroupName: EC2-Admin 153 | Policies: 154 | - PolicyName: EC2-Admin-Policy 155 | PolicyDocument: 156 | Version: '2012-10-17' 157 | Statement: 158 | - Effect: Allow 159 | Action: 160 | - ec2:Describe* 161 | - ec2:StartInstances 162 | - ec2:StopInstances 163 | Resource: 164 | - '*' 165 | EC2support: 166 | Type: AWS::IAM::Group 167 | Properties: 168 | Path: /spl66/ 169 | GroupName: EC2-Support 170 | ManagedPolicyArns: 171 | - arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess 172 | -------------------------------------------------------------------------------- /examples/lab-robust/v2/qwiklabs.es.yaml: -------------------------------------------------------------------------------- 1 | # qwiklabs.es.yaml for Spanish localization 2 | # There is no need to copy everything over from qwiklabs.yaml. 3 | # Only locale specific attributes need to go in here. 4 | 5 | title: Ejemplo de Robust Lab 6 | description: En serio, el mejor lab que has tomado. Sin excepción. 7 | 8 | resources: 9 | - type: file 10 | id: sample-pdf 11 | title: Ejemplo de PDF 12 | description: Este PDF contiene todos los ejemplos de código para el laboratorio. 13 | uri: resources/sample-es.pdf 14 | - type: video 15 | id: intro-video 16 | title: ¡Bienvenido a GCP! 17 | uri: https://www.youtu.be/7jjoyy7_RCk 18 | description: Descripción general de Google Cloud Platform 19 | 20 | environment: 21 | student_visible_outputs: 22 | - label: Abra la consola de GCP 23 | reference: primary_project.console_url 24 | - label: Proyecto GCP 25 | reference: primary_project.project_id 26 | - label: Nombre de usuario de GCP 27 | reference: primary_user.username 28 | - label: Contraseña de GCP 29 | reference: primary_user.password 30 | - label: InstanceDns 31 | reference: primary_project.startup_script.InstanceDns 32 | - label: Número de cuenta de AWS 33 | reference: the_account.account_number 34 | - label: nombre de usuario 35 | reference: the_account.username 36 | - label: clave 37 | reference: the_account.password 38 | - label: URL de la consola de AWS 39 | reference: the_account.console_url 40 | 41 | assessment: 42 | steps: 43 | - title: Crear un depósito de almacenamiento en la nube 44 | locale_id: create_bucket 45 | student_messages: 46 | success: ¡Gran trabajo! ¡Creaste el cubo! 47 | bucket_missing: ¡Uy! No se ha encontrado el cubo. 48 | bucket_misconfigured: Hmm. El cubo está allí, pero está mal configurado. 49 | -------------------------------------------------------------------------------- /examples/lab-robust/v2/qwiklabs.yaml: -------------------------------------------------------------------------------- 1 | schema_version: 2 2 | entity_type: Lab 3 | 4 | title: Robust Lab Example 5 | description: Seriously the best lab you've ever taken. Bar none. 6 | default_locale: en 7 | duration: 60 8 | level: easy 9 | tags: 10 | - sample 11 | - life-changing 12 | - gcp 13 | 14 | resources: 15 | - type: file 16 | id: sample-pdf 17 | title: Sample PDF 18 | description: This PDF contains all of the code samples for the lab. 19 | uri: resources/sample-en.pdf 20 | - type: video 21 | id: intro-video 22 | title: Welcome to GCP! 23 | uri: https://www.youtu.be/oHg5SJYRHA0 24 | description: Overview of Google Cloud Platform 25 | 26 | environment: 27 | resources: 28 | - type: gcp_folder 29 | id: primary_folder 30 | - type: gcp_project 31 | id: primary_project 32 | parent: primary_folder 33 | variant: gcpd 34 | ssh_key_user: primary_user 35 | startup_script: 36 | type: deployment_manager 37 | path: ./startup 38 | custom_properties: 39 | - key: userNameWindows 40 | value: student 41 | - key: userName 42 | reference: primary_user.local_username 43 | - key: userPassword 44 | reference: primary_user.password 45 | - key: sshPubKey 46 | reference: primary_user.public_key 47 | cleanup_script: 48 | type: deployment_manager 49 | path: ./cleanup 50 | custom_properties: 51 | - key: primary_project_zone 52 | reference: primary_project.default_zone 53 | - key: folder_name 54 | reference: primary_folder.display_name 55 | allowed_locations: 56 | - us-central1-a 57 | - type: gcp_user 58 | id: primary_user 59 | permissions: 60 | - project: primary_project 61 | roles: 62 | - roles/editor 63 | - roles/appengine.appAdmin 64 | - roles/bigquery.admin 65 | - roles/bigquery.user 66 | - folder: primary_folder 67 | roles: 68 | - roles/compute.xpnAdmin 69 | - type: aws_account 70 | id: the_account 71 | variant: aws_vpc 72 | startup_script: 73 | type: cloud_formation 74 | path: ./lab.template 75 | user_policy: ./iam_policy.json 76 | account_restrictions: 77 | allow_spot_instances: true 78 | allow_subnet_deletion: false 79 | allow_vpc_deletion: false 80 | allowed_rds_instances: ['db.t2.micro'] 81 | allowed_locations: ['us-east-1', 'us-central-1'] 82 | student_visible_outputs: 83 | - label: Open GCP Console 84 | reference: primary_project.console_url 85 | - label: GCP Project 86 | reference: primary_project.project_id 87 | - label: GCP Username 88 | reference: primary_user.username 89 | - label: GCP Password 90 | reference: primary_user.password 91 | - label: InstanceDns 92 | reference: primary_project.startup_script.InstanceDns 93 | - label: AWS Account Number 94 | reference: the_account.account_number 95 | - label: Username 96 | reference: the_account.username 97 | - label: password 98 | reference: the_account.password 99 | - label: AWS Console URL 100 | reference: the_account.console_url 101 | - label: SSH Key 102 | reference: primary_user.ssh_key 103 | - label: GCP Folder Name 104 | reference: primary_folder.folder_name 105 | - label: GCP Folder Display Name 106 | reference: primary_folder.display_name 107 | 108 | assessment: 109 | passing_percentage: 75 110 | steps: 111 | - title: Create a Cloud Storage bucket 112 | locale_id: create_bucket 113 | maximum_score: 5 114 | student_messages: 115 | success: Great job! You created the bucket! 116 | bucket_missing: Oops! No bucket found. 117 | bucket_misconfigured: Hmm. The bucket is there, but it is misconfigured. 118 | services: 119 | - primary_project.StorageV1 120 | method_name: step_one_check # Refers to "assessments/step_one_check.rb" 121 | -------------------------------------------------------------------------------- /examples/lab-robust/v2/resources/sample-en.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/examples/lab-robust/v2/resources/sample-en.pdf -------------------------------------------------------------------------------- /examples/lab-robust/v2/resources/sample-es.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/examples/lab-robust/v2/resources/sample-es.pdf -------------------------------------------------------------------------------- /examples/lab-robust/v2/startup/qwiklabs.jinja: -------------------------------------------------------------------------------- 1 | resources: 2 | - name: good-vm 3 | type: vm-type.jinja 4 | properties: 5 | zone: {{ properties["zone"] }} 6 | 7 | outputs: 8 | - name: InstanceDns 9 | value: 35.238.252.133 10 | -------------------------------------------------------------------------------- /examples/lab-robust/v2/startup/vm-type.jinja: -------------------------------------------------------------------------------- 1 | resources: 2 | - name: name-of-instance 3 | type: compute.v1.instance 4 | properties: 5 | zone: {{ properties["zone"] }} 6 | machineType: https://www.googleapis.com/compute/v1/projects/{{ env["project"] }}/zones/{{ properties["zone"] }}/machineTypes/n1-standard-1 7 | disks: 8 | - deviceName: boot 9 | type: PERSISTENT 10 | boot: true 11 | autoDelete: true 12 | initializeParams: 13 | sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/family/debian-9 14 | networkInterfaces: 15 | - network: https://www.googleapis.com/compute/v1/projects/{{ env["project"] }}/global/networks/default 16 | accessConfigs: 17 | - name: External NAT 18 | type: ONE_TO_ONE_NAT 19 | -------------------------------------------------------------------------------- /examples/peer-assignment-robust/instructions/en.html: -------------------------------------------------------------------------------- 1 |

Robust Peer Assignment Example

2 | 3 |

Step 1: Access the template

4 |

Use this template for your storyboard.

5 | 6 |

Step 2: Build a big picture storyboard

7 |

8 |

9 | 10 |

Step 3: Build a close-up storyboard

11 |

Huzzah! You’re ready to take on the world!

12 | 13 | Example Image 14 | 15 | Template Link 16 | -------------------------------------------------------------------------------- /examples/peer-assignment-robust/instructions/es.html: -------------------------------------------------------------------------------- 1 |

Ejemplo de Robust Peer Assignment

2 | 3 |

Paso 1: Accede a la plantilla

4 |

Utilice esta plantilla para su guión gráfico .

5 | 6 |

Step 2: Cree un guión gráfico de imagen grande

7 |

8 |

9 | 10 |

Step 3: Cree un guión gráfico de primer plano

11 |

¡Huzzah! ¡Estás listo para enfrentarte al mundo!

12 | -------------------------------------------------------------------------------- /examples/peer-assignment-robust/instructions/img/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/examples/peer-assignment-robust/instructions/img/example.png -------------------------------------------------------------------------------- /examples/peer-assignment-robust/qwiklabs.es.yaml: -------------------------------------------------------------------------------- 1 | # qwiklabs.es.yaml for Spanish localization 2 | # There is no need to copy everything over from qwiklabs.yaml. 3 | # Only locale specific attributes need to go in here. 4 | 5 | title: Ejemplo de Robust Peer Assignment 6 | 7 | review_criteria: Solo lo básico, nada más. 8 | 9 | instruction: 10 | type: html 11 | uri: "./instructions/es.html" 12 | 13 | objectives: Aprende a hacer una tarea entre compañeros. 14 | 15 | prompts: 16 | - id: prompt-1 17 | stem: Cargue el guión gráfico general. 18 | response_types: 19 | - file_upload 20 | - url 21 | rubric_items: 22 | - type: multiple-choice 23 | id: prompt-1-rubric-1 24 | stem: La plantilla está llena. 25 | options: 26 | - id: prompt-1-rubric-1-option-1 27 | title: Se completan 0 partes de la plantilla. 28 | points: 0 29 | - id: prompt-1-rubric-1-option-2 30 | title: Algunas partes de la plantilla están llenas. 31 | points: 1 32 | - id: prompt-1-rubric-1-option-3 33 | title: Todas las partes de la plantilla están llenas. 34 | points: 2 35 | - type: true-false 36 | id: prompt-1-rubric-2 37 | stem: El guión gráfico general está claramente centrado en un usuario. 38 | true_points: 1 39 | false_points: 0 40 | - id: prompt-2 41 | stem: Cargue un guión gráfico de primer plano. 42 | response_types: 43 | - file_upload 44 | - url 45 | rubric_items: 46 | - type: multiple-choice 47 | id: prompt-2-rubric-1 48 | stem: La plantilla está llena. 49 | options: 50 | - id: prompt-2-rubric-1-option-1 51 | title: La plantilla está llena. 52 | points: 0 53 | - id: prompt-2-rubric-1-option-2 54 | title: Algunas partes de la plantilla están llenas. 55 | points: 1 56 | - id: prompt-2-rubric-1-option-3 57 | title: Todas las partes de la plantilla están llenas. 58 | points: 2 59 | - type: true-false 60 | id: prompt-2-rubric-2 61 | stem: El guión gráfico de primer plano está claramente centrado en un usuario. 62 | true_points: 1 63 | false_points: 0 64 | - type: reflective-text 65 | id: prompt-2-rubric-3 66 | stem: Proporcione comentarios sobre el guión gráfico de primer plano. 67 | 68 | exemplars: 69 | - id: examplar-1 70 | prompt_responses: 71 | - id: prompt-response-1 72 | prompt_id: prompt-1 73 | response_type: url 74 | response_content: http://www.google.com 75 | - id: prompt-response-2 76 | prompt_id: prompt-2 77 | response_type: rich_text 78 | response_content: This is my rich text answer in spanish 79 | -------------------------------------------------------------------------------- /examples/peer-assignment-robust/qwiklabs.yaml: -------------------------------------------------------------------------------- 1 | entity_type: PeerAssignment 2 | schema_version: 1 3 | 4 | default_locale: en 5 | 6 | title: Robust Peer Assignment Example 7 | 8 | review_criteria: Just the basics, nothing more. 9 | 10 | duration: 120 11 | 12 | instruction: 13 | type: html 14 | uri: "./instructions/en.html" 15 | 16 | objectives: Learn how to do a peer assignment. 17 | 18 | passing_score: 5 19 | 20 | prompts: 21 | - id: prompt-1 22 | stem: Upload a big picture storyboard. 23 | response_types: 24 | - file_upload 25 | - url 26 | rubric_items: 27 | - type: multiple-choice 28 | id: prompt-1-rubric-1 29 | stem: The template is filled out. 30 | options: 31 | - id: prompt-1-rubric-1-option-1 32 | title: 0 parts of the template are filled out. 33 | points: 0 34 | - id: prompt-1-rubric-1-option-2 35 | title: Some parts of the template are filled out. 36 | points: 1 37 | - id: prompt-1-rubric-1-option-3 38 | title: All parts of the template are filled out. 39 | points: 2 40 | - type: true-false 41 | id: prompt-1-rubric-2 42 | stem: The big picture storyboard is clearly focused on a user. 43 | true_points: 1 44 | false_points: 0 45 | - id: prompt-2 46 | stem: Upload a close-up storyboard. 47 | response_types: 48 | - file_upload 49 | - url 50 | rubric_items: 51 | - type: multiple-choice 52 | id: prompt-2-rubric-1 53 | stem: The template is filled out. 54 | options: 55 | - id: prompt-2-rubric-1-option-1 56 | title: 0 parts of the template are filled out. 57 | points: 0 58 | - id: prompt-2-rubric-1-option-2 59 | title: Some parts of the template are filled out. 60 | points: 1 61 | - id: prompt-2-rubric-1-option-3 62 | title: All parts of the template are filled out. 63 | points: 2 64 | - type: true-false 65 | id: prompt-2-rubric-2 66 | stem: The close-up storyboard is clearly focused on a user. 67 | true_points: 1 68 | false_points: 0 69 | - type: reflective-text 70 | id: prompt-2-rubric-3 71 | stem: Provide feedback on the close-up storyboard. 72 | 73 | exemplars: 74 | - id: examplar-1 75 | prompt_responses: 76 | - id: prompt-response-1 77 | prompt_id: prompt-1 78 | response_type: url 79 | response_content: http://www.google.com 80 | - id: prompt-response-2 81 | prompt_id: prompt-2 82 | response_type: rich_text 83 | response_content: This is my rich text answer 84 | -------------------------------------------------------------------------------- /game-template-bundle-spec.md: -------------------------------------------------------------------------------- 1 | # Qwiklabs GameTemplate Bundle Specification 2 | 3 | **Version 1** 4 | 5 | > This is a DRAFT document. We welcome feedback as this format evolves. 6 | 7 | ## `qwiklabs.yaml` Structure 8 | 9 | The `GameTemplate` bundle specification exactly matches the 10 | [CourseTemplate bundle spec](./course-template-bundle-spec.md), with the 11 | following exceptions: 12 | 13 | * `entity_type` should be set to `GameTemplate`. 14 | * `GameTemplate` does not have a `max_hot_labs` field. 15 | * `GameTemplate` does not have an `instructor_resources` section. 16 | * For `GameTemplate`s, if a step only contains activities with the type 17 | `resource`, the step will be optional by default. If you would like the step 18 | to be required, this can be overridden by setting `optional: false` for the 19 | step. 20 | -------------------------------------------------------------------------------- /html/html-spec.md: -------------------------------------------------------------------------------- 1 | # HTML Specification 2 | 3 | Before rendering, Qwiklabs will aggressively sanitize the provided HTML. 4 | 5 | * Remove all script tags. 6 | * Remove all style tags. 7 | * Remove all tags, classes, and attributes that are not explicitly allowed. 8 | 9 | The allowed tags, classes, and attributes depend on the context. We currently 10 | have two contexts: restricted, and instruction. 11 | 12 | ## Instruction HTML 13 | 14 | ### Allowed Tags 15 | 16 | * `h1`, `h2`, `h3`, `h4`, `h5`, `h6` 17 | * `p` 18 | * `div`, `span`? 19 | * `table`, `tr`, `td`, `th`, 20 | * `b`, `i`, `em`, `strong`, `u`, `sup` 21 | * `img` 22 | * `a` 23 | * `aside` 24 | * `button` 25 | * `ul`, `ol`, `li` 26 | * `pre`, `code` 27 | * `blockquote` 28 | 29 | ## Qwiklabs Custom Elements 30 | 31 | We have built a small library of helpful Web Components that you may use within 32 | your lab instructions. 33 | 34 | ### `` and `` 35 | 36 | Renders pre-formatted and syntax-highlighted code blocks. 37 | 38 | `` may be used on its own, or several may be placed within a 39 | `` to show multiple tabs of code blocks. 40 | 41 | #### Attributes for `` 42 | 43 | * `language: string|null` 44 | 45 | Language of this code block. 46 | 47 | If not specified, the language will be automatically inferred. 48 | 49 | See 50 | [the highlight.js docs](https://github.com/highlightjs/highlight.js/blob/main/SUPPORTED_LANGUAGES.md) 51 | for a list of supported languages. 52 | 53 | * `noWrap: boolean` 54 | 55 | By default, code blocks wrap their contents. Setting this attribute will 56 | make code blocks *not* wrap text within themselves. Instead, a horizontal 57 | scrollbar will appear to view the full contents. 58 | 59 | * `tabTitle: string|null` 60 | 61 | This is not relevant when using `` as a standalone element. 62 | 63 | When using `` inside ``, this is the title of the 64 | tab for this code block. 65 | 66 | * `output: boolean` 67 | 68 | There are two types of code blocks in labs: input and output. 69 | 70 | Input code blocks contain content such as terminal commands, bash scripts, 71 | lines of code, etc. Things that are meant to be copied and pasted. An input 72 | code-block has a button to quickly copy the contents. 73 | 74 | Output code blocks contain the results of previous commands, such as 75 | terminal output - things that are not meant to be copied around. An output 76 | code-block does not have a copy button, and has different styling. 77 | 78 | Use this property to set this block as "output", instead of "input". 79 | 80 | * `templated: boolean` 81 | 82 | Allows the use of templated variables in this code block. See 83 | [Templated Variables](#templated-variables) below. 84 | 85 | #### Indentation 86 | 87 | Code block indentation is determined by the amount of indentation preceding the 88 | closing tag. Take the following example: 89 | 90 | ```html 91 | 92 | console.log("some code in here"); 93 | console.log("some more code here"); 94 | 95 | if (2 + 2 == 4) { 96 | [1, 2, 3].forEach(console.log); 97 | } 98 | 99 | ``` 100 | 101 | The closing tag above is preceded by two spaces. Every line will be "dedented" 102 | by exactly those two spaces, to produce the following output: 103 | 104 | ```js 105 | console.log("some code in here"); 106 | console.log("some more code here"); 107 | 108 | if (2 + 2 == 4) { 109 | [1, 2, 3].forEach(console.log); 110 | } 111 | ``` 112 | 113 | If the indentation of the closing tag does not match the indentation of the 114 | start of every line in the code block (not including lines that are empty or 115 | only whitespace), the code will not be dedented. For example: 116 | 117 | ```html 118 | 119 | console.log("some code in here"); 120 | console.log("some more code here"); 121 | 122 | if (2 + 2 == 4) { 123 | [1, 2, 3].forEach(console.log); 124 | } 125 | 126 | ``` 127 | 128 | Would be rendered as: 129 | 130 | ```js 131 | console.log("some code in here"); 132 | console.log("some more code here"); 133 | 134 | if (2 + 2 == 4) { 135 | [1, 2, 3].forEach(console.log); 136 | } 137 | ``` 138 | 139 | #### Escaping Content 140 | 141 | The contents of code blocks must be 142 | [HTML-escaped](https://www.w3.org/International/questions/qa-escapes#use) in 143 | order to render correctly. 144 | 145 | This is most relevant for HTML/XML content, for example: 146 | 147 | ```html 148 | 149 | <h1>What is a monad?</h1> 150 | <p>A monad is just a monoid in the category of endofunctors.</p> 151 | <img src="monad.png" alt="Monad diagram"> 152 | 153 | ``` 154 | 155 | will render as: 156 | 157 | ![example preview](./images/ql-code-block-01.png) 158 | 159 | #### Templated Variables 160 | 161 | Much like [\](#ql-variable), Lab outputs such as usernames, 162 | passwords, project IDs, etc. can be rendered directly within code blocks using 163 | the `templated` attribute. 164 | 165 | Code blocks marked as `templated` will allow the usage of triple curly braces 166 | within the code content. The curly braces must contain the output `key` to be 167 | rendered, and optionally may contain a `placeholder` that is rendered before the 168 | lab is started and data is available. 169 | 170 | ``` 171 | {{{key}}} 172 | {{{key|placeholder}}} 173 | ``` 174 | 175 | For example, say you want to use the user's username and password in a snippet 176 | of Python. See the following example: 177 | 178 | ```html 179 | 180 | def init_api(): 181 | # Logs into Cool API with your username {{{user_1.username}}} 182 | api = CoolApi.login( 183 | '{{{user_1.username|your_username}}}', 184 | '{{{user_1.username|your_password}}}', 185 | ) 186 | return api 187 | 188 | ``` 189 | 190 | When the lab page is first opened, only the placeholders will be shown: 191 | 192 | ![example preview](./images/ql-code-block-02.png) 193 | 194 | After the lab has been started and provisioned, the code block will be updated 195 | to include the lab outputs: 196 | 197 | ![example preview](./images/ql-code-block-03.png) 198 | 199 | ### Markdown Syntax (GitHub integration only) 200 | 201 | Code blocks can be rendered with Markdown using triple back ticks: 202 | 203 | ~~~ 204 | ```javascript 205 | console.log('hello world!'); 206 | ``` 207 | ~~~ 208 | 209 | Code block properties can be easily utilized in Markdown as well: 210 | 211 | ~~~ 212 | ```python output noWrap 213 | print('this will be styled as an output code block and will not wrap lines.') 214 | ``` 215 | ~~~ 216 | 217 | When rendering a code block through Markdown, HTML-escaping the contents is not 218 | necessary and will be handled automatically. 219 | 220 | Also, Markdown code blocks without an explicit `language` specified will be 221 | rendered with `language="plaintext"`. 222 | 223 | #### Examples 224 | 225 | Two tabs of code blocks, one with a custom title. 226 | 227 | ```html 228 | 229 | 230 | console.log("some code in here"); 231 | console.log("some more code here"); 232 | [1, 2, 3].forEach(console.log); 233 | 234 | 235 | print("some code in here") 236 | 237 | 238 | ``` 239 | 240 | Result: 241 | 242 | ![example preview](./images/ql-code-01.png) 243 | 244 | -------------------------------------------------------------------------------- 245 | 246 | A `` on its own without tabs, in "output mode". 247 | 248 | ```html 249 | 250 | { 251 | "id": 321, 252 | "age": 6, 253 | "breed": "Daschund", 254 | "weight": { 255 | "value": 23, 256 | "unit": "lb" 257 | } 258 | } 259 | 260 | ``` 261 | 262 | Result: 263 | 264 | ![example preview](./images/ql-code-02.png) 265 | 266 | ### `` 267 | 268 | Much like a [templated \](#templated-variables), Lab outputs such 269 | as usernames, passwords, project IDs, etc. can be rendered directly within lab 270 | instructions using the `` component. 271 | 272 | #### Attributes for `` 273 | 274 | * `key: string` 275 | 276 | The lab output key that this variable should render within the instructions. 277 | 278 | * `placeholder: string = '____'` 279 | 280 | Before a lab is started, this variable will render this placeholder value in 281 | place of the currently unknown actual value. 282 | 283 | This attribute is optional. It defaults to `____`. 284 | 285 | #### Markdown Syntax (GitHub integration only) 286 | 287 | Instead of writing out the full HTML form of ``, a Markdown 288 | shorthand syntax is available using triple curly braces (`{{{}}}`) surrounding 289 | the key. A custom placeholder may optionally be included following a vertical 290 | pipe character (`|`). 291 | 292 | See the next section for examples of what this looks like. 293 | 294 | #### Examples 295 | 296 | A variable rendered within instructions using the default placeholder. 297 | 298 | HTML form: 299 | 300 | ```html 301 | Sign in with your username to begin. 302 | ``` 303 | 304 | Equivalent Markdown form: 305 | 306 | ```md 307 | Sign in with your username {{{ username }}} to begin. 308 | ``` 309 | 310 | Result (lab not started): 311 | 312 | ![example preview](./images/ql-variable-01.png) 313 | 314 | Result (lab started): 315 | 316 | ![example preview](./images/ql-variable-03.png) 317 | 318 | -------------------------------------------------------------------------------- 319 | 320 | A variable rendered within instructions with a custom placeholder. 321 | 322 | HTML form: 323 | 324 | ```html 325 | Sign in with your username to begin. 326 | ``` 327 | 328 | Equivalent Markdown form: 329 | 330 | ```md 331 | Sign in with your username {{{ username | (username) }}} to begin. 332 | ``` 333 | 334 | Result (lab not started, showing custom placeholder): 335 | 336 | ![example preview](./images/ql-variable-02.png) 337 | 338 | Result (lab started, same as the previous example): 339 | 340 | ![example preview](./images/ql-variable-03.png) 341 | 342 | ### `` 343 | 344 | TODO: add documentation 345 | 346 | ### `` 347 | 348 | TODO: add documentation 349 | 350 | ### `` 351 | 352 | TODO: add documentation 353 | 354 | ### `` 355 | 356 | TODO: add documentation 357 | 358 | ### `` 359 | 360 | TODO: add documentation 361 | 362 | ### `` 363 | 364 | TODO: add documentation 365 | 366 | ### `` 367 | 368 | TODO: add documentation 369 | 370 | ### `` 371 | 372 | TODO: add documentation 373 | 374 | ### `` 375 | 376 | Videos can be inserted, either with a link to the direct video file source or as 377 | a YouTube video ID. 378 | 379 | Details: 380 | 381 | Attribute | Type | Required | Description 382 | --------- | ------- | -------- | ----------- 383 | src | string | true* | A URL that leads directly to a video file. 384 | youtubeId | string | true* | The ID of the YouTube video to embed.
(the part of the URL after `?v=`) 385 | width | integer | false | Display width of the video, in pixels. 386 | height | integer | false | Display height of the video, in pixels. 387 | loop | boolean | false | Whether to loop this video automatically. 388 | autoplay | boolean | false | Whether to play this video immediately on page load. 389 | controls | boolean | false | Whether to show video playback and volume controls.
Only applicable to videos using `src`. 390 | lang | string | false | Subtitle preference for YouTube videos (2-letter language code) 391 | 392 | \* One of `src` or `youtubeId` must be present, but not both. 393 | 394 | ##### Direct Source Videos 395 | 396 | Source: 397 | 398 | ```html 399 | 400 | 401 | ``` 402 | 403 | Rendered: 404 | 405 | 406 | 407 | 408 | 409 | ##### YouTube Videos 410 | 411 | ```html 412 | 413 | 414 | ``` 415 | 416 | Rendered: 417 | 418 | 419 | 420 | 421 | 422 | ## Features 423 | 424 | * Automatic table of contents generation. 425 | * `

` is the title of the document and will not be included in TOC. 426 | * `

`s will be navigable links in the TOC. 427 | * By not styling yourself, your instructions will not become outdated as the 428 | Qwiklabs learning interface changes. 429 | -------------------------------------------------------------------------------- /html/images/ql-code-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/html/images/ql-code-01.png -------------------------------------------------------------------------------- /html/images/ql-code-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/html/images/ql-code-02.png -------------------------------------------------------------------------------- /html/images/ql-code-block-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/html/images/ql-code-block-01.png -------------------------------------------------------------------------------- /html/images/ql-code-block-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/html/images/ql-code-block-02.png -------------------------------------------------------------------------------- /html/images/ql-code-block-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/html/images/ql-code-block-03.png -------------------------------------------------------------------------------- /html/images/ql-variable-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/html/images/ql-variable-01.png -------------------------------------------------------------------------------- /html/images/ql-variable-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/html/images/ql-variable-02.png -------------------------------------------------------------------------------- /html/images/ql-variable-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/html/images/ql-variable-03.png -------------------------------------------------------------------------------- /lab_control_panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudVLab/qwiklabs-content-bundle-spec/ef06cb2e624d008c72f9138605fd214009a23e35/lab_control_panel.png -------------------------------------------------------------------------------- /learning-path-bundle-spec.md: -------------------------------------------------------------------------------- 1 | # Qwiklabs LearningPath Bundle Specification 2 | 3 | **Version 1** 4 | 5 | > This is a DRAFT document. We welcome feedback as this format evolves. 6 | 7 | ## `qwiklabs.yaml` Structure 8 | 9 | The `LearningPath` bundle specification exactly matches the 10 | [CourseTemplate bundle spec](./course-template-bundle-spec.md), with the 11 | following exceptions: 12 | 13 | * `entity_type` should be set to `LearningPath`. 14 | * `LearningPath` does not have a `max_hot_labs` field. 15 | * `LearningPath` can have a `resources` section. 16 | * `LearningPath` does not have an `instructor_resources` section. 17 | * `LearningPath` must have exactly 1 module. 18 | * `LearningPath` can contain a pre-assessment lab that allows learners to test 19 | out of the `LearningPath`'s learning activities depending on their 20 | performance in the pre-assessment. The pre-assessment is defined by a 21 | `preassessment` section and its bundle specification can be found 22 | [here](./preassessment-bundle-spec.md). 23 | -------------------------------------------------------------------------------- /peer-assignment-bundle-spec.md: -------------------------------------------------------------------------------- 1 | # Qwiklabs Peer Assignment Bundle Specification 2 | 3 | > **Version 1** 4 | 5 | ## `qwiklabs.yaml` Structure 6 | 7 | Here's a sample `qwiklabs.yaml` file, with all nested details removed to make it 8 | easier to see the general file structure. 9 | 10 | ```yaml 11 | entity_type: PeerAssignment 12 | schema_version: 1 13 | default_locale: en 14 | 15 | title: Create storyboards for your portfolio project 16 | 17 | review_criteria: "There are a total of 6 points for this activity. At least two of your peers will evaluate your project. Your final grade will be the median of these scores. You must get 5 out of 6 total points to pass." 18 | 19 | duration: 120 20 | 21 | # The primary instruction content for this peer assignment 22 | instruction: ... 23 | 24 | prompts: ... 25 | 26 | exemplars: ... 27 | ``` 28 | 29 | Note that all of the main chunks of localized content (title, review_criteria, 30 | text, stem and title) are HTML content that may be displayed in various 31 | contexts. All of these chunks will be sanitized according to the restricted set 32 | in the HTML spec. 33 | 34 | ### Default Locale 35 | 36 | The peer assignment bundle MUST specify a `default_locale`. It corresponds to 37 | the locale that the peer assignment is originally authored in. Authoring tools 38 | can use this as a hint to notify localizers when content in the default locale 39 | is updated. Also, it provides a hint to the learner interface about which locale 40 | to display if an instruction/resource is not localized for the learner's current 41 | locale. 42 | 43 | 44 | Add an additional locale specific file of the form "qwiklabs.xx.yaml" for each 45 | locale to be included. For example, Japanese entries would be in a file named 46 | "qwiklabs.ja.yaml". Within a single piece of content, be sure to use consistent 47 | `ids` across all the "qwiklabs.xx.yaml" files for data that contains lists of 48 | objects. 49 | 50 | 51 | ### Attribute specification 52 | 53 | attribute | required | type | notes 54 | ---------------------- | -------- | ----------------- | ----- 55 | entity_type | ✓ | string | Must be `PeerAssignment` 56 | schema_version | ✓ | integer | 57 | default_locale | ✓ | string | Must be a valid locale code 58 | instruction | ✓ | locale dictionary | 59 | title | ✓ | string | 60 | review_criteria | ✓ | string | 61 | objectives | | string | Objectives of the assignment 62 | duration | ✓ | integer | Estimated amount of time it should take an average learner to complete the assignment (in minutes) 63 | passing_score | | integer | If none, default is 0 64 | prompts | ✓ | array | See [below](#prompt) 65 | exemplars | | array | See [below](#exemplar) 66 | 67 | ### Instructions 68 | 69 | Place your instruction files under "instructions" folder. Name of the file MUST 70 | be same as the locale key. 71 | 72 | Your folder structure may look like: 73 | ``` 74 | my-peer-assignment/instructions/en.md 75 | my-peer-assignment/instructions/es.html 76 | ``` 77 | You can only have one file per locale. 78 | 79 | attribute | required | type | notes 80 | --------- | -------- | ----------------- | ----- 81 | type | ✓ | enum | [See list of valid types below] 82 | uri | ✓ | string | Relative path to a file 83 | 84 | ```yaml 85 | instruction: 86 | type: html 87 | uri: instructions/en.html 88 | ``` 89 | 90 | #### Valid types 91 | 92 | 93 | * `html` 94 | * `pdf` 95 | * `md` 96 | 97 | 98 | 99 | Markdown (MD) or HTML are the preferred formats for stored instructions. PDFs 100 | will be displayed embedded in the learner interface, but will lack any 101 | navigation or interactive functionality. 102 | ##### Qwiklabs supported markup 103 | 104 | There are benefits to formatting lab instructions as HTML. 105 | 106 | * Instruction styling will be updated automatically as the Qwiklabs interface 107 | evolves. 108 | * Qwiklabs will help users navigate within your instruction document with a 109 | table of contents or direct links. It will also remember the learner's 110 | location in the document if they leave the page. 111 | * Authors can specify interactive elements that will be displayed inline with 112 | your instructions in the learner's interface (quizzes, checkpoints, etc). 113 | 114 | However, we will not accept arbitrary HTML. Your input will be heavily scrubbed. 115 | 116 | * Only a standard subset of HTML elements will be supported (`

`, `

`, 117 | ``, etc). All other tags will be stripped out of displayed content. 118 | * All styling will be removed. 119 | * All scripting will be removed. 120 | 121 | See the Instruction part of the [HTML spec](./html/html-spec.md) for details. 122 | 123 | ### Prompt 124 | 125 | A prompt defines what a learner needs to do to complete the activity, and has rubric criteria to help the other learners evaluate. The full specification is as follows: 126 | 127 | attribute | required | type | notes 128 | -------------- | -------- | ----------------- | ----- 129 | id | ✓ | string | A unique identifier for this module 130 | stem | ✓ | string | Prompt text 131 | response_types | ✓ | enum | One of: "url", "file_upload", "rich_text" 132 | rubric_items | ✓ | array | Array of rubric items. See [below](#rubric_item) 133 | 134 | Note: We do not allow more than 2 prompts in one peer assignment. 135 | 136 | ### Rubric Item 137 | 138 | Rubric items are used for peers to evaluate other learner submission. Rubric items are polymorphic - i.e. there are several different types that are defined slightly differently. `rubric_items` is an array of dictionaries with appropriate attributes for the given type. The allowed values for `type` are: 139 | 140 | * `multiple-choice` 141 | * `true-false` 142 | * `reflective-text` 143 | 144 | #### multiple-choice Rubric Item 145 | 146 | A rubric item that has multiple options, each associated with points. 147 | 148 | attribute | required | type | notes 149 | --------- | -------- | ----------------- | ----- 150 | id | ✓ | string | A unique identifier for this item 151 | type | ✓ | enum | The item type, which is always `multiple-choice` 152 | stem | ✓ | string | e.g. _"The email includes the subject line, greeting, body, and closing."_ 153 | options | ✓ | array | Array of `options`. See [below](#option) 154 | 155 | #### true-false Rubric Item 156 | 157 | A rubric item that has two predefined options (true and false), each associated with points. 158 | 159 | attribute | required | type | notes 160 | ------------ | -------- | ----------------- | ----- 161 | id | ✓ | string | A unique identifier for this item. 162 | type | ✓ | enum | The item type, which is always `true-false` 163 | stem | ✓ | string | e.g. _"All parts of the big picture storyboard template are filled out."_ 164 | true_points | ✓ | integer | Usually 1 165 | false_points | ✓ | integer | Usually 0 166 | 167 | #### reflective-text Rubric Item 168 | 169 | A rubric item that has an reflective text question, associated with no points. 170 | 171 | attribute | required | type | notes 172 | ------------ | -------- | ----------------- | ----- 173 | id | ✓ | string | A unique identifier for this item. 174 | type | ✓ | enum | The item type, which is always `reflective-text` 175 | stem | ✓ | string | e.g. _"Provide constructive feedback for your classmates on their submission."_ 176 | 177 | ### Option 178 | 179 | `multiple-choice` contains an array of all the `options` that the user may choose from. The full specification is as follows: 180 | 181 | attribute | required | type | notes 182 | ------------ | -------- | ----------------- | ----- 183 | id | ✓ | string | A unique identifier for this option. 184 | title | ✓ | string | e.g. _"The email includes 2-3 of these elements."_ 185 | points | ✓ | integer | 186 | 187 | ### Exemplar 188 | 189 | An exemplar is a sample answer for the prompts in this assignment: 190 | 191 | attribute | required | type | notes 192 | -------------- | -------- | ----------------- | ----- 193 | id | ✓ | string | A unique identifier for this examplar 194 | prompt_responses| ✓ | array | Array of prompt response. See [below](#prompt_response) 195 | 196 | 197 | ### Prompt Response 198 | 199 | A prompt response is a sample answer for the prompt. The number of prompt 200 | responses is the same as the number of prompts. 201 | 202 | attribute | required | type | notes 203 | -------------- | -------- | ----------------- | ----- 204 | id | ✓ | string | A unique identifier for this prompt response. 205 | prompt_id | ✓ | string | Corresponding prompt id. 206 | response_type | ✓ | enum | One of: "url", "rich_text" 207 | response_content | ✓ | string | url link or free text content 208 | -------------------------------------------------------------------------------- /preassessment-bundle-spec.md: -------------------------------------------------------------------------------- 1 | # Preassessment Bundle Specification 2 | 3 | This bundle specification is used to define pre-assessment labs and the 4 | activities they test out of. A sample pre-assessment is provided below: 5 | 6 | ``` 7 | preassessment: 8 | id: gcp-spl-content/gsp610-fundamentals-of-cloud-logging 9 | equivalencies: 10 | - preassessment_step: 1 11 | tested_out_type: lab 12 | tested_out_id: advanced-gcp-task 13 | 14 | - preassessment_step: 2 15 | tested_out_type: video 16 | tested_out_id: storage-options 17 | ``` 18 | 19 | Pre-assessments are defined by a `preassessment` field, and contain the 20 | following required attributes: 21 | 22 | | attribute | type | notes | 23 | | ------------- | ------ | --------------------------------------------------- | 24 | | id | string | Reference to the unique identifier for the lab used as a pre-assessment - `library/slug` or `slug`. | 25 | | equivalencies | array | See [below](#equivalencies) | 26 | 27 | ## Equivalencies 28 | 29 | The `equivalencies` field is an array that defines the content the 30 | pre-assessment tests out of in terms of its assessment steps. Each entry in the 31 | array contains the following required attributes: 32 | 33 | | attribute | type | notes | 34 | | ------------------ | ------- | --------------------------------------------- | 35 | | preassessment_step | integer | The step number of one of the pre-assessment lab's activity tracking steps, starting from 1. | 36 | | tested_out_id | string | Reference to the unique identifier for the tested out activity - `library/slug` or `slug`. | 37 | | tested_out_type | string | The type of the tested out activity - `lab`, `quiz`, `video`, or `document`(refers to both `link` and `file` activities). | 38 | 39 | Pre-assessment bundle specifications also must adhere to the following rules: 40 | 41 | * The pre-assessment cannot test out itself. 42 | * `preassessment.equivalencies.tested_out_id` must refer to one of the 43 | activities in the underlying quest/course. 44 | * Duplicate equivalencies are not allowed. For example, the following would be 45 | invalid: 46 | 47 | ``` 48 | - preassessment_step: 1 49 | tested_out_type: lab 50 | tested_out_id: slug1 51 | - preassessment_step: 1 52 | tested_out_type: lab 53 | tested_out_id: slug1 54 | ``` 55 | -------------------------------------------------------------------------------- /quiz-bundle-spec.md: -------------------------------------------------------------------------------- 1 | # Qwiklabs Quiz Bundle Specification 2 | 3 | **Version 1** 4 | 5 | > This is a DRAFT document. We welcome feedback as this format evolves. 6 | 7 | ## `qwiklabs.yaml` Structure 8 | 9 | Here's a sample `qwiklabs.yaml` file with all nested details removed to make it 10 | easier to see the general file structure. 11 | 12 | ```yaml 13 | entity_type: Quiz 14 | schema_version: 1 15 | 16 | passing_percentage: 67 17 | default_locale: en 18 | 19 | items: ... 20 | ``` 21 | 22 | Note that all of the localized content (stem, option titles, rationales, etc) 23 | are HTML content that may be displayed in various contexts. All of these chunks 24 | will be sanitized according to the restricted set in the 25 | [HTML spec](./html/html-spec.md). 26 | 27 | ### Quiz attributes 28 | 29 | attribute | required | type | notes 30 | ------------------ | -------- | ---------- | ----- 31 | default_locale | ✓ | string | Corresponds to the locale that the quiz is authored in. Authoring tools can use this as a hint to notify localizers when content in the default locale is updated. Also, it provides a hint to the learner interface about which locale to display if an instruction/resource is not localized for the learner's current locale. 32 | schema_version | ✓ | integer | Which version of the quiz bundle schema you are using 33 | title | ✓ | dictionary | A locale dictionary of the quiz title, such as "My Awesome Quiz" 34 | passing_percentage | ✓ | integer | The threshold grade that a student needs to achieve in order to count as "passing" the quiz. 35 | fixed_place | | boolean | `true` if the items should be presented in a fixed order rather than shuffled (this is treated as `false` if it's missing). 36 | duration | | integer | The default time a student is allotted for the quiz, in minutes. If unspecified, the quiz will not be timed. 37 | sections | | array | An ordered array of `sections` (see [below for details](#sections)) in this quiz; not allowed if `items` are specified; required if `items` are unspecified. 38 | items | | array | An ordered array of `items` (see [below for details](#items)) in a default section of this quiz; not allowed if `sections` are specified; required if `sections` are unspecified. 39 | 40 | ### Sections 41 | 42 | Sections are groupings of related quiz items. Can be used as item banks grouping 43 | "equivalent" items. 44 | 45 | ```yaml 46 | id: section-0 47 | name: Networking 48 | item_count: 2 49 | items: ... 50 | ``` 51 | 52 | attribute | required | type | notes 53 | ---------- | -------- | ------- | ----- 54 | id | ✓ | string | A unique identifier for this section 55 | name | | string | A name for this section 56 | item_count | | integer | The number of items to select from this section when composing the quiz displayed to the student. Can be used to indicate the number of items to choose from an item bank. If unspecified, defaults to the total number of `items` specified below. 57 | items | ✓ | array | An ordered array of `items` (see below for details) in this section 58 | 59 | ### Items 60 | 61 | Items are polymorphic - i.e. there are several different _item types_ that are 62 | defined slightly differently. `items` is an array of dictionaries with 63 | appropriate attributes for the given `type`. The allowed values for `type` are: 64 | 65 | * `multiple-choice` 66 | * `multiple-select` 67 | * `true-false` 68 | * `reflective-text` 69 | * `match` 70 | 71 | #### multiple-choice Items 72 | 73 | A quiz item that has multiple options and one answer. One option is the 74 | _answer_, and the rest are _distractors_. There must be exactly one answer. 75 | 76 | attribute | required | type | notes 77 | --------- | -------- | ---------- | ----- 78 | id | ✓ | string | A unique identifier for this item 79 | type | ✓ | string | The item type, which is always `multiple-choice` 80 | stem | ✓ | dictionary | A locale dictionary of the text that asks the question, such as "Which of the following is a color?" 81 | options | ✓ | array | An array of `options` (see below for details); order does not matter 82 | 83 | #### multiple-select Items 84 | 85 | A quiz item that has multiple options, any number of which are answers. Correct 86 | options are _answers_, and incorrect options are _distractors_. 87 | 88 | attribute | required | type | notes 89 | --------- | -------- | ---------- | ----- 90 | id | ✓ | string | A unique identifier for this item 91 | type | ✓ | string | The item type, which is always `multiple-select` 92 | stem | ✓ | dictionary | A locale dictionary for the text that asks the question, such as "Which of the following is a color?" 93 | options | ✓ | array | An array of `options` (see below for details); order does not matter 94 | 95 | #### true-false Items 96 | 97 | A quiz item that has two predefined options: true and false. The correct option 98 | (e.g. "True") is the answer and the other is the distractor. 99 | 100 | attribute | required | type | notes 101 | --------------- | -------- | ---------- | ----- 102 | id | ✓ | string | A unique identifier for this item 103 | type | ✓ | string | The item type, which is always `true-false` 104 | stem | ✓ | dictionary | A locale dictionary of text that asks the question, such as "True or false: the world is round." 105 | answer | ✓ | boolean | The correct answer. `true` for "True", `false` for "False" 106 | true_rationale | ✓ | dictionary | A locale dictionary for the text that explains why "True" is correct or incorrect 107 | false_rationale | ✓ | dictionary | A locale dictionary for the text that explains why "False" is correct or incorrect 108 | 109 | #### reflective-text 110 | 111 | A quiz item that has a free-text question. No matter what a learner answers, it 112 | will always be correct as long as the answer has more than five words. 113 | 114 | attribute | required | type | notes 115 | --------- | -------- | ---------- | ----- 116 | id | ✓ | string | A unique identifier for this item 117 | type | ✓ | string | The item type, which is always `reflective-text` 118 | stem | ✓ | dictionary | A locale dictionary for the text that asks the question, such as "What skills do you already have that can help you on your journey to becoming a UX designer?" 119 | feedback | ✓ | dictionary | A locale dictionary for the text that responses to the learner's written text, such as "Thank you for reflecting on the skills you bring to this certificate program." 120 | 121 | #### match Items 122 | 123 | A quiz item that has multiple stems with a "lead in" prompt. The correct option 124 | for each matching stem is directly specified as the answer. A match item will be 125 | scored based on correctly matching *all* the stems. 126 | 127 | attribute | required | type | notes 128 | --------- | -------- | ---------- | ----- 129 | id | ✓ | string | A unique identifier for this item 130 | type | ✓ | string | The item type, which is always `match` 131 | lead_in | ✓ | dictionary | A locale dictionary of text that provides a lead-in, such as "Can You Match the Capital City to the Correct US State?" 132 | stems | ✓ | array | An array of `matching stems` (see below for details); order does not matter 133 | options | ✓ | array | An array of `options` (see below for details); order does not matter 134 | 135 | ### matching Stems 136 | 137 | Match items need an additional `stems` array which contains the question(s) for 138 | which the user must provide the matching answer. 139 | 140 | attribute | required | type | notes 141 | --------- | -------- | ---------- | ----- 142 | id | ✓ | string | A unique ID for this matching Stem 143 | title | ✓ | dictionary | A locale dictionary for the content of this stem, such as "Springfield" 144 | answer | ✓ | string | ID for option that is the answer for this stem 145 | 146 | ### Option 147 | 148 | `multiple-choice`, `multiple-select` and `match` items all have an `options` 149 | array which contains all of the answer(s) and distractors that the user may 150 | choose from. Options are defined for these item types below: 151 | 152 | attribute | required | type | notes 153 | --------- | -------- | ---------- | ----- 154 | id | ✓ | string | A unique ID for this Option 155 | title | ✓ | dictionary | A locale dictionary for the content of this option, such as "Blue" 156 | rationale | ✓ | dictionary | A locale dictionary for an explanation of why this option is correct or incorrect (optional for `match` type) 157 | is_answer | ✓ | boolean | `true` if this option is an answer, and `false` if it is a distractor (unused for `match` type) 158 | fixedPlace | | boolean | `true` if this option should be fixed in place when shuffling the answer (this is treated as `false` if it's missing) 159 | -------------------------------------------------------------------------------- /resource-spec.md: -------------------------------------------------------------------------------- 1 | # Qwiklabs Resource Specification 2 | 3 | Resources are additional materials that learners may refer to while taking a lab 4 | or course. They show up in the student resources section of the lab's control 5 | panel ([example](https://screenshot.googleplex.com/5zaM3fpob85Yorw)) 6 | 7 | We encourage content authors to use as few external links as possible. Qwiklabs 8 | cannot guarantee that those links will be available when a learner takes your 9 | lab or course. For instance, if you have a PDF that you wish to include, you 10 | should add it as a file in this bundle instead of referencing it as a link to 11 | Cloud Storage or S3. 12 | 13 | For files larger than 50MB, please use an externally referenced resource. Your 14 | entire content bundle should be less than 100MB. 15 | 16 | > **Note**: If you are linking to an external resource that has its own 17 | > understanding of source control, please link to the specific revision of that 18 | > resource. That way, if the external resource is updated, your learners will 19 | > not be affected. For example, if you are referencing a Github repo, include 20 | > the link to a specific tag, instead of the default branch. 21 | > 22 | > Brittle: 23 | > 24 | > Better: 25 | > 26 | 27 | attribute | required | type | notes 28 | ----------- | -------- | ---------- | ----- 29 | type | ✓ | enum | [See list of valid types below] 30 | id | | string | Identifier that can be used throughout project bundle and translation pipeline 31 | title | ✓ | dictionary | Localized title of the resource 32 | description | | dictionary | Localized description of the resource 33 | uri | | dictionary | Localized URI of the resource 34 | 35 | ## Videos for Courses 36 | 37 | Videos for general container entities (non-labs) have the following additional 38 | attributes: 39 | 40 | attribute | required | type | notes 41 | -------------- | -------- | ---------- | ----- 42 | video_id | ✓ | dictionary | Localized video_ids as defined by the video provider. For example, a YouTube video_id has the form dQw4w9WgXcQ 43 | video_provider | ✓ | string | The video provider, e.g. YouTube 44 | duration | ✓ | integer | The duration of the video (in seconds). 45 | 46 | ## Example 47 | 48 | ```yaml 49 | resources: 50 | - type: link 51 | id: repo-link 52 | title: Self-referential Github Repo 53 | uri: https://github.com/CloudVLab/qwiklabs-lab-bundle-spec/tree/v1-prerelease 54 | - type: file 55 | title: Sample PDF 56 | description: This PDF contains all of the code samples for the lab. 57 | uri: "./resources/sample-en.pdf" 58 | - type: video 59 | id: course-video 60 | title: Welcome to GCP! 61 | video_id: oHg5SJYRHA0 62 | video_provider: YouTube 63 | duration: 360 64 | - type: html_bundle 65 | title: Sample HTML 66 | description: This HTML page makes learning interactive. 67 | uri: "https://storage.googleapis.com/cloud-training/cls-html5-courses/C-GTI-I/index.html" 68 | ``` 69 | 70 | ## Valid types 71 | 72 | * `file` - A relative path to a file in the bundle 73 | * `link` - A url to an external resource 74 | * `video` - A link to a video outside of the bundle such as on Youtube 75 | * `html_bundle` - A url to an HTML file. The file must be stored in the Cloud Training GCS bucket: https://pantheon.corp.google.com/storage/browser/cloud-training. 76 | 77 | To prevent confusion, all resources must explicitly define what type they are. 78 | 79 | > **Aside:** Why define external resources instead of putting links directly in 80 | > lab instructions? 81 | > 82 | > 1. You can reference your resource directly in your instructions and will be 83 | > displayed in a special format, depending on its type. For example, a 84 | > YouTube link will be displayed as an embedded widget. 85 | > 86 | > 2. You can edit the resource in one location and every place it is referenced 87 | > will be updated (also across locales). 88 | > 89 | > 3. In courses resources appear as standalone steps, which raises learners' 90 | > awareness of them. 91 | --------------------------------------------------------------------------------