├── .gitignore ├── LICENSE ├── README.md ├── section-1 ├── video-1.2 │ ├── README.md │ └── spring-boot-http-gradle │ │ ├── .dockerignore │ │ ├── .gitignore │ │ ├── .helmignore │ │ ├── Dockerfile │ │ ├── LICENSE │ │ ├── README.md │ │ ├── build.gradle │ │ ├── charts │ │ ├── preview │ │ │ ├── Chart.yaml │ │ │ ├── Makefile │ │ │ ├── requirements.yaml │ │ │ └── values.yaml │ │ └── spring-boot-http-gradle │ │ │ ├── .helmignore │ │ │ ├── Chart.yaml │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── templates │ │ │ ├── NOTES.txt │ │ │ ├── _helpers.tpl │ │ │ ├── canary.yaml │ │ │ ├── deployment.yaml │ │ │ ├── hpa.yaml │ │ │ ├── ksvc.yaml │ │ │ └── service.yaml │ │ │ └── values.yaml │ │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ ├── jenkins-x.yml │ │ ├── skaffold.yaml │ │ ├── src │ │ ├── main │ │ │ └── java │ │ │ │ └── hello │ │ │ │ ├── Application.java │ │ │ │ ├── Greeting.java │ │ │ │ └── GreetingController.java │ │ └── test │ │ │ └── java │ │ │ └── hello │ │ │ └── GreetingControllerTests.java │ │ └── watch.sh ├── video-1.3 │ └── README.md ├── video-1.4 │ └── README.md ├── video-1.5 │ └── README.md └── video-1.6 │ ├── README.md │ └── jx-requirements.yml ├── section-2 ├── video-2.1 │ └── README.md ├── video-2.2 │ ├── README.md │ └── express-hello │ │ ├── .gitignore │ │ ├── index.js │ │ ├── package-lock.json │ │ └── package.json ├── video-2.3 │ └── README.md ├── video-2.4 │ └── README.md ├── video-2.5 │ └── README.md └── video-2.6 │ └── README.md ├── section-3 ├── video-3.1 │ ├── README.md │ └── hello-video-3-1 │ │ ├── .gitignore │ │ ├── index.js │ │ ├── package-lock.json │ │ └── package.json ├── video-3.2 │ ├── README.md │ ├── hello-3-2-auto │ │ ├── .gitignore │ │ ├── index.js │ │ ├── package-lock.json │ │ └── package.json │ └── hello-3-2-specify │ │ ├── .gitignore │ │ ├── index.js │ │ ├── package-lock.json │ │ └── package.json ├── video-3.3 │ └── README.md ├── video-3.4 │ └── README.md └── video-3.5 │ ├── README.md │ ├── hello-3-5-audit │ ├── .gitignore │ ├── index.js │ ├── jenkins-x.yml │ ├── package-lock.json │ └── package.json │ └── hello-3-5-replace │ ├── .gitignore │ ├── index.js │ ├── jenkins-x.yml │ ├── package-lock.json │ └── package.json ├── section-4 ├── video-4.1 │ ├── README.md │ └── hello-4-1 │ │ ├── .gitignore │ │ ├── index.js │ │ ├── jenkins-x.yml │ │ ├── package-lock.json │ │ └── package.json ├── video-4.2 │ ├── README.md │ └── hello-4-2 │ │ ├── .gitignore │ │ ├── index.js │ │ ├── jenkins-x.yml │ │ ├── package-lock.json │ │ └── package.json ├── video-4.3 │ ├── README.md │ └── hello-4-3 │ │ ├── .gitignore │ │ ├── index.js │ │ ├── jenkins-x.yml │ │ ├── package-lock.json │ │ └── package.json ├── video-4.4 │ ├── README.md │ └── hello-4-4 │ │ ├── .gitignore │ │ ├── index.js │ │ ├── jenkins-x.yml │ │ ├── package-lock.json │ │ └── package.json └── video-4.5 │ └── README.md ├── section-5 ├── video-5.1 │ ├── README.md │ └── plone.yaml ├── video-5.2 │ ├── README.md │ └── deployment.yaml ├── video-5.3 │ ├── README.md │ └── service.yaml ├── video-5.4 │ ├── README.md │ └── plone.yaml ├── video-5.5 │ ├── README.md │ └── values.yaml └── video-5.6 │ ├── README.md │ ├── bad-command │ └── deployment.yaml │ ├── bad-image-name │ └── deployment.yaml │ └── good-deployment │ └── deployment.yaml └── section-6 ├── video-6.1 └── README.md ├── video-6.2 └── README.md ├── video-6.3 └── README.md └── video-6.4 └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | jenkins-x-boot-config 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Hands-On Continuous Integration and Delivery with Jenkins X and Kubernetes [Video] 5 | This is the code repository for [Hands-On Continuous Integration and Delivery with Jenkins X and Kubernetes [Video]]( https://www.packtpub.com/cloud-networking/hands-on-continuous-integration-and-delivery-with-jenkins-x-and-kubernetes-video), published by [Packt](https://www.packtpub.com/?utm_source=github ). It contains all the supporting project files necessary to work through the video course from start to finish. 6 | 7 | ## About the Video Course 8 | Jenkins X is an exciting and fast way to build applications on Kubernetes. Jenkins X handles the job of configuring Kubernetes to build, test, and deploy your applications, so you can focus on fast delivery and make your applications great! 9 | Kubernetes is powerful but complicated; using it not only to run your application but also to build and test it requires a lot of configuration. Jenkins X provides automation for Kubernetes so you can use it to its full potential without spending all of your time configuring and debugging. 10 | This course adopts a step-by-step approach to show you how to use Jenkins X, with plenty of hands-on examples that you can use for your own applications. You'll start with a simple example application deployed to Kubernetes using Jenkins X, then build up to awesome features such as preview environments, promotion, and monitoring. With this course, you can learn Jenkins X fast, and immediately apply what you've learned.
11 | 12 |

What You Will Learn

13 |
14 | 15 |
22 | 23 | ## Instructions and Navigation 24 | ### Assumed Knowledge 25 | This course is for developers, IT/DevOps professionals, or system admins keen to take advantage of Jenkins X and Kubernetes to enhance their Continuous Delivery processes. A basic knowledge of developing and building software is assumed. 26 | This course requires use of a text editor (e.g. Atom); Git client (graphical or command line); and access to Google Cloud Engine and GitHub. 27 | 28 | ## Technical Requirements
29 | #### Minimum Hardware Requirements 30 | For successful completion of this course, students will require a computer system with at least the following: 31 | 32 | OS: Linux (recommended), Windows, or macOS 33 | Processor: Dual-core processor 34 | Memory: 4 GB 35 | Storage: 120 GB 36 | 37 | The course examples demonstrate the installation and use on Linux. To run with the minimum hardware requirements, students will also need the ability to create Kubernetes clusters in a cloud environment. 38 | 39 | #### Recommended Hardware Requirements
40 | For an optimal experience with hands-on labs and other practical activities, students require access to sufficient hardware to run a virtual machine: 41 | 42 | OS: Linux (recommended), Windows, or macOS 43 | Processor: Quad-core processor 44 | Memory: 8 GB 45 | Storage: 120 GB 46 | 47 | This will permit using Jenkins X and Kubernetes via Minikube. Access to a cloud environment is also strongly recommended. 48 | 49 | #### Software Requirements
50 | The following requirements are recommended to view and edit the example files. 51 | 52 | Operating system: Windows, Linux, or macOS 53 | Hypervisor: VirtualBox or Hyper-V 54 | Browser: Chrome or Firefox (latest version) 55 | IDE (Visual Studio Code or IntelliJ recommended) 56 |
57 | 58 | ## Important Note 59 | 60 | We will be using cloud resources, with the possibility that this will cost 61 | money. Google Cloud Platform has a limited-time free tier, and our 62 | setup will stay within the free tier, but once your free period expires 63 | there will be a cost, which is greater as long as you have nodes in your 64 | cluster's node pool. 65 | 66 | To reduce costs while keeping your cluster configuration, you can resize the 67 | cluster's node pool to 0, and then size it back up when you're ready to use 68 | it. Remember to also turn off autoscaling so it doesn't scale back up again, 69 | and revisit the cluster page to make sure the nodes were deleted properly. 70 | 71 | Of course, you can also delete your cluster entirely and re-create it using 72 | the instructions in Section 1. 73 | 74 | ## Application Cleanup 75 | 76 | Throughout these videos, we will be creating applications in our Jenkins X 77 | cluster. These applications will continue to run unless deleted or the cluster 78 | is deleted from Google Kubernetes Engine. 79 | 80 | To delete applications from Jenkins X, use the `jx delete application` 81 | command. This will prompt you for one or more applications to delete. You will 82 | have to manually remove the Git repository in GitHub. 83 | 84 | One note of caution: as of when these videos were recorded, deleting the 85 | application does not completely remove it from Jenkins X. There will still be 86 | files in the boot configuration repository and Helm charts in chartmuseum. For 87 | this reason, it is not safe to delete an application and add a new application 88 | with the same name. 89 | 90 | ## Related Products 91 | * [Adobe After Effects CC: Tips, Tricks, and Techniques [Video]](https://www.packtpub.com/business-other/adobe-after-effects-cc-tips-tricks-and-techniques-video) 92 | 93 | * [Mastering Palo Alto Networks [Video]](https://www.packtpub.com/networking-and-servers/mastering-palo-alto-networks-video) 94 | 95 | * [Azure Cognitive Services for Developers [Video]](https://www.packtpub.com/application-development/azure-cognitive-services-developers-video) 96 | -------------------------------------------------------------------------------- /section-1/video-1.2/README.md: -------------------------------------------------------------------------------- 1 | # Video 1.2 2 | 3 | This video demonstrates Jenkins X. 4 | 5 | ## Prerequisites 6 | 7 | To try out this example for yourself, you will need a Jenkins X cluster up 8 | and running. You can accomplish this by following the instructions in the 9 | rest of Section 1. 10 | 11 | ## Import 12 | 13 | This directory contains source code from a Jenkins X quickstart example. Once 14 | you have a Jenkins X cluster, you can add this software to your Jenkins X 15 | cluster using the `jx import` command: 16 | 17 | ``` 18 | jx import spring-boot-http-gradle 19 | ``` 20 | 21 | Or, even easier, you can follow the instructions in Video 2.1 to create 22 | this application from the original quickstart. 23 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/.dockerignore: -------------------------------------------------------------------------------- 1 | draft.toml 2 | charts/ 3 | NOTICE 4 | LICENSE 5 | README.md -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/.gitignore: -------------------------------------------------------------------------------- 1 | *.sw? 2 | .#* 3 | *# 4 | *~ 5 | .classpath 6 | .project 7 | .settings 8 | bin 9 | build 10 | target 11 | dependency-reduced-pom.xml 12 | *.sublime-* 13 | /scratch 14 | .gradle 15 | README.html 16 | *.iml 17 | .idea 18 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | *.png 23 | 24 | # known compile time folders 25 | target/ 26 | node_modules/ 27 | vendor/ -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jdk-slim 2 | ENV PORT 8080 3 | EXPOSE 8080 4 | COPY build/libs/*.jar /opt/app.jar 5 | WORKDIR /opt 6 | CMD ["java", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseCGroupMemoryLimitForHeap", "-jar", "app.jar"] -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/README.md: -------------------------------------------------------------------------------- 1 | Minimal Jenkins X demo repo based on https://spring.io/guides/gs/consuming-rest/ with the [Spring Actuator](https://spring.io/guides/gs/actuator-service) added in 2 | 3 | While the original example offers both Maven and Gradle the idea with this demo was to focus purely on Gradle, exercising a new Jenkins X Gradle build pack. 4 | 5 | Run locally with `gradlew bootRun` 6 | 7 | Test via http://localhost:8080/greeting 8 | 9 | Health check at http://localhost:8080/actuator/health 10 | 11 | Credit: thanks to https://github.com/Cervator for the contribution of this quickstart 12 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | mavenCentral() 4 | } 5 | dependencies { 6 | classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.2.RELEASE") 7 | } 8 | } 9 | 10 | apply plugin: 'java' 11 | apply plugin: 'eclipse' 12 | apply plugin: 'idea' 13 | apply plugin: 'org.springframework.boot' 14 | apply plugin: 'io.spring.dependency-management' 15 | 16 | bootJar { 17 | baseName = 'restyserv' 18 | version = '0.3.0' 19 | } 20 | 21 | repositories { 22 | mavenCentral() 23 | } 24 | 25 | sourceCompatibility = 1.8 26 | targetCompatibility = 1.8 27 | 28 | dependencies { 29 | compile("org.springframework.boot:spring-boot-starter-web") 30 | compile("org.springframework.boot:spring-boot-starter-actuator") 31 | testCompile('org.springframework.boot:spring-boot-starter-test') 32 | testCompile('com.jayway.jsonpath:json-path') 33 | } 34 | 35 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/charts/preview/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | description: A Helm chart for Kubernetes 3 | icon: https://raw.githubusercontent.com/jenkins-x/jenkins-x-platform/master/images/java.png 4 | name: preview 5 | version: 0.1.0-SNAPSHOT 6 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/charts/preview/Makefile: -------------------------------------------------------------------------------- 1 | OS := $(shell uname) 2 | 3 | preview: 4 | ifeq ($(OS),Darwin) 5 | sed -i "" -e "s/version:.*/version: $(PREVIEW_VERSION)/" Chart.yaml 6 | sed -i "" -e "s/version:.*/version: $(PREVIEW_VERSION)/" ../*/Chart.yaml 7 | sed -i "" -e "s/tag:.*/tag: $(PREVIEW_VERSION)/" values.yaml 8 | else ifeq ($(OS),Linux) 9 | sed -i -e "s/version:.*/version: $(PREVIEW_VERSION)/" Chart.yaml 10 | sed -i -e "s/version:.*/version: $(PREVIEW_VERSION)/" ../*/Chart.yaml 11 | sed -i -e "s|repository:.*|repository: $(DOCKER_REGISTRY)\/jenkins-x-263922\/spring-boot-http-gradle|" values.yaml 12 | sed -i -e "s/tag:.*/tag: $(PREVIEW_VERSION)/" values.yaml 13 | else 14 | echo "platfrom $(OS) not supported to release from" 15 | exit -1 16 | endif 17 | echo " version: $(PREVIEW_VERSION)" >> requirements.yaml 18 | jx step helm build 19 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/charts/preview/requirements.yaml: -------------------------------------------------------------------------------- 1 | # !! File must end with empty line !! 2 | dependencies: 3 | - alias: expose 4 | name: exposecontroller 5 | repository: http://chartmuseum.jenkins-x.io 6 | version: 2.3.92 7 | - alias: cleanup 8 | name: exposecontroller 9 | repository: http://chartmuseum.jenkins-x.io 10 | version: 2.3.92 11 | 12 | # !! "alias: preview" must be last entry in dependencies array !! 13 | # !! Place custom dependencies above !! 14 | - alias: preview 15 | name: spring-boot-http-gradle 16 | repository: file://../spring-boot-http-gradle 17 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/charts/preview/values.yaml: -------------------------------------------------------------------------------- 1 | 2 | expose: 3 | Annotations: 4 | helm.sh/hook: post-install,post-upgrade 5 | helm.sh/hook-delete-policy: hook-succeeded 6 | config: 7 | exposer: Ingress 8 | http: true 9 | tlsacme: false 10 | 11 | cleanup: 12 | Args: 13 | - --cleanup 14 | Annotations: 15 | helm.sh/hook: pre-delete 16 | helm.sh/hook-delete-policy: hook-succeeded 17 | 18 | preview: 19 | image: 20 | repository: 21 | tag: 22 | pullPolicy: IfNotPresent -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/charts/spring-boot-http-gradle/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/charts/spring-boot-http-gradle/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | description: A Helm chart for Kubernetes 3 | icon: https://raw.githubusercontent.com/jenkins-x/jenkins-x-platform/master/images/java.png 4 | name: spring-boot-http-gradle 5 | version: 0.1.0-SNAPSHOT 6 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/charts/spring-boot-http-gradle/Makefile: -------------------------------------------------------------------------------- 1 | CHART_REPO := http://jenkins-x-chartmuseum:8080 2 | CURRENT=$(pwd) 3 | NAME := spring-boot-http-gradle 4 | OS := $(shell uname) 5 | RELEASE_VERSION := $(shell cat ../../VERSION) 6 | 7 | build: clean 8 | rm -rf requirements.lock 9 | helm dependency build 10 | helm lint 11 | 12 | install: clean build 13 | helm install . --name ${NAME} 14 | 15 | upgrade: clean build 16 | helm upgrade ${NAME} . 17 | 18 | delete: 19 | helm delete --purge ${NAME} 20 | 21 | clean: 22 | rm -rf charts 23 | rm -rf ${NAME}*.tgz 24 | 25 | release: clean 26 | helm dependency build 27 | helm lint 28 | helm init --client-only 29 | helm package . 30 | curl --fail -u $(CHARTMUSEUM_CREDS_USR):$(CHARTMUSEUM_CREDS_PSW) --data-binary "@$(NAME)-$(shell sed -n 's/^version: //p' Chart.yaml).tgz" $(CHART_REPO)/api/charts 31 | rm -rf ${NAME}*.tgz% 32 | 33 | tag: 34 | ifeq ($(OS),Darwin) 35 | sed -i "" -e "s/version:.*/version: $(RELEASE_VERSION)/" Chart.yaml 36 | sed -i "" -e "s/tag:.*/tag: $(RELEASE_VERSION)/" values.yaml 37 | else ifeq ($(OS),Linux) 38 | sed -i -e "s/version:.*/version: $(RELEASE_VERSION)/" Chart.yaml 39 | sed -i -e "s|repository:.*|repository: $(DOCKER_REGISTRY)\/jenkins-x-263922\/spring-boot-http-gradle|" values.yaml 40 | sed -i -e "s/tag:.*/tag: $(RELEASE_VERSION)/" values.yaml 41 | else 42 | echo "platfrom $(OS) not supported to release from" 43 | exit -1 44 | endif 45 | git add --all 46 | git commit -m "release $(RELEASE_VERSION)" --allow-empty # if first release then no verion update is performed 47 | git tag -fa v$(RELEASE_VERSION) -m "Release version $(RELEASE_VERSION)" 48 | git push origin v$(RELEASE_VERSION) 49 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/charts/spring-boot-http-gradle/README.md: -------------------------------------------------------------------------------- 1 | # Java application -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/charts/spring-boot-http-gradle/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 2 | Get the application URL by running these commands: 3 | 4 | kubectl get ingress {{ template "fullname" . }} 5 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/charts/spring-boot-http-gradle/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | */}} 13 | {{- define "fullname" -}} 14 | {{- $name := default .Chart.Name .Values.nameOverride -}} 15 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 16 | {{- end -}} 17 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/charts/spring-boot-http-gradle/templates/canary.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.canary.enabled }} 2 | apiVersion: flagger.app/v1alpha3 3 | kind: Canary 4 | metadata: 5 | name: {{ template "fullname" . }} 6 | labels: 7 | draft: {{ default "draft-app" .Values.draft }} 8 | chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" 9 | spec: 10 | provider: istio 11 | targetRef: 12 | apiVersion: apps/v1 13 | kind: Deployment 14 | name: {{ template "fullname" . }} 15 | progressDeadlineSeconds: {{ .Values.canary.progressDeadlineSeconds }} 16 | {{- if .Values.hpa.enabled }} 17 | autoscalerRef: 18 | apiVersion: autoscaling/v2beta1 19 | kind: HorizontalPodAutoscaler 20 | name: {{ template "fullname" . }} 21 | {{- end }} 22 | service: 23 | port: {{ .Values.service.externalPort }} 24 | targetPort: {{ .Values.service.internalPort }} 25 | gateways: 26 | - {{ template "fullname" . }} 27 | hosts: 28 | - {{ .Values.canary.host }} 29 | canaryAnalysis: 30 | interval: {{ .Values.canary.canaryAnalysis.interval }} 31 | threshold: {{ .Values.canary.canaryAnalysis.threshold }} 32 | maxWeight: {{ .Values.canary.canaryAnalysis.maxWeight }} 33 | stepWeight: {{ .Values.canary.canaryAnalysis.stepWeight }} 34 | metrics: 35 | - name: request-success-rate 36 | threshold: {{ .Values.canary.canaryAnalysis.metrics.requestSuccessRate.threshold }} 37 | interval: {{ .Values.canary.canaryAnalysis.metrics.requestSuccessRate.interval }} 38 | - name: request-duration 39 | threshold: {{ .Values.canary.canaryAnalysis.metrics.requestDuration.threshold }} 40 | interval: {{ .Values.canary.canaryAnalysis.metrics.requestDuration.interval }} 41 | 42 | --- 43 | 44 | apiVersion: networking.istio.io/v1alpha3 45 | kind: Gateway 46 | metadata: 47 | name: {{ template "fullname" . }} 48 | spec: 49 | selector: 50 | istio: ingressgateway 51 | servers: 52 | - port: 53 | number: {{ .Values.service.externalPort }} 54 | name: http 55 | protocol: HTTP 56 | hosts: 57 | - {{ .Values.canary.host }} 58 | {{- end }} 59 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/charts/spring-boot-http-gradle/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.knativeDeploy }} 2 | {{- else }} 3 | apiVersion: extensions/v1beta1 4 | kind: Deployment 5 | metadata: 6 | name: {{ template "fullname" . }} 7 | labels: 8 | draft: {{ default "draft-app" .Values.draft }} 9 | chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" 10 | spec: 11 | {{- if .Values.hpa.enabled }} 12 | {{- else }} 13 | replicas: {{ .Values.replicaCount }} 14 | {{- end }} 15 | template: 16 | metadata: 17 | labels: 18 | draft: {{ default "draft-app" .Values.draft }} 19 | app: {{ template "fullname" . }} 20 | {{- if .Values.podAnnotations }} 21 | annotations: 22 | {{ toYaml .Values.podAnnotations | indent 8 }} 23 | {{- end }} 24 | spec: 25 | containers: 26 | - name: {{ .Chart.Name }} 27 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" 28 | imagePullPolicy: {{ .Values.image.pullPolicy }} 29 | env: 30 | {{- range $pkey, $pval := .Values.env }} 31 | - name: {{ $pkey }} 32 | value: {{ quote $pval }} 33 | {{- end }} 34 | envFrom: 35 | {{ toYaml .Values.envFrom | indent 10 }} 36 | ports: 37 | - containerPort: {{ .Values.service.internalPort }} 38 | livenessProbe: 39 | httpGet: 40 | path: {{ .Values.probePath }} 41 | port: {{ .Values.service.internalPort }} 42 | initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} 43 | periodSeconds: {{ .Values.livenessProbe.periodSeconds }} 44 | successThreshold: {{ .Values.livenessProbe.successThreshold }} 45 | timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} 46 | readinessProbe: 47 | httpGet: 48 | path: {{ .Values.probePath }} 49 | port: {{ .Values.service.internalPort }} 50 | periodSeconds: {{ .Values.readinessProbe.periodSeconds }} 51 | successThreshold: {{ .Values.readinessProbe.successThreshold }} 52 | timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} 53 | resources: 54 | {{ toYaml .Values.resources | indent 12 }} 55 | terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} 56 | {{- end }} 57 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/charts/spring-boot-http-gradle/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.hpa.enabled }} 2 | apiVersion: autoscaling/v2beta1 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ template "fullname" . }} 6 | labels: 7 | draft: {{ default "draft-app" .Values.draft }} 8 | chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" 9 | spec: 10 | scaleTargetRef: 11 | apiVersion: apps/v1 12 | kind: Deployment 13 | name: {{ template "fullname" . }} 14 | minReplicas: {{ .Values.hpa.minReplicas }} 15 | maxReplicas: {{ .Values.hpa.maxReplicas }} 16 | metrics: 17 | - type: Resource 18 | resource: 19 | name: cpu 20 | targetAverageUtilization: {{ .Values.hpa.cpuTargetAverageUtilization }} 21 | - type: Resource 22 | resource: 23 | name: memory 24 | targetAverageUtilization: {{ .Values.hpa.memoryTargetAverageUtilization }} 25 | {{- end }} -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/charts/spring-boot-http-gradle/templates/ksvc.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.knativeDeploy }} 2 | apiVersion: serving.knative.dev/v1alpha1 3 | kind: Service 4 | metadata: 5 | {{- if .Values.service.name }} 6 | name: {{ .Values.service.name }} 7 | {{- else }} 8 | name: {{ template "fullname" . }} 9 | {{- end }} 10 | labels: 11 | chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" 12 | spec: 13 | runLatest: 14 | configuration: 15 | revisionTemplate: 16 | spec: 17 | container: 18 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" 19 | imagePullPolicy: {{ .Values.image.pullPolicy }} 20 | env: 21 | {{- range $pkey, $pval := .Values.env }} 22 | - name: {{ $pkey }} 23 | value: {{ quote $pval }} 24 | {{- end }} 25 | livenessProbe: 26 | httpGet: 27 | path: {{ .Values.probePath }} 28 | initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} 29 | periodSeconds: {{ .Values.livenessProbe.periodSeconds }} 30 | successThreshold: {{ .Values.livenessProbe.successThreshold }} 31 | timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} 32 | readinessProbe: 33 | failureThreshold: {{ .Values.readinessProbe.failureThreshold }} 34 | httpGet: 35 | path: {{ .Values.probePath }} 36 | periodSeconds: {{ .Values.readinessProbe.periodSeconds }} 37 | successThreshold: {{ .Values.readinessProbe.successThreshold }} 38 | timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} 39 | resources: 40 | {{ toYaml .Values.resources | indent 14 }} 41 | {{- end }} 42 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/charts/spring-boot-http-gradle/templates/service.yaml: -------------------------------------------------------------------------------- 1 | {{- if or .Values.knativeDeploy .Values.canary.enabled }} 2 | {{- else }} 3 | apiVersion: v1 4 | kind: Service 5 | metadata: 6 | {{- if .Values.service.name }} 7 | name: {{ .Values.service.name }} 8 | {{- else }} 9 | name: {{ template "fullname" . }} 10 | {{- end }} 11 | labels: 12 | chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" 13 | {{- if .Values.service.annotations }} 14 | annotations: 15 | {{ toYaml .Values.service.annotations | indent 4 }} 16 | {{- end }} 17 | spec: 18 | type: {{ .Values.service.type }} 19 | ports: 20 | - port: {{ .Values.service.externalPort }} 21 | targetPort: {{ .Values.service.internalPort }} 22 | protocol: TCP 23 | name: http 24 | selector: 25 | app: {{ template "fullname" . }} 26 | {{- end }} 27 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/charts/spring-boot-http-gradle/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for Gradle projects. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | replicaCount: 1 5 | image: 6 | repository: draft 7 | tag: dev 8 | pullPolicy: IfNotPresent 9 | 10 | # define environment variables here as a map of key: value 11 | env: 12 | 13 | # enable this flag to use knative serve to deploy the app 14 | knativeDeploy: false 15 | 16 | # HorizontalPodAutoscaler 17 | hpa: 18 | enabled: false 19 | minReplicas: 2 20 | maxReplicas: 6 21 | cpuTargetAverageUtilization: 80 22 | memoryTargetAverageUtilization: 80 23 | 24 | # Canary deployments 25 | # If enabled, Istio and Flagger need to be installed in the cluster 26 | canary: 27 | enabled: false 28 | progressDeadlineSeconds: 60 29 | canaryAnalysis: 30 | interval: "1m" 31 | threshold: 5 32 | maxWeight: 60 33 | stepWeight: 20 34 | # WARNING: Canary deployments will fail and rollback if there is no traffic that will generate the below specified metrics. 35 | metrics: 36 | requestSuccessRate: 37 | threshold: 99 38 | interval: "1m" 39 | requestDuration: 40 | threshold: 1000 41 | interval: "1m" 42 | # The host is using Istio Gateway and is currently not auto-generated 43 | # Please overwrite the `canary.host` in `values.yaml` in each environment repository (e.g., staging, production) 44 | host: acme.com 45 | 46 | service: 47 | name: spring-boot-http-gradle 48 | type: ClusterIP 49 | externalPort: 80 50 | internalPort: 8080 51 | annotations: 52 | fabric8.io/expose: "true" 53 | fabric8.io/ingress.annotations: "kubernetes.io/ingress.class: nginx" 54 | resources: 55 | limits: 56 | cpu: 500m 57 | memory: 512Mi 58 | requests: 59 | cpu: 400m 60 | memory: 512Mi 61 | probePath: /actuator/health 62 | livenessProbe: 63 | initialDelaySeconds: 60 64 | periodSeconds: 10 65 | successThreshold: 1 66 | timeoutSeconds: 1 67 | readinessProbe: 68 | failureThreshold: 1 69 | periodSeconds: 10 70 | successThreshold: 1 71 | timeoutSeconds: 1 72 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Hands-On-Continuous-Integration-and-Delivery-with-Jenkins-X-and-Kubernetes/b0d9e86698f3506540e3e360fce1d695ded447e0/section-1/video-1.2/spring-boot-http-gradle/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon May 28 22:31:05 EDT 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip 7 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/jenkins-x.yml: -------------------------------------------------------------------------------- 1 | buildPack: gradle 2 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/skaffold.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: skaffold/v1beta2 2 | kind: Config 3 | build: 4 | artifacts: 5 | - image: jenkins-x-263922/spring-boot-http-gradle 6 | context: . 7 | docker: {} 8 | tagPolicy: 9 | envTemplate: 10 | template: '{{.DOCKER_REGISTRY}}/{{.IMAGE_NAME}}:{{.VERSION}}' 11 | local: {} 12 | deploy: 13 | kubectl: {} 14 | profiles: 15 | - name: dev 16 | build: 17 | tagPolicy: 18 | envTemplate: 19 | template: '{{.DOCKER_REGISTRY}}/{{.IMAGE_NAME}}:{{.DIGEST_HEX}}' 20 | local: {} 21 | deploy: 22 | helm: 23 | releases: 24 | - name: spring-boot-http-gradle 25 | chartPath: charts/spring-boot-http-gradle 26 | setValueTemplates: 27 | image.repository: '{{.DOCKER_REGISTRY}}/{{.IMAGE_NAME}}' 28 | image.tag: '{{.DIGEST_HEX}}' 29 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/src/main/java/hello/Application.java: -------------------------------------------------------------------------------- 1 | package hello; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Application { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(Application.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/src/main/java/hello/Greeting.java: -------------------------------------------------------------------------------- 1 | package hello; 2 | 3 | public class Greeting { 4 | 5 | private final long id; 6 | private final String content; 7 | 8 | public Greeting(long id, String content) { 9 | this.id = id; 10 | this.content = content; 11 | } 12 | 13 | public long getId() { 14 | return id; 15 | } 16 | 17 | public String getContent() { 18 | return content; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/src/main/java/hello/GreetingController.java: -------------------------------------------------------------------------------- 1 | package hello; 2 | 3 | import java.util.concurrent.atomic.AtomicLong; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | public class GreetingController { 10 | 11 | private static final String template = "Hello there, %s!"; 12 | private final AtomicLong counter = new AtomicLong(); 13 | 14 | @RequestMapping("/universe") 15 | public Greeting universe(@RequestParam(value="name", defaultValue="Universe") String name) { 16 | return new Greeting(counter.incrementAndGet(), 17 | String.format(template, name)); 18 | } 19 | 20 | @RequestMapping("/greeting") 21 | public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) { 22 | return new Greeting(counter.incrementAndGet(), 23 | String.format(template, name)); 24 | } 25 | 26 | @RequestMapping("/") 27 | public String defaultEndpoint(@RequestParam(value="name", defaultValue="World") String name) { 28 | return String.format(template, name); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/src/test/java/hello/GreetingControllerTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package hello; 17 | 18 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 19 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; 20 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; 21 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 22 | 23 | import org.junit.Test; 24 | import org.junit.runner.RunWith; 25 | import org.springframework.beans.factory.annotation.Autowired; 26 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; 27 | import org.springframework.boot.test.context.SpringBootTest; 28 | import org.springframework.test.context.junit4.SpringRunner; 29 | import org.springframework.test.web.servlet.MockMvc; 30 | 31 | @RunWith(SpringRunner.class) 32 | @SpringBootTest 33 | @AutoConfigureMockMvc 34 | public class GreetingControllerTests { 35 | 36 | @Autowired 37 | private MockMvc mockMvc; 38 | 39 | @Test 40 | public void noParamGreetingShouldReturnDefaultMessage() throws Exception { 41 | 42 | this.mockMvc.perform(get("/greeting")).andDo(print()).andExpect(status().isOk()) 43 | .andExpect(jsonPath("$.content").value("Hello there, World!")); 44 | } 45 | 46 | @Test 47 | public void noParamDefaultEndpointShouldReturnDefaultMessage() throws Exception { 48 | this.mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk()); 49 | } 50 | 51 | @Test 52 | public void paramGreetingShouldReturnTailoredMessage() throws Exception { 53 | 54 | this.mockMvc.perform(get("/greeting").param("name", "Spring Community")) 55 | .andDo(print()).andExpect(status().isOk()) 56 | .andExpect(jsonPath("$.content").value("Hello there, Spring Community!")); 57 | } 58 | 59 | @Test 60 | public void paramDefaultEndpointShouldReturnTailoredMessage() throws Exception { 61 | this.mockMvc.perform(get("/").param("name", "Spring Community")) 62 | .andDo(print()).andExpect(status().isOk()); 63 | } 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /section-1/video-1.2/spring-boot-http-gradle/watch.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # watch the java files and continously deploy the service 4 | gradle build 5 | skaffold run -p dev 6 | reflex -r "\.java$" -- bash -c 'gradle build && skaffold run -p dev' 7 | -------------------------------------------------------------------------------- /section-1/video-1.3/README.md: -------------------------------------------------------------------------------- 1 | # Video 1.3 2 | 3 | In this video we will install `jx`, the Jenkins X command line tool. 4 | 5 | ## Installing 6 | 7 | Start by visiting this link: 8 | 9 | https://jenkins-x.io/docs/getting-started/setup/install/ 10 | 11 | There are download instructions for macOS, Linux, and Windows. 12 | 13 | ## Linux PATH 14 | 15 | For the Linux installation, we need to make sure that `jx` is on the PATH. 16 | I recommend creating a directory `$HOME/bin` as this will allow updating 17 | `jx` as a normal user. 18 | 19 | To create the directory and move `jx` there: 20 | 21 | ``` 22 | mkdir -p $HOME/bin 23 | mv jx $HOME/bin 24 | ``` 25 | 26 | In many cases, the `$HOME/bin` directory will already be on the PATH. If not, 27 | add this line to `$HOME/.bashrc` or `$HOME/.bash_profile`, as applicable: 28 | 29 | ``` 30 | export PATH="$HOME/bin:${PATH}" 31 | ``` 32 | 33 | ## Verifying Install 34 | 35 | To verify that `jx` is installed correctly and check the version, run: 36 | 37 | ``` 38 | jx --version 39 | ``` 40 | -------------------------------------------------------------------------------- /section-1/video-1.4/README.md: -------------------------------------------------------------------------------- 1 | # Video 1.4 2 | 3 | To create a Kubernetes cluster for Jenkins X, we will use Google Kubernetes 4 | Engine. 5 | 6 | ## Prerequisites 7 | 8 | In order to complete this lesson, you will need to create an account with 9 | Google Cloud Platform: 10 | 11 | https://cloud.google.com/ 12 | 13 | You will also need a Google Cloud Platform project. Follow the instructions 14 | here: 15 | 16 | https://cloud.google.com/resource-manager/docs/creating-managing-projects 17 | 18 | Finally, you will need the `jx` command line tool as installed in the previous 19 | video. 20 | 21 | ## Creating a Cluster 22 | 23 | We will use the `jx create cluster gke` command to create the cluster. 24 | 25 | Run: 26 | 27 | ``` 28 | jx create cluster gke --cluster-name=jenkinsx --skip-installation 29 | ``` 30 | 31 | Follow the prompts as described in the video. 32 | -------------------------------------------------------------------------------- /section-1/video-1.5/README.md: -------------------------------------------------------------------------------- 1 | # Video 1.5 2 | 3 | ## GitOps 4 | 5 | Jenkins X uses GitOps to manage the Jenkins X installation. This means 6 | that the Jenkins X configuration is stored in a Git repository, and any 7 | changes we make, whether directly or with the `jx` command line tool, are 8 | reflected in the Git repository for the installation. 9 | 10 | ## GitHub Setup 11 | 12 | In order for Jenkins X to perform GitOps, it needs access to a Git repository 13 | server. For this course, we are using GitHub. You can choose to either use 14 | your personal GitHub account for everything, or create a separate "bot" account 15 | and a GitHub organization. Just be sure to follow the GitHub terms of service 16 | for any accounts created for machine purposes. 17 | 18 | For this video, we'll demonstrate a GitHub organization that includes a 19 | personal account and a separate bot account. This will allow us to use the 20 | bot account for Jenkins X changes so we can see automated changes more easily. 21 | 22 | ## GitHub Access Token 23 | 24 | To get started, we need to give Jenkins X rights to make changes in our Git 25 | repositories. For GitHub, we can do this by creating a personal access token. 26 | 27 | To configure a personal access token, go here: 28 | 29 | https://github.com/settings/tokens 30 | 31 | Be sure that you're logged in with the account you want Jenkins X to use. 32 | 33 | Jenkins X requires the following permissions: 34 | 35 | * repo (all) 36 | * read:org 37 | * write:repo_hook 38 | * read:repo_hook 39 | * read:user 40 | * user:email 41 | * delete_repo 42 | 43 | Once you have created a token with these permissions, be sure to keep the 44 | token in a safe place so we can use it for `jx boot`. 45 | -------------------------------------------------------------------------------- /section-1/video-1.6/README.md: -------------------------------------------------------------------------------- 1 | # Video 1.6 2 | 3 | We're now ready to install Jenkins X using the `jx boot` command. 4 | We'll be using our Kubernetes cluster configuration and our GitHub token. 5 | 6 | ## Prerequisites 7 | 8 | * Create a Kubernetes cluster and GitHub token per the instructions. 9 | * Have your Git command line client installed and configured with your 10 | name and email. 11 | 12 | ## Jenkins X Boot 13 | 14 | The `jx boot` command uses the cluster's Git repository to configure the 15 | running installation of Jenkins X. This includes installing or modifying 16 | any pieces as necessary. 17 | 18 | When we first run `jx boot`, we will not have a Git repository, so `jx boot` 19 | will clone it for us. It will then push this repository to the GitHub 20 | account or organization we specify. From that point forward, we should make 21 | configuration changes to our cluster only from within the Git repository. 22 | 23 | To get the Jenkins X Boot process started, we can supply a 24 | `jx-requirements.yml` file. There is a sample one in this directory. 25 | 26 | To run using the provided configuration: 27 | 28 | ``` 29 | jx boot -r jx-requirements.yml 30 | ``` 31 | 32 | Once you've successfully booted Jenkins X, you can either re-clone the Git 33 | repository it created for you, or just move the `jenkins-x-boot-config` 34 | directory somewhere else on your system. Be sure to use this directory to 35 | configure your cluster! 36 | 37 | ## Public vs. Private Environments 38 | 39 | Most of `jx-requirements.yml` matches the default, but there is one change. 40 | 41 | Because we install into a GitHub organization that is running under the free 42 | tier, we are only allowed to create public repositories. Jenkins X defaults 43 | to using private repositories for cluster configuration, so we need to tell 44 | Jenkins X to make the repositories public. We do this by setting 45 | `environmentGitPublic` to `true` in `jx-requirements.yml`. 46 | 47 | If you are installing into a paid organization or a personal account, you 48 | can choose to remove this configuration entry to use private repositories. 49 | 50 | ## Configuring TLS 51 | 52 | This Jenkins X setup is designed for you to learn how to use Jenkins X. 53 | Once you have your Jenkins X cluster up and running, you will want to 54 | configure Transport Layer Security (TLS). To enable TLS, you will need a custom 55 | domain that you own in order to issue the certificates. For this reason, 56 | enabling TLS is not shown as part of the course. 57 | 58 | It's important to enable TLS, because our Jenkins X server will be creating 59 | webhooks to GitHub that include tokens that Jenkins X uses to ensure that the 60 | webhook comes from the right source. We want to secure the communication from 61 | GitHub to Jenkins X to ensure that token is not sent in the clear. To do this we 62 | need to enable TLS in `jx-requirements.yml`. 63 | -------------------------------------------------------------------------------- /section-1/video-1.6/jx-requirements.yml: -------------------------------------------------------------------------------- 1 | autoUpdate: 2 | enabled: false 3 | schedule: "" 4 | bootConfigURL: https://github.com/jenkins-x/jenkins-x-boot-config.git 5 | cluster: 6 | gitKind: github 7 | gitName: github 8 | gitServer: https://github.com 9 | environmentGitPublic: true 10 | namespace: jx 11 | provider: gke 12 | environments: 13 | - ingress: 14 | domain: "" 15 | externalDNS: false 16 | namespaceSubDomain: "" 17 | tls: 18 | email: "" 19 | enabled: false 20 | production: false 21 | key: dev 22 | - ingress: 23 | domain: "" 24 | externalDNS: false 25 | namespaceSubDomain: "" 26 | tls: 27 | email: "" 28 | enabled: false 29 | production: false 30 | key: staging 31 | - ingress: 32 | domain: "" 33 | externalDNS: false 34 | namespaceSubDomain: "" 35 | tls: 36 | email: "" 37 | enabled: false 38 | production: false 39 | key: production 40 | gitops: true 41 | ingress: 42 | domain: "" 43 | externalDNS: false 44 | namespaceSubDomain: -jx. 45 | tls: 46 | email: "" 47 | enabled: false 48 | production: false 49 | kaniko: true 50 | repository: nexus 51 | secretStorage: local 52 | storage: 53 | backup: 54 | enabled: false 55 | url: "" 56 | logs: 57 | enabled: false 58 | url: "" 59 | reports: 60 | enabled: false 61 | url: "" 62 | repository: 63 | enabled: false 64 | url: "" 65 | vault: {} 66 | velero: 67 | schedule: "" 68 | ttl: "" 69 | versionStream: 70 | ref: master 71 | url: https://github.com/jenkins-x/jenkins-x-versions.git 72 | webhook: prow 73 | -------------------------------------------------------------------------------- /section-2/video-2.1/README.md: -------------------------------------------------------------------------------- 1 | # Video 2.1 2 | 3 | This video demonstrates adding an application to Jenkins X from a quickstart. 4 | 5 | ## Prerequisites 6 | 7 | To try out this example for yourself, you will need a Jenkins X cluster up 8 | and running. You can accomplish this by following the instructions in the 9 | rest of Section 1. 10 | 11 | ## Quickstart 12 | 13 | Jenkins X includes "quickstarts", which are repositories that already have 14 | some code available. You can use these to quickly add a new application to 15 | Jenkins X, allowing you to place your own code into a repository that is 16 | already configured for Jenkins X. 17 | 18 | To create a new Jenkins X quickstart, run: 19 | 20 | ``` 21 | jx create quickstart 22 | ``` 23 | 24 | Once the process is complete, you will have a new Git repository published to 25 | GitHub and configured to build and deploy using Jenkins X and Kubernetes. 26 | 27 | ## Inspection 28 | 29 | You can inspect your new application using a variety of Jenkins X commands, 30 | as documented here: 31 | 32 | https://jenkins-x.io/docs/using-jx/developing/browsing/ 33 | -------------------------------------------------------------------------------- /section-2/video-2.2/README.md: -------------------------------------------------------------------------------- 1 | # Video 2.2 2 | 3 | This video demonstrates importing existing code as an application in Jenkins X. 4 | 5 | ## Prerequisites 6 | 7 | To try out this example for yourself, you will need a Jenkins X cluster up 8 | and running. You can accomplish this by following the instructions in the 9 | rest of Section 1. 10 | 11 | ## Import 12 | 13 | The `jx import` command will import existing code into Jenkins X. It will 14 | create the necessary Docker build and Helm chart to deploy the application 15 | to Kubernetes. 16 | 17 | This folder contains a "Hello World" Node application using Express. To import 18 | it to Jenkins X, run: 19 | 20 | ``` 21 | jx import express-hello 22 | ``` 23 | 24 | Once the process is complete, you will have a new Git repository published to 25 | GitHub and configured to build and deploy using Jenkins X and Kubernetes. 26 | 27 | ## Inspection 28 | 29 | You can inspect your new application using a variety of Jenkins X commands, 30 | as documented here: 31 | 32 | https://jenkins-x.io/docs/using-jx/developing/browsing/ 33 | -------------------------------------------------------------------------------- /section-2/video-2.2/express-hello/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /section-2/video-2.2/express-hello/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const app = express() 3 | const port = 8080 4 | 5 | app.get('/', (req, res) => res.send('Hello World!\n')) 6 | 7 | app.listen(port, () => console.log(`Example app listening on port ${port}!`)) 8 | -------------------------------------------------------------------------------- /section-2/video-2.2/express-hello/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-hello", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.7", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 10 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 11 | "requires": { 12 | "mime-types": "~2.1.24", 13 | "negotiator": "0.6.2" 14 | } 15 | }, 16 | "array-flatten": { 17 | "version": "1.1.1", 18 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 19 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 20 | }, 21 | "body-parser": { 22 | "version": "1.19.0", 23 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 24 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 25 | "requires": { 26 | "bytes": "3.1.0", 27 | "content-type": "~1.0.4", 28 | "debug": "2.6.9", 29 | "depd": "~1.1.2", 30 | "http-errors": "1.7.2", 31 | "iconv-lite": "0.4.24", 32 | "on-finished": "~2.3.0", 33 | "qs": "6.7.0", 34 | "raw-body": "2.4.0", 35 | "type-is": "~1.6.17" 36 | } 37 | }, 38 | "bytes": { 39 | "version": "3.1.0", 40 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 41 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" 42 | }, 43 | "content-disposition": { 44 | "version": "0.5.3", 45 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 46 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 47 | "requires": { 48 | "safe-buffer": "5.1.2" 49 | } 50 | }, 51 | "content-type": { 52 | "version": "1.0.4", 53 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 54 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 55 | }, 56 | "cookie": { 57 | "version": "0.4.0", 58 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 59 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" 60 | }, 61 | "cookie-signature": { 62 | "version": "1.0.6", 63 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 64 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 65 | }, 66 | "debug": { 67 | "version": "2.6.9", 68 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 69 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 70 | "requires": { 71 | "ms": "2.0.0" 72 | } 73 | }, 74 | "depd": { 75 | "version": "1.1.2", 76 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 77 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 78 | }, 79 | "destroy": { 80 | "version": "1.0.4", 81 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 82 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 83 | }, 84 | "ee-first": { 85 | "version": "1.1.1", 86 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 87 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 88 | }, 89 | "encodeurl": { 90 | "version": "1.0.2", 91 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 92 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 93 | }, 94 | "escape-html": { 95 | "version": "1.0.3", 96 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 97 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 98 | }, 99 | "etag": { 100 | "version": "1.8.1", 101 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 102 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 103 | }, 104 | "express": { 105 | "version": "4.17.1", 106 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 107 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 108 | "requires": { 109 | "accepts": "~1.3.7", 110 | "array-flatten": "1.1.1", 111 | "body-parser": "1.19.0", 112 | "content-disposition": "0.5.3", 113 | "content-type": "~1.0.4", 114 | "cookie": "0.4.0", 115 | "cookie-signature": "1.0.6", 116 | "debug": "2.6.9", 117 | "depd": "~1.1.2", 118 | "encodeurl": "~1.0.2", 119 | "escape-html": "~1.0.3", 120 | "etag": "~1.8.1", 121 | "finalhandler": "~1.1.2", 122 | "fresh": "0.5.2", 123 | "merge-descriptors": "1.0.1", 124 | "methods": "~1.1.2", 125 | "on-finished": "~2.3.0", 126 | "parseurl": "~1.3.3", 127 | "path-to-regexp": "0.1.7", 128 | "proxy-addr": "~2.0.5", 129 | "qs": "6.7.0", 130 | "range-parser": "~1.2.1", 131 | "safe-buffer": "5.1.2", 132 | "send": "0.17.1", 133 | "serve-static": "1.14.1", 134 | "setprototypeof": "1.1.1", 135 | "statuses": "~1.5.0", 136 | "type-is": "~1.6.18", 137 | "utils-merge": "1.0.1", 138 | "vary": "~1.1.2" 139 | } 140 | }, 141 | "finalhandler": { 142 | "version": "1.1.2", 143 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 144 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 145 | "requires": { 146 | "debug": "2.6.9", 147 | "encodeurl": "~1.0.2", 148 | "escape-html": "~1.0.3", 149 | "on-finished": "~2.3.0", 150 | "parseurl": "~1.3.3", 151 | "statuses": "~1.5.0", 152 | "unpipe": "~1.0.0" 153 | } 154 | }, 155 | "forwarded": { 156 | "version": "0.1.2", 157 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 158 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 159 | }, 160 | "fresh": { 161 | "version": "0.5.2", 162 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 163 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 164 | }, 165 | "http-errors": { 166 | "version": "1.7.2", 167 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 168 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 169 | "requires": { 170 | "depd": "~1.1.2", 171 | "inherits": "2.0.3", 172 | "setprototypeof": "1.1.1", 173 | "statuses": ">= 1.5.0 < 2", 174 | "toidentifier": "1.0.0" 175 | } 176 | }, 177 | "iconv-lite": { 178 | "version": "0.4.24", 179 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 180 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 181 | "requires": { 182 | "safer-buffer": ">= 2.1.2 < 3" 183 | } 184 | }, 185 | "inherits": { 186 | "version": "2.0.3", 187 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 188 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 189 | }, 190 | "ipaddr.js": { 191 | "version": "1.9.0", 192 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", 193 | "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" 194 | }, 195 | "media-typer": { 196 | "version": "0.3.0", 197 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 198 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 199 | }, 200 | "merge-descriptors": { 201 | "version": "1.0.1", 202 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 203 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 204 | }, 205 | "methods": { 206 | "version": "1.1.2", 207 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 208 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 209 | }, 210 | "mime": { 211 | "version": "1.6.0", 212 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 213 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 214 | }, 215 | "mime-db": { 216 | "version": "1.43.0", 217 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", 218 | "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" 219 | }, 220 | "mime-types": { 221 | "version": "2.1.26", 222 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", 223 | "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", 224 | "requires": { 225 | "mime-db": "1.43.0" 226 | } 227 | }, 228 | "ms": { 229 | "version": "2.0.0", 230 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 231 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 232 | }, 233 | "negotiator": { 234 | "version": "0.6.2", 235 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 236 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 237 | }, 238 | "on-finished": { 239 | "version": "2.3.0", 240 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 241 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 242 | "requires": { 243 | "ee-first": "1.1.1" 244 | } 245 | }, 246 | "parseurl": { 247 | "version": "1.3.3", 248 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 249 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 250 | }, 251 | "path-to-regexp": { 252 | "version": "0.1.7", 253 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 254 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 255 | }, 256 | "proxy-addr": { 257 | "version": "2.0.5", 258 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", 259 | "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", 260 | "requires": { 261 | "forwarded": "~0.1.2", 262 | "ipaddr.js": "1.9.0" 263 | } 264 | }, 265 | "qs": { 266 | "version": "6.7.0", 267 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 268 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 269 | }, 270 | "range-parser": { 271 | "version": "1.2.1", 272 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 273 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 274 | }, 275 | "raw-body": { 276 | "version": "2.4.0", 277 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 278 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 279 | "requires": { 280 | "bytes": "3.1.0", 281 | "http-errors": "1.7.2", 282 | "iconv-lite": "0.4.24", 283 | "unpipe": "1.0.0" 284 | } 285 | }, 286 | "safe-buffer": { 287 | "version": "5.1.2", 288 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 289 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 290 | }, 291 | "safer-buffer": { 292 | "version": "2.1.2", 293 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 294 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 295 | }, 296 | "send": { 297 | "version": "0.17.1", 298 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 299 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 300 | "requires": { 301 | "debug": "2.6.9", 302 | "depd": "~1.1.2", 303 | "destroy": "~1.0.4", 304 | "encodeurl": "~1.0.2", 305 | "escape-html": "~1.0.3", 306 | "etag": "~1.8.1", 307 | "fresh": "0.5.2", 308 | "http-errors": "~1.7.2", 309 | "mime": "1.6.0", 310 | "ms": "2.1.1", 311 | "on-finished": "~2.3.0", 312 | "range-parser": "~1.2.1", 313 | "statuses": "~1.5.0" 314 | }, 315 | "dependencies": { 316 | "ms": { 317 | "version": "2.1.1", 318 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 319 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 320 | } 321 | } 322 | }, 323 | "serve-static": { 324 | "version": "1.14.1", 325 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 326 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 327 | "requires": { 328 | "encodeurl": "~1.0.2", 329 | "escape-html": "~1.0.3", 330 | "parseurl": "~1.3.3", 331 | "send": "0.17.1" 332 | } 333 | }, 334 | "setprototypeof": { 335 | "version": "1.1.1", 336 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 337 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 338 | }, 339 | "statuses": { 340 | "version": "1.5.0", 341 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 342 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 343 | }, 344 | "toidentifier": { 345 | "version": "1.0.0", 346 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 347 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 348 | }, 349 | "type-is": { 350 | "version": "1.6.18", 351 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 352 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 353 | "requires": { 354 | "media-typer": "0.3.0", 355 | "mime-types": "~2.1.24" 356 | } 357 | }, 358 | "unpipe": { 359 | "version": "1.0.0", 360 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 361 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 362 | }, 363 | "utils-merge": { 364 | "version": "1.0.1", 365 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 366 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 367 | }, 368 | "vary": { 369 | "version": "1.1.2", 370 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 371 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 372 | } 373 | } 374 | } 375 | -------------------------------------------------------------------------------- /section-2/video-2.2/express-hello/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-hello", 3 | "version": "1.0.0", 4 | "description": "Express Hello World", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js", 8 | "test": "exit 0" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.17.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /section-2/video-2.3/README.md: -------------------------------------------------------------------------------- 1 | # Video 2.3 2 | 3 | This video demonstrates what happens behind the scenes when we add an 4 | application to Jenkins X. 5 | 6 | ## Prerequisites 7 | 8 | To see similar pull requests in your own Jenkins configuration repository, 9 | create your Jenkins X installation as described in Section 1, then add at 10 | least one application as described in Video 2.1 or 2.2. 11 | 12 | ## GitOps 13 | 14 | Every command we run that modifies the Jenkins X installation, such as adding 15 | an application with `jx create quickstart` or `jx import`, also results in a 16 | Git commit to our configuration repository. This configuration repository 17 | tells Jenkins X what applications are configured and how to obtain the source 18 | code. As we will see in the future, it also identifies what version of an 19 | application is running in each environment. 20 | 21 | See the video for details on how Jenkins X uses GitOps. 22 | -------------------------------------------------------------------------------- /section-2/video-2.4/README.md: -------------------------------------------------------------------------------- 1 | # Video 2.4 2 | 3 | This video demonstrates the Prow web interface that shows a build status 4 | screen. 5 | 6 | ## Prerequisites 7 | 8 | To see the Prow status screen and build status for jobs in your own cluster, 9 | create your Jenkins X installation as described in Section 1, then add at 10 | least one application as described in Video 2.1 or 2.2. 11 | 12 | ## Prow 13 | 14 | Prow is a Kubernetes native CI/CD server. It is triggered by webhooks from 15 | the Git repository and runs builds in Docker containers in Kubernetes. It 16 | provides a basic status page and also reports build results back to GitHub 17 | as updates to pull requests. 18 | 19 | See the video for details on Prow. 20 | -------------------------------------------------------------------------------- /section-2/video-2.5/README.md: -------------------------------------------------------------------------------- 1 | # Video 2.5 2 | 3 | This video demonstrates viewing pipeline logs for Jenkins X builds. 4 | 5 | ## Prerequisites 6 | 7 | To see pipeline logs for jobs in your own cluster, create your Jenkins X 8 | installation as described in Section 1, then add at least one application as 9 | described in Video 2.1 or 2.2. 10 | 11 | ## Applications, Activities and Logs 12 | 13 | As we saw before, you can get a list of applications using: 14 | 15 | ``` 16 | jx get applications 17 | ``` 18 | 19 | You can also get a list of build activities: 20 | 21 | ``` 22 | jx get activities 23 | ``` 24 | 25 | Finally, you can see specific build logs: 26 | 27 | ``` 28 | jx get build logs 29 | ``` 30 | 31 | See the video for examples. 32 | -------------------------------------------------------------------------------- /section-2/video-2.6/README.md: -------------------------------------------------------------------------------- 1 | # Video 2.6 2 | 3 | This video demonstrates the underlying Kubernetes resources that Jenkins X 4 | creates when it deploys an application. 5 | 6 | ## Prerequisites 7 | 8 | To see the Kubernetes resources for applications in your own cluster, create 9 | your Jenkins X installation as described in Section 1, then add at least one 10 | application as described in Video 2.1 or 2.2. 11 | 12 | ## Kubernetes 13 | 14 | Kubernetes is a container orchestration platform. Jenkins X uses Kubernetes to 15 | run its own components, run builds, and deploy applications. We can use the 16 | `kubectl` command to inspect Kubernetes resources. 17 | 18 | Kubernetes organizes containers and other resources into namespaces. We can 19 | see the list of namespaces using: 20 | 21 | ``` 22 | kubectl get ns 23 | ``` 24 | 25 | Kubernetes organizes running containers into "pods". To see the pods in the 26 | `jx-staging` namespace, we can run: 27 | 28 | ``` 29 | kubectl -n jx-staging get pods 30 | ``` 31 | 32 | Finally, we can see the log for a given pod using: 33 | 34 | ``` 35 | kubectl -n jx-staging logs 36 | ``` 37 | 38 | See the video for examples. 39 | -------------------------------------------------------------------------------- /section-3/video-3.1/README.md: -------------------------------------------------------------------------------- 1 | # Video 3.1 2 | 3 | This video demonstrates how Jenkins X uses build packs to tell it what 4 | steps to take to build, test, and deploy software. 5 | 6 | ## Prerequisites 7 | 8 | To see the Jenkins X build packs, configuration file, and resulting build 9 | steps in your own cluster, first install your cluster per the instructions 10 | in section 1. 11 | 12 | ## Build Packs 13 | 14 | Jenkins X includes "build packs", which contain instructions for how to build 15 | and deploy code in various programming languages (Java, Python, JavaScript, 16 | etc.). 17 | 18 | Default Jenkins X build packs are in Git repositories on GitHub. Jenkins X 19 | downloads build packs to our `$HOME/.jx` directory so it can choose the right 20 | build pack for our code. 21 | 22 | To get started, import the JavaScript project in this folder: 23 | 24 | ``` 25 | jx import hello-video-3-1 26 | ``` 27 | 28 | Once the project is imported, you can see a new file `jenkins-x.yml` with 29 | the content: 30 | 31 | ``` 32 | buildPack: javascript 33 | ``` 34 | 35 | This tells Jenkins X what build pack to use to build the project. 36 | -------------------------------------------------------------------------------- /section-3/video-3.1/hello-video-3-1/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /section-3/video-3.1/hello-video-3-1/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const app = express() 3 | const port = 8080 4 | 5 | app.get('/', (req, res) => res.send('Hello World!\n')) 6 | 7 | app.listen(port, () => console.log(`Example app listening on port ${port}!`)) 8 | -------------------------------------------------------------------------------- /section-3/video-3.1/hello-video-3-1/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-hello", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.7", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 10 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 11 | "requires": { 12 | "mime-types": "~2.1.24", 13 | "negotiator": "0.6.2" 14 | } 15 | }, 16 | "array-flatten": { 17 | "version": "1.1.1", 18 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 19 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 20 | }, 21 | "body-parser": { 22 | "version": "1.19.0", 23 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 24 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 25 | "requires": { 26 | "bytes": "3.1.0", 27 | "content-type": "~1.0.4", 28 | "debug": "2.6.9", 29 | "depd": "~1.1.2", 30 | "http-errors": "1.7.2", 31 | "iconv-lite": "0.4.24", 32 | "on-finished": "~2.3.0", 33 | "qs": "6.7.0", 34 | "raw-body": "2.4.0", 35 | "type-is": "~1.6.17" 36 | } 37 | }, 38 | "bytes": { 39 | "version": "3.1.0", 40 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 41 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" 42 | }, 43 | "content-disposition": { 44 | "version": "0.5.3", 45 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 46 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 47 | "requires": { 48 | "safe-buffer": "5.1.2" 49 | } 50 | }, 51 | "content-type": { 52 | "version": "1.0.4", 53 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 54 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 55 | }, 56 | "cookie": { 57 | "version": "0.4.0", 58 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 59 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" 60 | }, 61 | "cookie-signature": { 62 | "version": "1.0.6", 63 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 64 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 65 | }, 66 | "debug": { 67 | "version": "2.6.9", 68 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 69 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 70 | "requires": { 71 | "ms": "2.0.0" 72 | } 73 | }, 74 | "depd": { 75 | "version": "1.1.2", 76 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 77 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 78 | }, 79 | "destroy": { 80 | "version": "1.0.4", 81 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 82 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 83 | }, 84 | "ee-first": { 85 | "version": "1.1.1", 86 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 87 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 88 | }, 89 | "encodeurl": { 90 | "version": "1.0.2", 91 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 92 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 93 | }, 94 | "escape-html": { 95 | "version": "1.0.3", 96 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 97 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 98 | }, 99 | "etag": { 100 | "version": "1.8.1", 101 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 102 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 103 | }, 104 | "express": { 105 | "version": "4.17.1", 106 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 107 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 108 | "requires": { 109 | "accepts": "~1.3.7", 110 | "array-flatten": "1.1.1", 111 | "body-parser": "1.19.0", 112 | "content-disposition": "0.5.3", 113 | "content-type": "~1.0.4", 114 | "cookie": "0.4.0", 115 | "cookie-signature": "1.0.6", 116 | "debug": "2.6.9", 117 | "depd": "~1.1.2", 118 | "encodeurl": "~1.0.2", 119 | "escape-html": "~1.0.3", 120 | "etag": "~1.8.1", 121 | "finalhandler": "~1.1.2", 122 | "fresh": "0.5.2", 123 | "merge-descriptors": "1.0.1", 124 | "methods": "~1.1.2", 125 | "on-finished": "~2.3.0", 126 | "parseurl": "~1.3.3", 127 | "path-to-regexp": "0.1.7", 128 | "proxy-addr": "~2.0.5", 129 | "qs": "6.7.0", 130 | "range-parser": "~1.2.1", 131 | "safe-buffer": "5.1.2", 132 | "send": "0.17.1", 133 | "serve-static": "1.14.1", 134 | "setprototypeof": "1.1.1", 135 | "statuses": "~1.5.0", 136 | "type-is": "~1.6.18", 137 | "utils-merge": "1.0.1", 138 | "vary": "~1.1.2" 139 | } 140 | }, 141 | "finalhandler": { 142 | "version": "1.1.2", 143 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 144 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 145 | "requires": { 146 | "debug": "2.6.9", 147 | "encodeurl": "~1.0.2", 148 | "escape-html": "~1.0.3", 149 | "on-finished": "~2.3.0", 150 | "parseurl": "~1.3.3", 151 | "statuses": "~1.5.0", 152 | "unpipe": "~1.0.0" 153 | } 154 | }, 155 | "forwarded": { 156 | "version": "0.1.2", 157 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 158 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 159 | }, 160 | "fresh": { 161 | "version": "0.5.2", 162 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 163 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 164 | }, 165 | "http-errors": { 166 | "version": "1.7.2", 167 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 168 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 169 | "requires": { 170 | "depd": "~1.1.2", 171 | "inherits": "2.0.3", 172 | "setprototypeof": "1.1.1", 173 | "statuses": ">= 1.5.0 < 2", 174 | "toidentifier": "1.0.0" 175 | } 176 | }, 177 | "iconv-lite": { 178 | "version": "0.4.24", 179 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 180 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 181 | "requires": { 182 | "safer-buffer": ">= 2.1.2 < 3" 183 | } 184 | }, 185 | "inherits": { 186 | "version": "2.0.3", 187 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 188 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 189 | }, 190 | "ipaddr.js": { 191 | "version": "1.9.0", 192 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", 193 | "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" 194 | }, 195 | "media-typer": { 196 | "version": "0.3.0", 197 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 198 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 199 | }, 200 | "merge-descriptors": { 201 | "version": "1.0.1", 202 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 203 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 204 | }, 205 | "methods": { 206 | "version": "1.1.2", 207 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 208 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 209 | }, 210 | "mime": { 211 | "version": "1.6.0", 212 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 213 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 214 | }, 215 | "mime-db": { 216 | "version": "1.43.0", 217 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", 218 | "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" 219 | }, 220 | "mime-types": { 221 | "version": "2.1.26", 222 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", 223 | "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", 224 | "requires": { 225 | "mime-db": "1.43.0" 226 | } 227 | }, 228 | "ms": { 229 | "version": "2.0.0", 230 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 231 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 232 | }, 233 | "negotiator": { 234 | "version": "0.6.2", 235 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 236 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 237 | }, 238 | "on-finished": { 239 | "version": "2.3.0", 240 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 241 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 242 | "requires": { 243 | "ee-first": "1.1.1" 244 | } 245 | }, 246 | "parseurl": { 247 | "version": "1.3.3", 248 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 249 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 250 | }, 251 | "path-to-regexp": { 252 | "version": "0.1.7", 253 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 254 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 255 | }, 256 | "proxy-addr": { 257 | "version": "2.0.5", 258 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", 259 | "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", 260 | "requires": { 261 | "forwarded": "~0.1.2", 262 | "ipaddr.js": "1.9.0" 263 | } 264 | }, 265 | "qs": { 266 | "version": "6.7.0", 267 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 268 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 269 | }, 270 | "range-parser": { 271 | "version": "1.2.1", 272 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 273 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 274 | }, 275 | "raw-body": { 276 | "version": "2.4.0", 277 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 278 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 279 | "requires": { 280 | "bytes": "3.1.0", 281 | "http-errors": "1.7.2", 282 | "iconv-lite": "0.4.24", 283 | "unpipe": "1.0.0" 284 | } 285 | }, 286 | "safe-buffer": { 287 | "version": "5.1.2", 288 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 289 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 290 | }, 291 | "safer-buffer": { 292 | "version": "2.1.2", 293 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 294 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 295 | }, 296 | "send": { 297 | "version": "0.17.1", 298 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 299 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 300 | "requires": { 301 | "debug": "2.6.9", 302 | "depd": "~1.1.2", 303 | "destroy": "~1.0.4", 304 | "encodeurl": "~1.0.2", 305 | "escape-html": "~1.0.3", 306 | "etag": "~1.8.1", 307 | "fresh": "0.5.2", 308 | "http-errors": "~1.7.2", 309 | "mime": "1.6.0", 310 | "ms": "2.1.1", 311 | "on-finished": "~2.3.0", 312 | "range-parser": "~1.2.1", 313 | "statuses": "~1.5.0" 314 | }, 315 | "dependencies": { 316 | "ms": { 317 | "version": "2.1.1", 318 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 319 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 320 | } 321 | } 322 | }, 323 | "serve-static": { 324 | "version": "1.14.1", 325 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 326 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 327 | "requires": { 328 | "encodeurl": "~1.0.2", 329 | "escape-html": "~1.0.3", 330 | "parseurl": "~1.3.3", 331 | "send": "0.17.1" 332 | } 333 | }, 334 | "setprototypeof": { 335 | "version": "1.1.1", 336 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 337 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 338 | }, 339 | "statuses": { 340 | "version": "1.5.0", 341 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 342 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 343 | }, 344 | "toidentifier": { 345 | "version": "1.0.0", 346 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 347 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 348 | }, 349 | "type-is": { 350 | "version": "1.6.18", 351 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 352 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 353 | "requires": { 354 | "media-typer": "0.3.0", 355 | "mime-types": "~2.1.24" 356 | } 357 | }, 358 | "unpipe": { 359 | "version": "1.0.0", 360 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 361 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 362 | }, 363 | "utils-merge": { 364 | "version": "1.0.1", 365 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 366 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 367 | }, 368 | "vary": { 369 | "version": "1.1.2", 370 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 371 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 372 | } 373 | } 374 | } 375 | -------------------------------------------------------------------------------- /section-3/video-3.1/hello-video-3-1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-hello", 3 | "version": "1.0.0", 4 | "description": "Express Hello World", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js", 8 | "test": "exit 0" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.17.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /section-3/video-3.2/README.md: -------------------------------------------------------------------------------- 1 | # Video 3.2 2 | 3 | This video demonstrates how Jenkins X can auto-detect the build pack and how 4 | it can be specified on the command line. 5 | 6 | ## Prerequisites 7 | 8 | First install your cluster per the instruction in section 1. 9 | 10 | ## Build Pack Auto-detection 11 | 12 | When we run `jx import`, Jenkins X looks for a `jenkins-x.yml` file. If it 13 | is not present, it will attempt to auto-detect the build pack to use based 14 | on what type of code it finds in the directory. 15 | 16 | To see an example of auto-detection, import the `hello-3-2-auto` folder. 17 | 18 | ``` 19 | jx import hello-3-2-auto 20 | ``` 21 | 22 | Once the project is imported, you can see a new file `jenkins-x.yml` with 23 | the content: 24 | 25 | ``` 26 | buildPack: javascript 27 | ``` 28 | 29 | ## Specify Build Pack 30 | 31 | We can specify the build pack either by creating the `jenkins-x.yml` file or 32 | by specifying on the command line. 33 | 34 | To see the list of available build packs: 35 | 36 | ``` 37 | jx import --list-packs 38 | ``` 39 | 40 | To specify a build pack (using `hello-3-2-specify` as an example): 41 | 42 | ``` 43 | jx import hello-3-2-specify --pack=javascript 44 | ``` 45 | -------------------------------------------------------------------------------- /section-3/video-3.2/hello-3-2-auto/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /section-3/video-3.2/hello-3-2-auto/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const app = express() 3 | const port = 8080 4 | 5 | app.get('/', (req, res) => res.send('Hello World!\n')) 6 | 7 | app.listen(port, () => console.log(`Example app listening on port ${port}!`)) 8 | -------------------------------------------------------------------------------- /section-3/video-3.2/hello-3-2-auto/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-hello", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.7", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 10 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 11 | "requires": { 12 | "mime-types": "~2.1.24", 13 | "negotiator": "0.6.2" 14 | } 15 | }, 16 | "array-flatten": { 17 | "version": "1.1.1", 18 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 19 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 20 | }, 21 | "body-parser": { 22 | "version": "1.19.0", 23 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 24 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 25 | "requires": { 26 | "bytes": "3.1.0", 27 | "content-type": "~1.0.4", 28 | "debug": "2.6.9", 29 | "depd": "~1.1.2", 30 | "http-errors": "1.7.2", 31 | "iconv-lite": "0.4.24", 32 | "on-finished": "~2.3.0", 33 | "qs": "6.7.0", 34 | "raw-body": "2.4.0", 35 | "type-is": "~1.6.17" 36 | } 37 | }, 38 | "bytes": { 39 | "version": "3.1.0", 40 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 41 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" 42 | }, 43 | "content-disposition": { 44 | "version": "0.5.3", 45 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 46 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 47 | "requires": { 48 | "safe-buffer": "5.1.2" 49 | } 50 | }, 51 | "content-type": { 52 | "version": "1.0.4", 53 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 54 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 55 | }, 56 | "cookie": { 57 | "version": "0.4.0", 58 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 59 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" 60 | }, 61 | "cookie-signature": { 62 | "version": "1.0.6", 63 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 64 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 65 | }, 66 | "debug": { 67 | "version": "2.6.9", 68 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 69 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 70 | "requires": { 71 | "ms": "2.0.0" 72 | } 73 | }, 74 | "depd": { 75 | "version": "1.1.2", 76 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 77 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 78 | }, 79 | "destroy": { 80 | "version": "1.0.4", 81 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 82 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 83 | }, 84 | "ee-first": { 85 | "version": "1.1.1", 86 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 87 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 88 | }, 89 | "encodeurl": { 90 | "version": "1.0.2", 91 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 92 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 93 | }, 94 | "escape-html": { 95 | "version": "1.0.3", 96 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 97 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 98 | }, 99 | "etag": { 100 | "version": "1.8.1", 101 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 102 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 103 | }, 104 | "express": { 105 | "version": "4.17.1", 106 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 107 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 108 | "requires": { 109 | "accepts": "~1.3.7", 110 | "array-flatten": "1.1.1", 111 | "body-parser": "1.19.0", 112 | "content-disposition": "0.5.3", 113 | "content-type": "~1.0.4", 114 | "cookie": "0.4.0", 115 | "cookie-signature": "1.0.6", 116 | "debug": "2.6.9", 117 | "depd": "~1.1.2", 118 | "encodeurl": "~1.0.2", 119 | "escape-html": "~1.0.3", 120 | "etag": "~1.8.1", 121 | "finalhandler": "~1.1.2", 122 | "fresh": "0.5.2", 123 | "merge-descriptors": "1.0.1", 124 | "methods": "~1.1.2", 125 | "on-finished": "~2.3.0", 126 | "parseurl": "~1.3.3", 127 | "path-to-regexp": "0.1.7", 128 | "proxy-addr": "~2.0.5", 129 | "qs": "6.7.0", 130 | "range-parser": "~1.2.1", 131 | "safe-buffer": "5.1.2", 132 | "send": "0.17.1", 133 | "serve-static": "1.14.1", 134 | "setprototypeof": "1.1.1", 135 | "statuses": "~1.5.0", 136 | "type-is": "~1.6.18", 137 | "utils-merge": "1.0.1", 138 | "vary": "~1.1.2" 139 | } 140 | }, 141 | "finalhandler": { 142 | "version": "1.1.2", 143 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 144 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 145 | "requires": { 146 | "debug": "2.6.9", 147 | "encodeurl": "~1.0.2", 148 | "escape-html": "~1.0.3", 149 | "on-finished": "~2.3.0", 150 | "parseurl": "~1.3.3", 151 | "statuses": "~1.5.0", 152 | "unpipe": "~1.0.0" 153 | } 154 | }, 155 | "forwarded": { 156 | "version": "0.1.2", 157 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 158 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 159 | }, 160 | "fresh": { 161 | "version": "0.5.2", 162 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 163 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 164 | }, 165 | "http-errors": { 166 | "version": "1.7.2", 167 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 168 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 169 | "requires": { 170 | "depd": "~1.1.2", 171 | "inherits": "2.0.3", 172 | "setprototypeof": "1.1.1", 173 | "statuses": ">= 1.5.0 < 2", 174 | "toidentifier": "1.0.0" 175 | } 176 | }, 177 | "iconv-lite": { 178 | "version": "0.4.24", 179 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 180 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 181 | "requires": { 182 | "safer-buffer": ">= 2.1.2 < 3" 183 | } 184 | }, 185 | "inherits": { 186 | "version": "2.0.3", 187 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 188 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 189 | }, 190 | "ipaddr.js": { 191 | "version": "1.9.0", 192 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", 193 | "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" 194 | }, 195 | "media-typer": { 196 | "version": "0.3.0", 197 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 198 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 199 | }, 200 | "merge-descriptors": { 201 | "version": "1.0.1", 202 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 203 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 204 | }, 205 | "methods": { 206 | "version": "1.1.2", 207 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 208 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 209 | }, 210 | "mime": { 211 | "version": "1.6.0", 212 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 213 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 214 | }, 215 | "mime-db": { 216 | "version": "1.43.0", 217 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", 218 | "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" 219 | }, 220 | "mime-types": { 221 | "version": "2.1.26", 222 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", 223 | "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", 224 | "requires": { 225 | "mime-db": "1.43.0" 226 | } 227 | }, 228 | "ms": { 229 | "version": "2.0.0", 230 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 231 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 232 | }, 233 | "negotiator": { 234 | "version": "0.6.2", 235 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 236 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 237 | }, 238 | "on-finished": { 239 | "version": "2.3.0", 240 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 241 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 242 | "requires": { 243 | "ee-first": "1.1.1" 244 | } 245 | }, 246 | "parseurl": { 247 | "version": "1.3.3", 248 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 249 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 250 | }, 251 | "path-to-regexp": { 252 | "version": "0.1.7", 253 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 254 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 255 | }, 256 | "proxy-addr": { 257 | "version": "2.0.5", 258 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", 259 | "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", 260 | "requires": { 261 | "forwarded": "~0.1.2", 262 | "ipaddr.js": "1.9.0" 263 | } 264 | }, 265 | "qs": { 266 | "version": "6.7.0", 267 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 268 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 269 | }, 270 | "range-parser": { 271 | "version": "1.2.1", 272 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 273 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 274 | }, 275 | "raw-body": { 276 | "version": "2.4.0", 277 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 278 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 279 | "requires": { 280 | "bytes": "3.1.0", 281 | "http-errors": "1.7.2", 282 | "iconv-lite": "0.4.24", 283 | "unpipe": "1.0.0" 284 | } 285 | }, 286 | "safe-buffer": { 287 | "version": "5.1.2", 288 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 289 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 290 | }, 291 | "safer-buffer": { 292 | "version": "2.1.2", 293 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 294 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 295 | }, 296 | "send": { 297 | "version": "0.17.1", 298 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 299 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 300 | "requires": { 301 | "debug": "2.6.9", 302 | "depd": "~1.1.2", 303 | "destroy": "~1.0.4", 304 | "encodeurl": "~1.0.2", 305 | "escape-html": "~1.0.3", 306 | "etag": "~1.8.1", 307 | "fresh": "0.5.2", 308 | "http-errors": "~1.7.2", 309 | "mime": "1.6.0", 310 | "ms": "2.1.1", 311 | "on-finished": "~2.3.0", 312 | "range-parser": "~1.2.1", 313 | "statuses": "~1.5.0" 314 | }, 315 | "dependencies": { 316 | "ms": { 317 | "version": "2.1.1", 318 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 319 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 320 | } 321 | } 322 | }, 323 | "serve-static": { 324 | "version": "1.14.1", 325 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 326 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 327 | "requires": { 328 | "encodeurl": "~1.0.2", 329 | "escape-html": "~1.0.3", 330 | "parseurl": "~1.3.3", 331 | "send": "0.17.1" 332 | } 333 | }, 334 | "setprototypeof": { 335 | "version": "1.1.1", 336 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 337 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 338 | }, 339 | "statuses": { 340 | "version": "1.5.0", 341 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 342 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 343 | }, 344 | "toidentifier": { 345 | "version": "1.0.0", 346 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 347 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 348 | }, 349 | "type-is": { 350 | "version": "1.6.18", 351 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 352 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 353 | "requires": { 354 | "media-typer": "0.3.0", 355 | "mime-types": "~2.1.24" 356 | } 357 | }, 358 | "unpipe": { 359 | "version": "1.0.0", 360 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 361 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 362 | }, 363 | "utils-merge": { 364 | "version": "1.0.1", 365 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 366 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 367 | }, 368 | "vary": { 369 | "version": "1.1.2", 370 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 371 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 372 | } 373 | } 374 | } 375 | -------------------------------------------------------------------------------- /section-3/video-3.2/hello-3-2-auto/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-hello", 3 | "version": "1.0.0", 4 | "description": "Express Hello World", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js", 8 | "test": "exit 0" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.17.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /section-3/video-3.2/hello-3-2-specify/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /section-3/video-3.2/hello-3-2-specify/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const app = express() 3 | const port = 8080 4 | 5 | app.get('/', (req, res) => res.send('Hello World!\n')) 6 | 7 | app.listen(port, () => console.log(`Example app listening on port ${port}!`)) 8 | -------------------------------------------------------------------------------- /section-3/video-3.2/hello-3-2-specify/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-hello", 3 | "version": "1.0.0", 4 | "description": "Express Hello World", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js", 8 | "test": "exit 0" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.17.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /section-3/video-3.3/README.md: -------------------------------------------------------------------------------- 1 | # Video 3.3 2 | 3 | This video discusses how build packs use YAML to define the build steps. 4 | 5 | ## Prerequisites 6 | 7 | None 8 | 9 | ## Build Pack YAML 10 | 11 | See the video for information on build packs and YAML. You can use 12 | these links for more information. 13 | 14 | * About YAML: https://yaml.org/ 15 | * Jenkins X Build Pack Documentation: https://jenkins-x.io/docs/reference/components/build-packs/ 16 | * Jenkins X Classic Build Packs: https://github.com/jenkins-x-buildpacks/jenkins-x-classic 17 | * Jenkins X Kubernetes Build Packs: https://github.com/jenkins-x-buildpacks/jenkins-x-kubernetes 18 | -------------------------------------------------------------------------------- /section-3/video-3.4/README.md: -------------------------------------------------------------------------------- 1 | # Video 3.4 2 | 3 | This video discusses how Jenkins X build packs use inheritance to avoid 4 | duplication in defining build steps. 5 | 6 | ## Prerequisites 7 | 8 | None 9 | 10 | ## Build Pack Inheritance 11 | 12 | See the video for information on build packs and YAML. You can use 13 | these links for more information. 14 | 15 | * Jenkins X Build Pack Inheritance Documentation: https://jenkins-x.io/docs/reference/components/build-packs/#extending 16 | * Jenkins X Classic Build Packs: https://github.com/jenkins-x-buildpacks/jenkins-x-classic 17 | * Jenkins X Kubernetes Build Packs: https://github.com/jenkins-x-buildpacks/jenkins-x-kubernetes 18 | -------------------------------------------------------------------------------- /section-3/video-3.5/README.md: -------------------------------------------------------------------------------- 1 | # Video 3.5 2 | 3 | This video demonstrates how to add or replace build steps in a Jenkins X 4 | build pack. 5 | 6 | ## Prerequisites 7 | 8 | First install your cluster per the instruction in section 1. 9 | 10 | ## Build Pack Overrides 11 | 12 | We can add or replace build steps in a pipeline through the `jenkins-x.yml` 13 | file. 14 | 15 | For example, to add `npm audit` to our JavaScript build, we just need this 16 | content in `jenkins-x.yml`: 17 | 18 | ``` 19 | buildPack: javascript 20 | pipelineConfig: 21 | pipelines: 22 | release: 23 | build: 24 | steps: 25 | - sh: npm audit 26 | name: npm-audit 27 | ``` 28 | 29 | This will result in `npm audit` being run after all of the build steps that 30 | are defined in the build pack (including any build steps in inherited 31 | pipelines). 32 | 33 | If we instead want to completely replace the build steps, we can use the 34 | `replace` field. For example, to change the JavaScript build to remove the 35 | `npm test` step: 36 | 37 | ``` 38 | buildPack: javascript 39 | pipelineConfig: 40 | pipelines: 41 | release: 42 | build: 43 | replace: true 44 | steps: 45 | - sh: jx step credential -s npm-token -k file -f /builder/home/.npmrc --optional=true 46 | name: npmrc 47 | - sh: npm install 48 | name: npm-install 49 | - sh: export VERSION=$PREVIEW_VERSION && skaffold build -f skaffold.yaml 50 | name: container-build 51 | ``` 52 | 53 | Note that we needed to bring in the build steps from all of the inherited 54 | pipeline files because they are all replaced. 55 | -------------------------------------------------------------------------------- /section-3/video-3.5/hello-3-5-audit/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /section-3/video-3.5/hello-3-5-audit/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const app = express() 3 | const port = 8080 4 | 5 | app.get('/', (req, res) => res.send('Hello World!\n')) 6 | 7 | app.listen(port, () => console.log(`Example app listening on port ${port}!`)) 8 | -------------------------------------------------------------------------------- /section-3/video-3.5/hello-3-5-audit/jenkins-x.yml: -------------------------------------------------------------------------------- 1 | buildPack: javascript 2 | pipelineConfig: 3 | pipelines: 4 | release: 5 | build: 6 | steps: 7 | - sh: npm audit 8 | name: npm-audit 9 | -------------------------------------------------------------------------------- /section-3/video-3.5/hello-3-5-audit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-hello", 3 | "version": "1.0.0", 4 | "description": "Express Hello World", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js", 8 | "test": "exit 0" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.17.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /section-3/video-3.5/hello-3-5-replace/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /section-3/video-3.5/hello-3-5-replace/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const app = express() 3 | const port = 8080 4 | 5 | app.get('/', (req, res) => res.send('Hello World!\n')) 6 | 7 | app.listen(port, () => console.log(`Example app listening on port ${port}!`)) 8 | -------------------------------------------------------------------------------- /section-3/video-3.5/hello-3-5-replace/jenkins-x.yml: -------------------------------------------------------------------------------- 1 | buildPack: javascript 2 | pipelineConfig: 3 | pipelines: 4 | release: 5 | build: 6 | replace: true 7 | steps: 8 | - sh: jx step credential -s npm-token -k file -f /builder/home/.npmrc --optional=true 9 | name: npmrc 10 | - sh: npm install 11 | name: npm-install 12 | - sh: export VERSION=$PREVIEW_VERSION && skaffold build -f skaffold.yaml 13 | name: container-build 14 | -------------------------------------------------------------------------------- /section-3/video-3.5/hello-3-5-replace/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-hello", 3 | "version": "1.0.0", 4 | "description": "Express Hello World", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js", 8 | "test": "exit 0" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.17.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /section-4/video-4.1/README.md: -------------------------------------------------------------------------------- 1 | # Video 4.1 2 | 3 | This video demonstrates promoting an application to the production environment. 4 | 5 | ## Prerequisites 6 | 7 | First install your cluster per the instruction in section 1. 8 | 9 | ## Environments and Promotion 10 | 11 | Jenkins X uses environments to take an application through a typical 12 | continuous delivery workflow. By default, any pull requests are deployed to 13 | a "development" environment. Any changes to master (from a pull request or a 14 | direct push to master) are deployed automatically to a "staging" environment. 15 | This allows us to test the latest version before manually deploying to 16 | "production". 17 | 18 | To try this out, first import the application in `hello-4-1` using `jx import`. 19 | Then, once it has finished deploying to "staging", you can test it. When you 20 | are ready to deploy to production, run: 21 | 22 | ``` 23 | jx promote hello-4-1 --version 0.0.1 --env production 24 | ``` 25 | 26 | If you specified a different application name, or if you pushed changes to 27 | `master`, you may need to use a different application name or version number. 28 | You can always use `jx get applications` to see your application and figure 29 | out what parameters to use to promote to production. 30 | 31 | Once the promotion has succeeded, `jx get applications` will show your new 32 | application promoted to production and let you keep track of what version has 33 | been promoted there. 34 | -------------------------------------------------------------------------------- /section-4/video-4.1/hello-4-1/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /section-4/video-4.1/hello-4-1/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const app = express() 3 | const port = 8080 4 | 5 | app.get('/', (req, res) => res.send('Hello World!\n')) 6 | 7 | app.listen(port, () => console.log(`Example app listening on port ${port}!`)) 8 | -------------------------------------------------------------------------------- /section-4/video-4.1/hello-4-1/jenkins-x.yml: -------------------------------------------------------------------------------- 1 | buildPack: javascript 2 | -------------------------------------------------------------------------------- /section-4/video-4.1/hello-4-1/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-hello", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.7", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 10 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 11 | "requires": { 12 | "mime-types": "~2.1.24", 13 | "negotiator": "0.6.2" 14 | } 15 | }, 16 | "array-flatten": { 17 | "version": "1.1.1", 18 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 19 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 20 | }, 21 | "body-parser": { 22 | "version": "1.19.0", 23 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 24 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 25 | "requires": { 26 | "bytes": "3.1.0", 27 | "content-type": "~1.0.4", 28 | "debug": "2.6.9", 29 | "depd": "~1.1.2", 30 | "http-errors": "1.7.2", 31 | "iconv-lite": "0.4.24", 32 | "on-finished": "~2.3.0", 33 | "qs": "6.7.0", 34 | "raw-body": "2.4.0", 35 | "type-is": "~1.6.17" 36 | } 37 | }, 38 | "bytes": { 39 | "version": "3.1.0", 40 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 41 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" 42 | }, 43 | "content-disposition": { 44 | "version": "0.5.3", 45 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 46 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 47 | "requires": { 48 | "safe-buffer": "5.1.2" 49 | } 50 | }, 51 | "content-type": { 52 | "version": "1.0.4", 53 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 54 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 55 | }, 56 | "cookie": { 57 | "version": "0.4.0", 58 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 59 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" 60 | }, 61 | "cookie-signature": { 62 | "version": "1.0.6", 63 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 64 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 65 | }, 66 | "debug": { 67 | "version": "2.6.9", 68 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 69 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 70 | "requires": { 71 | "ms": "2.0.0" 72 | } 73 | }, 74 | "depd": { 75 | "version": "1.1.2", 76 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 77 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 78 | }, 79 | "destroy": { 80 | "version": "1.0.4", 81 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 82 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 83 | }, 84 | "ee-first": { 85 | "version": "1.1.1", 86 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 87 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 88 | }, 89 | "encodeurl": { 90 | "version": "1.0.2", 91 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 92 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 93 | }, 94 | "escape-html": { 95 | "version": "1.0.3", 96 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 97 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 98 | }, 99 | "etag": { 100 | "version": "1.8.1", 101 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 102 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 103 | }, 104 | "express": { 105 | "version": "4.17.1", 106 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 107 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 108 | "requires": { 109 | "accepts": "~1.3.7", 110 | "array-flatten": "1.1.1", 111 | "body-parser": "1.19.0", 112 | "content-disposition": "0.5.3", 113 | "content-type": "~1.0.4", 114 | "cookie": "0.4.0", 115 | "cookie-signature": "1.0.6", 116 | "debug": "2.6.9", 117 | "depd": "~1.1.2", 118 | "encodeurl": "~1.0.2", 119 | "escape-html": "~1.0.3", 120 | "etag": "~1.8.1", 121 | "finalhandler": "~1.1.2", 122 | "fresh": "0.5.2", 123 | "merge-descriptors": "1.0.1", 124 | "methods": "~1.1.2", 125 | "on-finished": "~2.3.0", 126 | "parseurl": "~1.3.3", 127 | "path-to-regexp": "0.1.7", 128 | "proxy-addr": "~2.0.5", 129 | "qs": "6.7.0", 130 | "range-parser": "~1.2.1", 131 | "safe-buffer": "5.1.2", 132 | "send": "0.17.1", 133 | "serve-static": "1.14.1", 134 | "setprototypeof": "1.1.1", 135 | "statuses": "~1.5.0", 136 | "type-is": "~1.6.18", 137 | "utils-merge": "1.0.1", 138 | "vary": "~1.1.2" 139 | } 140 | }, 141 | "finalhandler": { 142 | "version": "1.1.2", 143 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 144 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 145 | "requires": { 146 | "debug": "2.6.9", 147 | "encodeurl": "~1.0.2", 148 | "escape-html": "~1.0.3", 149 | "on-finished": "~2.3.0", 150 | "parseurl": "~1.3.3", 151 | "statuses": "~1.5.0", 152 | "unpipe": "~1.0.0" 153 | } 154 | }, 155 | "forwarded": { 156 | "version": "0.1.2", 157 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 158 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 159 | }, 160 | "fresh": { 161 | "version": "0.5.2", 162 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 163 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 164 | }, 165 | "http-errors": { 166 | "version": "1.7.2", 167 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 168 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 169 | "requires": { 170 | "depd": "~1.1.2", 171 | "inherits": "2.0.3", 172 | "setprototypeof": "1.1.1", 173 | "statuses": ">= 1.5.0 < 2", 174 | "toidentifier": "1.0.0" 175 | } 176 | }, 177 | "iconv-lite": { 178 | "version": "0.4.24", 179 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 180 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 181 | "requires": { 182 | "safer-buffer": ">= 2.1.2 < 3" 183 | } 184 | }, 185 | "inherits": { 186 | "version": "2.0.3", 187 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 188 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 189 | }, 190 | "ipaddr.js": { 191 | "version": "1.9.0", 192 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", 193 | "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" 194 | }, 195 | "media-typer": { 196 | "version": "0.3.0", 197 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 198 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 199 | }, 200 | "merge-descriptors": { 201 | "version": "1.0.1", 202 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 203 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 204 | }, 205 | "methods": { 206 | "version": "1.1.2", 207 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 208 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 209 | }, 210 | "mime": { 211 | "version": "1.6.0", 212 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 213 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 214 | }, 215 | "mime-db": { 216 | "version": "1.43.0", 217 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", 218 | "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" 219 | }, 220 | "mime-types": { 221 | "version": "2.1.26", 222 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", 223 | "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", 224 | "requires": { 225 | "mime-db": "1.43.0" 226 | } 227 | }, 228 | "ms": { 229 | "version": "2.0.0", 230 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 231 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 232 | }, 233 | "negotiator": { 234 | "version": "0.6.2", 235 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 236 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 237 | }, 238 | "on-finished": { 239 | "version": "2.3.0", 240 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 241 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 242 | "requires": { 243 | "ee-first": "1.1.1" 244 | } 245 | }, 246 | "parseurl": { 247 | "version": "1.3.3", 248 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 249 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 250 | }, 251 | "path-to-regexp": { 252 | "version": "0.1.7", 253 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 254 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 255 | }, 256 | "proxy-addr": { 257 | "version": "2.0.5", 258 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", 259 | "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", 260 | "requires": { 261 | "forwarded": "~0.1.2", 262 | "ipaddr.js": "1.9.0" 263 | } 264 | }, 265 | "qs": { 266 | "version": "6.7.0", 267 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 268 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 269 | }, 270 | "range-parser": { 271 | "version": "1.2.1", 272 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 273 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 274 | }, 275 | "raw-body": { 276 | "version": "2.4.0", 277 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 278 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 279 | "requires": { 280 | "bytes": "3.1.0", 281 | "http-errors": "1.7.2", 282 | "iconv-lite": "0.4.24", 283 | "unpipe": "1.0.0" 284 | } 285 | }, 286 | "safe-buffer": { 287 | "version": "5.1.2", 288 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 289 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 290 | }, 291 | "safer-buffer": { 292 | "version": "2.1.2", 293 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 294 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 295 | }, 296 | "send": { 297 | "version": "0.17.1", 298 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 299 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 300 | "requires": { 301 | "debug": "2.6.9", 302 | "depd": "~1.1.2", 303 | "destroy": "~1.0.4", 304 | "encodeurl": "~1.0.2", 305 | "escape-html": "~1.0.3", 306 | "etag": "~1.8.1", 307 | "fresh": "0.5.2", 308 | "http-errors": "~1.7.2", 309 | "mime": "1.6.0", 310 | "ms": "2.1.1", 311 | "on-finished": "~2.3.0", 312 | "range-parser": "~1.2.1", 313 | "statuses": "~1.5.0" 314 | }, 315 | "dependencies": { 316 | "ms": { 317 | "version": "2.1.1", 318 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 319 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 320 | } 321 | } 322 | }, 323 | "serve-static": { 324 | "version": "1.14.1", 325 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 326 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 327 | "requires": { 328 | "encodeurl": "~1.0.2", 329 | "escape-html": "~1.0.3", 330 | "parseurl": "~1.3.3", 331 | "send": "0.17.1" 332 | } 333 | }, 334 | "setprototypeof": { 335 | "version": "1.1.1", 336 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 337 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 338 | }, 339 | "statuses": { 340 | "version": "1.5.0", 341 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 342 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 343 | }, 344 | "toidentifier": { 345 | "version": "1.0.0", 346 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 347 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 348 | }, 349 | "type-is": { 350 | "version": "1.6.18", 351 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 352 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 353 | "requires": { 354 | "media-typer": "0.3.0", 355 | "mime-types": "~2.1.24" 356 | } 357 | }, 358 | "unpipe": { 359 | "version": "1.0.0", 360 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 361 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 362 | }, 363 | "utils-merge": { 364 | "version": "1.0.1", 365 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 366 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 367 | }, 368 | "vary": { 369 | "version": "1.1.2", 370 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 371 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 372 | } 373 | } 374 | } 375 | -------------------------------------------------------------------------------- /section-4/video-4.1/hello-4-1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-hello", 3 | "version": "1.0.0", 4 | "description": "Express Hello World", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js", 8 | "test": "exit 0" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.17.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /section-4/video-4.2/README.md: -------------------------------------------------------------------------------- 1 | # Video 4.2 2 | 3 | This video demonstrates how Jenkins X uses preview environments to deploy a 4 | temporary version of an application during a pull request. 5 | 6 | ## Prerequisites 7 | 8 | First install your cluster per the instruction in section 1. 9 | 10 | ## Preview Environments 11 | 12 | It is common when making changes to an application to create a "feature branch" 13 | and make the changes in that separate branch. Once we are ready to merge the 14 | changes into the master branch, we create a "pull request" in GitHub. This is 15 | an opportunity for others on the team to review the changes before they are 16 | merged into master. 17 | 18 | Jenkins X provides additional functionality for pull requests, including running 19 | a build of the application with the changes merged in, reporting the build 20 | results back to the pull request review page, and deploying the application to 21 | a temporary preview environment that reviewers can use to test the changes. 22 | 23 | To try this out, first import the application in `hello-4-2` using `jx import`. 24 | Then, once it has finished deploying to "staging", create a feature branch: 25 | 26 | ``` 27 | cd hello-4-2 28 | git checkout -b trial-change 29 | ``` 30 | 31 | At this point you can edit one or more of the files. Then, commit and push the 32 | change: 33 | 34 | ``` 35 | git add . 36 | git commit -m 'trial change' 37 | git push -u origin trial-change 38 | ``` 39 | 40 | If you visit the application's Git repository in GitHub, you will see Jenkins X 41 | start building the application and report back the results. If the build is 42 | successful, you will see it deploy to a preview environment. 43 | 44 | ## Cleanup 45 | 46 | You can see the list of preview environments using `jx get preview` and delete 47 | preview requirements when they are no longer needed using `jx delete preview`. 48 | -------------------------------------------------------------------------------- /section-4/video-4.2/hello-4-2/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /section-4/video-4.2/hello-4-2/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const app = express() 3 | const port = 8080 4 | 5 | app.get('/', (req, res) => res.send('Hello World!\n')) 6 | 7 | app.listen(port, () => console.log(`Example app listening on port ${port}!`)) 8 | -------------------------------------------------------------------------------- /section-4/video-4.2/hello-4-2/jenkins-x.yml: -------------------------------------------------------------------------------- 1 | buildPack: javascript 2 | -------------------------------------------------------------------------------- /section-4/video-4.2/hello-4-2/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-hello", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.7", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 10 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 11 | "requires": { 12 | "mime-types": "~2.1.24", 13 | "negotiator": "0.6.2" 14 | } 15 | }, 16 | "array-flatten": { 17 | "version": "1.1.1", 18 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 19 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 20 | }, 21 | "body-parser": { 22 | "version": "1.19.0", 23 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 24 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 25 | "requires": { 26 | "bytes": "3.1.0", 27 | "content-type": "~1.0.4", 28 | "debug": "2.6.9", 29 | "depd": "~1.1.2", 30 | "http-errors": "1.7.2", 31 | "iconv-lite": "0.4.24", 32 | "on-finished": "~2.3.0", 33 | "qs": "6.7.0", 34 | "raw-body": "2.4.0", 35 | "type-is": "~1.6.17" 36 | } 37 | }, 38 | "bytes": { 39 | "version": "3.1.0", 40 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 41 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" 42 | }, 43 | "content-disposition": { 44 | "version": "0.5.3", 45 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 46 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 47 | "requires": { 48 | "safe-buffer": "5.1.2" 49 | } 50 | }, 51 | "content-type": { 52 | "version": "1.0.4", 53 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 54 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 55 | }, 56 | "cookie": { 57 | "version": "0.4.0", 58 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 59 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" 60 | }, 61 | "cookie-signature": { 62 | "version": "1.0.6", 63 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 64 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 65 | }, 66 | "debug": { 67 | "version": "2.6.9", 68 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 69 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 70 | "requires": { 71 | "ms": "2.0.0" 72 | } 73 | }, 74 | "depd": { 75 | "version": "1.1.2", 76 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 77 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 78 | }, 79 | "destroy": { 80 | "version": "1.0.4", 81 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 82 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 83 | }, 84 | "ee-first": { 85 | "version": "1.1.1", 86 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 87 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 88 | }, 89 | "encodeurl": { 90 | "version": "1.0.2", 91 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 92 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 93 | }, 94 | "escape-html": { 95 | "version": "1.0.3", 96 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 97 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 98 | }, 99 | "etag": { 100 | "version": "1.8.1", 101 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 102 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 103 | }, 104 | "express": { 105 | "version": "4.17.1", 106 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 107 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 108 | "requires": { 109 | "accepts": "~1.3.7", 110 | "array-flatten": "1.1.1", 111 | "body-parser": "1.19.0", 112 | "content-disposition": "0.5.3", 113 | "content-type": "~1.0.4", 114 | "cookie": "0.4.0", 115 | "cookie-signature": "1.0.6", 116 | "debug": "2.6.9", 117 | "depd": "~1.1.2", 118 | "encodeurl": "~1.0.2", 119 | "escape-html": "~1.0.3", 120 | "etag": "~1.8.1", 121 | "finalhandler": "~1.1.2", 122 | "fresh": "0.5.2", 123 | "merge-descriptors": "1.0.1", 124 | "methods": "~1.1.2", 125 | "on-finished": "~2.3.0", 126 | "parseurl": "~1.3.3", 127 | "path-to-regexp": "0.1.7", 128 | "proxy-addr": "~2.0.5", 129 | "qs": "6.7.0", 130 | "range-parser": "~1.2.1", 131 | "safe-buffer": "5.1.2", 132 | "send": "0.17.1", 133 | "serve-static": "1.14.1", 134 | "setprototypeof": "1.1.1", 135 | "statuses": "~1.5.0", 136 | "type-is": "~1.6.18", 137 | "utils-merge": "1.0.1", 138 | "vary": "~1.1.2" 139 | } 140 | }, 141 | "finalhandler": { 142 | "version": "1.1.2", 143 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 144 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 145 | "requires": { 146 | "debug": "2.6.9", 147 | "encodeurl": "~1.0.2", 148 | "escape-html": "~1.0.3", 149 | "on-finished": "~2.3.0", 150 | "parseurl": "~1.3.3", 151 | "statuses": "~1.5.0", 152 | "unpipe": "~1.0.0" 153 | } 154 | }, 155 | "forwarded": { 156 | "version": "0.1.2", 157 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 158 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 159 | }, 160 | "fresh": { 161 | "version": "0.5.2", 162 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 163 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 164 | }, 165 | "http-errors": { 166 | "version": "1.7.2", 167 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 168 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 169 | "requires": { 170 | "depd": "~1.1.2", 171 | "inherits": "2.0.3", 172 | "setprototypeof": "1.1.1", 173 | "statuses": ">= 1.5.0 < 2", 174 | "toidentifier": "1.0.0" 175 | } 176 | }, 177 | "iconv-lite": { 178 | "version": "0.4.24", 179 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 180 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 181 | "requires": { 182 | "safer-buffer": ">= 2.1.2 < 3" 183 | } 184 | }, 185 | "inherits": { 186 | "version": "2.0.3", 187 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 188 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 189 | }, 190 | "ipaddr.js": { 191 | "version": "1.9.0", 192 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", 193 | "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" 194 | }, 195 | "media-typer": { 196 | "version": "0.3.0", 197 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 198 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 199 | }, 200 | "merge-descriptors": { 201 | "version": "1.0.1", 202 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 203 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 204 | }, 205 | "methods": { 206 | "version": "1.1.2", 207 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 208 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 209 | }, 210 | "mime": { 211 | "version": "1.6.0", 212 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 213 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 214 | }, 215 | "mime-db": { 216 | "version": "1.43.0", 217 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", 218 | "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" 219 | }, 220 | "mime-types": { 221 | "version": "2.1.26", 222 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", 223 | "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", 224 | "requires": { 225 | "mime-db": "1.43.0" 226 | } 227 | }, 228 | "ms": { 229 | "version": "2.0.0", 230 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 231 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 232 | }, 233 | "negotiator": { 234 | "version": "0.6.2", 235 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 236 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 237 | }, 238 | "on-finished": { 239 | "version": "2.3.0", 240 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 241 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 242 | "requires": { 243 | "ee-first": "1.1.1" 244 | } 245 | }, 246 | "parseurl": { 247 | "version": "1.3.3", 248 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 249 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 250 | }, 251 | "path-to-regexp": { 252 | "version": "0.1.7", 253 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 254 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 255 | }, 256 | "proxy-addr": { 257 | "version": "2.0.5", 258 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", 259 | "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", 260 | "requires": { 261 | "forwarded": "~0.1.2", 262 | "ipaddr.js": "1.9.0" 263 | } 264 | }, 265 | "qs": { 266 | "version": "6.7.0", 267 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 268 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 269 | }, 270 | "range-parser": { 271 | "version": "1.2.1", 272 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 273 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 274 | }, 275 | "raw-body": { 276 | "version": "2.4.0", 277 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 278 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 279 | "requires": { 280 | "bytes": "3.1.0", 281 | "http-errors": "1.7.2", 282 | "iconv-lite": "0.4.24", 283 | "unpipe": "1.0.0" 284 | } 285 | }, 286 | "safe-buffer": { 287 | "version": "5.1.2", 288 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 289 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 290 | }, 291 | "safer-buffer": { 292 | "version": "2.1.2", 293 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 294 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 295 | }, 296 | "send": { 297 | "version": "0.17.1", 298 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 299 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 300 | "requires": { 301 | "debug": "2.6.9", 302 | "depd": "~1.1.2", 303 | "destroy": "~1.0.4", 304 | "encodeurl": "~1.0.2", 305 | "escape-html": "~1.0.3", 306 | "etag": "~1.8.1", 307 | "fresh": "0.5.2", 308 | "http-errors": "~1.7.2", 309 | "mime": "1.6.0", 310 | "ms": "2.1.1", 311 | "on-finished": "~2.3.0", 312 | "range-parser": "~1.2.1", 313 | "statuses": "~1.5.0" 314 | }, 315 | "dependencies": { 316 | "ms": { 317 | "version": "2.1.1", 318 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 319 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 320 | } 321 | } 322 | }, 323 | "serve-static": { 324 | "version": "1.14.1", 325 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 326 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 327 | "requires": { 328 | "encodeurl": "~1.0.2", 329 | "escape-html": "~1.0.3", 330 | "parseurl": "~1.3.3", 331 | "send": "0.17.1" 332 | } 333 | }, 334 | "setprototypeof": { 335 | "version": "1.1.1", 336 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 337 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 338 | }, 339 | "statuses": { 340 | "version": "1.5.0", 341 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 342 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 343 | }, 344 | "toidentifier": { 345 | "version": "1.0.0", 346 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 347 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 348 | }, 349 | "type-is": { 350 | "version": "1.6.18", 351 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 352 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 353 | "requires": { 354 | "media-typer": "0.3.0", 355 | "mime-types": "~2.1.24" 356 | } 357 | }, 358 | "unpipe": { 359 | "version": "1.0.0", 360 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 361 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 362 | }, 363 | "utils-merge": { 364 | "version": "1.0.1", 365 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 366 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 367 | }, 368 | "vary": { 369 | "version": "1.1.2", 370 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 371 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 372 | } 373 | } 374 | } 375 | -------------------------------------------------------------------------------- /section-4/video-4.2/hello-4-2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-hello", 3 | "version": "1.0.0", 4 | "description": "Express Hello World", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js", 8 | "test": "exit 0" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.17.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /section-4/video-4.3/README.md: -------------------------------------------------------------------------------- 1 | # Video 4.3 2 | 3 | This video demonstrates how to use a Jenkins X DevPod to run an application 4 | within the Kubernetes cluster, allowing us to see changes immediately. 5 | 6 | ## Prerequisites 7 | 8 | First install your cluster per the instruction in section 1. 9 | 10 | ## DevPod 11 | 12 | A Jenkins X DevPod is a version of our application that is based on our local 13 | code directories rather than what is in Git. Using a Jenkins X DevPod allows 14 | us to test our code in a more realistic environment running in Kubernetes 15 | itself rather than just on the local computer. 16 | 17 | To create a DevPod, run this command from inside the code directory for an 18 | application: 19 | 20 | ``` 21 | jx create devpod 22 | ``` 23 | 24 | This will create the DevPod and open a shell. You can then start the 25 | application as normal (e.g. `npm start` for our example JavaScript application). 26 | 27 | You can open an additional shell in the DevPod from another terminal window 28 | by running: 29 | 30 | ``` 31 | jx create devpod --reuse 32 | ``` 33 | 34 | When finished, just run `jx delete devpod` to clean up. 35 | -------------------------------------------------------------------------------- /section-4/video-4.3/hello-4-3/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /section-4/video-4.3/hello-4-3/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const app = express() 3 | const port = 8080 4 | 5 | app.get('/', (req, res) => res.send('Hello World!\n')) 6 | 7 | app.listen(port, () => console.log(`Example app listening on port ${port}!`)) 8 | -------------------------------------------------------------------------------- /section-4/video-4.3/hello-4-3/jenkins-x.yml: -------------------------------------------------------------------------------- 1 | buildPack: javascript 2 | -------------------------------------------------------------------------------- /section-4/video-4.3/hello-4-3/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-hello", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.7", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 10 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 11 | "requires": { 12 | "mime-types": "~2.1.24", 13 | "negotiator": "0.6.2" 14 | } 15 | }, 16 | "array-flatten": { 17 | "version": "1.1.1", 18 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 19 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 20 | }, 21 | "body-parser": { 22 | "version": "1.19.0", 23 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 24 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 25 | "requires": { 26 | "bytes": "3.1.0", 27 | "content-type": "~1.0.4", 28 | "debug": "2.6.9", 29 | "depd": "~1.1.2", 30 | "http-errors": "1.7.2", 31 | "iconv-lite": "0.4.24", 32 | "on-finished": "~2.3.0", 33 | "qs": "6.7.0", 34 | "raw-body": "2.4.0", 35 | "type-is": "~1.6.17" 36 | } 37 | }, 38 | "bytes": { 39 | "version": "3.1.0", 40 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 41 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" 42 | }, 43 | "content-disposition": { 44 | "version": "0.5.3", 45 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 46 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 47 | "requires": { 48 | "safe-buffer": "5.1.2" 49 | } 50 | }, 51 | "content-type": { 52 | "version": "1.0.4", 53 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 54 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 55 | }, 56 | "cookie": { 57 | "version": "0.4.0", 58 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 59 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" 60 | }, 61 | "cookie-signature": { 62 | "version": "1.0.6", 63 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 64 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 65 | }, 66 | "debug": { 67 | "version": "2.6.9", 68 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 69 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 70 | "requires": { 71 | "ms": "2.0.0" 72 | } 73 | }, 74 | "depd": { 75 | "version": "1.1.2", 76 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 77 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 78 | }, 79 | "destroy": { 80 | "version": "1.0.4", 81 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 82 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 83 | }, 84 | "ee-first": { 85 | "version": "1.1.1", 86 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 87 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 88 | }, 89 | "encodeurl": { 90 | "version": "1.0.2", 91 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 92 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 93 | }, 94 | "escape-html": { 95 | "version": "1.0.3", 96 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 97 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 98 | }, 99 | "etag": { 100 | "version": "1.8.1", 101 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 102 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 103 | }, 104 | "express": { 105 | "version": "4.17.1", 106 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 107 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 108 | "requires": { 109 | "accepts": "~1.3.7", 110 | "array-flatten": "1.1.1", 111 | "body-parser": "1.19.0", 112 | "content-disposition": "0.5.3", 113 | "content-type": "~1.0.4", 114 | "cookie": "0.4.0", 115 | "cookie-signature": "1.0.6", 116 | "debug": "2.6.9", 117 | "depd": "~1.1.2", 118 | "encodeurl": "~1.0.2", 119 | "escape-html": "~1.0.3", 120 | "etag": "~1.8.1", 121 | "finalhandler": "~1.1.2", 122 | "fresh": "0.5.2", 123 | "merge-descriptors": "1.0.1", 124 | "methods": "~1.1.2", 125 | "on-finished": "~2.3.0", 126 | "parseurl": "~1.3.3", 127 | "path-to-regexp": "0.1.7", 128 | "proxy-addr": "~2.0.5", 129 | "qs": "6.7.0", 130 | "range-parser": "~1.2.1", 131 | "safe-buffer": "5.1.2", 132 | "send": "0.17.1", 133 | "serve-static": "1.14.1", 134 | "setprototypeof": "1.1.1", 135 | "statuses": "~1.5.0", 136 | "type-is": "~1.6.18", 137 | "utils-merge": "1.0.1", 138 | "vary": "~1.1.2" 139 | } 140 | }, 141 | "finalhandler": { 142 | "version": "1.1.2", 143 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 144 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 145 | "requires": { 146 | "debug": "2.6.9", 147 | "encodeurl": "~1.0.2", 148 | "escape-html": "~1.0.3", 149 | "on-finished": "~2.3.0", 150 | "parseurl": "~1.3.3", 151 | "statuses": "~1.5.0", 152 | "unpipe": "~1.0.0" 153 | } 154 | }, 155 | "forwarded": { 156 | "version": "0.1.2", 157 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 158 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 159 | }, 160 | "fresh": { 161 | "version": "0.5.2", 162 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 163 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 164 | }, 165 | "http-errors": { 166 | "version": "1.7.2", 167 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 168 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 169 | "requires": { 170 | "depd": "~1.1.2", 171 | "inherits": "2.0.3", 172 | "setprototypeof": "1.1.1", 173 | "statuses": ">= 1.5.0 < 2", 174 | "toidentifier": "1.0.0" 175 | } 176 | }, 177 | "iconv-lite": { 178 | "version": "0.4.24", 179 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 180 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 181 | "requires": { 182 | "safer-buffer": ">= 2.1.2 < 3" 183 | } 184 | }, 185 | "inherits": { 186 | "version": "2.0.3", 187 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 188 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 189 | }, 190 | "ipaddr.js": { 191 | "version": "1.9.0", 192 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", 193 | "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" 194 | }, 195 | "media-typer": { 196 | "version": "0.3.0", 197 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 198 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 199 | }, 200 | "merge-descriptors": { 201 | "version": "1.0.1", 202 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 203 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 204 | }, 205 | "methods": { 206 | "version": "1.1.2", 207 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 208 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 209 | }, 210 | "mime": { 211 | "version": "1.6.0", 212 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 213 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 214 | }, 215 | "mime-db": { 216 | "version": "1.43.0", 217 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", 218 | "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" 219 | }, 220 | "mime-types": { 221 | "version": "2.1.26", 222 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", 223 | "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", 224 | "requires": { 225 | "mime-db": "1.43.0" 226 | } 227 | }, 228 | "ms": { 229 | "version": "2.0.0", 230 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 231 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 232 | }, 233 | "negotiator": { 234 | "version": "0.6.2", 235 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 236 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 237 | }, 238 | "on-finished": { 239 | "version": "2.3.0", 240 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 241 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 242 | "requires": { 243 | "ee-first": "1.1.1" 244 | } 245 | }, 246 | "parseurl": { 247 | "version": "1.3.3", 248 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 249 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 250 | }, 251 | "path-to-regexp": { 252 | "version": "0.1.7", 253 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 254 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 255 | }, 256 | "proxy-addr": { 257 | "version": "2.0.5", 258 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", 259 | "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", 260 | "requires": { 261 | "forwarded": "~0.1.2", 262 | "ipaddr.js": "1.9.0" 263 | } 264 | }, 265 | "qs": { 266 | "version": "6.7.0", 267 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 268 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 269 | }, 270 | "range-parser": { 271 | "version": "1.2.1", 272 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 273 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 274 | }, 275 | "raw-body": { 276 | "version": "2.4.0", 277 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 278 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 279 | "requires": { 280 | "bytes": "3.1.0", 281 | "http-errors": "1.7.2", 282 | "iconv-lite": "0.4.24", 283 | "unpipe": "1.0.0" 284 | } 285 | }, 286 | "safe-buffer": { 287 | "version": "5.1.2", 288 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 289 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 290 | }, 291 | "safer-buffer": { 292 | "version": "2.1.2", 293 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 294 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 295 | }, 296 | "send": { 297 | "version": "0.17.1", 298 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 299 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 300 | "requires": { 301 | "debug": "2.6.9", 302 | "depd": "~1.1.2", 303 | "destroy": "~1.0.4", 304 | "encodeurl": "~1.0.2", 305 | "escape-html": "~1.0.3", 306 | "etag": "~1.8.1", 307 | "fresh": "0.5.2", 308 | "http-errors": "~1.7.2", 309 | "mime": "1.6.0", 310 | "ms": "2.1.1", 311 | "on-finished": "~2.3.0", 312 | "range-parser": "~1.2.1", 313 | "statuses": "~1.5.0" 314 | }, 315 | "dependencies": { 316 | "ms": { 317 | "version": "2.1.1", 318 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 319 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 320 | } 321 | } 322 | }, 323 | "serve-static": { 324 | "version": "1.14.1", 325 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 326 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 327 | "requires": { 328 | "encodeurl": "~1.0.2", 329 | "escape-html": "~1.0.3", 330 | "parseurl": "~1.3.3", 331 | "send": "0.17.1" 332 | } 333 | }, 334 | "setprototypeof": { 335 | "version": "1.1.1", 336 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 337 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 338 | }, 339 | "statuses": { 340 | "version": "1.5.0", 341 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 342 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 343 | }, 344 | "toidentifier": { 345 | "version": "1.0.0", 346 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 347 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 348 | }, 349 | "type-is": { 350 | "version": "1.6.18", 351 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 352 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 353 | "requires": { 354 | "media-typer": "0.3.0", 355 | "mime-types": "~2.1.24" 356 | } 357 | }, 358 | "unpipe": { 359 | "version": "1.0.0", 360 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 361 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 362 | }, 363 | "utils-merge": { 364 | "version": "1.0.1", 365 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 366 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 367 | }, 368 | "vary": { 369 | "version": "1.1.2", 370 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 371 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 372 | } 373 | } 374 | } 375 | -------------------------------------------------------------------------------- /section-4/video-4.3/hello-4-3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-hello", 3 | "version": "1.0.0", 4 | "description": "Express Hello World", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js", 8 | "test": "exit 0" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.17.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /section-4/video-4.4/README.md: -------------------------------------------------------------------------------- 1 | # Video 4.4 2 | 3 | This video demonstrates editing an application in a DevPod using the editor 4 | built into the DevPod. 5 | 6 | ## Prerequisites 7 | 8 | First install your cluster per the instruction in section 1. 9 | 10 | ## DevPod 11 | 12 | Jenkins X can provide an editor running within the DevPod; by default this is 13 | Visual Studio Code. We can use this to edit our application source code from 14 | a web browser to rapidly see changes. 15 | 16 | Start by creating a DevPod: 17 | 18 | ``` 19 | jx create devpod 20 | ``` 21 | 22 | From the DevPod shell, note the URL for the IDE. Also start the application. 23 | 24 | At this point you can visit the IDE in the browser to edit your code. 25 | -------------------------------------------------------------------------------- /section-4/video-4.4/hello-4-4/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /section-4/video-4.4/hello-4-4/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const app = express() 3 | const port = 8080 4 | 5 | app.get('/', (req, res) => res.send('Hello World!\n')) 6 | 7 | app.listen(port, () => console.log(`Example app listening on port ${port}!`)) 8 | -------------------------------------------------------------------------------- /section-4/video-4.4/hello-4-4/jenkins-x.yml: -------------------------------------------------------------------------------- 1 | buildPack: javascript 2 | -------------------------------------------------------------------------------- /section-4/video-4.4/hello-4-4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-hello", 3 | "version": "1.0.0", 4 | "description": "Express Hello World", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "nodemon index.js", 8 | "start": "node index.js", 9 | "test": "exit 0" 10 | }, 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "express": "^4.17.1" 15 | }, 16 | "devDependencies": { 17 | "nodemon": "^2.0.2" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /section-4/video-4.5/README.md: -------------------------------------------------------------------------------- 1 | # Video 4.5 2 | 3 | This video shows how Jenkins X uses Skaffold to build the Docker images used 4 | to run applications. 5 | 6 | ## Prerequisites 7 | 8 | None 9 | 10 | ## Skaffold 11 | 12 | Skaffold is a tool to help with the building of Docker images. It allows us 13 | to configure the Docker build using a YAML file rather than passing all of 14 | the parameters on the command line to `docker build`. It also supports 15 | incremental re-build, so it can be used for rapid development. 16 | 17 | When we import a project, Jenkins X creates a `Dockerfile` and `skaffold.yaml` 18 | file if they don't already exist. The `Dockerfile` consists of instructions to 19 | Docker as to how to build the image. The `skaffold.yaml` configures the name of 20 | the image, what registry to push to after completion, and other parameters. 21 | 22 | The `Dockerfile` and `skaffold.yaml` come from the build pack so they can be 23 | specific to the language and runtime we're using (e.g. `javascript` with Node). 24 | The build pack also contains the command to run `skaffold` to build and push 25 | the image. 26 | -------------------------------------------------------------------------------- /section-5/video-5.1/README.md: -------------------------------------------------------------------------------- 1 | # Video 5.1 2 | 3 | This video demonstrates an application deployed to Kubernetes. 4 | 5 | ## Prerequisites 6 | 7 | First install your cluster per the instruction in section 1. 8 | 9 | Second, you need to know the domain name that your cluster is using for 10 | ingress. Because of the way we create the cluster using Google Kubernetes 11 | Engine in section 1, it gets a single IP address. We can use `nip.io` to 12 | treat that IP address as a domain, but first we need to know what it is. 13 | 14 | To find out, run: 15 | 16 | ``` 17 | kubectl get ingress 18 | ``` 19 | 20 | You will see a list of Kubernetes Ingress resources (more on those later) 21 | that all share the same IP address. Copy that IP address to the clipboard and 22 | paste it into the `plone.yaml` file where it says `REPLACE_ME_INGRESS_IP`. 23 | 24 | When finished, you should have a line in your `plone.yaml` that looks like 25 | this (but with a different IP address; don't use this one!): 26 | 27 | ``` 28 | - host: plone.10.11.12.13.nip.io 29 | ``` 30 | 31 | ## Kubernetes 32 | 33 | Jenkins X uses Kubernetes as the platform on which it runs its own components, 34 | runs builds, and deploys applications. Kubernetes is a "container orchestration" 35 | platform. This means that it runs containerized applications (such as Docker 36 | images), providing them with configuration, storage, networking, and fault 37 | tolerance (including health checks, load balancing, and failover). 38 | 39 | When we deployed our cluster in Section 1, before we could run `jx boot`, we 40 | first had to create a Kubernetes cluster on which to deploy Jenkins X. In 41 | addition to using this cluster with Jenkins X, we can also configure it directly 42 | using the `kubectl` command (which we saw in Section 2). 43 | 44 | ## Deploying to Kubernetes 45 | 46 | To deploy an application to Kubernetes, we create "resources" in the cluster. 47 | The Kubernetes control plane (the set of services that manage the cluster) 48 | does the necessary work to start containers, configure networking, etc. 49 | 50 | We specify the necessary resources using YAML configuration files. We can 51 | then apply these resources to the cluster (create or update, as needed) 52 | using the `kubectl apply` command. For example: 53 | 54 | ``` 55 | kubectl apply -f plone.yaml 56 | ``` 57 | 58 | You can now visit your Plone instance in a browser using the host name you 59 | configured in the ingress above. 60 | 61 | ## Cleaning Up 62 | 63 | To clean up the resources in a file, we can just run `kubectl delete`: 64 | 65 | ``` 66 | kubectl delete -f plone.yaml 67 | ``` 68 | -------------------------------------------------------------------------------- /section-5/video-5.1/plone.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: Deployment 3 | apiVersion: apps/v1 4 | metadata: 5 | name: plone 6 | labels: 7 | app: plone 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | app: plone 13 | template: 14 | metadata: 15 | labels: 16 | app: plone 17 | spec: 18 | containers: 19 | - name: plone 20 | image: plone:5.2.1-alpine 21 | ports: 22 | - containerPort: 8080 23 | --- 24 | kind: Service 25 | apiVersion: v1 26 | metadata: 27 | name: plone 28 | spec: 29 | selector: 30 | app: plone 31 | type: ClusterIP 32 | ports: 33 | - protocol: TCP 34 | port: 8080 35 | targetPort: 8080 36 | --- 37 | kind: Ingress 38 | apiVersion: extensions/v1beta1 39 | metadata: 40 | name: plone 41 | spec: 42 | rules: 43 | - host: plone.REPLACE_ME_INGRESS_IP.nip.io 44 | http: 45 | paths: 46 | - backend: 47 | serviceName: plone 48 | servicePort: 8080 49 | -------------------------------------------------------------------------------- /section-5/video-5.2/README.md: -------------------------------------------------------------------------------- 1 | # Video 5.2 2 | 3 | This video shows Kubernetes deployments and pods. 4 | 5 | ## Prerequisites 6 | 7 | First install your cluster per the instruction in section 1. 8 | 9 | ## Deployments and Pods 10 | 11 | A pod is a logical group of containers that all run on the same Kubernetes node 12 | and share a Pod IP address. Kubernetes uses deployments to manage pods, 13 | including creating pods, creating multiple replicas of pods, performing a 14 | rolling update to allow for upgrading an application with zero downtime, and 15 | replacing pods when there is a failure in a container or in a Kubernetes node. 16 | 17 | When we create a deployment, we give it a template for the pods it creates. 18 | This includes information on what containers to create. It also includes a 19 | set of labels that are used by the deployment to find and manage its pods. 20 | This means we have to configure a "selector" in the deployment that matches 21 | the "labels" that we give in the pod template. 22 | 23 | ## Creating a Deployment 24 | 25 | As before, we use `kubectl apply`: 26 | 27 | ``` 28 | kubectl apply -f deployment.yaml 29 | ``` 30 | 31 | We can verify that the deployment exists and that the matching pods were 32 | created: 33 | 34 | ``` 35 | kubectl get deployment plone 36 | kubectl get pods -l app=plone 37 | ``` 38 | 39 | ## Cleaning Up 40 | 41 | To clean up the resources in a file, we can just run `kubectl delete`: 42 | 43 | ``` 44 | kubectl delete -f deployment.yaml 45 | ``` 46 | 47 | We can also delete individual resources directly: 48 | 49 | ``` 50 | kubectl delete deployment plone 51 | ``` 52 | 53 | However, note that if you only delete a pod, the deployment will automatically 54 | create a replacement. 55 | -------------------------------------------------------------------------------- /section-5/video-5.2/deployment.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: Deployment 3 | apiVersion: apps/v1 4 | metadata: 5 | name: plone 6 | labels: 7 | app: plone 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | app: plone 13 | template: 14 | metadata: 15 | labels: 16 | app: plone 17 | spec: 18 | containers: 19 | - name: plone 20 | image: plone:5.2.1-alpine 21 | ports: 22 | - containerPort: 8080 23 | -------------------------------------------------------------------------------- /section-5/video-5.3/README.md: -------------------------------------------------------------------------------- 1 | # Video 5.3 2 | 3 | This video shows Kubernetes services. 4 | 5 | ## Prerequisites 6 | 7 | First install your cluster per the instruction in section 1. 8 | 9 | ## Services 10 | 11 | Pods may come and go in a cluster, either because of failure or because we 12 | are upgrading our application. In addition, we may have multiple pod replicas 13 | to providing horizontal scaling. Therefore, while each pod has its own IP 14 | address, we can't use the pod IP address to reliably communicate with our 15 | application. 16 | 17 | A Kubernetes service provides a well-known name and a long-lasting IP address 18 | for our application. The service receives a cluster IP address, and any traffic 19 | to the cluster IP address is automatically load balanced across all pods that 20 | match the service's selector. Even as pods come and go, clients can still use 21 | the service and will be routed to a healthy pod. 22 | 23 | ## Creating a Service 24 | 25 | As before, we use `kubectl apply`: 26 | 27 | ``` 28 | kubectl apply -f service.yaml 29 | ``` 30 | 31 | We can verify that the service exists and matches the pods in the deployment: 32 | 33 | ``` 34 | kubectl get service plone 35 | kubectl describe service plone 36 | ``` 37 | 38 | ## Cleaning Up 39 | 40 | To clean up the resources in a file, we can just run `kubectl delete`: 41 | 42 | ``` 43 | kubectl delete -f service.yaml 44 | ``` 45 | 46 | We can also delete individual resources directly: 47 | 48 | ``` 49 | kubectl delete service plone 50 | kubectl delete deployment plone 51 | ``` 52 | -------------------------------------------------------------------------------- /section-5/video-5.3/service.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: Service 3 | apiVersion: v1 4 | metadata: 5 | name: plone 6 | spec: 7 | selector: 8 | app: plone 9 | type: ClusterIP 10 | ports: 11 | - protocol: TCP 12 | port: 8080 13 | targetPort: 8080 14 | --- 15 | kind: Deployment 16 | apiVersion: apps/v1 17 | metadata: 18 | name: plone 19 | labels: 20 | app: plone 21 | spec: 22 | replicas: 3 23 | selector: 24 | matchLabels: 25 | app: plone 26 | template: 27 | metadata: 28 | labels: 29 | app: plone 30 | spec: 31 | containers: 32 | - name: plone 33 | image: plone:5.2.1-alpine 34 | ports: 35 | - containerPort: 8080 36 | -------------------------------------------------------------------------------- /section-5/video-5.4/README.md: -------------------------------------------------------------------------------- 1 | # Video 5.4 2 | 3 | This video shows Kubernetes ingress resources. 4 | 5 | ## Prerequisites 6 | 7 | First install your cluster per the instruction in section 1. 8 | 9 | Second, you need to know the domain name that your cluster is using for 10 | ingress. Because of the way we create the cluster using Google Kubernetes 11 | Engine in section 1, it gets a single IP address. We can use `nip.io` to 12 | treat that IP address as a domain, but first we need to know what it is. 13 | 14 | To find out, run: 15 | 16 | ``` 17 | kubectl get ingress 18 | ``` 19 | 20 | You will see a list of Kubernetes Ingress resources (as described in this video) 21 | that all share the same IP address. Copy that IP address to the clipboard and 22 | paste it into the `plone.yaml` file where it says `REPLACE_ME_INGRESS_IP`. 23 | 24 | When finished, you should have a line in your `plone.yaml` that looks like 25 | this (but with a different IP address; don't use this one!): 26 | 27 | ``` 28 | - host: plone.10.11.12.13.nip.io 29 | ``` 30 | 31 | ## Ingress 32 | 33 | The cluster IP we created for our service is only accessible from inside the 34 | cluster. While there are other types of services that we can use to get 35 | external IP addresses (IP addresses that we can access from outside the cluster) 36 | it is usually easier and more efficient to just use an ingress. 37 | 38 | An ingress is a special kind of Kubernetes service that has an external IP 39 | address and routes traffic to services. The ingress has an ingress controller 40 | that is configured with rules telling it how to route traffic. This typically 41 | means HTTP traffic, and the rules are based on the `Host` header in the request 42 | or matching the path of the URL. 43 | 44 | The ingress uses these rules to route traffic to a service; the service then 45 | routes traffic to a specific pod instance. 46 | 47 | ## Creating an Ingress 48 | 49 | As before, we use `kubectl apply`: 50 | 51 | ``` 52 | kubectl apply -f plone.yaml 53 | ``` 54 | 55 | We can verify that the ingress exists and has the right routing rules: 56 | 57 | ``` 58 | kubectl get ingress plone 59 | kubectl describe ingress plone 60 | ``` 61 | 62 | ## Cleaning Up 63 | 64 | To clean up the resources in a file, we can just run `kubectl delete`: 65 | 66 | ``` 67 | kubectl delete -f plone.yaml 68 | ``` 69 | 70 | We can also delete individual resources directly: 71 | 72 | ``` 73 | kubectl delete ingress plone 74 | kubectl delete service plone 75 | kubectl delete deployment plone 76 | ``` 77 | -------------------------------------------------------------------------------- /section-5/video-5.4/plone.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: Ingress 3 | apiVersion: extensions/v1beta1 4 | metadata: 5 | name: plone 6 | spec: 7 | rules: 8 | - host: plone.REPLACE_ME_INGRESS_IP.nip.io 9 | http: 10 | paths: 11 | - backend: 12 | serviceName: plone 13 | servicePort: 8080 14 | --- 15 | kind: Service 16 | apiVersion: v1 17 | metadata: 18 | name: plone 19 | spec: 20 | selector: 21 | app: plone 22 | type: ClusterIP 23 | ports: 24 | - protocol: TCP 25 | port: 8080 26 | targetPort: 8080 27 | --- 28 | kind: Deployment 29 | apiVersion: apps/v1 30 | metadata: 31 | name: plone 32 | labels: 33 | app: plone 34 | spec: 35 | replicas: 1 36 | selector: 37 | matchLabels: 38 | app: plone 39 | template: 40 | metadata: 41 | labels: 42 | app: plone 43 | spec: 44 | containers: 45 | - name: plone 46 | image: plone:5.2.1-alpine 47 | ports: 48 | - containerPort: 8080 49 | -------------------------------------------------------------------------------- /section-5/video-5.5/README.md: -------------------------------------------------------------------------------- 1 | # Video 5.5 2 | 3 | This video demonstrates Helm, the Kubernetes package manager. 4 | 5 | ## Prerequisites 6 | 7 | First install your cluster per the instruction in section 1. 8 | 9 | Second, you need to know the domain name that your cluster is using for 10 | ingress. Because of the way we create the cluster using Google Kubernetes 11 | Engine in section 1, it gets a single IP address. We can use `nip.io` to 12 | treat that IP address as a domain, but first we need to know what it is. 13 | 14 | To find out, run: 15 | 16 | ``` 17 | kubectl get ingress 18 | ``` 19 | 20 | You will see a list of Kubernetes Ingress resources (as described previously) 21 | that all share the same IP address. Copy that IP address to the clipboard and 22 | paste it into the `values.yaml` file where it says `REPLACE_ME_INGRESS_IP`. 23 | 24 | When finished, you should have a section in your `values.yaml` that looks like 25 | this (but with a different IP address; don't use this one!): 26 | 27 | ``` 28 | hosts: 29 | - bookstack.10.11.12.13.nip.io 30 | ``` 31 | 32 | Finally, you need to install the Helm client and add the stable repo as 33 | described [in the documentation][helm]. 34 | 35 | [helm]:https://helm.sh/docs/intro/quickstart/ 36 | 37 | ## Helm 38 | 39 | To deploy an application to Kubernetes, we need to know not just about 40 | Kubernetes but also about how to configure the application we're deploying. 41 | Additionally, Kubernetes YAML files quickly get long and hard to maintain. 42 | 43 | Helm is designed to address this by offering "charts", which are collections 44 | of Kubernetes resources designed to make it easy to deploy an application. 45 | Helm supports downloading and installing charts from repositories, overriding 46 | configuration for a chart, upgrading a chart to a new version, and deleting 47 | a chart. 48 | 49 | Once Helm is configured, you can install an application from a chart using: 50 | 51 | ``` 52 | helm install bookstack stable/bookstack -f values.yaml 53 | ``` 54 | 55 | The application will take a few minutes to install and be available. You can 56 | verify it by visiting the URL in the browser. 57 | 58 | ## Cleaning Up 59 | 60 | To delete the application: 61 | 62 | ``` 63 | helm delete bookstack 64 | ``` 65 | -------------------------------------------------------------------------------- /section-5/video-5.5/values.yaml: -------------------------------------------------------------------------------- 1 | ingress: 2 | enabled: true 3 | hosts: 4 | - bookstack.REPLACE_ME_INGRESS_IP.nip.io 5 | -------------------------------------------------------------------------------- /section-5/video-5.6/README.md: -------------------------------------------------------------------------------- 1 | # Video 5.6 2 | 3 | This video demonstrates debugging applications within Kubernetes. 4 | 5 | ## Prerequisites 6 | 7 | First install your cluster per the instruction in section 1. 8 | 9 | ## Debugging Kubernetes 10 | 11 | Once an application is up and running, Kubernetes will do its best to keep 12 | it running with the number of specified replicas, and will route traffic 13 | to it. However, sometimes it can be challenging to get an application up 14 | as it can be challenging to figure out what is going wrong. 15 | 16 | There are a few key commands for debugging an application in Kubernetes: 17 | 18 | * `kubectl get []`: List all resources of `type`, or just the 19 | resource with the provided `name`. Use an output format such as `-o wide` 20 | to get more information, or `-o yaml` to see the complete configuration. 21 | * `kubectl describe `: Show the current status of the resource, 22 | together with recent events. 23 | * `kubectl logs `: See the logs for an individual pod. 24 | * `kubectl exec -ti [-c ] `: Run a command 25 | inside a pod. If there are multiple containers in the pod you must provide 26 | a container name. 27 | 28 | Generally, the first two commands are used prior to getting the pod to the 29 | `Running` state, and the last two commands are used after the pod runs the 30 | first time. 31 | 32 | There are multiple different error states for a pod, but two are the most 33 | commonly seen: 34 | 35 | * `ImagePullBackOff`: This means that Kubernetes has tried multiple times to 36 | pull the Docker image and has been unsuccessful. This may indicate that the 37 | image name is incorrect, that the registry is down, or that there is an 38 | issue with authentication or authorization to pull the image. 39 | * `CrashLoopBackOff`: This means that Kubernetes was able to pull the image, 40 | but the command to start the container keeps failing. This may indicate a 41 | bad command, a bad configuration of the pod, or an error in the application 42 | that causes it to exit. If the pod is configured with health checks, it may 43 | also mean that the pod is failing health checks. 44 | 45 | To help illustrate these errors, this folder has three deployments: 46 | 47 | * `bad-image-name`: The name of the Plone image is misspelled to cause an 48 | `ImagePullBackOff`. 49 | * `bad-command`: The command `/bin/false` is specified to cause a container 50 | that will fail repeatedly and cause `CrashLoopBackOff`. 51 | * `good-deployment`: Both of these errors are fixed to allow creation of a 52 | `Running` container to test `log` and `exec`. 53 | -------------------------------------------------------------------------------- /section-5/video-5.6/bad-command/deployment.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: Deployment 3 | apiVersion: apps/v1 4 | metadata: 5 | name: plone 6 | labels: 7 | app: plone 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | app: plone 13 | template: 14 | metadata: 15 | labels: 16 | app: plone 17 | spec: 18 | containers: 19 | - name: plone 20 | image: plone:5.2.1-alpine 21 | command: ["/bin/false"] # Causes the container to fail on startup 22 | ports: 23 | - containerPort: 8080 24 | -------------------------------------------------------------------------------- /section-5/video-5.6/bad-image-name/deployment.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: Deployment 3 | apiVersion: apps/v1 4 | metadata: 5 | name: plone 6 | labels: 7 | app: plone 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | app: plone 13 | template: 14 | metadata: 15 | labels: 16 | app: plone 17 | spec: 18 | containers: 19 | - name: plone 20 | image: plone:5.2.1-alpne # Should be 5.2.1-alpine 21 | ports: 22 | - containerPort: 8080 23 | -------------------------------------------------------------------------------- /section-5/video-5.6/good-deployment/deployment.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: Deployment 3 | apiVersion: apps/v1 4 | metadata: 5 | name: plone 6 | labels: 7 | app: plone 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | app: plone 13 | template: 14 | metadata: 15 | labels: 16 | app: plone 17 | spec: 18 | containers: 19 | - name: plone 20 | image: plone:5.2.1-alpine 21 | ports: 22 | - containerPort: 8080 23 | -------------------------------------------------------------------------------- /section-6/video-6.1/README.md: -------------------------------------------------------------------------------- 1 | # Video 6.1 2 | 3 | This video demonstrates adding "apps" to Jenkins X. 4 | 5 | ## Prerequisites 6 | 7 | First install your cluster per the instruction in section 1. 8 | 9 | Second, if you installed Helm 3 in your PATH as part of Video 5.5, you may 10 | need to make sure it is no longer in your PATH, as of this writing (March 2020) 11 | Jenkins X does not yet support Helm 3. 12 | 13 | ## Jenkins X Apps 14 | 15 | Jenkins X has the concept of an "app" that we can add to the cluster. This is 16 | different from an application that Jenkins X builds and deploys; Jenkins X 17 | only manages deployement for an app. 18 | 19 | We can deploy an app using a Helm chart; the only difference with using Helm 20 | directly is that Jenkins X will manage the deployment for us using GitOps 21 | so we can more easily rebuild the cluster if needed. 22 | 23 | ## Adding an App to Jenkins X 24 | 25 | We can add an app to Jenkins X by referencing the name and repository for the 26 | Helm chart. For example: 27 | 28 | ``` 29 | jx add app mongodb --repository https://charts.bitnami.com/bitnami 30 | ``` 31 | 32 | This will create a pull request that will eventually end up adding MongoDB 33 | to our Kubernetes cluster. 34 | 35 | ## Cleaning Up 36 | 37 | To delete the MongoDB Jenkins X app, run: 38 | 39 | ``` 40 | jx delete app mongodb 41 | ``` 42 | -------------------------------------------------------------------------------- /section-6/video-6.2/README.md: -------------------------------------------------------------------------------- 1 | # Video 6.2 2 | 3 | This video demonstrates Jenkins X addons. 4 | 5 | ## Prerequisites 6 | 7 | First install your cluster per the instruction in section 1. 8 | 9 | ## Jenkins X Addons 10 | 11 | Jenkins X Addons are, confusingly, different from Jenkins X Apps. There is a 12 | proposal to merge the two concepts but for now they are separate. 13 | 14 | A Jenkins X Addon allows us to add optional core functionality to Jenkins X. 15 | There are a number of addons; you can run `jx create addon --help` to see a 16 | list. 17 | 18 | Unlike apps, addons are not tracked using GitOps. 19 | 20 | ## Installing an Addon 21 | 22 | Run the `jx create addon` command. For example: 23 | 24 | ``` 25 | jx create addon anchore 26 | ``` 27 | 28 | ## Cleaning Up 29 | 30 | To delete the addon, run: 31 | 32 | ``` 33 | jx delete addon anchore 34 | ``` 35 | -------------------------------------------------------------------------------- /section-6/video-6.3/README.md: -------------------------------------------------------------------------------- 1 | # Video 6.3 2 | 3 | This video demonstrates installing Prometheus as a Jenkins X addon. 4 | 5 | ## Prerequisites 6 | 7 | First install your cluster per the instruction in section 1. 8 | 9 | ## Prometheus 10 | 11 | Prometheus is a monitoring service. It is configured with a list of endpoints 12 | that it "scrapes" periodically to collect data. This data can include health 13 | information or metrics such as number of requests. Prometheus provides a 14 | database of all of the data it scrapes for use in visualizations. 15 | 16 | Many of the Kubernetes and Jenkins X services are already configured with 17 | endpoints to provide data to Prometheus, and when we install Prometheus in 18 | Kubernetes, it can automatically detect where to scrape metrics data. This 19 | makes it very easy to add monitoring for Kubernetes components and our own 20 | applications. 21 | 22 | ## Installing Prometheus 23 | 24 | Install Prometheus as a Jenkins X addon: 25 | 26 | ``` 27 | jx create addon prometheus 28 | ``` 29 | 30 | Then visit the Prometheus server in the browser. You can get the URL by 31 | running `kubectl get ingress`. Use `admin` as the username and password. 32 | 33 | ## Cleaning Up 34 | 35 | To delete the addon, run: 36 | 37 | ``` 38 | jx delete addon prometheus 39 | ``` 40 | -------------------------------------------------------------------------------- /section-6/video-6.4/README.md: -------------------------------------------------------------------------------- 1 | # Video 6.4 2 | 3 | This video demonstrates installing Grafana as a Jenkins X addon. 4 | 5 | ## Prerequisites 6 | 7 | First install your cluster per the instruction in section 1. 8 | 9 | ## Grafana 10 | 11 | Grafana is a visualization tool. It can pull data from sources such as 12 | Prometheus and present them in a variety of ways. 13 | 14 | ## Installing Grafana 15 | 16 | Install Grafana as a Jenkins X addon: 17 | 18 | ``` 19 | jx create addon grafana 20 | ``` 21 | 22 | Next, we need to retrieve the password. First get the name of the running 23 | pod: 24 | 25 | ``` 26 | kubectl get pods -l app=grafana 27 | ``` 28 | 29 | Now use that pod name to get the password: 30 | 31 | ``` 32 | kubectl exec -ti env | grep PASS 33 | ``` 34 | 35 | ## Cleaning Up 36 | 37 | To delete the addon, run: 38 | 39 | ``` 40 | jx delete addon grafana 41 | ``` 42 | --------------------------------------------------------------------------------